diff options
author | quou <quou@disroot.org> | 2025-03-10 15:03:05 +1100 |
---|---|---|
committer | quou <quou@disroot.org> | 2025-03-10 15:03:05 +1100 |
commit | 37b929e148e5b003f68903eb9ee192d24517e683 (patch) | |
tree | 79c39617fa73ddc95f30f0ff2c86b5b81c6de0bc | |
parent | 075e530b9964d1eb000dded329d2e8d80ee277c3 (diff) |
point light
-rw-r--r-- | c2.cpp | 18 | ||||
-rw-r--r-- | intermediate/forward.h | 13 | ||||
-rw-r--r-- | intermediate/surface.glsl | 21 | ||||
-rw-r--r-- | lighting.cpp | 32 | ||||
-rw-r--r-- | lighting.hpp | 9 |
5 files changed, 86 insertions, 7 deletions
@@ -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 |