From 0ee8d5f81eb207cee368f296348462fb6438ca82 Mon Sep 17 00:00:00 2001
From: Agent X <44549182+AgentXLP@users.noreply.github.com>
Date: Fri, 28 Mar 2025 23:06:48 -0400
Subject: [PATCH] Fix/optimize/improve lighting engine
---
autogen/lua_definitions/functions.lua | 27 +++++-
autogen/lua_definitions/manual.lua | 4 +-
autogen/lua_definitions/structs.lua | 1 +
data/behavior_data.c | 4 +-
data/dynos_mgr_builtin.cpp | 2 +-
docs/lua/functions-2.md | 63 ++++++++++++-
docs/lua/functions-3.md | 4 +-
docs/lua/functions.md | 4 +-
docs/lua/structs.md | 1 +
include/object_fields.h | 3 +-
src/engine/lighting_engine.c | 129 ++++++++++++++++++--------
src/engine/lighting_engine.h | 12 ++-
src/game/behavior_actions.h | 6 +-
src/game/behaviors/light.inc.c | 36 ++++++-
src/pc/gfx/gfx_pc.c | 1 -
src/pc/lua/smlua_cobject_autogen.c | 3 +-
src/pc/lua/smlua_functions_autogen.c | 66 ++++++++++++-
17 files changed, 301 insertions(+), 65 deletions(-)
diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index 06794286b..54f4d5e4c 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -120,7 +120,7 @@ function bhv_alpha_boo_key_loop()
end
--- Behavior loop function for the lighting engine ambient light. Takes the first 3 behavior parameter bytes for RGB color
-function bhv_ambient_light_init()
+function bhv_ambient_light_update()
-- ...
end
@@ -2841,6 +2841,18 @@ function play_penguin_walking_sound(walk)
-- ...
end
+--- @param x number
+--- @param y number
+--- @param z number
+--- @param r integer
+--- @param g integer
+--- @param b integer
+--- @return Object
+--- Spawns a lighting engine point light
+function spawn_ambient_light(x, y, z, r, g, b)
+ -- ...
+end
+
--- @param x number
--- @param y number
--- @param z number
@@ -2872,6 +2884,19 @@ function spawn_no_exit_star(x, y, z)
-- ...
end
+--- @param x number
+--- @param y number
+--- @param z number
+--- @param r integer
+--- @param g integer
+--- @param b integer
+--- @param radius number
+--- @return Object
+--- Spawns a lighting engine ambient light
+function spawn_point_light(x, y, z, r, g, b, radius)
+ -- ...
+end
+
--- @param x number
--- @param y number
--- @param z number
diff --git a/autogen/lua_definitions/manual.lua b/autogen/lua_definitions/manual.lua
index da6186217..65bef6f64 100644
--- a/autogen/lua_definitions/manual.lua
+++ b/autogen/lua_definitions/manual.lua
@@ -356,12 +356,12 @@ function texture_override_reset(textureName)
-- ...
end
---- @class bhvData
+--- @class BehaviorData
--- @field behavior BehaviorId
--- @field behaviorArg integer
--- @param levelNum LevelNum | integer
---- @param func fun(areaIndex:number, bhvData:bhvData, macroBhvIds:BehaviorId[], macroBhvArgs:integer[])
+--- @param func fun(areaIndex:number, bhvData:BehaviorData, macroBhvIds:BehaviorId[], macroBhvArgs:integer[])
--- When `func` is called, arguments are filled depending on the level command:
--- - `AREA` command: only `areaIndex` is filled. It's a number
--- - `OBJECT` command: only `bhvData` is filled. `bhvData` is a table with nine fields: 'behavior', 'behaviorArg', 'model', 'posX', 'posY', 'posZ', 'pitch', 'yaw' and 'roll'
diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua
index 143ff8670..481cd2a00 100644
--- a/autogen/lua_definitions/structs.lua
+++ b/autogen/lua_definitions/structs.lua
@@ -1709,6 +1709,7 @@
--- @field public oKoopaTurningAwayFromWall integer
--- @field public oKoopaUnshelledTimeUntilTurn integer
--- @field public oLightID integer
+--- @field public oLightRadius number
--- @field public oLllRotatingHexFlameUnkF4 number
--- @field public oLllRotatingHexFlameUnkF8 number
--- @field public oLllRotatingHexFlameUnkFC number
diff --git a/data/behavior_data.c b/data/behavior_data.c
index 335b10187..f691d3c11 100644
--- a/data/behavior_data.c
+++ b/data/behavior_data.c
@@ -6440,7 +6440,9 @@ const BehaviorScript editor_Scroll_Texture[] = {
const BehaviorScript bhvAmbientLight[] = {
BEGIN(OBJ_LIST_DEFAULT),
ID(id_bhvAmbientLight),
- CALL_NATIVE(bhv_ambient_light_init),
+ BEGIN_LOOP(),
+ CALL_NATIVE(bhv_ambient_light_update),
+ END_LOOP(),
};
const BehaviorScript bhvPointLight[] = {
diff --git a/data/dynos_mgr_builtin.cpp b/data/dynos_mgr_builtin.cpp
index de1ca0de5..d222411a3 100644
--- a/data/dynos_mgr_builtin.cpp
+++ b/data/dynos_mgr_builtin.cpp
@@ -2030,7 +2030,7 @@ static const void* sDynosBuiltinFuncs[] = {
define_builtin(spawn_star_number),
define_builtin(bhv_ferris_wheel_platform_init),
define_builtin(geo_mario_cap_display_list),
- define_builtin(bhv_ambient_light_init),
+ define_builtin(bhv_ambient_light_update),
define_builtin(bhv_point_light_init),
define_builtin(bhv_point_light_loop),
};
diff --git a/docs/lua/functions-2.md b/docs/lua/functions-2.md
index 4381b0942..fa6ffb4b3 100644
--- a/docs/lua/functions-2.md
+++ b/docs/lua/functions-2.md
@@ -436,13 +436,13 @@ Behavior loop function for alpha boo key
-## [bhv_ambient_light_init](#bhv_ambient_light_init)
+## [bhv_ambient_light_update](#bhv_ambient_light_update)
### Description
Behavior loop function for the lighting engine ambient light. Takes the first 3 behavior parameter bytes for RGB color
### Lua Example
-`bhv_ambient_light_init()`
+`bhv_ambient_light_update()`
### Parameters
- None
@@ -451,7 +451,7 @@ Behavior loop function for the lighting engine ambient light. Takes the first 3
- None
### C Prototype
-`void bhv_ambient_light_init(void);`
+`void bhv_ambient_light_update(void);`
[:arrow_up_small:](#)
@@ -11818,6 +11818,34 @@ Plays the penguin walking sound
+## [spawn_ambient_light](#spawn_ambient_light)
+
+### Description
+Spawns a lighting engine point light
+
+### Lua Example
+`local ObjectValue = spawn_ambient_light(x, y, z, r, g, b)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| x | `number` |
+| y | `number` |
+| z | `number` |
+| r | `integer` |
+| g | `integer` |
+| b | `integer` |
+
+### Returns
+[Object](structs.md#Object)
+
+### C Prototype
+`struct Object* spawn_ambient_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b);`
+
+[:arrow_up_small:](#)
+
+
+
## [spawn_default_star](#spawn_default_star)
### Description
@@ -11914,6 +11942,35 @@ Spawns a Star that won't make Mario exit the level with an ID corresponding to t
+## [spawn_point_light](#spawn_point_light)
+
+### Description
+Spawns a lighting engine ambient light
+
+### Lua Example
+`local ObjectValue = spawn_point_light(x, y, z, r, g, b, radius)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| x | `number` |
+| y | `number` |
+| z | `number` |
+| r | `integer` |
+| g | `integer` |
+| b | `integer` |
+| radius | `number` |
+
+### Returns
+[Object](structs.md#Object)
+
+### C Prototype
+`struct Object* spawn_point_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius);`
+
+[:arrow_up_small:](#)
+
+
+
## [spawn_red_coin_cutscene_star](#spawn_red_coin_cutscene_star)
### Description
diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md
index 4c5b339f6..31ce79ac4 100644
--- a/docs/lua/functions-3.md
+++ b/docs/lua/functions-3.md
@@ -6273,7 +6273,7 @@ Adds a lighting engine point light at `x`, `y`, `z` with color `r`, `g`, `b` and
- `integer`
### C Prototype
-`s16 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity);`
+`s32 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity);`
[:arrow_up_small:](#)
@@ -6343,7 +6343,7 @@ Gets the total number of lights currently loaded in the lighting engine
- `integer`
### C Prototype
-`s16 le_get_light_count(void);`
+`s32 le_get_light_count(void);`
[:arrow_up_small:](#)
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index b80ee43c1..bd3bf4392 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -59,7 +59,7 @@
- [bhv_activated_back_and_forth_platform_init](functions-2.md#bhv_activated_back_and_forth_platform_init)
- [bhv_activated_back_and_forth_platform_update](functions-2.md#bhv_activated_back_and_forth_platform_update)
- [bhv_alpha_boo_key_loop](functions-2.md#bhv_alpha_boo_key_loop)
- - [bhv_ambient_light_init](functions-2.md#bhv_ambient_light_init)
+ - [bhv_ambient_light_update](functions-2.md#bhv_ambient_light_update)
- [bhv_ambient_sounds_init](functions-2.md#bhv_ambient_sounds_init)
- [bhv_animated_texture_loop](functions-2.md#bhv_animated_texture_loop)
- [bhv_animates_on_floor_switch_press_init](functions-2.md#bhv_animates_on_floor_switch_press_init)
@@ -600,10 +600,12 @@
- [mario_moving_fast_enough_to_make_piranha_plant_bite](functions-2.md#mario_moving_fast_enough_to_make_piranha_plant_bite)
- [obj_set_secondary_camera_focus](functions-2.md#obj_set_secondary_camera_focus)
- [play_penguin_walking_sound](functions-2.md#play_penguin_walking_sound)
+ - [spawn_ambient_light](functions-2.md#spawn_ambient_light)
- [spawn_default_star](functions-2.md#spawn_default_star)
- [spawn_mist_from_global](functions-2.md#spawn_mist_from_global)
- [spawn_mist_particles_variable](functions-2.md#spawn_mist_particles_variable)
- [spawn_no_exit_star](functions-2.md#spawn_no_exit_star)
+ - [spawn_point_light](functions-2.md#spawn_point_light)
- [spawn_red_coin_cutscene_star](functions-2.md#spawn_red_coin_cutscene_star)
- [spawn_star_number](functions-2.md#spawn_star_number)
- [spawn_triangle_break_particles](functions-2.md#spawn_triangle_break_particles)
diff --git a/docs/lua/structs.md b/docs/lua/structs.md
index 9af8a2141..8bb810723 100644
--- a/docs/lua/structs.md
+++ b/docs/lua/structs.md
@@ -2762,6 +2762,7 @@
| oYoshiTargetYaw | `integer` | |
| oBreakableWallForce | `integer` | |
| oLightID | `integer` | |
+| oLightRadius | `number` | |
[:arrow_up_small:](#)
diff --git a/include/object_fields.h b/include/object_fields.h
index d96906ea3..e9ba6e21b 100644
--- a/include/object_fields.h
+++ b/include/object_fields.h
@@ -1167,6 +1167,7 @@
#define /*0x104*/ oBreakableWallForce OBJECT_FIELD_S32(0x1F)
/* Point Light */
-#define /*0x104*/ oLightID OBJECT_FIELD_S32(0x1F)
+#define /*0x0F4*/ oLightID OBJECT_FIELD_S32(0x1B)
+#define /*0x0F8*/ oLightRadius OBJECT_FIELD_F32(0x1C)
#endif // OBJECT_FIELDS_H
diff --git a/src/engine/lighting_engine.c b/src/engine/lighting_engine.c
index a8b6b3c60..b27839df5 100644
--- a/src/engine/lighting_engine.c
+++ b/src/engine/lighting_engine.c
@@ -2,11 +2,15 @@
#include "math_util.h"
#include "surface_collision.h"
#include "pc/lua/utils/smlua_math_utils.h"
+#include "pc/debuglog.h"
#include "data/dynos_cmap.cpp.h"
+#define LE_MAX_LIGHTS 256
+#define LE_TOTAL_WEIGHTED_LIGHTING
+
static Color sAmbientColor;
static void* sLights = NULL;
-static s16 sLightID = -1;
+static s32 sLightID = 0;
static inline void color_set(Color color, u8 r, u8 g, u8 b) {
color[0] = r;
@@ -17,84 +21,115 @@ static inline void color_set(Color color, u8 r, u8 g, u8 b) {
void le_calculate_vertex_lighting(Vtx_t* v, Color out) {
if (sLights == NULL) { return; }
+#ifdef LE_TOTAL_WEIGHTED_LIGHTING
+ f32 r = v->cn[0] * (sAmbientColor[0] / 255.0f);
+ f32 g = v->cn[1] * (sAmbientColor[1] / 255.0f);
+ f32 b = v->cn[2] * (sAmbientColor[2] / 255.0f);
+#else
f32 r = 0;
f32 g = 0;
f32 b = 0;
+#endif
+ f32 weight = 1.0f;
for (struct LELight* light = hmap_begin(sLights); light != NULL; light = hmap_next(sLights)) {
- f32 dist = vec3f_dist(light->pos, v->ob);
- if (dist > light->radius) { continue; }
- dist = 1 - minf(dist / light->radius, 1);
+ f32 diffX = light->posX - v->ob[0];
+ f32 diffY = light->posY - v->ob[1];
+ f32 diffZ = light->posZ - v->ob[2];
+ f32 dist = (diffX * diffX) + (diffY * diffY) + (diffZ * diffZ);
+ f32 radius = light->radius * light->radius;
+ if (dist > radius) { continue; }
- r += light->color[0] * dist * light->intensity;
- g += light->color[1] * dist * light->intensity;
- b += light->color[2] * dist * light->intensity;
+ f32 brightness = (1 - (dist / radius)) * light->intensity;
+ r += light->colorR * brightness;
+ g += light->colorG * brightness;
+ b += light->colorB * brightness;
+ weight += brightness;
}
- out[0] = min((v->cn[0] * (sAmbientColor[0] / 255.0f)) + r, 255);
- out[1] = min((v->cn[1] * (sAmbientColor[1] / 255.0f)) + g, 255);
- out[2] = min((v->cn[2] * (sAmbientColor[2] / 255.0f)) + b, 255);
+#ifdef LE_TOTAL_WEIGHTED_LIGHTING
+ out[0] = min(r / weight, 255);
+ out[1] = min(g / weight, 255);
+ out[2] = min(b / weight, 255);
+#else
+ out[0] = min((v->cn[0] * (sAmbientColor[0] / 255.0f)) + (r / weight), 255);
+ out[1] = min((v->cn[1] * (sAmbientColor[1] / 255.0f)) + (g / weight), 255);
+ out[2] = min((v->cn[2] * (sAmbientColor[2] / 255.0f)) + (b / weight), 255);
+#endif
}
void le_calculate_lighting_color(Vec3f pos, Color out, f32 lightIntensityScalar) {
if (sLights == NULL) { return; }
- f32 r = 0;
- f32 g = 0;
- f32 b = 0;
+ f32 r = sAmbientColor[0];
+ f32 g = sAmbientColor[1];
+ f32 b = sAmbientColor[2];
for (struct LELight* light = hmap_begin(sLights); light != NULL; light = hmap_next(sLights)) {
- f32 dist = vec3f_dist(light->pos, pos);
- if (dist > light->radius) { continue; }
- dist = 1 - minf(dist / light->radius, 1);
+ 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; }
- r += light->color[0] * dist * light->intensity * lightIntensityScalar;
- g += light->color[1] * dist * light->intensity * lightIntensityScalar;
- b += light->color[2] * dist * light->intensity * lightIntensityScalar;
+ f32 brightness = (1 - (dist / radius)) * light->intensity * lightIntensityScalar;
+ r += light->colorR * brightness;
+ g += light->colorG * brightness;
+ b += light->colorB * brightness;
}
- out[0] = min(sAmbientColor[0] + r, 255);
- out[1] = min(sAmbientColor[1] + g, 255);
- out[2] = min(sAmbientColor[2] + b, 255);
+ out[0] = min(r, 255);
+ out[1] = min(g, 255);
+ out[2] = min(b, 255);
}
void le_calculate_lighting_dir(Vec3f pos, Vec3f out) {
if (sLights == NULL) { return; }
Vec3f lightingDir = { 0, 0, 0 };
- s16 count = 0;
+ s16 count = 1;
for (struct LELight* light = hmap_begin(sLights); light != NULL; light = hmap_next(sLights)) {
- f32 dist = vec3f_dist(light->pos, pos);
- if (dist > light->radius) { continue; }
- dist = 1 - minf(dist / light->radius, 1);
+ 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->pos[0],
- pos[1] - light->pos[1],
- pos[2] - light->pos[2],
+ pos[0] - light->posX,
+ pos[1] - light->posY,
+ pos[2] - light->posZ,
};
vec3f_normalize(dir);
- lightingDir[0] += dir[0] * dist * light->intensity;
- lightingDir[1] += dir[1] * dist * light->intensity;
- lightingDir[2] += dir[2] * dist * light->intensity;
+ f32 intensity = (1 - (dist / radius)) * light->intensity;
+ lightingDir[0] += dir[0] * intensity;
+ lightingDir[1] += dir[1] * intensity;
+ lightingDir[2] += dir[2] * intensity;
count++;
}
- count++; // additional increment
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) {
+s32 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity) {
if (sLights == NULL) {
sLights = hmap_create(true);
+ } else if (hmap_len(sLights) >= LE_MAX_LIGHTS) {
+ return 0;
}
struct LELight* light = calloc(1, sizeof(struct LELight));
- vec3f_set(light->pos, x, y, z);
- color_set(light->color, r, g, b);
+ light->posX = x;
+ light->posY = y;
+ light->posZ = z;
+ light->colorR = r;
+ light->colorG = g;
+ light->colorB = b;
light->radius = radius;
light->intensity = intensity;
hmap_put(sLights, ++sLightID, light);
@@ -102,11 +137,13 @@ s16 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensit
}
void le_remove_light(s16 id) {
+ if (sLights == NULL || id <= 0) { return; }
+
free(hmap_get(sLights, id));
hmap_del(sLights, id);
}
-s16 le_get_light_count(void) {
+s32 le_get_light_count(void) {
if (sLights == NULL) { return 0; }
return hmap_len(sLights);
}
@@ -116,24 +153,36 @@ void le_set_ambient_color(u8 r, u8 g, u8 b) {
}
void le_set_light_pos(s16 id, f32 x, f32 y, f32 z) {
+ if (sLights == NULL || id <= 0) { return; }
+
struct LELight* light = hmap_get(sLights, id);
if (light == NULL) { return; }
- vec3f_set(light->pos, x, y, z);
+ light->posX = x;
+ light->posY = y;
+ light->posZ = z;
}
void le_set_light_color(s16 id, u8 r, u8 g, u8 b) {
+ if (sLights == NULL || id <= 0) { return; }
+
struct LELight* light = hmap_get(sLights, id);
if (light == NULL) { return; }
- color_set(light->color, r, g, b);
+ light->colorR = r;
+ light->colorG = g;
+ light->colorB = b;
}
void le_set_light_radius(s16 id, f32 radius) {
+ if (sLights == NULL || id <= 0) { return; }
+
struct LELight* light = hmap_get(sLights, id);
if (light == NULL) { return; }
light->radius = radius;
}
void le_set_light_intensity(s16 id, f32 intensity) {
+ if (sLights == NULL || id <= 0) { return; }
+
struct LELight* light = hmap_get(sLights, id);
if (light == NULL) { return; }
light->intensity = intensity;
@@ -146,7 +195,7 @@ void le_clear(void) {
free(light);
}
hmap_clear(sLights);
- sLightID = -1;
+ sLightID = 0;
sAmbientColor[0] = 0;
sAmbientColor[1] = 0;
sAmbientColor[2] = 0;
diff --git a/src/engine/lighting_engine.h b/src/engine/lighting_engine.h
index 3feb3cf33..5708722df 100644
--- a/src/engine/lighting_engine.h
+++ b/src/engine/lighting_engine.h
@@ -5,8 +5,12 @@
struct LELight
{
- Vec3f pos;
- Color color;
+ f32 posX;
+ f32 posY;
+ f32 posZ;
+ u8 colorR;
+ u8 colorG;
+ u8 colorB;
f32 radius;
f32 intensity;
};
@@ -17,11 +21,11 @@ void le_calculate_lighting_color(Vec3f pos, Color out, f32 lightIntensityScalar)
/* |description|Calculates the lighting direction from a position and outputs the result in `out`|descriptionEnd| */
void le_calculate_lighting_dir(Vec3f pos, Vec3f out);
/* |description|Adds a lighting engine point light at `x`, `y`, `z` with color `r`, `g`, `b` and `radius` with `intensity`|descriptionEnd| */
-s16 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity);
+s32 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity);
/* |description|Removes a lighting engine point light corresponding to `id`|descriptionEnd| */
void le_remove_light(s16 id);
/* |description|Gets the total number of lights currently loaded in the lighting engine|descriptionEnd| */
-s16 le_get_light_count(void);
+s32 le_get_light_count(void);
/* |description|Sets the lighting engine ambient color|descriptionEnd| */
void le_set_ambient_color(u8 r, u8 g, u8 b);
/* |description|Sets a lighting engine point light's position to `x`, `y`, `z`|descriptionEnd| */
diff --git a/src/game/behavior_actions.h b/src/game/behavior_actions.h
index a19889ae1..968da5949 100644
--- a/src/game/behavior_actions.h
+++ b/src/game/behavior_actions.h
@@ -1147,8 +1147,12 @@ void bhv_yoshi_loop(void);
void bhv_volcano_trap_loop(void);
/* |description|Behavior loop function for UV texture scrolling|descriptionEnd| */
void uv_update_scroll(void);
+/* |description|Spawns a lighting engine point light|descriptionEnd| */
+struct Object* spawn_ambient_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b);
+/* |description|Spawns a lighting engine ambient light|descriptionEnd| */
+struct Object* spawn_point_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius);
/* |description|Behavior loop function for the lighting engine ambient light. Takes the first 3 behavior parameter bytes for RGB color|descriptionEnd| */
-void bhv_ambient_light_init(void);
+void bhv_ambient_light_update(void);
/* |description|Behavior init function for the lighting engine point light. Takes the first 3 behavior parameter bytes for RGB color and the last for radius|descriptionEnd| */
void bhv_point_light_init(void);
/* |description|Behavior loop function for the lighting engine point light|descriptionEnd| */
diff --git a/src/game/behaviors/light.inc.c b/src/game/behaviors/light.inc.c
index 7d5ebbe30..cb8dfcf19 100644
--- a/src/game/behaviors/light.inc.c
+++ b/src/game/behaviors/light.inc.c
@@ -1,4 +1,25 @@
-void bhv_ambient_light_init(void) {
+struct Object* spawn_ambient_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b) {
+ struct Object* obj = spawn_object(NULL, MODEL_NONE, bhvAmbientLight);
+
+ obj->oPosX = x;
+ obj->oPosY = y;
+ obj->oPosZ = z;
+ obj->oBehParams = (r << 24) | (g << 16) | (b << 8) | (0x00);
+ return obj;
+}
+
+struct Object* spawn_point_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius) {
+ struct Object* obj = spawn_object(NULL, MODEL_NONE, bhvPointLight);
+
+ obj->oPosX = x;
+ obj->oPosY = y;
+ obj->oPosZ = z;
+ obj->oBehParams = (r << 24) | (g << 16) | (b << 8) | (0x00);
+ obj->oLightRadius = radius;
+ return obj;
+}
+
+void bhv_ambient_light_update(void) {
le_set_ambient_color(
(o->oBehParams >> 24) & 0xFF,
(o->oBehParams >> 16) & 0xFF,
@@ -8,13 +29,21 @@ void bhv_ambient_light_init(void) {
void bhv_point_light_init(void) {
+ // assign oLightRadius
+ f32 radius = (o->oBehParams & 0xFF) * 10.0f;
+ if (o->oLightRadius != 0.0f) {
+ radius = o->oLightRadius;
+ } else if (radius != 0) {
+ o->oLightRadius = radius;
+ }
+
o->oLightID = le_add_light(
// position
o->oPosX, o->oPosY, o->oPosZ,
// color
(o->oBehParams >> 24) & 0xFF, (o->oBehParams >> 16) & 0xFF, (o->oBehParams >> 8) & 0xFF,
// radius
- (o->oBehParams & 0xFF) * 10.0f,
+ radius,
// intensity (2 by default)
2.0f
);
@@ -31,5 +60,8 @@ void bhv_point_light_loop(void) {
obj_copy_pos(o, o->parentObj);
}
+ // update these values every frame
le_set_light_pos(o->oLightID, o->oPosX, o->oPosY, o->oPosZ);
+ le_set_light_color(o->oLightID, (o->oBehParams >> 24) & 0xFF, (o->oBehParams >> 16) & 0xFF, (o->oBehParams >> 8) & 0xFF);
+ le_set_light_radius(o->oLightID, o->oLightRadius);
}
diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c
index b2ecf41ae..449fad7cd 100644
--- a/src/pc/gfx/gfx_pc.c
+++ b/src/pc/gfx/gfx_pc.c
@@ -877,7 +877,6 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons
d->color.g = color[1];
d->color.b = color[2];
}
-
} else {
if (!(rsp.geometry_mode & G_LIGHT_MAP_EXT) && luaVertexColor) {
d->color.r = v->cn[0] * vertexColorCached[0];
diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c
index 9e55d95b6..b1e5d88ef 100644
--- a/src/pc/lua/smlua_cobject_autogen.c
+++ b/src/pc/lua/smlua_cobject_autogen.c
@@ -1616,7 +1616,7 @@ static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT
{ "type", LVT_U8, offsetof(struct NetworkPlayer, type), true, LOT_NONE, 1, sizeof(u8) },
};
-#define LUA_OBJECT_FIELD_COUNT 761
+#define LUA_OBJECT_FIELD_COUNT 762
static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
{ "activeFlags", LVT_S16, offsetof(struct Object, activeFlags), false, LOT_NONE, 1, sizeof(s16) },
{ "allowRemoteInteractions", LVT_U8, offsetof(struct Object, allowRemoteInteractions), false, LOT_NONE, 1, sizeof(u8) },
@@ -2022,6 +2022,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
{ "oKoopaTurningAwayFromWall", LVT_S32, offsetof(struct Object, oKoopaTurningAwayFromWall), false, LOT_NONE, 1, sizeof(s32) },
{ "oKoopaUnshelledTimeUntilTurn", LVT_S32, offsetof(struct Object, oKoopaUnshelledTimeUntilTurn), false, LOT_NONE, 1, sizeof(s32) },
{ "oLightID", LVT_S32, offsetof(struct Object, oLightID), false, LOT_NONE, 1, sizeof(s32) },
+ { "oLightRadius", LVT_F32, offsetof(struct Object, oLightRadius), false, LOT_NONE, 1, sizeof(f32) },
{ "oLllRotatingHexFlameUnkF4", LVT_F32, offsetof(struct Object, oLllRotatingHexFlameUnkF4), false, LOT_NONE, 1, sizeof(f32) },
{ "oLllRotatingHexFlameUnkF8", LVT_F32, offsetof(struct Object, oLllRotatingHexFlameUnkF8), false, LOT_NONE, 1, sizeof(f32) },
{ "oLllRotatingHexFlameUnkFC", LVT_F32, offsetof(struct Object, oLllRotatingHexFlameUnkFC), false, LOT_NONE, 1, sizeof(f32) },
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index ec19820b2..edbe878be 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -565,18 +565,18 @@ int smlua_func_bhv_alpha_boo_key_loop(UNUSED lua_State* L) {
return 1;
}
-int smlua_func_bhv_ambient_light_init(UNUSED lua_State* L) {
+int smlua_func_bhv_ambient_light_update(UNUSED lua_State* L) {
if (!gCurrentObject) { return 0; }
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 0) {
- LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "bhv_ambient_light_init", 0, top);
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "bhv_ambient_light_update", 0, top);
return 0;
}
- bhv_ambient_light_init();
+ bhv_ambient_light_update();
return 1;
}
@@ -9465,6 +9465,33 @@ int smlua_func_play_penguin_walking_sound(lua_State* L) {
return 1;
}
+int smlua_func_spawn_ambient_light(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 6) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "spawn_ambient_light", 6, top);
+ return 0;
+ }
+
+ f32 x = smlua_to_number(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "spawn_ambient_light"); return 0; }
+ f32 y = smlua_to_number(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "spawn_ambient_light"); return 0; }
+ f32 z = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "spawn_ambient_light"); return 0; }
+ u8 r = smlua_to_integer(L, 4);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "spawn_ambient_light"); return 0; }
+ u8 g = smlua_to_integer(L, 5);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "spawn_ambient_light"); return 0; }
+ u8 b = smlua_to_integer(L, 6);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 6, "spawn_ambient_light"); return 0; }
+
+ smlua_push_object(L, LOT_OBJECT, spawn_ambient_light(x, y, z, r, g, b), NULL);
+
+ return 1;
+}
+
int smlua_func_spawn_default_star(lua_State* L) {
if (L == NULL) { return 0; }
@@ -9543,6 +9570,35 @@ int smlua_func_spawn_no_exit_star(lua_State* L) {
return 1;
}
+int smlua_func_spawn_point_light(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 7) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "spawn_point_light", 7, top);
+ return 0;
+ }
+
+ f32 x = smlua_to_number(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "spawn_point_light"); return 0; }
+ f32 y = smlua_to_number(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "spawn_point_light"); return 0; }
+ f32 z = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "spawn_point_light"); return 0; }
+ u8 r = smlua_to_integer(L, 4);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "spawn_point_light"); return 0; }
+ u8 g = smlua_to_integer(L, 5);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "spawn_point_light"); return 0; }
+ u8 b = smlua_to_integer(L, 6);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 6, "spawn_point_light"); return 0; }
+ f32 radius = smlua_to_number(L, 7);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 7, "spawn_point_light"); return 0; }
+
+ smlua_push_object(L, LOT_OBJECT, spawn_point_light(x, y, z, r, g, b, radius), NULL);
+
+ return 1;
+}
+
int smlua_func_spawn_red_coin_cutscene_star(lua_State* L) {
if (L == NULL) { return 0; }
@@ -33155,7 +33211,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "bhv_activated_back_and_forth_platform_init", smlua_func_bhv_activated_back_and_forth_platform_init);
smlua_bind_function(L, "bhv_activated_back_and_forth_platform_update", smlua_func_bhv_activated_back_and_forth_platform_update);
smlua_bind_function(L, "bhv_alpha_boo_key_loop", smlua_func_bhv_alpha_boo_key_loop);
- smlua_bind_function(L, "bhv_ambient_light_init", smlua_func_bhv_ambient_light_init);
+ smlua_bind_function(L, "bhv_ambient_light_update", smlua_func_bhv_ambient_light_update);
smlua_bind_function(L, "bhv_ambient_sounds_init", smlua_func_bhv_ambient_sounds_init);
smlua_bind_function(L, "bhv_animated_texture_loop", smlua_func_bhv_animated_texture_loop);
smlua_bind_function(L, "bhv_animates_on_floor_switch_press_init", smlua_func_bhv_animates_on_floor_switch_press_init);
@@ -33707,10 +33763,12 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "mario_moving_fast_enough_to_make_piranha_plant_bite", smlua_func_mario_moving_fast_enough_to_make_piranha_plant_bite);
smlua_bind_function(L, "obj_set_secondary_camera_focus", smlua_func_obj_set_secondary_camera_focus);
smlua_bind_function(L, "play_penguin_walking_sound", smlua_func_play_penguin_walking_sound);
+ smlua_bind_function(L, "spawn_ambient_light", smlua_func_spawn_ambient_light);
smlua_bind_function(L, "spawn_default_star", smlua_func_spawn_default_star);
smlua_bind_function(L, "spawn_mist_from_global", smlua_func_spawn_mist_from_global);
smlua_bind_function(L, "spawn_mist_particles_variable", smlua_func_spawn_mist_particles_variable);
smlua_bind_function(L, "spawn_no_exit_star", smlua_func_spawn_no_exit_star);
+ smlua_bind_function(L, "spawn_point_light", smlua_func_spawn_point_light);
smlua_bind_function(L, "spawn_red_coin_cutscene_star", smlua_func_spawn_red_coin_cutscene_star);
smlua_bind_function(L, "spawn_star_number", smlua_func_spawn_star_number);
smlua_bind_function(L, "spawn_triangle_break_particles", smlua_func_spawn_triangle_break_particles);