Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/base/StarCellularLightArray.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-03-20 01:53:34 +1100
committerKae <80987908+Novaenia@users.noreply.github.com>2024-03-20 01:53:34 +1100
commit6d76a11e256cd96c9cdd7ae5a10c0276e6347277 (patch)
treed52459889408115d1e0eb657a05dc58e098e50eb /source/base/StarCellularLightArray.cpp
parent58a346e563df12af9194c198c7ffe974411abb28 (diff)
experiment: unclamped lighting
Diffstat (limited to 'source/base/StarCellularLightArray.cpp')
-rw-r--r--source/base/StarCellularLightArray.cpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/source/base/StarCellularLightArray.cpp b/source/base/StarCellularLightArray.cpp
new file mode 100644
index 0000000..60a6d95
--- /dev/null
+++ b/source/base/StarCellularLightArray.cpp
@@ -0,0 +1,130 @@
+#include "StarCellularLightArray.hpp"
+// just specializing these in a cpp file so I can iterate on them without recompiling like 40 files!!
+
+namespace Star {
+
+template <>
+void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin, size_t ymin, size_t xmax, size_t ymax) {
+ float perBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle;
+ float perBlockAirAttenuation = 1.0f / m_pointMaxAir;
+
+ for (PointLight light : m_pointLights) {
+ if (light.position[0] < 0 || light.position[0] > m_width - 1 || light.position[1] < 0 || light.position[1] > m_height - 1)
+ continue;
+
+ float maxIntensity = ScalarLightTraits::maxIntensity(light.value);
+ Vec2F beamDirection = Vec2F(1, 0).rotate(light.beamAngle);
+
+ float maxRange = maxIntensity * m_pointMaxAir;
+ // The min / max considering the radius of the light
+ size_t lxmin = std::floor(std::max<float>(xmin, light.position[0] - maxRange));
+ size_t lymin = std::floor(std::max<float>(ymin, light.position[1] - maxRange));
+ size_t lxmax = std::ceil(std::min<float>(xmax, light.position[0] + maxRange));
+ size_t lymax = std::ceil(std::min<float>(ymax, light.position[1] + maxRange));
+
+ for (size_t x = lxmin; x < lxmax; ++x) {
+ for (size_t y = lymin; y < lymax; ++y) {
+ LightValue lvalue = getLight(x, y);
+ // + 0.5f to correct block position to center
+ Vec2F blockPos = Vec2F(x + 0.5f, y + 0.5f);
+
+ Vec2F relativeLightPosition = blockPos - light.position;
+ float distance = relativeLightPosition.magnitude();
+ if (distance == 0.0f) {
+ setLight(x, y, light.value + lvalue);
+ continue;
+ }
+
+ float attenuation = distance * perBlockAirAttenuation;
+ if (attenuation >= 1.0f)
+ continue;
+
+ Vec2F direction = relativeLightPosition / distance;
+ if (light.beam > 0.0f) {
+ attenuation += (1.0f - light.beamAmbience) * clamp(light.beam * (1.0f - direction * beamDirection), 0.0f, 1.0f);
+ if (attenuation >= 1.0f)
+ continue;
+ }
+
+ float remainingAttenuation = maxIntensity - attenuation;
+ if (remainingAttenuation <= 0.0f)
+ continue;
+
+ // Need to circularize manhattan attenuation here
+ float circularizedPerBlockObstacleAttenuation = perBlockObstacleAttenuation / max(fabs(direction[0]), fabs(direction[1]));
+ float blockAttenuation = lineAttenuation(blockPos, light.position, circularizedPerBlockObstacleAttenuation, remainingAttenuation);
+
+ // Apply single obstacle boost (determine single obstacle by one
+ // block unit of attenuation).
+ attenuation += blockAttenuation + min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost;
+
+ if (attenuation < 1.0f)
+ setLight(x, y, lvalue + ScalarLightTraits::subtract(light.value, attenuation));
+ }
+ }
+ }
+}
+
+template <>
+void CellularLightArray<ColoredLightTraits>::calculatePointLighting(size_t xmin, size_t ymin, size_t xmax, size_t ymax) {
+ float perBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle;
+ float perBlockAirAttenuation = 1.0f / m_pointMaxAir;
+
+ for (PointLight light : m_pointLights) {
+ if (light.position[0] < 0 || light.position[0] > m_width - 1 || light.position[1] < 0 || light.position[1] > m_height - 1)
+ continue;
+
+ float maxIntensity = ColoredLightTraits::maxIntensity(light.value);
+ Vec2F beamDirection = Vec2F(1, 0).rotate(light.beamAngle);
+
+ float maxRange = maxIntensity * m_pointMaxAir;
+ // The min / max considering the radius of the light
+ size_t lxmin = std::floor(std::max<float>(xmin, light.position[0] - maxRange));
+ size_t lymin = std::floor(std::max<float>(ymin, light.position[1] - maxRange));
+ size_t lxmax = std::ceil(std::min<float>(xmax, light.position[0] + maxRange));
+ size_t lymax = std::ceil(std::min<float>(ymax, light.position[1] + maxRange));
+
+ for (size_t x = lxmin; x < lxmax; ++x) {
+ for (size_t y = lymin; y < lymax; ++y) {
+ LightValue lvalue = getLight(x, y);
+ // + 0.5f to correct block position to center
+ Vec2F blockPos = Vec2F(x + 0.5f, y + 0.5f);
+
+ Vec2F relativeLightPosition = blockPos - light.position;
+ float distance = relativeLightPosition.magnitude();
+ if (distance == 0.0f) {
+ setLight(x, y, light.value + lvalue);
+ continue;
+ }
+
+ float attenuation = distance * perBlockAirAttenuation;
+ if (attenuation >= 1.0f)
+ continue;
+
+ Vec2F direction = relativeLightPosition / distance;
+ if (light.beam > 0.0f) {
+ attenuation += (1.0f - light.beamAmbience) * clamp(light.beam * (1.0f - direction * beamDirection), 0.0f, 1.0f);
+ if (attenuation >= 1.0f)
+ continue;
+ }
+
+ float remainingAttenuation = maxIntensity - attenuation;
+ if (remainingAttenuation <= 0.0f)
+ continue;
+
+ // Need to circularize manhattan attenuation here
+ float circularizedPerBlockObstacleAttenuation = perBlockObstacleAttenuation / max(fabs(direction[0]), fabs(direction[1]));
+ float blockAttenuation = lineAttenuation(blockPos, light.position, circularizedPerBlockObstacleAttenuation, remainingAttenuation);
+
+ // Apply single obstacle boost (determine single obstacle by one
+ // block unit of attenuation).
+ attenuation += blockAttenuation + min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost;
+
+ if (attenuation < 1.0f)
+ setLight(x, y, lvalue + ColoredLightTraits::subtract(light.value, attenuation));
+ }
+ }
+ }
+}
+
+} \ No newline at end of file