Peachy changes

This commit is contained in:
Agent X 2026-02-17 15:30:30 -05:00
parent d8b6aa7d38
commit 636f644ccd
7 changed files with 151 additions and 156 deletions

View file

@ -5103,6 +5103,12 @@ function le_set_ambient_color(r, g, b)
-- ...
end
--- @param count integer
--- Sets the max amount of lights that can affect a vertex
function le_set_max_lights_per_vertex(count)
-- ...
end
--- @param pos Vec3f
--- @param out Color
--- @param lightIntensityScalar number

View file

@ -147,6 +147,29 @@ Sets the lighting engine ambient color
<br />
## [le_set_max_lights_per_vertex](#le_set_max_lights_per_vertex)
### Description
Sets the max amount of lights that can affect a vertex
### Lua Example
`le_set_max_lights_per_vertex(count)`
### Parameters
| Field | Type |
| ----- | ---- |
| count | `integer` |
### Returns
- None
### C Prototype
`void le_set_max_lights_per_vertex(u8 count);`
[:arrow_up_small:](#)
<br />
## [le_calculate_lighting_color](#le_calculate_lighting_color)
### Description

View file

@ -976,6 +976,7 @@
- [le_set_tone_mapping](functions-4.md#le_set_tone_mapping)
- [le_get_ambient_color](functions-4.md#le_get_ambient_color)
- [le_set_ambient_color](functions-4.md#le_set_ambient_color)
- [le_set_max_lights_per_vertex](functions-4.md#le_set_max_lights_per_vertex)
- [le_calculate_lighting_color](functions-4.md#le_calculate_lighting_color)
- [le_calculate_lighting_color_with_normal](functions-4.md#le_calculate_lighting_color_with_normal)
- [le_calculate_lighting_dir](functions-4.md#le_calculate_lighting_dir)

View file

@ -1,6 +1,7 @@
#include "lighting_engine.h"
extern "C" {
#include "math_util.h"
#include "pc/lua/smlua.h"
}
#undef clamp
#undef min
@ -13,17 +14,11 @@ extern "C" {
#define C_FIELD extern "C"
#define LE_MAX_LIGHTS_PER_VERTEX 4
struct LELight
{
s16 id;
f32 posX;
f32 posY;
f32 posZ;
u8 colorR;
u8 colorG;
u8 colorB;
Vec3f pos;
Color color;
f32 radius;
f32 intensity;
bool useSurfaceNormals;
@ -36,6 +31,7 @@ static s16 sLightID = -1;
static enum LEMode sMode = LE_MODE_AFFECT_ALL_SHADED_AND_COLORED;
static enum LEToneMapping sToneMapping = LE_TONE_MAPPING_WEIGHTED;
static bool sEnabled = false;
static u8 sMaxLightsPerVertex = 4;
static inline f32 rsqrt(f32 value) {
#ifdef __SSE__
@ -57,9 +53,8 @@ static inline void color_copy(Color dest, Color src) {
dest[2] = src[2];
}
static inline u8 to_u8(float value) {
int v = (int)value;
static inline u8 clamp_u8(f32 value) {
s32 v = (s32)value;
v = v < 0 ? 0 : v;
v = v > 255 ? 255 : v;
return (u8)v;
@ -93,22 +88,26 @@ C_FIELD void le_set_ambient_color(u8 r, u8 g, u8 b) {
sEnabled = true;
}
static inline void le_tone_map_total_weighted(Color out, Color inAmbient, Vec3f inColor, float weight) {
out[0] = to_u8((inAmbient[0] + inColor[0]) / weight);
out[1] = to_u8((inAmbient[1] + inColor[1]) / weight);
out[2] = to_u8((inAmbient[2] + inColor[2]) / weight);
C_FIELD void le_set_max_lights_per_vertex(u8 count) {
sMaxLightsPerVertex = count;
}
static inline void le_tone_map_weighted(Color out, Color inAmbient, Vec3f inColor, float weight) {
out[0] = to_u8(inAmbient[0] + (inColor[0] / weight));
out[1] = to_u8(inAmbient[1] + (inColor[1] / weight));
out[2] = to_u8(inAmbient[2] + (inColor[2] / weight));
static inline void le_tone_map_total_weighted(Color out, Color inAmbient, Vec3f inColor, f32 weight) {
out[0] = clamp_u8((inAmbient[0] + inColor[0]) / weight);
out[1] = clamp_u8((inAmbient[1] + inColor[1]) / weight);
out[2] = clamp_u8((inAmbient[2] + inColor[2]) / weight);
}
static inline void le_tone_map_weighted(Color out, Color inAmbient, Vec3f inColor, f32 weight) {
out[0] = clamp_u8(inAmbient[0] + (inColor[0] / weight));
out[1] = clamp_u8(inAmbient[1] + (inColor[1] / weight));
out[2] = clamp_u8(inAmbient[2] + (inColor[2] / weight));
}
static inline void le_tone_map_clamp(Color out, Color inAmbient, Vec3f inColor) {
out[0] = to_u8(inAmbient[0] + inColor[0]);
out[1] = to_u8(inAmbient[1] + inColor[1]);
out[2] = to_u8(inAmbient[2] + inColor[2]);
out[0] = clamp_u8(inAmbient[0] + inColor[0]);
out[1] = clamp_u8(inAmbient[1] + inColor[1]);
out[2] = clamp_u8(inAmbient[2] + inColor[2]);
}
static inline void le_tone_map_reinhard(Color out, Color inAmbient, Vec3f inColor) {
@ -116,12 +115,12 @@ static inline void le_tone_map_reinhard(Color out, Color inAmbient, Vec3f inColo
inColor[1] += inAmbient[1];
inColor[2] += inAmbient[2];
out[0] = to_u8((inColor[0] / (inColor[0] + 255.0f)) * 255.0f);
out[1] = to_u8((inColor[1] / (inColor[1] + 255.0f)) * 255.0f);
out[2] = to_u8((inColor[2] / (inColor[2] + 255.0f)) * 255.0f);
out[0] = clamp_u8((inColor[0] / (inColor[0] + 255.0f)) * 255.0f);
out[1] = clamp_u8((inColor[1] / (inColor[1] + 255.0f)) * 255.0f);
out[2] = clamp_u8((inColor[2] / (inColor[2] + 255.0f)) * 255.0f);
}
static inline void le_tone_map(Color out, Color inAmbient, Vec3f inColor, float weight) {
static void le_tone_map(Color out, Color inAmbient, Vec3f inColor, f32 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;
@ -139,11 +138,11 @@ static void le_update_active_lights() {
}
}
static inline OPTIMIZE_O3 void le_calculate_light_contribution(const LELight& light, Vec3f pos, Vec3f normal, f32 lightIntensityScalar, Vec3f out_color, f32& weight, u8& contribution) {
static inline OPTIMIZE_O3 void le_calculate_light_contribution(const LELight& light, Vec3f pos, Vec3f normal, f32 lightIntensityScalar, Vec3f outColor, f32& weight, u8& contribution) {
// vector to light
f32 diffX = light.posX - pos[0];
f32 diffY = light.posY - pos[1];
f32 diffZ = light.posZ - pos[2];
f32 diffX = light.pos[0] - pos[0];
f32 diffY = light.pos[1] - pos[1];
f32 diffZ = light.pos[2] - pos[2];
// squared distance check
f32 dist2 = (diffX * diffX) + (diffY * diffY) + (diffZ * diffZ);
@ -170,14 +169,14 @@ static inline OPTIMIZE_O3 void le_calculate_light_contribution(const LELight& li
}
// accumulate
out_color[0] += light.colorR * brightness;
out_color[1] += light.colorG * brightness;
out_color[2] += light.colorB * brightness;
outColor[0] += light.color[0] * brightness;
outColor[1] += light.color[1] * brightness;
outColor[2] += light.color[2] * brightness;
weight += brightness;
contribution++;
}
C_FIELD OPTIMIZE_O3 void le_calculate_vertex_lighting(Vtx_t* v, Vec3f pos, Color out) {
C_FIELD OPTIMIZE_O3 void le_calculate_vertex_lighting(const Vtx_t* v, Vec3f pos, VEC_OUT Color out) {
// clear color
Vec3f color = { 0 };
@ -186,7 +185,7 @@ C_FIELD OPTIMIZE_O3 void le_calculate_vertex_lighting(Vtx_t* v, Vec3f pos, Color
u8 contribution = 0;
for (LELight* light : sActiveLights) {
le_calculate_light_contribution(*light, pos, NULL, 1.0f, color, weight, contribution);
if (contribution == LE_MAX_LIGHTS_PER_VERTEX) { break; }
if (contribution == sMaxLightsPerVertex) { break; }
}
// tone map and output
@ -198,7 +197,7 @@ C_FIELD OPTIMIZE_O3 void le_calculate_vertex_lighting(Vtx_t* v, Vec3f pos, Color
le_tone_map(out, vtxAmbient, color, weight);
}
C_FIELD OPTIMIZE_O3 void le_calculate_lighting_color(Vec3f pos, Color out, f32 lightIntensityScalar) {
C_FIELD OPTIMIZE_O3 void le_calculate_lighting_color(Vec3f pos, VEC_OUT Color out, f32 lightIntensityScalar) {
// clear color
Vec3f color = { 0 };
@ -207,14 +206,14 @@ C_FIELD OPTIMIZE_O3 void le_calculate_lighting_color(Vec3f pos, Color out, f32 l
u8 contribution = 0;
for (LELight* light : sActiveLights) {
le_calculate_light_contribution(*light, pos, NULL, lightIntensityScalar, color, weight, contribution);
if (contribution == LE_MAX_LIGHTS_PER_VERTEX) { break; }
if (contribution == sMaxLightsPerVertex) { break; }
}
// 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) {
C_FIELD OPTIMIZE_O3 void le_calculate_lighting_color_with_normal(Vec3f pos, Vec3f normal, VEC_OUT Color out, f32 lightIntensityScalar) {
// normalize normal
if (normal) { vec3f_normalize(normal); }
@ -226,29 +225,29 @@ C_FIELD OPTIMIZE_O3 void le_calculate_lighting_color_with_normal(Vec3f pos, Vec3
u8 contribution = 0;
for (LELight* light : sActiveLights) {
le_calculate_light_contribution(*light, pos, normal, lightIntensityScalar, color, weight, contribution);
if (contribution == LE_MAX_LIGHTS_PER_VERTEX) { break; }
if (contribution == sMaxLightsPerVertex) { break; }
}
// tone map and output
le_tone_map(out, gLEAmbientColor, color, weight);
}
C_FIELD void le_calculate_lighting_dir(Vec3f pos, Vec3f out) {
C_FIELD void le_calculate_lighting_dir(Vec3f pos, VEC_OUT Vec3f out) {
Vec3f lightingDir = { 0, 0, 0 };
s16 count = 1;
for (LELight* light : sActiveLights) {
f32 diffX = light->posX - pos[0];
f32 diffY = light->posY - pos[1];
f32 diffZ = light->posZ - pos[2];
f32 diffX = light->pos[0] - pos[0];
f32 diffY = light->pos[1] - pos[1];
f32 diffZ = light->pos[2] - 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,
pos[0] - light->pos[0],
pos[1] - light->pos[1],
pos[2] - light->pos[2],
};
vec3f_normalize(dir);
@ -267,16 +266,19 @@ C_FIELD void le_calculate_lighting_dir(Vec3f pos, Vec3f out) {
}
C_FIELD s16 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity) {
if (sLightPool.size() >= LE_MAX_LIGHTS) { return -1; }
if (sLightPool.size() >= LE_MAX_LIGHTS) {
LOG_LUA_LINE("LE light count cannot exceed %d lights!", 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.pos[0] = x;
newLight.pos[1] = y;
newLight.pos[2] = z;
newLight.color[0] = r;
newLight.color[1] = g;
newLight.color[2] = b;
newLight.radius = radius;
newLight.intensity = intensity;
newLight.useSurfaceNormals = true;
@ -292,15 +294,16 @@ C_FIELD s16 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32
C_FIELD void le_remove_light(s16 id) {
if (id < 0) { return; }
sLightPool.erase(
std::remove_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
),
sLightPool.end()
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
sLightPool.erase(it);
}
le_update_active_lights();
}
@ -318,8 +321,8 @@ C_FIELD bool le_light_exists(s16 id) {
);
}
C_FIELD void le_get_light_pos(s16 id, VEC_OUT Vec3f out) {
if (id < 0) { return; }
static LELight* le_find_light(s16 id) {
if (id < 0) { return nullptr; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
@ -327,73 +330,51 @@ C_FIELD void le_get_light_pos(s16 id, VEC_OUT Vec3f out) {
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
vec3f_set(out, light.posX, light.posY, light.posZ);
// kinda cursed syntax but it works
return (it != sLightPool.end()) ? &(*it) : nullptr;
}
C_FIELD void le_get_light_pos(s16 id, VEC_OUT Vec3f out) {
if (id < 0) { return; }
if (auto* light = le_find_light(id)) {
vec3f_set(out, light->pos[0], light->pos[1], light->pos[2]);
}
}
C_FIELD void le_set_light_pos(s16 id, f32 x, f32 y, f32 z) {
if (id < 0) { return; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
light.posX = x;
light.posY = y;
light.posZ = z;
if (auto* light = le_find_light(id)) {
light->pos[0] = x;
light->pos[1] = y;
light->pos[2] = z;
}
}
C_FIELD void le_get_light_color(s16 id, VEC_OUT Color out) {
if (id < 0) { return; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
color_set(out, light.colorR, light.colorG, light.colorB);
if (auto* light = le_find_light(id)) {
color_set(out, light->color[0], light->color[1], light->color[2]);
}
}
C_FIELD void le_set_light_color(s16 id, u8 r, u8 g, u8 b) {
if (id < 0) { return; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
light.colorR = r;
light.colorG = g;
light.colorB = b;
if (auto* light = le_find_light(id)) {
light->color[0] = r;
light->color[1] = g;
light->color[2] = b;
}
}
C_FIELD f32 le_get_light_radius(s16 id) {
if (id < 0) { return 0.0f; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
return light.radius;
if (auto* light = le_find_light(id)) {
return light->radius;
}
return 0.0f;
@ -402,15 +383,8 @@ C_FIELD f32 le_get_light_radius(s16 id) {
C_FIELD void le_set_light_radius(s16 id, f32 radius) {
if (id < 0) { return; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
light.radius = radius;
if (auto* light = le_find_light(id)) {
light->radius = radius;
}
le_update_active_lights();
@ -419,15 +393,8 @@ C_FIELD void le_set_light_radius(s16 id, f32 radius) {
C_FIELD f32 le_get_light_intensity(s16 id) {
if (id < 0) { return 0.0f; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
return light.intensity;
if (auto* light = le_find_light(id)) {
return light->intensity;
}
return 0.0f;
@ -436,15 +403,8 @@ C_FIELD f32 le_get_light_intensity(s16 id) {
C_FIELD void le_set_light_intensity(s16 id, f32 intensity) {
if (id < 0) { return; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
light.intensity = intensity;
if (auto* light = le_find_light(id)) {
light->intensity = intensity;
}
le_update_active_lights();
@ -453,15 +413,8 @@ C_FIELD void le_set_light_intensity(s16 id, f32 intensity) {
C_FIELD bool le_get_light_use_surface_normals(s16 id) {
if (id < 0) { return false; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
return light.useSurfaceNormals;
if (auto* light = le_find_light(id)) {
return light->useSurfaceNormals;
}
return false;
@ -470,30 +423,22 @@ C_FIELD bool le_get_light_use_surface_normals(s16 id) {
C_FIELD void le_set_light_use_surface_normals(s16 id, bool useSurfaceNormals) {
if (id < 0) { return; }
auto it = std::find_if(sLightPool.begin(), sLightPool.end(),
[id](const LELight& light) {
return light.id == id;
}
);
if (it != sLightPool.end()) {
LELight& light = *it;
light.useSurfaceNormals = useSurfaceNormals;
if (auto* light = le_find_light(id)) {
light->useSurfaceNormals = useSurfaceNormals;
}
}
void le_clear(void) {
sLightPool.clear();
sLightID = 0;
sLightID = -1;
gLEAmbientColor[0] = 127;
gLEAmbientColor[1] = 127;
gLEAmbientColor[2] = 127;
color_set(gLEAmbientColor, 127, 127, 127);
}
void le_shutdown(void) {
sEnabled = false;
sMode = LE_MODE_AFFECT_ALL_SHADED_AND_COLORED;
sToneMapping = LE_TONE_MAPPING_WEIGHTED;
sMaxLightsPerVertex = 4;
le_clear();
}

View file

@ -35,8 +35,10 @@ void le_set_tone_mapping(enum LEToneMapping toneMapping);
void le_get_ambient_color(VEC_OUT Color out);
/* |description|Sets the lighting engine ambient color|descriptionEnd| */
void le_set_ambient_color(u8 r, u8 g, u8 b);
/* |description|Sets the max amount of lights that can affect a vertex|descriptionEnd| */
void le_set_max_lights_per_vertex(u8 count);
void le_calculate_vertex_lighting(Vtx_t* v, Vec3f pos, VEC_OUT Color out);
void le_calculate_vertex_lighting(const Vtx_t* v, Vec3f pos, VEC_OUT Color out);
/* |description|Calculates the lighting with `lightIntensityScalar` at a position and outputs the color in `out`|descriptionEnd|*/
void le_calculate_lighting_color(Vec3f pos, VEC_OUT Color out, f32 lightIntensityScalar);
/* |description|Calculates the lighting with `lightIntensityScalar` at a position and with a normal and outputs the color in `out`|descriptionEnd|*/

View file

@ -929,7 +929,7 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons
if (affectAllVertexColored && !(rsp.geometry_mode & G_LIGHTING_ENGINE_EXT)) {
le_calculate_lighting_color(vpos, color, 1.0f);
} else {
le_calculate_vertex_lighting((Vtx_t*)v, vpos, color);
le_calculate_vertex_lighting(v, vpos, color);
}
CTX_END(CTX_LIGHTING);

View file

@ -15768,6 +15768,23 @@ int smlua_func_le_set_ambient_color(lua_State* L) {
return 1;
}
int smlua_func_le_set_max_lights_per_vertex(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 1) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "le_set_max_lights_per_vertex", 1, top);
return 0;
}
u8 count = smlua_to_integer(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "le_set_max_lights_per_vertex"); return 0; }
le_set_max_lights_per_vertex(count);
return 1;
}
int smlua_func_le_calculate_lighting_color(lua_State* L) {
if (L == NULL) { return 0; }
@ -37935,6 +37952,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "le_set_tone_mapping", smlua_func_le_set_tone_mapping);
smlua_bind_function(L, "le_get_ambient_color", smlua_func_le_get_ambient_color);
smlua_bind_function(L, "le_set_ambient_color", smlua_func_le_set_ambient_color);
smlua_bind_function(L, "le_set_max_lights_per_vertex", smlua_func_le_set_max_lights_per_vertex);
smlua_bind_function(L, "le_calculate_lighting_color", smlua_func_le_calculate_lighting_color);
smlua_bind_function(L, "le_calculate_lighting_color_with_normal", smlua_func_le_calculate_lighting_color_with_normal);
smlua_bind_function(L, "le_calculate_lighting_dir", smlua_func_le_calculate_lighting_dir);