From 1a12f9a621f920bcdd7098a49171745d141e0a48 Mon Sep 17 00:00:00 2001 From: Agent X <44549182+AgentXLP@users.noreply.github.com> Date: Sat, 17 Jan 2026 16:31:52 -0500 Subject: [PATCH] C++ lighting engine Runs better using my new system for storing and iterating through lights. I removed the lighting ctx profiler because after I've realized its very inaccurate and was probably programmed incorrectly from the start. Although I remember it working fine before and not constantly showing 20 ms or higher when I'm in an extremely simple level with extremely simple lights and the FPS is way too high for it to be taking 20 ms. --- autogen/lua_definitions/constants.lua | 2 +- src/engine/lighting_engine.c | 382 ------------------------ src/engine/lighting_engine.cpp | 409 ++++++++++++++++++++++++++ src/engine/lighting_engine.h | 9 +- src/pc/debug_context.h | 1 - src/pc/djui/djui_ctx_display.c | 1 - src/pc/gfx/gfx_pc.c | 6 - src/pc/lua/smlua_constants_autogen.c | 2 +- src/pc/mods/mod_storage.h | 4 +- 9 files changed, 421 insertions(+), 395 deletions(-) delete mode 100644 src/engine/lighting_engine.c create mode 100644 src/engine/lighting_engine.cpp diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index f2d30851a..6afd27a56 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -3635,7 +3635,7 @@ HUD_DISPLAY_DEFAULT = HUD_DISPLAY_FLAG_LIVES | HUD_DISPLAY_FLAG_CO --- | `HUD_DISPLAY_DEFAULT` --- @type integer -LE_MAX_LIGHTS = 512 +LE_MAX_LIGHTS = 1024 LE_MODE_AFFECT_ALL_SHADED_AND_COLORED = 0 --- @type LEMode LE_MODE_AFFECT_ALL_SHADED = 1 --- @type LEMode diff --git a/src/engine/lighting_engine.c b/src/engine/lighting_engine.c deleted file mode 100644 index 7466a5d80..000000000 --- a/src/engine/lighting_engine.c +++ /dev/null @@ -1,382 +0,0 @@ -#include "lighting_engine.h" -#include "math_util.h" - -struct LELight -{ - f32 posX; - f32 posY; - f32 posZ; - u8 colorR; - u8 colorG; - u8 colorB; - f32 radius; - f32 intensity; - bool added; - bool useSurfaceNormals; -}; - -Color gLEAmbientColor = { 127, 127, 127 }; -static struct LELight sLights[LE_MAX_LIGHTS] = { 0 }; -static enum LEMode sMode = LE_MODE_AFFECT_ALL_SHADED_AND_COLORED; -static enum LEToneMapping sToneMapping = LE_TONE_MAPPING_WEIGHTED; -static bool sEnabled = false; - -static inline void color_set(Color color, u8 r, u8 g, u8 b) { - color[0] = r; - color[1] = g; - color[2] = b; -} - -static inline void color_copy(Color dest, Color src) { - dest[0] = src[0]; - dest[1] = src[1]; - dest[2] = src[2]; -} - -bool le_is_enabled(void) { - // this is needed because we don't want to make vanilla darker, - // and we don't want to set the ambient color to { 255, 255, 255 } - // because then no one could see the effect of their lights - return sEnabled; -} - -void le_set_mode(enum LEMode mode) { - sMode = mode; -} - -enum LEMode le_get_mode(void) { - return sMode; -} - -void le_set_tone_mapping(enum LEToneMapping toneMapping) { - sToneMapping = toneMapping; -} - -void le_get_ambient_color(VEC_OUT Color out) { - color_copy(out, gLEAmbientColor); -} - -void le_set_ambient_color(u8 r, u8 g, u8 b) { - color_set(gLEAmbientColor, r, g, b); - sEnabled = true; -} - -static inline void le_tone_map_total_weighted(Color out, Color inAmbient, Vec3f inColor, float weight) { - out[0] = clamp((inAmbient[0] + inColor[0]) / weight, 0, 255); - out[1] = clamp((inAmbient[1] + inColor[1]) / weight, 0, 255); - out[2] = clamp((inAmbient[2] + inColor[2]) / weight, 0, 255); -} - -static inline void le_tone_map_weighted(Color out, Color inAmbient, Vec3f inColor, float weight) { - out[0] = clamp(inAmbient[0] + (inColor[0] / weight), 0, 255); - out[1] = clamp(inAmbient[1] + (inColor[1] / weight), 0, 255); - out[2] = clamp(inAmbient[2] + (inColor[2] / weight), 0, 255); -} - -static inline void le_tone_map_clamp(Color out, Color inAmbient, Vec3f inColor) { - out[0] = clamp(inAmbient[0] + inColor[0], 0, 255); - out[1] = clamp(inAmbient[1] + inColor[1], 0, 255); - out[2] = clamp(inAmbient[2] + inColor[2], 0, 255); -} - -static inline void le_tone_map_reinhard(Color out, Color inAmbient, Vec3f inColor) { - inColor[0] += inAmbient[0]; - inColor[1] += inAmbient[1]; - inColor[2] += inAmbient[2]; - - out[0] = clamp((inColor[0] / (inColor[0] + 255.0f)) * 255.0f, 0, 255); - out[1] = clamp((inColor[1] / (inColor[1] + 255.0f)) * 255.0f, 0, 255); - out[2] = clamp((inColor[2] / (inColor[2] + 255.0f)) * 255.0f, 0, 255); -} - -static inline void le_tone_map(Color out, Color inAmbient, Vec3f inColor, float weight) { - switch (sToneMapping) { - case LE_TONE_MAPPING_TOTAL_WEIGHTED: le_tone_map_total_weighted(out, inAmbient, inColor, weight); break; - case LE_TONE_MAPPING_WEIGHTED: le_tone_map_weighted(out, inAmbient, inColor, weight); break; - case LE_TONE_MAPPING_CLAMP: le_tone_map_clamp(out, inAmbient, inColor); break; - case LE_TONE_MAPPING_REINHARD: le_tone_map_reinhard(out, inAmbient, inColor); break; - } -} - -static inline void le_calculate_light_contribution(struct LELight* light, Vec3f pos, Vec3f normal, f32 lightIntensityScalar, Vec3f out_color, f32* weight) { - // skip 'inactive' lights - if (light->intensity <= 0 || light->radius <= 0) { return; } - - // vector to light - f32 diffX = light->posX - pos[0]; - f32 diffY = light->posY - pos[1]; - f32 diffZ = light->posZ - pos[2]; - - // squared distance check - f32 dist2 = (diffX * diffX) + (diffY * diffY) + (diffZ * diffZ); - f32 radius2 = light->radius * light->radius; - if (dist2 > radius2 || dist2 <= 0) { return; } - - // attenuation & intensity - f32 att = 1.0f - (dist2 / radius2); - f32 brightness = att * light->intensity * lightIntensityScalar; - - // normalize diff - f32 invLen = 1.0f / sqrtf(dist2); - diffX *= invLen; - diffY *= invLen; - diffZ *= invLen; - - if (light->useSurfaceNormals && normal) { - // lambert term - f32 nl = (normal[0] * diffX) + (normal[1] * diffY) + (normal[2] * diffZ); - if (nl <= 0.0f) { return; } - - // modulate by normal - brightness *= nl; - } - - // accumulate - out_color[0] += light->colorR * brightness; - out_color[1] += light->colorG * brightness; - out_color[2] += light->colorB * brightness; - *weight += brightness; -} - -void le_calculate_vertex_lighting(Vtx_t* v, Vec3f pos, Color out) { - // clear color - Vec3f color = { 0 }; - - // accumulate lighting - f32 weight = 1.0f; - for (s16 i = 0; i < LE_MAX_LIGHTS; i++) { - struct LELight* light = &sLights[i]; - if (!light->added) { continue; } - - le_calculate_light_contribution(light, pos, NULL, 1.0f, color, &weight); - } - - // tone map and output - Color vtxAmbient = { - v->cn[0] * (gLEAmbientColor[0] / 255.0f), - v->cn[1] * (gLEAmbientColor[1] / 255.0f), - v->cn[2] * (gLEAmbientColor[2] / 255.0f), - }; - le_tone_map(out, vtxAmbient, color, weight); -} - -void le_calculate_lighting_color(Vec3f pos, Color out, f32 lightIntensityScalar) { - // clear color - Vec3f color = { 0 }; - - // accumulate lighting - f32 weight = 1.0f; - for (s16 i = 0; i < LE_MAX_LIGHTS; i++) { - struct LELight* light = &sLights[i]; - if (!light->added) { continue; } - - le_calculate_light_contribution(light, pos, NULL, lightIntensityScalar, color, &weight); - } - - // tone map and output - le_tone_map(out, gLEAmbientColor, color, weight); -} - -void le_calculate_lighting_color_with_normal(Vec3f pos, Vec3f normal, Color out, f32 lightIntensityScalar) { - // normalize normal - if (normal) { vec3f_normalize(normal); } - - // clear color - Vec3f color = { 0 }; - - // accumulate lighting - f32 weight = 1.0f; - for (s16 i = 0; i < LE_MAX_LIGHTS; i++) { - struct LELight* light = &sLights[i]; - if (!light->added) { continue; } - - le_calculate_light_contribution(light, pos, normal, lightIntensityScalar, color, &weight); - } - - // tone map and output - le_tone_map(out, gLEAmbientColor, color, weight); -} - -void le_calculate_lighting_dir(Vec3f pos, Vec3f out) { - Vec3f lightingDir = { 0, 0, 0 }; - s16 count = 1; - - for (s16 i = 0; i < LE_MAX_LIGHTS; i++) { - struct LELight* light = &sLights[i]; - if (!light->added) { continue; } - - f32 diffX = light->posX - pos[0]; - f32 diffY = light->posY - pos[1]; - f32 diffZ = light->posZ - pos[2]; - f32 dist = (diffX * diffX) + (diffY * diffY) + (diffZ * diffZ); - f32 radius = light->radius * light->radius; - if (dist > radius) { continue; } - - Vec3f dir = { - pos[0] - light->posX, - pos[1] - light->posY, - pos[2] - light->posZ, - }; - vec3f_normalize(dir); - - f32 intensity = (1 - (dist / radius)) * light->intensity; - lightingDir[0] += dir[0] * intensity; - lightingDir[1] += dir[1] * intensity; - lightingDir[2] += dir[2] * intensity; - - count++; - } - - out[0] = lightingDir[0] / (f32)(count); - out[1] = lightingDir[1] / (f32)(count); - out[2] = lightingDir[2] / (f32)(count); - vec3f_normalize(out); -} - -s16 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity) { - struct LELight* newLight = NULL; - s16 lightID = -1; - - for (s16 i = 0; i < LE_MAX_LIGHTS; i++) { - struct LELight* light = &sLights[i]; - if (!light->added) { - newLight = light; - lightID = i; - break; - } - } - if (newLight == NULL) { return -1; } - - newLight->posX = x; - newLight->posY = y; - newLight->posZ = z; - newLight->colorR = r; - newLight->colorG = g; - newLight->colorB = b; - newLight->radius = radius; - newLight->intensity = intensity; - newLight->added = true; - newLight->useSurfaceNormals = true; - - sEnabled = true; - return lightID; -} - -void le_remove_light(s16 id) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return; } - - memset(&sLights[id], 0, sizeof(struct LELight)); -} - -s16 le_get_light_count(void) { - s16 count = 0; - for (s16 i = 0; i < LE_MAX_LIGHTS; i++) { - if (sLights[i].added) { count++; } - } - - return count; -} - -bool le_light_exists(s16 id) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return false; } - return sLights[id].added; -} - -void le_get_light_pos(s16 id, VEC_OUT Vec3f out) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return; } - vec3f_set(out, light->posX, light->posY, light->posZ); -} - -void le_set_light_pos(s16 id, f32 x, f32 y, f32 z) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return; } - light->posX = x; - light->posY = y; - light->posZ = z; -} - -void le_get_light_color(s16 id, VEC_OUT Color out) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return; } - color_set(out, light->colorR, light->colorG, light->colorB); -} - -void le_set_light_color(s16 id, u8 r, u8 g, u8 b) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return; } - light->colorR = r; - light->colorG = g; - light->colorB = b; -} - -f32 le_get_light_radius(s16 id) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return 0.0f; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return 0.0f; } - return light->radius; -} - -void le_set_light_radius(s16 id, f32 radius) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return; } - light->radius = radius; -} - -f32 le_get_light_intensity(s16 id) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return 0.0f; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return 0.0f; } - return light->intensity; -} - -void le_set_light_intensity(s16 id, f32 intensity) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return; } - light->intensity = intensity; -} - -bool le_get_light_use_surface_normals(s16 id) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return false; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return false; } - return light->useSurfaceNormals; -} - -void le_set_light_use_surface_normals(s16 id, bool useSurfaceNormals) { - if (id < 0 || id >= LE_MAX_LIGHTS) { return; } - - struct LELight* light = &sLights[id]; - if (!light->added) { return; } - light->useSurfaceNormals = useSurfaceNormals; -} - -void le_clear(void) { - memset(&sLights, 0, sizeof(struct LELight) * LE_MAX_LIGHTS); - - gLEAmbientColor[0] = 127; - gLEAmbientColor[1] = 127; - gLEAmbientColor[2] = 127; -} - -void le_shutdown(void) { - sEnabled = false; - sMode = LE_MODE_AFFECT_ALL_SHADED_AND_COLORED; - sToneMapping = LE_TONE_MAPPING_WEIGHTED; - le_clear(); -} diff --git a/src/engine/lighting_engine.cpp b/src/engine/lighting_engine.cpp new file mode 100644 index 000000000..1605828a6 --- /dev/null +++ b/src/engine/lighting_engine.cpp @@ -0,0 +1,409 @@ +#include "lighting_engine.h" +extern "C" { +#include "math_util.h" +} +#undef clamp +#undef min +#undef max +#include +#include + +#define C_FIELD extern "C" + +struct LELight +{ + s16 id; + f32 posX; + f32 posY; + f32 posZ; + u8 colorR; + u8 colorG; + u8 colorB; + f32 radius; + f32 intensity; + bool useSurfaceNormals; +}; + +Color gLEAmbientColor = { 127, 127, 127 }; +static std::vector sLights; +static s16 sLightID = 0; +static enum LEMode sMode = LE_MODE_AFFECT_ALL_SHADED_AND_COLORED; +static enum LEToneMapping sToneMapping = LE_TONE_MAPPING_WEIGHTED; +static bool sEnabled = false; + +static inline void color_set(Color color, u8 r, u8 g, u8 b) { + color[0] = r; + color[1] = g; + color[2] = b; +} + +static inline void color_copy(Color dest, Color src) { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; +} + +C_FIELD bool le_is_enabled(void) { + // this is needed because we don't want to make vanilla darker, + // and we don't want to set the ambient color to { 255, 255, 255 } + // because then no one could see the effect of their lights + return sEnabled; +} + +C_FIELD void le_set_mode(enum LEMode mode) { + sMode = mode; +} + +C_FIELD enum LEMode le_get_mode(void) { + return sMode; +} + +C_FIELD void le_set_tone_mapping(enum LEToneMapping toneMapping) { + sToneMapping = toneMapping; +} + +C_FIELD void le_get_ambient_color(VEC_OUT Color out) { + color_copy(out, gLEAmbientColor); +} + +C_FIELD void le_set_ambient_color(u8 r, u8 g, u8 b) { + color_set(gLEAmbientColor, r, g, b); + sEnabled = true; +} + +static inline void le_tone_map_total_weighted(Color out, Color inAmbient, Vec3f inColor, float weight) { + out[0] = std::clamp((s32)((inAmbient[0] + inColor[0]) / weight), 0, 255); + out[1] = std::clamp((s32)((inAmbient[1] + inColor[1]) / weight), 0, 255); + out[2] = std::clamp((s32)((inAmbient[2] + inColor[2]) / weight), 0, 255); +} + +static inline void le_tone_map_weighted(Color out, Color inAmbient, Vec3f inColor, float weight) { + out[0] = std::clamp((s32)(inAmbient[0] + (inColor[0] / weight)), 0, 255); + out[1] = std::clamp((s32)(inAmbient[1] + (inColor[1] / weight)), 0, 255); + out[2] = std::clamp((s32)(inAmbient[2] + (inColor[2] / weight)), 0, 255); +} + +static inline void le_tone_map_clamp(Color out, Color inAmbient, Vec3f inColor) { + out[0] = std::clamp((s32)(inAmbient[0] + inColor[0]), 0, 255); + out[1] = std::clamp((s32)(inAmbient[1] + inColor[1]), 0, 255); + out[2] = std::clamp((s32)(inAmbient[2] + inColor[2]), 0, 255); +} + +static inline void le_tone_map_reinhard(Color out, Color inAmbient, Vec3f inColor) { + inColor[0] += inAmbient[0]; + inColor[1] += inAmbient[1]; + inColor[2] += inAmbient[2]; + + out[0] = std::clamp((s32)((inColor[0] / (inColor[0] + 255.0f)) * 255.0f), 0, 255); + out[1] = std::clamp((s32)((inColor[1] / (inColor[1] + 255.0f)) * 255.0f), 0, 255); + out[2] = std::clamp((s32)((inColor[2] / (inColor[2] + 255.0f)) * 255.0f), 0, 255); +} + +static inline void le_tone_map(Color out, Color inAmbient, Vec3f inColor, float weight) { + switch (sToneMapping) { + case LE_TONE_MAPPING_TOTAL_WEIGHTED: le_tone_map_total_weighted(out, inAmbient, inColor, weight); break; + case LE_TONE_MAPPING_WEIGHTED: le_tone_map_weighted(out, inAmbient, inColor, weight); break; + case LE_TONE_MAPPING_CLAMP: le_tone_map_clamp(out, inAmbient, inColor); break; + case LE_TONE_MAPPING_REINHARD: le_tone_map_reinhard(out, inAmbient, inColor); break; + } +} + +static inline void le_calculate_light_contribution(LELight light, Vec3f pos, Vec3f normal, f32 lightIntensityScalar, Vec3f out_color, f32* weight) { + // skip 'inactive' lights + if (light.intensity <= 0 || light.radius <= 0) { return; } + + // vector to light + f32 diffX = light.posX - pos[0]; + f32 diffY = light.posY - pos[1]; + f32 diffZ = light.posZ - pos[2]; + + // squared distance check + f32 dist2 = (diffX * diffX) + (diffY * diffY) + (diffZ * diffZ); + f32 radius2 = light.radius * light.radius; + if (dist2 > radius2 || dist2 <= 0) { return; } + + // attenuation & intensity + f32 att = 1.0f - (dist2 / radius2); + f32 brightness = att * light.intensity * lightIntensityScalar; + + // normalize diff + f32 invLen = 1.0f / sqrtf(dist2); + diffX *= invLen; + diffY *= invLen; + diffZ *= invLen; + + if (light.useSurfaceNormals && normal) { + // lambert term + f32 nl = (normal[0] * diffX) + (normal[1] * diffY) + (normal[2] * diffZ); + if (nl <= 0.0f) { return; } + + // modulate by normal + brightness *= nl; + } + + // accumulate + out_color[0] += light.colorR * brightness; + out_color[1] += light.colorG * brightness; + out_color[2] += light.colorB * brightness; + *weight += brightness; +} + +C_FIELD OPTIMIZE_O3 void le_calculate_vertex_lighting(Vtx_t* v, Vec3f pos, Color out) { + // clear color + Vec3f color = { 0 }; + + // accumulate lighting + f32 weight = 1.0f; + for (auto& light : sLights) { + le_calculate_light_contribution(light, pos, NULL, 1.0f, color, &weight); + } + + // tone map and output + Color vtxAmbient = { + (u8)(v->cn[0] * (gLEAmbientColor[0] / 255.0f)), + (u8)(v->cn[1] * (gLEAmbientColor[1] / 255.0f)), + (u8)(v->cn[2] * (gLEAmbientColor[2] / 255.0f)), + }; + le_tone_map(out, vtxAmbient, color, weight); +} + +C_FIELD OPTIMIZE_O3 void le_calculate_lighting_color(Vec3f pos, Color out, f32 lightIntensityScalar) { + // clear color + Vec3f color = { 0 }; + + // accumulate lighting + f32 weight = 1.0f; + for (auto& light : sLights) { + le_calculate_light_contribution(light, pos, NULL, lightIntensityScalar, color, &weight); + } + + // tone map and output + le_tone_map(out, gLEAmbientColor, color, weight); +} + +C_FIELD OPTIMIZE_O3 void le_calculate_lighting_color_with_normal(Vec3f pos, Vec3f normal, Color out, f32 lightIntensityScalar) { + // normalize normal + if (normal) { vec3f_normalize(normal); } + + // clear color + Vec3f color = { 0 }; + + // accumulate lighting + f32 weight = 1.0f; + for (auto& light : sLights) { + le_calculate_light_contribution(light, pos, normal, lightIntensityScalar, color, &weight); + } + + // tone map and output + le_tone_map(out, gLEAmbientColor, color, weight); +} + +C_FIELD void le_calculate_lighting_dir(Vec3f pos, Vec3f out) { + Vec3f lightingDir = { 0, 0, 0 }; + s16 count = 1; + + for (auto& light : sLights) { + f32 diffX = light.posX - pos[0]; + f32 diffY = light.posY - pos[1]; + f32 diffZ = light.posZ - pos[2]; + f32 dist = (diffX * diffX) + (diffY * diffY) + (diffZ * diffZ); + f32 radius = light.radius * light.radius; + if (dist > radius) { continue; } + + Vec3f dir = { + pos[0] - light.posX, + pos[1] - light.posY, + pos[2] - light.posZ, + }; + vec3f_normalize(dir); + + f32 intensity = (1 - (dist / radius)) * light.intensity; + lightingDir[0] += dir[0] * intensity; + lightingDir[1] += dir[1] * intensity; + lightingDir[2] += dir[2] * intensity; + + count++; + } + + out[0] = lightingDir[0] / (f32)(count); + out[1] = lightingDir[1] / (f32)(count); + out[2] = lightingDir[2] / (f32)(count); + vec3f_normalize(out); +} + +C_FIELD s16 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity) { + if (sLights.size() >= LE_MAX_LIGHTS) { return -1; } + + LELight newLight; + newLight.id = sLightID++; + newLight.posX = x; + newLight.posY = y; + newLight.posZ = z; + newLight.colorR = r; + newLight.colorG = g; + newLight.colorB = b; + newLight.radius = radius; + newLight.intensity = intensity; + newLight.useSurfaceNormals = true; + + sLights.push_back(newLight); + + sEnabled = true; + return sLightID; +} + +C_FIELD void le_remove_light(s16 id) { + if (id < 0) { return; } + + s16 index = 0; + for (auto& light : sLights) { + if (light.id == id) { + sLights.erase(sLights.begin() + index); + return; + } + index++; + } +} + +C_FIELD s16 le_get_light_count(void) { + return sLights.size(); +} + +C_FIELD bool le_light_exists(s16 id) { + if (id < 0) { return false; } + + for (auto& light : sLights) { + if (light.id == id) { + return true; + } + } + + return false; +} + +C_FIELD void le_get_light_pos(s16 id, VEC_OUT Vec3f out) { + if (id < 0) { return; } + + for (auto& light : sLights) { + if (light.id == id) { + vec3f_set(out, light.posX, light.posY, light.posZ); + } + } +} + +C_FIELD void le_set_light_pos(s16 id, f32 x, f32 y, f32 z) { + if (id < 0) { return; } + + for (auto& light : sLights) { + if (light.id == id) { + light.posX = x; + light.posY = y; + light.posZ = z; + } + } +} + +C_FIELD void le_get_light_color(s16 id, VEC_OUT Color out) { + if (id < 0) { return; } + + for (auto& light : sLights) { + if (light.id == id) { + color_set(out, light.colorR, light.colorG, light.colorB); + } + } +} + +C_FIELD void le_set_light_color(s16 id, u8 r, u8 g, u8 b) { + if (id < 0) { return; } + + for (auto& light : sLights) { + if (light.id == id) { + light.colorR = r; + light.colorG = g; + light.colorB = b; + } + } + +} + +C_FIELD f32 le_get_light_radius(s16 id) { + if (id < 0) { return 0.0f; } + + for (auto& light : sLights) { + if (light.id == id) { + return light.radius; + } + } + + return 0.0f; +} + +C_FIELD void le_set_light_radius(s16 id, f32 radius) { + if (id < 0) { return; } + + for (auto& light : sLights) { + if (light.id == id) { + light.radius = radius; + } + } +} + +C_FIELD f32 le_get_light_intensity(s16 id) { + if (id < 0) { return 0.0f; } + + for (auto& light : sLights) { + if (light.id == id) { + return light.intensity; + } + } + + return 0.0f; +} + +C_FIELD void le_set_light_intensity(s16 id, f32 intensity) { + if (id < 0) { return; } + + for (auto& light : sLights) { + if (light.id == id) { + light.intensity = intensity; + } + } +} + +C_FIELD bool le_get_light_use_surface_normals(s16 id) { + if (id < 0) { return false; } + + for (auto& light : sLights) { + if (light.id == id) { + return light.useSurfaceNormals; + } + } + + return false; +} + +C_FIELD void le_set_light_use_surface_normals(s16 id, bool useSurfaceNormals) { + if (id < 0) { return; } + + for (auto& light : sLights) { + if (light.id == id) { + light.useSurfaceNormals = useSurfaceNormals; + } + } +} + +void le_clear(void) { + sLights.clear(); + sLightID = 0; + + gLEAmbientColor[0] = 127; + gLEAmbientColor[1] = 127; + gLEAmbientColor[2] = 127; +} + +void le_shutdown(void) { + sEnabled = false; + sMode = LE_MODE_AFFECT_ALL_SHADED_AND_COLORED; + sToneMapping = LE_TONE_MAPPING_WEIGHTED; + le_clear(); +} diff --git a/src/engine/lighting_engine.h b/src/engine/lighting_engine.h index 669e31d63..0d038c750 100644 --- a/src/engine/lighting_engine.h +++ b/src/engine/lighting_engine.h @@ -1,9 +1,12 @@ #ifndef LIGHTING_ENGINE_H #define LIGHTING_ENGINE_H +#ifdef __cplusplus +extern "C" { +#endif #include "types.h" -#define LE_MAX_LIGHTS 512 +#define LE_MAX_LIGHTS 1024 enum LEMode { LE_MODE_AFFECT_ALL_SHADED_AND_COLORED, @@ -71,4 +74,8 @@ void le_set_light_use_surface_normals(s16 id, bool useSurfaceNormals); void le_clear(void); void le_shutdown(void); +#ifdef __cplusplus +} +#endif + #endif // LIGHTING_ENGINE_H diff --git a/src/pc/debug_context.h b/src/pc/debug_context.h index 013f1e469..27048a91f 100644 --- a/src/pc/debug_context.h +++ b/src/pc/debug_context.h @@ -20,7 +20,6 @@ enum DebugContext { CTX_RENDER, CTX_LEVEL_SCRIPT, CTX_HOOK, - CTX_LIGHTING, CTX_MAX, // MUST BE KEPT IN SYNC WITH sDebugContextNames }; diff --git a/src/pc/djui/djui_ctx_display.c b/src/pc/djui/djui_ctx_display.c index 08359ec32..b485f76a4 100644 --- a/src/pc/djui/djui_ctx_display.c +++ b/src/pc/djui/djui_ctx_display.c @@ -17,7 +17,6 @@ static char* sDebugContextNames[] = { "RENDER", "LEVEL", "HOOK", - "LIGHTING", "OTHER", "MAX", }; diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index a89bcac74..340a4205b 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -894,7 +894,6 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons // if lighting engine is enabled and either we want to affect all shaded surfaces or the lighting engine geometry mode is on if (le_is_enabled() && ((le_get_mode() != LE_MODE_AFFECT_ONLY_GEOMETRY_MODE) || (rsp.geometry_mode & G_LIGHTING_ENGINE_EXT))) { Color color = { gLEAmbientColor[0], gLEAmbientColor[1], gLEAmbientColor[2] }; - CTX_BEGIN(CTX_LIGHTING); Vec3f vpos = { v->ob[0], v->ob[1], v->ob[2] }; Vec3f vnormal = { nx, ny, nz }; @@ -904,8 +903,6 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons le_calculate_lighting_color_with_normal(vpos, vnormal, color, 1.0f); - CTX_END(CTX_LIGHTING); - d->color.r *= color[0] / 255.0f; d->color.g *= color[1] / 255.0f; d->color.b *= color[2] / 255.0f; @@ -913,7 +910,6 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons // if lighting engine is enabled and we should affect all vertex colored surfaces or the lighting engine geometry mode is on } else if (le_is_enabled() && !(rsp.geometry_mode & G_LIGHT_MAP_EXT) && (affectAllVertexColored || (rsp.geometry_mode & G_LIGHTING_ENGINE_EXT))) { Color color = { gLEAmbientColor[0], gLEAmbientColor[1], gLEAmbientColor[2] }; - CTX_BEGIN(CTX_LIGHTING); Vec3f vpos = { v->ob[0], v->ob[1], v->ob[2] }; @@ -930,8 +926,6 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons le_calculate_vertex_lighting((Vtx_t*)v, vpos, color); } - CTX_END(CTX_LIGHTING); - // combine the colors if (affectAllVertexColored && !(rsp.geometry_mode & G_LIGHTING_ENGINE_EXT)) { d->color.r = (v->cn[0] * color[0] / 255.0f) * vertexColorCached[0]; diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index a55aae378..90b2512ce 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1794,7 +1794,7 @@ char gSmluaConstants[] = "" "HUD_DISPLAY_FLAG_EMPHASIZE_POWER=0x8000\n" "HUD_DISPLAY_NONE=0x0000\n" "HUD_DISPLAY_DEFAULT=HUD_DISPLAY_FLAG_LIVES | HUD_DISPLAY_FLAG_COIN_COUNT | HUD_DISPLAY_FLAG_STAR_COUNT | HUD_DISPLAY_FLAG_CAMERA_AND_POWER | HUD_DISPLAY_FLAG_CAMERA | HUD_DISPLAY_FLAG_POWER | HUD_DISPLAY_FLAG_KEYS | HUD_DISPLAY_FLAG_UNKNOWN_0020\n" -"LE_MAX_LIGHTS=512\n" +"LE_MAX_LIGHTS=1024\n" "LE_MODE_AFFECT_ALL_SHADED_AND_COLORED=0\n" "LE_MODE_AFFECT_ALL_SHADED=1\n" "LE_MODE_AFFECT_ONLY_GEOMETRY_MODE=2\n" diff --git a/src/pc/mods/mod_storage.h b/src/pc/mods/mod_storage.h index a3762e3f7..ee41af4a4 100644 --- a/src/pc/mods/mod_storage.h +++ b/src/pc/mods/mod_storage.h @@ -1,11 +1,11 @@ #ifndef MOD_STORAGE_H #define MOD_STORAGE_H -#include - #ifdef __cplusplus extern "C" { #endif +#include + #include "pc/lua/smlua_utils.h" #define MAX_KEYS 4096