From 7009e7da86bba1ac395a8f95148f630a82b41ba7 Mon Sep 17 00:00:00 2001 From: Agent X <44549182+AgentXLP@users.noreply.github.com> Date: Sun, 29 Jun 2025 12:08:04 -0400 Subject: [PATCH] Lighting Engine: Awesome Edition Just making a brief commit and thats all to add onto dj's lighting engine improvements because I heard about the PR, in mine I * allowed all Vtx objects to be manipulated/retrieved * updated lighting engine demo to be an SM64 night mode with a flashlight * Fixed longterm bug where lighting bugs out unless you spawn a light * Added new default LE mode LE_MODE_AFFECT_ALL_SHADED_AND_COLORED which also affects vertex colored surfaces --- autogen/convert_constants.py | 6 +- autogen/lua_definitions/constants.lua | 9 +- data/dynos_mgr_gfx.cpp | 2 +- docs/lua/constants.md | 13 ++- .../levels/canals/model.inc.c | 6 +- .../examples/lighting-engine-demo/main.lua | 108 +++++------------- .../examples/lighting-engine-demo/objects.lua | 58 ++++++++++ .../examples/lighting-engine-demo/shading.lua | 51 +++++++++ src/engine/lighting_engine.c | 24 ++-- src/engine/lighting_engine.h | 3 + src/pc/gfx/gfx_pc.c | 45 +++++--- src/pc/lua/smlua_constants_autogen.c | 6 +- src/pc/lua/utils/smlua_gfx_utils.c | 4 +- 13 files changed, 218 insertions(+), 117 deletions(-) create mode 100644 docs/lua/examples/lighting-engine-demo/objects.lua create mode 100644 docs/lua/examples/lighting-engine-demo/shading.lua diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py index db338d9fb..dcf8e6048 100644 --- a/autogen/convert_constants.py +++ b/autogen/convert_constants.py @@ -52,7 +52,8 @@ in_files = [ "src/pc/network/lag_compensation.h", "src/pc/djui/djui_panel_menu.h", "src/engine/lighting_engine.h", - "include/PR/gbi.h" + "include/PR/gbi.h", + "include/PR/gbi_extension.h" ] exclude_constants = { @@ -106,7 +107,8 @@ include_constants = { "^G_SETSCISSOR$", "^G_TEXRECTFLIP$", "^G_TEXRECT$", - ] + ], + "include/PR/gbi_extension.h": [ "G_VTX_EXT" ] } # Constants that exist in the source code but should not appear diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index ceca13102..926eb0c32 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -2933,6 +2933,9 @@ G_TEXRECTFLIP = 0xe5 --- @type integer G_TEXRECT = 0xe4 +--- @type integer +G_VTX_EXT = 0x11 + BACKGROUND_OCEAN_SKY = 0 --- @type SkyBackgroundParams BACKGROUND_FLAMING_SKY = 1 --- @type SkyBackgroundParams BACKGROUND_UNDERWATER_CITY = 2 --- @type SkyBackgroundParams @@ -3608,10 +3611,12 @@ HUD_DISPLAY_DEFAULT = HUD_DISPLAY_FLAG_LIVES | HUD_DISPLAY_FLAG_CO --- | `HUD_DISPLAY_NONE` --- | `HUD_DISPLAY_DEFAULT` -LE_MODE_AFFECT_ALL_SHADED = 0 --- @type LEMode -LE_MODE_AFFECT_ONLY_GEOMETRY_MODE = 1 --- @type LEMode +LE_MODE_AFFECT_ALL_SHADED_AND_COLORED = 0 --- @type LEMode +LE_MODE_AFFECT_ALL_SHADED = 1 --- @type LEMode +LE_MODE_AFFECT_ONLY_GEOMETRY_MODE = 2 --- @type LEMode --- @alias LEMode +--- | `LE_MODE_AFFECT_ALL_SHADED_AND_COLORED` --- | `LE_MODE_AFFECT_ALL_SHADED` --- | `LE_MODE_AFFECT_ONLY_GEOMETRY_MODE` diff --git a/data/dynos_mgr_gfx.cpp b/data/dynos_mgr_gfx.cpp index a0a0cba1e..068cba698 100644 --- a/data/dynos_mgr_gfx.cpp +++ b/data/dynos_mgr_gfx.cpp @@ -69,7 +69,7 @@ static Gfx *DynOS_Gfx_Duplicate(Gfx *aGfx, bool shouldDuplicate) { } // Duplicate referenced vertices - if (op == G_VTX) { + if (op == G_VTX || op == G_VTX_EXT) { cmd->words.w1 = (uintptr_t) DynOS_Vtx_Duplicate((Vtx *) cmd->words.w1, C0(cmd, 12, 8), shouldDuplicate); } } diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 0cdb90306..bfde0e8b9 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -26,6 +26,7 @@ - [enum DialogSound](#enum-DialogSound) - [first_person_cam.h](#first_person_camh) - [gbi.h](#gbih) +- [gbi_extension.h](#gbi_extensionh) - [geo_commands.h](#geo_commandsh) - [enum SkyBackgroundParams](#enum-SkyBackgroundParams) - [graph_node.h](#graph_nodeh) @@ -1289,6 +1290,13 @@
+## [gbi_extension.h](#gbi_extension.h) +- G_VTX_EXT + +[:arrow_up_small:](#) + +
+ ## [geo_commands.h](#geo_commands.h) ### [enum SkyBackgroundParams](#SkyBackgroundParams) @@ -1627,8 +1635,9 @@ ### [enum LEMode](#LEMode) | Identifier | Value | | :--------- | :---- | -| LE_MODE_AFFECT_ALL_SHADED | 0 | -| LE_MODE_AFFECT_ONLY_GEOMETRY_MODE | 1 | +| LE_MODE_AFFECT_ALL_SHADED_AND_COLORED | 0 | +| LE_MODE_AFFECT_ALL_SHADED | 1 | +| LE_MODE_AFFECT_ONLY_GEOMETRY_MODE | 2 | ### [enum LEToneMapping](#LEToneMapping) | Identifier | Value | diff --git a/docs/lua/examples/lighting-engine-demo/levels/canals/model.inc.c b/docs/lua/examples/lighting-engine-demo/levels/canals/model.inc.c index c142811f8..dcc80cc2b 100644 --- a/docs/lua/examples/lighting-engine-demo/levels/canals/model.inc.c +++ b/docs/lua/examples/lighting-engine-demo/levels/canals/model.inc.c @@ -4274,7 +4274,7 @@ Vtx canals_dl_skybox_mesh_layer_5_vtx_0[46] = { }; Gfx canals_dl_skybox_mesh_layer_5_tri_0[] = { - gsSPVertex(canals_dl_skybox_mesh_layer_5_vtx_0 + 0, 16, 0), + gsSPVertexNonGlobal(canals_dl_skybox_mesh_layer_5_vtx_0 + 0, 16, 0), gsSP1Triangle(0, 1, 2, 0), gsSP1Triangle(0, 3, 1, 0), gsSP1Triangle(4, 3, 0, 0), @@ -4289,7 +4289,7 @@ Gfx canals_dl_skybox_mesh_layer_5_tri_0[] = { gsSP1Triangle(12, 11, 13, 0), gsSP1Triangle(14, 12, 13, 0), gsSP1Triangle(14, 13, 15, 0), - gsSPVertex(canals_dl_skybox_mesh_layer_5_vtx_0 + 16, 16, 0), + gsSPVertexNonGlobal(canals_dl_skybox_mesh_layer_5_vtx_0 + 16, 16, 0), gsSP1Triangle(0, 1, 2, 0), gsSP1Triangle(0, 2, 3, 0), gsSP1Triangle(1, 0, 4, 0), @@ -4304,7 +4304,7 @@ Gfx canals_dl_skybox_mesh_layer_5_tri_0[] = { gsSP1Triangle(12, 11, 13, 0), gsSP1Triangle(13, 11, 14, 0), gsSP1Triangle(13, 14, 15, 0), - gsSPVertex(canals_dl_skybox_mesh_layer_5_vtx_0 + 32, 14, 0), + gsSPVertexNonGlobal(canals_dl_skybox_mesh_layer_5_vtx_0 + 32, 14, 0), gsSP1Triangle(0, 1, 2, 0), gsSP1Triangle(3, 1, 0, 0), gsSP1Triangle(3, 4, 1, 0), diff --git a/docs/lua/examples/lighting-engine-demo/main.lua b/docs/lua/examples/lighting-engine-demo/main.lua index 68103887d..1a4646087 100644 --- a/docs/lua/examples/lighting-engine-demo/main.lua +++ b/docs/lua/examples/lighting-engine-demo/main.lua @@ -1,88 +1,27 @@ -- name: Lighting Engine Demo --- description: Lighting Engine Demo\nBy \\#ec7731\\Agent X\n\n\\#dcdcdc\\Open the panel in the pause menu to see what you can do. +-- description: Lighting Engine Demo\nBy \\#ec7731\\Agent X\n\n\\#dcdcdc\\Open the mod menu in the pause menu to see what you can do. -local flashlightColor = { 255, 255, 200 } +flashlightColor = { 255, 255, 200 } + +--- @param cmd Gfx +--- @param op integer +local function parse_dl(cmd, op) + if op == G_SETENVCOLOR then + gfx_set_command(cmd, "gsDPSetEnvColor(255, 255, 255, %i)", if_then_else(_G.dayNightCycleApi ~= nil and _G.dayNightCycleApi.is_dnc_enabled(), 0, 255)) + end +end --- @param node GraphNode function geo_hide_if_dnc(node) local dl = cast_graph_node(node.next) - gfx_parse(dl.displayList, function(cmd, op) - if op == G_SETENVCOLOR then - gfx_set_command(cmd, "gsDPSetEnvColor(255, 255, 255, %i)", if_then_else(_G.dayNightCycleApi ~= nil and _G.dayNightCycleApi.is_dnc_enabled(), 0, 255)) - end - end) + gfx_parse(dl.displayList, parse_dl) end ---- @param o Object -local function bhv_spawn_point_light(o) - local light = spawn_non_sync_object( - id_bhvPointLight, - E_MODEL_NONE, - o.oPosX, o.oPosY, o.oPosZ, - nil - ) - if get_id_from_behavior(o.behavior) == id_bhvKoopaShell then - light.oBehParams = 0x00FF0032 - else - light.oBehParams = 0xFFFFFF32 - end - light.parentObj = o -end +local function update() + shading_update() ---- @param o Object -function bhv_flashlight_loop(o) - local pos = gMarioStates[0].pos - local yaw = gFirstPersonCamera.yaw + 0x8000 - o.oPosX = pos.x + sins(yaw) * 300 - o.oPosY = pos.y + -gFirstPersonCamera.pitch * 0.06 - o.oPosZ = pos.z + coss(yaw) * 300 - le_set_light_pos(o.oLightID, o.oPosX, o.oPosY, o.oPosZ) - le_set_light_color(o.oLightID, flashlightColor[1], flashlightColor[2], flashlightColor[3]) -end - -local function spawn_flashlight() - local flashlight = spawn_non_sync_object( - bhvFlashlight, - E_MODEL_NONE, - 0, 0, 0, - nil - ) - flashlight.oBehParams = (flashlightColor[1] << 24) | (flashlightColor[2] << 16) | (flashlightColor[3] << 8) | (90) - return flashlight -end - ---- @param flashlight Object -local function delete_flashlight(flashlight) - le_remove_light(flashlight.oLightID) - obj_mark_for_deletion(flashlight) - return nil -end - ---- @param m MarioState -local function calculate_mario_lighting(m) - local color = { r = 0, g = 0, b = 0 } - local dir = { x = 0, y = 0, z = 0 } - - le_calculate_lighting_color(m.pos, color, 0.25) - le_calculate_lighting_dir(m.pos, dir) - - m.marioBodyState.lightR = color.r - m.marioBodyState.lightG = color.g - m.marioBodyState.lightB = color.b - m.marioBodyState.shadeR = m.marioBodyState.lightR * 0.5 - m.marioBodyState.shadeG = m.marioBodyState.lightG * 0.5 - m.marioBodyState.shadeB = m.marioBodyState.lightB * 0.5 - - m.marioBodyState.lightingDirX = -DEFAULT_LIGHTING_DIR + dir.x - m.marioBodyState.lightingDirY = -DEFAULT_LIGHTING_DIR + dir.y - m.marioBodyState.lightingDirZ = -DEFAULT_LIGHTING_DIR + dir.z -end - ---- @param m MarioState -local function mario_update(m) - if m.playerIndex ~= 0 then return end - - calculate_mario_lighting(m) + --- @type MarioState + local m = gMarioStates[0] if (m.controller.buttonPressed & L_JPAD) ~= 0 then audio_sample_play(SOUND_CUSTOM_FLASHLIGHT, m.pos, 1.0) @@ -95,14 +34,27 @@ local function mario_update(m) end end +local function on_level_init() + local levelNum = gNetworkPlayers[0].currLevelNum + if levelNum == LEVEL_HL or levelNum == LEVEL_CANALS then return end + + le_set_ambient_color(30, 30, 75) +end + local function on_set_flashlight_color(index, value) flashlightColor[index + 1] = value end -id_bhvKoopaShell = hook_behavior(id_bhvKoopaShell, OBJ_LIST_LEVEL, false, bhv_spawn_point_light, nil, "bhvKoopaShell") +set_override_skybox(BACKGROUND_HAUNTED) +set_fog_color(0, 30) +set_fog_color(1, 30) +set_fog_color(2, 75) -hook_event(HOOK_MARIO_UPDATE, mario_update) +djui_popup_create("Use Left D-Pad to turn on the flashlight.", 2) + +hook_event(HOOK_UPDATE, update) +hook_event(HOOK_ON_LEVEL_INIT, on_level_init) hook_mod_menu_slider("Flashlight Red", flashlightColor[1], 0, 255, on_set_flashlight_color) hook_mod_menu_slider("Flashlight Green", flashlightColor[2], 0, 255, on_set_flashlight_color) diff --git a/docs/lua/examples/lighting-engine-demo/objects.lua b/docs/lua/examples/lighting-engine-demo/objects.lua new file mode 100644 index 000000000..6ed1aeb3b --- /dev/null +++ b/docs/lua/examples/lighting-engine-demo/objects.lua @@ -0,0 +1,58 @@ +--- @param o Object +local function bhv_spawn_point_light(o) + local light = spawn_non_sync_object( + id_bhvPointLight, + E_MODEL_NONE, + o.oPosX, o.oPosY, o.oPosZ, + nil + ) + if get_id_from_behavior(o.behavior) == id_bhvKoopaShell then + light.oBehParams = 0x00FF0064 + else + light.oBehParams = 0xFFFFFF32 + end + light.parentObj = o +end + +--- @param o Object +function bhv_flashlight_loop(o) + local fp = get_first_person_enabled() + local pos = gMarioStates[0].pos + local yaw = if_then_else(fp, gFirstPersonCamera.yaw + 0x8000, gMarioStates[0].faceAngle.y) + + local dirX = sins(yaw) * 300 + local dirY = if_then_else(fp, -gFirstPersonCamera.pitch * 0.06, 120) + local dirZ = coss(yaw) * 300 + + local raycast = collision_find_surface_on_ray(pos.x, pos.y, pos.z, dirX, dirY, dirZ) + if raycast.surface == nil then + o.oPosX = pos.x + dirX + o.oPosY = pos.y + dirY + o.oPosZ = pos.z + dirZ + else + vec3f_to_object_pos(o, raycast.hitPos) + end + + le_set_light_pos(o.oLightID, o.oPosX, o.oPosY, o.oPosZ) + le_set_light_color(o.oLightID, flashlightColor[1], flashlightColor[2], flashlightColor[3]) +end + +function spawn_flashlight() + local flashlight = spawn_non_sync_object( + bhvFlashlight, + E_MODEL_NONE, + 0, 0, 0, + nil + ) + flashlight.oBehParams = (flashlightColor[1] << 24) | (flashlightColor[2] << 16) | (flashlightColor[3] << 8) | (90) + return flashlight +end + +--- @param flashlight Object +function delete_flashlight(flashlight) + le_remove_light(flashlight.oLightID) + obj_mark_for_deletion(flashlight) + return nil +end + +id_bhvKoopaShell = hook_behavior(id_bhvKoopaShell, OBJ_LIST_LEVEL, false, bhv_spawn_point_light, nil, "bhvKoopaShell") \ No newline at end of file diff --git a/docs/lua/examples/lighting-engine-demo/shading.lua b/docs/lua/examples/lighting-engine-demo/shading.lua new file mode 100644 index 000000000..e99b66146 --- /dev/null +++ b/docs/lua/examples/lighting-engine-demo/shading.lua @@ -0,0 +1,51 @@ +-- special thanks to Coolio for figuring out worldspace shading + +--- @param dest Vec3f +--- @param rotate Vec3f +--- Rotates `dest` around the Z, Y, and X axes +local function vec3f_rotate_zyx(dest, rotate) + local v = { x = dest.x, y = dest.y, z = dest.z } + + local sx = sins(rotate.x) + local cx = coss(rotate.x) + + local sy = sins(rotate.y) + local cy = coss(rotate.y) + + local sz = sins(rotate.z) + local cz = coss(rotate.z) + + -- Rotation around Z axis + local xz = v.x * cz - v.y * sz + local yz = v.x * sz + v.y * cz + local zz = v.z + + -- Rotation around Y axis + local xy = xz * cy + zz * sy + local yy = yz + local zy = -xz * sy + zz * cy + + -- Rotation around X axis + dest.x = xy + dest.y = yy * cx - zy * sx + dest.z = yy * sx + zy * cx + + return dest +end + +local LIGHTING_OFFSET = { x = 0x28 / 0xFF, y = 0x28 / 0xFF, z = 0x28 / 0xFF } + +function shading_update() + local l = gLakituState + local pitch = calculate_pitch(l.pos, l.focus) + local yaw = calculate_yaw(l.pos, l.focus) + local roll = l.roll + + local lightingDir = gVec3fOne() + vec3f_rotate_zyx(lightingDir, { x = -pitch, y = -yaw, z = roll }) + vec3f_sub(lightingDir, LIGHTING_OFFSET) + + set_lighting_dir(0, lightingDir.x) + set_lighting_dir(1, lightingDir.y) + set_lighting_dir(2, lightingDir.z) +end \ No newline at end of file diff --git a/src/engine/lighting_engine.c b/src/engine/lighting_engine.c index 9f7d785f2..28ecc7d06 100644 --- a/src/engine/lighting_engine.c +++ b/src/engine/lighting_engine.c @@ -6,10 +6,10 @@ #define LE_MAX_LIGHTS 256 -static Color sAmbientColor = { 127, 127, 127 }; +Color gLEAmbientColor = { 127, 127, 127 }; static void* sLights = NULL; static s32 sLightID = 0; -static enum LEMode sMode = LE_MODE_AFFECT_ALL_SHADED; +static enum LEMode sMode = LE_MODE_AFFECT_ALL_SHADED_AND_COLORED; static enum LEToneMapping sToneMapping = LE_TONE_MAPPING_WEIGHTED; static bool sEnabled = false; @@ -129,9 +129,9 @@ void le_calculate_vertex_lighting(Vtx_t* v, Vec3f pos, OUT Color out) { // tone map and output Color vtxAmbient = { - v->cn[0] * (sAmbientColor[0] / 255.0f), - v->cn[1] * (sAmbientColor[1] / 255.0f), - v->cn[2] * (sAmbientColor[2] / 255.0f), + 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); } @@ -149,7 +149,7 @@ void le_calculate_lighting_color(Vec3f pos, OUT Color out, f32 lightIntensitySca } // tone map and output - le_tone_map(out, sAmbientColor, color, weight); + le_tone_map(out, gLEAmbientColor, color, weight); } void le_calculate_lighting_color_with_normal(Vec3f pos, Vec3f normal, OUT Color out, f32 lightIntensityScalar) { @@ -168,7 +168,7 @@ void le_calculate_lighting_color_with_normal(Vec3f pos, Vec3f normal, OUT Color } // tone map and output - le_tone_map(out, sAmbientColor, color, weight); + le_tone_map(out, gLEAmbientColor, color, weight); } void le_calculate_lighting_dir(Vec3f pos, OUT Vec3f out) { @@ -241,7 +241,7 @@ s32 le_get_light_count(void) { } void le_set_ambient_color(u8 r, u8 g, u8 b) { - color_set(sAmbientColor, r, g, b); + color_set(gLEAmbientColor, r, g, b); sEnabled = true; } @@ -297,16 +297,16 @@ void le_clear(void) { } hmap_clear(sLights); sLightID = 0; - sAmbientColor[0] = 127; - sAmbientColor[1] = 127; - sAmbientColor[2] = 127; + gLEAmbientColor[0] = 127; + gLEAmbientColor[1] = 127; + gLEAmbientColor[2] = 127; } void le_shutdown(void) { if (sLights == NULL) { return; } sEnabled = false; - sMode = LE_MODE_AFFECT_ALL_SHADED; + sMode = LE_MODE_AFFECT_ALL_SHADED_AND_COLORED; sToneMapping = LE_TONE_MAPPING_WEIGHTED; le_clear(); hmap_destroy(sLights); diff --git a/src/engine/lighting_engine.h b/src/engine/lighting_engine.h index e5cc842b1..507544f96 100644 --- a/src/engine/lighting_engine.h +++ b/src/engine/lighting_engine.h @@ -17,6 +17,7 @@ struct LELight }; enum LEMode { + LE_MODE_AFFECT_ALL_SHADED_AND_COLORED, LE_MODE_AFFECT_ALL_SHADED, LE_MODE_AFFECT_ONLY_GEOMETRY_MODE, }; @@ -28,6 +29,8 @@ enum LEToneMapping { LE_TONE_MAPPING_REINHARD, }; +extern Color gLEAmbientColor; + /* |description|Sets the lighting engine mode to `mode`|descriptionEnd|*/ void le_set_mode(enum LEMode mode); /* |description|Gets the lighting engine mode|descriptionEnd|*/ diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index 59425e67b..31703ae09 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -724,7 +724,6 @@ static OPTIMIZE_O3 void gfx_local_to_world_space(OUT Vec3f pos, OUT Vec3f normal } } - static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, const Vtx *vertices, bool luaVertexColor) { if (!vertices) { return; } @@ -779,6 +778,9 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons short U = v->tc[0] * rsp.texture_scaling_factor.s >> 16; short V = v->tc[1] * rsp.texture_scaling_factor.t >> 16; + // are we on affect all shaded surfaces mode and on a vertex colorable surface + bool affectAllVertexColored = (le_get_mode() == LE_MODE_AFFECT_ALL_SHADED_AND_COLORED && luaVertexColor); + if (rsp.geometry_mode & G_LIGHTING) { if (rsp.lights_changed) { bool applyLightingDir = !(rsp.geometry_mode & G_TEXTURE_GEN); @@ -861,8 +863,9 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons V = (int32_t)((doty / 127.0f + 1.0f) / 4.0f * rsp.texture_scaling_factor.t); } - if (le_is_enabled() && ((le_get_mode() == LE_MODE_AFFECT_ALL_SHADED) || (rsp.geometry_mode & G_LIGHTING_ENGINE_EXT))) { - Color color; + // 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] }; @@ -879,8 +882,9 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons d->color.g *= color[1] / 255.0f; d->color.b *= color[2] / 255.0f; } - } else if (le_is_enabled() && (rsp.geometry_mode & G_LIGHTING_ENGINE_EXT)) { - Color color; + // 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() && (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] }; @@ -888,18 +892,33 @@ static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, cons // transform vpos to world space gfx_local_to_world_space(vpos, NULL); - le_calculate_vertex_lighting((Vtx_t*)v, vpos, color); + // do multiplication based lighting instead of additive based lighting if we're not using the lighting engine geometry mode, + // this is my compromise for retaining vertex colors vs lighting up darker surfaces. + // if retaining color is the most important like on a red coin, don't use the lighting engine geometry mode. + // if lighting up darker surfaces like in a map with prebaked lighting is the most important, use the lighting engine geometry mode. + 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); + } CTX_END(CTX_LIGHTING); - if (luaVertexColor) { - d->color.r = color[0] * vertexColorCached[0]; - d->color.g = color[1] * vertexColorCached[1]; - d->color.b = color[2] * vertexColorCached[2]; + // combine the colors + if (affectAllVertexColored && !(rsp.geometry_mode & G_LIGHTING_ENGINE_EXT)) { + d->color.r = (v->cn[0] * color[0] / 255.0f) * vertexColorCached[0]; + d->color.g = (v->cn[1] * color[1] / 255.0f) * vertexColorCached[1]; + d->color.b = (v->cn[2] * color[2] / 255.0f) * vertexColorCached[2]; } else { - d->color.r = color[0]; - d->color.g = color[1]; - d->color.b = color[2]; + if (luaVertexColor) { + d->color.r = color[0] * vertexColorCached[0]; + d->color.g = color[1] * vertexColorCached[1]; + d->color.b = color[2] * vertexColorCached[2]; + } else { + d->color.r = color[0]; + d->color.g = color[1]; + d->color.b = color[2]; + } } } else { if (!(rsp.geometry_mode & G_LIGHT_MAP_EXT) && luaVertexColor) { diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index bbda80aa3..e14a6d8c2 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1515,6 +1515,7 @@ char gSmluaConstants[] = "" "G_SETSCISSOR=0xed\n" "G_TEXRECTFLIP=0xe5\n" "G_TEXRECT=0xe4\n" +"G_VTX_EXT=0x11\n" "BACKGROUND_OCEAN_SKY=0\n" "BACKGROUND_FLAMING_SKY=1\n" "BACKGROUND_UNDERWATER_CITY=2\n" @@ -1777,8 +1778,9 @@ 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_MODE_AFFECT_ALL_SHADED=0\n" -"LE_MODE_AFFECT_ONLY_GEOMETRY_MODE=1\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" "LE_TONE_MAPPING_TOTAL_WEIGHTED=0\n" "LE_TONE_MAPPING_WEIGHTED=1\n" "LE_TONE_MAPPING_CLAMP=2\n" diff --git a/src/pc/lua/utils/smlua_gfx_utils.c b/src/pc/lua/utils/smlua_gfx_utils.c index 692ee8f1a..b9d663481 100644 --- a/src/pc/lua/utils/smlua_gfx_utils.c +++ b/src/pc/lua/utils/smlua_gfx_utils.c @@ -223,7 +223,7 @@ Gfx *gfx_get_display_list(Gfx *cmd) { Vtx *gfx_get_vertex_buffer(Gfx *cmd) { if (!cmd) { return NULL; } u32 op = GFX_OP(cmd); - if (op != G_VTX) { return NULL; } + if (op != G_VTX && op != G_VTX_EXT) { return NULL; } if (cmd->words.w1 == 0) { return NULL; } return (Vtx *) cmd->words.w1; @@ -232,7 +232,7 @@ Vtx *gfx_get_vertex_buffer(Gfx *cmd) { u16 gfx_get_vertex_count(Gfx *cmd) { if (!cmd) { return 0; } u32 op = GFX_OP(cmd); - if (op != G_VTX) { return 0; } + if (op != G_VTX && op != G_VTX_EXT) { return 0; } if (cmd->words.w1 == 0) { return 0; } return C0(cmd, 12, 8);