summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2025-03-10 15:03:05 +1100
committerquou <quou@disroot.org>2025-03-10 15:03:05 +1100
commit37b929e148e5b003f68903eb9ee192d24517e683 (patch)
tree79c39617fa73ddc95f30f0ff2c86b5b81c6de0bc
parent075e530b9964d1eb000dded329d2e8d80ee277c3 (diff)
point light
-rw-r--r--c2.cpp18
-rw-r--r--intermediate/forward.h13
-rw-r--r--intermediate/surface.glsl21
-rw-r--r--lighting.cpp32
-rw-r--r--lighting.hpp9
5 files changed, 86 insertions, 7 deletions
diff --git a/c2.cpp b/c2.cpp
index 1262241..58e33ff 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -761,6 +761,24 @@ struct C2 : public App {
light.caster = true;
}
{
+ auto l = world->create_entity();
+ auto [t, light] = world->add<Transform, Point_Light>(l);
+ t.mat = m4f::translate(m4f::identity(), v3f(-3.0f, 1.0f, 0.0f));
+ light.colour = v3f(1.0f, 0.0f, 0.0f);
+ light.brightness = 5.0f;
+ light.caster = true;
+ light.range = 5.0f;
+ }
+ {
+ auto l = world->create_entity();
+ auto [t, light] = world->add<Transform, Point_Light>(l);
+ t.mat = m4f::translate(m4f::identity(), v3f(3.0f, 2.0f, 0.0f));
+ light.colour = v3f(0.0f, 1.0f, 0.0f);
+ light.brightness = 5.0f;
+ light.caster = true;
+ light.range = 3.0f;
+ }
+ {
box_col = make_box(&asset_arena, v3f(1.0f, 1.0f, 1.0f));
floor_col = make_box(&asset_arena, v3f(10.0f, 0.1f, 10.0f));
box = world->create_entity();
diff --git a/intermediate/forward.h b/intermediate/forward.h
index 7c4c9d3..377a3cb 100644
--- a/intermediate/forward.h
+++ b/intermediate/forward.h
@@ -5,7 +5,7 @@
[struct]
name: Light
[variable]
-name: dir
+name: pos
type: vec3
[variable]
name: brightness
@@ -16,6 +16,12 @@ type: vec3
[variable]
name: caster_id
type: int
+[variable]
+name: type
+type: int
+[variable]
+name: range
+type: float
[struct]
name: Caster
@@ -41,4 +47,9 @@ type: Globals
stage: fragment
#endif
+
+/* match Light::Type in lighting.hpp */
+#define LT_SUN 0
+#define LT_POINT 1
+
#endif
diff --git a/intermediate/surface.glsl b/intermediate/surface.glsl
index 71a4307..79f5f65 100644
--- a/intermediate/surface.glsl
+++ b/intermediate/surface.glsl
@@ -244,8 +244,23 @@ void main() {
vec3 light = 0.0.xxx;
for (i = 0; i < globals.light_count; i++) {
Light l = lights[i];
- vec3 light_dir = l.dir;
- float cos_theta_i = max(dot(nrm, light_dir), 0.0);
+ vec3 light_dir;
+ float cos_theta_i, atten;
+ switch (l.type) {
+ case LT_SUN:
+ light_dir = l.pos;
+ cos_theta_i = max(dot(nrm, light_dir), 0.0);
+ atten = 1.0;
+ break;
+ case LT_POINT: {
+ float d;
+ light_dir = p - l.pos;
+ d = length(light_dir);
+ atten = max(d, 0.01);
+ atten = 1.0 / (atten * atten);
+ light_dir /= d;
+ } break;
+ }
vec3 diffuse = base_diffuse * cos_theta_i;
vec3 spec =
spec_col *
@@ -254,7 +269,7 @@ void main() {
float shadow = 1.0f;
if (l.caster_id >= 0)
shadow = get_shadow(l, p);
- light += (diffuse + spec) * l.brightness * l.colour * shadow;
+ light += (diffuse + spec) * atten * l.brightness * l.colour * shadow;
}
colour = vec4(ambient + light, 1.0);
diff --git a/lighting.cpp b/lighting.cpp
index 0e41ddd..bf01831 100644
--- a/lighting.cpp
+++ b/lighting.cpp
@@ -1,6 +1,7 @@
#include "lighting.hpp"
#include "model.hpp"
#include "renderer.hpp"
+#include "scene.hpp"
#include "world.hpp"
extern "C" {
@@ -10,10 +11,13 @@ extern "C" {
/* needs to match surface shader */
struct GPU_Light {
- v3f dir;
+ v3f pos;
float brightness;
v3f colour;
int caster_id;
+ int type;
+ float range;
+ int pad[2];
};
struct GPU_Caster {
@@ -102,11 +106,12 @@ void Lighting::write_bufs(
Sun_Light& l = v.get<Sun_Light>();
if (count >= max_lights) {
print_war("Over light limit.\n");
- return;
+ goto cancel;
}
+ gl.type = (int)Light::Type::sun;
gl.brightness = l.brightness;
gl.colour = l.colour;
- gl.dir = l.dir;
+ gl.pos = l.dir;
if (l.caster && ccount < max_shadows) {
int cid = ccount++;
GPU_Caster& c = cdst[cid];
@@ -122,6 +127,27 @@ void Lighting::write_bufs(
gl.caster_id = -1;
ldst[count++] = gl;
}
+ for (auto v : w.view<Transform, Point_Light>()) {
+ GPU_Light gl;
+ Transform& t = v.get<Transform>();
+ Point_Light& l = v.get<Point_Light>();
+ if (count >= max_lights) {
+ print_war("Over light limit.\n");
+ goto cancel;
+ }
+ gl.type = (int)Light::Type::point;
+ gl.brightness = l.brightness;
+ gl.colour = l.colour;
+ gl.pos = v3f(
+ t.mat.m[3][0],
+ t.mat.m[3][1],
+ t.mat.m[3][2]
+ );
+ gl.caster_id = -1;
+ gl.range = l.range;
+ ldst[count++] = gl;
+ }
+cancel:
light_count = count;
caster_count = ccount;
}
diff --git a/lighting.hpp b/lighting.hpp
index ccd08d3..38e95ae 100644
--- a/lighting.hpp
+++ b/lighting.hpp
@@ -41,6 +41,11 @@ struct Lighting {
};
struct Light {
+ enum class Type {
+ sun,
+ point
+ };
+
v3f colour;
float brightness;
bool caster;
@@ -50,4 +55,8 @@ struct Sun_Light : Light {
v3f dir;
};
+struct Point_Light : Light {
+ float range;
+};
+
#endif