From ed3cdeae101ebce28d729da1042ce481e0b49652 Mon Sep 17 00:00:00 2001
From: EmeraldLockdown <86802223+EmeraldLoc@users.noreply.github.com>
Date: Tue, 31 Mar 2026 21:20:37 -0500
Subject: [PATCH] Shaders
---
autogen/convert_constants.py | 1 +
autogen/convert_structs.py | 2 +
autogen/lua_definitions/constants.lua | 118 +-
autogen/lua_definitions/functions.lua | 81 ++
autogen/lua_definitions/structs.lua | 40 +
docs/lua/constants.md | 74 +-
docs/lua/functions-6.md | 1052 -----------------
docs/lua/functions-7.md | 1316 ++++++++++++++++++++++
docs/lua/functions.md | 101 +-
docs/lua/guides/hooks.md | 5 +-
docs/lua/structs.md | 72 ++
src/game/rendering_graph_node.c | 5 +-
src/game/rendering_graph_node.h | 3 +
src/game/skybox.c | 8 +-
src/pc/gfx/gfx_cc.h | 51 +-
src/pc/gfx/gfx_direct3d11.cpp | 16 +-
src/pc/gfx/gfx_dummy.c | 9 +
src/pc/gfx/gfx_opengl.c | 318 +++---
src/pc/gfx/gfx_opengl.h | 18 +
src/pc/gfx/gfx_opengl_legacy.c | 10 +
src/pc/gfx/gfx_pc.c | 211 ++--
src/pc/gfx/gfx_pc.h | 30 +
src/pc/gfx/gfx_rendering_api.h | 2 +
src/pc/gfx/gfx_sdl2.c | 4 +
src/pc/lua/smlua_cobject.c | 6 +
src/pc/lua/smlua_cobject.h | 2 +
src/pc/lua/smlua_cobject_autogen.c | 64 ++
src/pc/lua/smlua_cobject_autogen.h | 4 +
src/pc/lua/smlua_constants_autogen.c | 52 +-
src/pc/lua/smlua_functions_autogen.c | 224 ++++
src/pc/lua/smlua_hook_events.inl | 3 +
src/pc/lua/smlua_hook_events_autogen.inl | 94 ++
src/pc/lua/smlua_hooks.c | 1 +
src/pc/lua/smlua_hooks.h | 4 +
src/pc/lua/utils/smlua_gfx_utils.c | 85 ++
src/pc/lua/utils/smlua_gfx_utils.h | 22 +
src/pc/network/network.c | 2 +
37 files changed, 2742 insertions(+), 1368 deletions(-)
diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py
index 409cd8427..738d3554e 100644
--- a/autogen/convert_constants.py
+++ b/autogen/convert_constants.py
@@ -52,6 +52,7 @@ in_files = [
"src/game/player_palette.h",
"src/pc/network/lag_compensation.h",
"src/pc/djui/djui_panel_menu.h",
+ "src/pc/gfx/gfx_cc.h",
"src/engine/lighting_engine.h",
"include/PR/gbi.h",
"include/PR/gbi_extension.h",
diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py
index 3a88390ec..c48d03b84 100644
--- a/autogen/convert_structs.py
+++ b/autogen/convert_structs.py
@@ -31,6 +31,8 @@ in_files = [
"src/pc/lua/utils/smlua_audio_utils.h",
"src/game/paintings.h",
"src/pc/djui/djui_types.h",
+ "src/pc/gfx/gfx_cc.h",
+ "src/pc/gfx/gfx_opengl.h",
"src/game/first_person_cam.h",
"src/game/player_palette.h",
"src/engine/graph_node.h",
diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua
index 1d7dfb2dc..e29e09180 100644
--- a/autogen/lua_definitions/constants.lua
+++ b/autogen/lua_definitions/constants.lua
@@ -3056,6 +3056,116 @@ BACKGROUND_CUSTOM = 10 --- @type SkyBackgroundParams
--- | `BACKGROUND_PURPLE_SKY`
--- | `BACKGROUND_CUSTOM`
+CC_0 = 0 --- @type ColorCombinerSource
+CC_TEXEL0 = 1 --- @type ColorCombinerSource
+CC_TEXEL1 = 2 --- @type ColorCombinerSource
+CC_PRIM = 3 --- @type ColorCombinerSource
+CC_SHADE = 4 --- @type ColorCombinerSource
+CC_ENV = 5 --- @type ColorCombinerSource
+CC_TEXEL0A = 6 --- @type ColorCombinerSource
+CC_LOD = 7 --- @type ColorCombinerSource
+CC_1 = 8 --- @type ColorCombinerSource
+CC_TEXEL1A = 9 --- @type ColorCombinerSource
+CC_COMBINED = 10 --- @type ColorCombinerSource
+CC_COMBINEDA = 11 --- @type ColorCombinerSource
+CC_PRIMA = 12 --- @type ColorCombinerSource
+CC_SHADEA = 13 --- @type ColorCombinerSource
+CC_ENVA = 14 --- @type ColorCombinerSource
+CC_NOISE = 15 --- @type ColorCombinerSource
+CC_ENUM_MAX = 16 --- @type ColorCombinerSource
+
+--- @alias ColorCombinerSource
+--- | `CC_0`
+--- | `CC_TEXEL0`
+--- | `CC_TEXEL1`
+--- | `CC_PRIM`
+--- | `CC_SHADE`
+--- | `CC_ENV`
+--- | `CC_TEXEL0A`
+--- | `CC_LOD`
+--- | `CC_1`
+--- | `CC_TEXEL1A`
+--- | `CC_COMBINED`
+--- | `CC_COMBINEDA`
+--- | `CC_PRIMA`
+--- | `CC_SHADEA`
+--- | `CC_ENVA`
+--- | `CC_NOISE`
+--- | `CC_ENUM_MAX`
+
+SHADER_0 = 0 --- @type ShaderInput
+SHADER_INPUT_1 = 1 --- @type ShaderInput
+SHADER_INPUT_2 = 2 --- @type ShaderInput
+SHADER_INPUT_3 = 3 --- @type ShaderInput
+SHADER_INPUT_4 = 4 --- @type ShaderInput
+SHADER_INPUT_5 = 5 --- @type ShaderInput
+SHADER_INPUT_6 = 6 --- @type ShaderInput
+SHADER_INPUT_7 = 7 --- @type ShaderInput
+SHADER_INPUT_8 = 8 --- @type ShaderInput
+SHADER_TEXEL0 = 9 --- @type ShaderInput
+SHADER_TEXEL0A = 10 --- @type ShaderInput
+SHADER_TEXEL1 = 11 --- @type ShaderInput
+SHADER_TEXEL1A = 12 --- @type ShaderInput
+SHADER_1 = 13 --- @type ShaderInput
+SHADER_COMBINED = 14 --- @type ShaderInput
+SHADER_COMBINEDA = 15 --- @type ShaderInput
+SHADER_NOISE = 16 --- @type ShaderInput
+
+--- @alias ShaderInput
+--- | `SHADER_0`
+--- | `SHADER_INPUT_1`
+--- | `SHADER_INPUT_2`
+--- | `SHADER_INPUT_3`
+--- | `SHADER_INPUT_4`
+--- | `SHADER_INPUT_5`
+--- | `SHADER_INPUT_6`
+--- | `SHADER_INPUT_7`
+--- | `SHADER_INPUT_8`
+--- | `SHADER_TEXEL0`
+--- | `SHADER_TEXEL0A`
+--- | `SHADER_TEXEL1`
+--- | `SHADER_TEXEL1A`
+--- | `SHADER_1`
+--- | `SHADER_COMBINED`
+--- | `SHADER_COMBINEDA`
+--- | `SHADER_NOISE`
+
+--- @type integer
+SHADER_OPT_ALPHA = (1 << 24)
+
+--- @type integer
+SHADER_OPT_FOG = (1 << 25)
+
+--- @type integer
+SHADER_OPT_TEXTURE_EDGE = (1 << 26)
+
+--- @type integer
+SHADER_OPT_NOISE = (1 << 27)
+
+USE_ALPHA = 1 << 0 --- @type CombineModeFlags
+USE_FOG = 1 << 1 --- @type CombineModeFlags
+TEXTURE_EDGE = 1 << 2 --- @type CombineModeFlags
+USE_DITHER = 1 << 3 --- @type CombineModeFlags
+USE_2CYCLE = 1 << 4 --- @type CombineModeFlags
+LIGHT_MAP = 1 << 5 --- @type CombineModeFlags
+
+--- @alias CombineModeFlags
+--- | `USE_ALPHA`
+--- | `USE_FOG`
+--- | `TEXTURE_EDGE`
+--- | `USE_DITHER`
+--- | `USE_2CYCLE`
+--- | `LIGHT_MAP`
+
+--- @type integer
+SHADER_CMD_LENGTH = 16
+
+--- @type integer
+CC_MAX_SHADERS = 64
+
+--- @type integer
+CC_MAX_INPUTS = 8
+
--- @type integer
GRAPH_RENDER_ACTIVE = (1 << 0)
@@ -8213,7 +8323,10 @@ HOOK_ON_FIND_FLOOR = 62 --- @type LuaHookedEventType
HOOK_ON_FIND_WATER_LEVEL = 63 --- @type LuaHookedEventType
HOOK_ON_FIND_POISON_GAS_LEVEL = 64 --- @type LuaHookedEventType
HOOK_ON_FIND_SURFACE_ON_RAY = 65 --- @type LuaHookedEventType
-HOOK_MAX = 66 --- @type LuaHookedEventType
+HOOK_ON_REFRESH_SHADERS = 66 --- @type LuaHookedEventType
+HOOK_ON_VERTEX_SHADER_CREATE = 67 --- @type LuaHookedEventType
+HOOK_ON_FRAGMENT_SHADER_CREATE = 68 --- @type LuaHookedEventType
+HOOK_MAX = 69 --- @type LuaHookedEventType
--- @alias LuaHookedEventType
--- | `HOOK_UPDATE`
@@ -8282,6 +8395,9 @@ HOOK_MAX = 66 --- @type LuaHookedEventType
--- | `HOOK_ON_FIND_WATER_LEVEL`
--- | `HOOK_ON_FIND_POISON_GAS_LEVEL`
--- | `HOOK_ON_FIND_SURFACE_ON_RAY`
+--- | `HOOK_ON_REFRESH_SHADERS`
+--- | `HOOK_ON_VERTEX_SHADER_CREATE`
+--- | `HOOK_ON_FRAGMENT_SHADER_CREATE`
--- | `HOOK_MAX`
--- @type integer
diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index 08b0b1587..33af53f76 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -10966,6 +10966,87 @@ function gfx_delete_all()
-- ...
end
+--- Reloads all shaders
+function gfx_reload_shaders()
+ -- ...
+end
+
+--- @param cc ColorCombiner
+--- @return CCFeatures
+--- Gets features from a color combiner.
+function gfx_color_combiner_get_features(cc)
+ -- ...
+end
+
+--- @param shaderIndex integer
+--- @return integer
+--- Gets a program id from the shader index.
+function gfx_get_program_id_from_shader_index(shaderIndex)
+ -- ...
+end
+
+--- @param program integer
+--- Uses a specific program. Required for setting uniforms.
+function gfx_use_program(program)
+ -- ...
+end
+
+--- @param program integer
+--- @param name string
+--- @return integer
+--- Gets the location of a shader uniform in a program for modification.
+function gfx_shader_get_uniform_location(program, name)
+ -- ...
+end
+
+--- @param loc integer
+--- @param value integer
+--- Sets the value of a shader uniform of type int.
+function gfx_shader_set_int(loc, value)
+ -- ...
+end
+
+--- @param loc integer
+--- @param value number
+--- Sets the value of a shader uniform of type float.
+function gfx_shader_set_float(loc, value)
+ -- ...
+end
+
+--- @param loc integer
+--- @param x number
+--- @param y number
+--- Sets the value of a shader uniform of type vec2.
+function gfx_shader_set_vec2(loc, x, y)
+ -- ...
+end
+
+--- @param loc integer
+--- @param x number
+--- @param y number
+--- @param z number
+--- Sets the value of a shader uniform of type vec3.
+function gfx_shader_set_vec3(loc, x, y, z)
+ -- ...
+end
+
+--- @param loc integer
+--- @param w number
+--- @param x number
+--- @param y number
+--- @param z number
+--- Sets the value of a shader uniform of type vec4.
+function gfx_shader_set_vec4(loc, w, x, y, z)
+ -- ...
+end
+
+--- @param loc integer
+--- @param mat Mat4
+--- Sets the value of a shader uniform of type mat4.
+function gfx_shader_set_mat4(loc, mat)
+ -- ...
+end
+
--- @param name string
--- @return Pointer_Vtx
--- @return integer count
diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua
index 5441e7424..09bc6e9d3 100644
--- a/autogen/lua_definitions/structs.lua
+++ b/autogen/lua_definitions/structs.lua
@@ -201,6 +201,15 @@
--- @field public dialogs BehaviorDialogs
--- @field public trajectories BehaviorTrajectories
+--- @class CCFeatures
+--- @field public used_textures boolean[]
+--- @field public num_inputs integer
+--- @field public do_single boolean[]
+--- @field public do_multiply boolean[]
+--- @field public do_mix boolean[]
+--- @field public color_alpha_same boolean[]
+--- @field public do_noise boolean
+
--- @class Camera
--- @field public mode integer
--- @field public defMode integer
@@ -502,6 +511,24 @@
--- @field public soundOkeyDokey integer
--- @field public sounds integer[]
+--- @class ColorCombiner
+--- @field public cm CombineMode
+--- @field public prg ShaderProgram
+--- @field public shader_input_mapping integer[]
+--- @field public shader_input_mapping_as_u64 integer[]
+--- @field public shader_commands integer[]
+--- @field public shader_commands_as_u64 integer[]
+--- @field public hash integer
+
+--- @class CombineMode
+--- @field public rgb1 integer
+--- @field public alpha1 integer
+--- @field public rgb2 integer
+--- @field public alpha2 integer
+--- @field public all_values integer[]
+--- @field public flags integer
+--- @field public hash integer
+
--- @class Controller
--- @field public port integer
--- @field public stickX number
@@ -2167,6 +2194,19 @@
--- @field public maxPlayers integer
--- @field public pauseAnywhere integer
+--- @class ShaderProgram
+--- @field public hash integer
+--- @field public opengl_program_id integer
+--- @field public num_inputs integer
+--- @field public used_textures boolean[]
+--- @field public num_floats integer
+--- @field public attrib_locations integer[]
+--- @field public uniform_locations integer[]
+--- @field public attrib_sizes integer[]
+--- @field public num_attribs integer
+--- @field public used_noise boolean
+--- @field public used_lightmap boolean
+
--- @class SpawnInfo
--- @field public startPos Vec3s
--- @field public startAngle Vec3s
diff --git a/docs/lua/constants.md b/docs/lua/constants.md
index cf00279f7..3e95c6190 100644
--- a/docs/lua/constants.md
+++ b/docs/lua/constants.md
@@ -29,6 +29,10 @@
- [gbi_extension.h](#gbi_extensionh)
- [geo_commands.h](#geo_commandsh)
- [enum SkyBackgroundParams](#enum-SkyBackgroundParams)
+- [gfx_cc.h](#gfx_cch)
+ - [enum ColorCombinerSource](#enum-ColorCombinerSource)
+ - [enum ShaderInput](#enum-ShaderInput)
+ - [enum CombineModeFlags](#enum-CombineModeFlags)
- [graph_node.h](#graph_nodeh)
- [interaction.c](#interactionc)
- [interaction.h](#interactionh)
@@ -1339,6 +1343,71 @@
+## [gfx_cc.h](#gfx_cc.h)
+
+### [enum ColorCombinerSource](#ColorCombinerSource)
+| Identifier | Value |
+| :--------- | :---- |
+| CC_0 | 0 |
+| CC_TEXEL0 | 1 |
+| CC_TEXEL1 | 2 |
+| CC_PRIM | 3 |
+| CC_SHADE | 4 |
+| CC_ENV | 5 |
+| CC_TEXEL0A | 6 |
+| CC_LOD | 7 |
+| CC_1 | 8 |
+| CC_TEXEL1A | 9 |
+| CC_COMBINED | 10 |
+| CC_COMBINEDA | 11 |
+| CC_PRIMA | 12 |
+| CC_SHADEA | 13 |
+| CC_ENVA | 14 |
+| CC_NOISE | 15 |
+| CC_ENUM_MAX | 16 |
+
+### [enum ShaderInput](#ShaderInput)
+| Identifier | Value |
+| :--------- | :---- |
+| SHADER_0 | 0 |
+| SHADER_INPUT_1 | 1 |
+| SHADER_INPUT_2 | 2 |
+| SHADER_INPUT_3 | 3 |
+| SHADER_INPUT_4 | 4 |
+| SHADER_INPUT_5 | 5 |
+| SHADER_INPUT_6 | 6 |
+| SHADER_INPUT_7 | 7 |
+| SHADER_INPUT_8 | 8 |
+| SHADER_TEXEL0 | 9 |
+| SHADER_TEXEL0A | 10 |
+| SHADER_TEXEL1 | 11 |
+| SHADER_TEXEL1A | 12 |
+| SHADER_1 | 13 |
+| SHADER_COMBINED | 14 |
+| SHADER_COMBINEDA | 15 |
+| SHADER_NOISE | 16 |
+- SHADER_OPT_ALPHA
+- SHADER_OPT_FOG
+- SHADER_OPT_TEXTURE_EDGE
+- SHADER_OPT_NOISE
+
+### [enum CombineModeFlags](#CombineModeFlags)
+| Identifier | Value |
+| :--------- | :---- |
+| USE_ALPHA | 1 << 0 |
+| USE_FOG | 1 << 1 |
+| TEXTURE_EDGE | 1 << 2 |
+| USE_DITHER | 1 << 3 |
+| USE_2CYCLE | 1 << 4 |
+| LIGHT_MAP | 1 << 5 |
+- SHADER_CMD_LENGTH
+- CC_MAX_SHADERS
+- CC_MAX_INPUTS
+
+[:arrow_up_small:](#)
+
+
+
## [graph_node.h](#graph_node.h)
- GRAPH_RENDER_ACTIVE
- GRAPH_RENDER_CHILDREN_FIRST
@@ -3543,7 +3612,10 @@
| HOOK_ON_FIND_WATER_LEVEL | 63 |
| HOOK_ON_FIND_POISON_GAS_LEVEL | 64 |
| HOOK_ON_FIND_SURFACE_ON_RAY | 65 |
-| HOOK_MAX | 66 |
+| HOOK_ON_REFRESH_SHADERS | 66 |
+| HOOK_ON_VERTEX_SHADER_CREATE | 67 |
+| HOOK_ON_FRAGMENT_SHADER_CREATE | 68 |
+| HOOK_MAX | 69 |
- MAX_HOOKED_BEHAVIORS
[:arrow_up_small:](#)
diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md
index a639b7db9..533480370 100644
--- a/docs/lua/functions-6.md
+++ b/docs/lua/functions-6.md
@@ -7473,1058 +7473,6 @@ Checks if the surface is a painting warp
-
----
-# functions from smlua_gfx_utils.h
-
-
-
-
-## [set_override_fov](#set_override_fov)
-
-### Description
-Sets the override FOV
-
-### Lua Example
-`set_override_fov(fov)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| fov | `number` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_override_fov(f32 fov);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_override_near](#set_override_near)
-
-### Description
-Sets the override near plane
-
-### Lua Example
-`set_override_near(near)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| near | `number` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_override_near(f32 near);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_override_far](#set_override_far)
-
-### Description
-Sets the override far plane
-
-### Lua Example
-`set_override_far(far)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| far | `number` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_override_far(f32 far);`
-
-[:arrow_up_small:](#)
-
-
-
-## [get_lighting_dir](#get_lighting_dir)
-
-### Description
-Gets a value of the global lighting direction
-
-### Lua Example
-`local numberValue = get_lighting_dir(index)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-
-### Returns
-- `number`
-
-### C Prototype
-`f32 get_lighting_dir(u8 index);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_lighting_dir](#set_lighting_dir)
-
-### Description
-Sets a value of the global lighting direction
-
-### Lua Example
-`set_lighting_dir(index, value)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-| value | `number` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_lighting_dir(u8 index, f32 value);`
-
-[:arrow_up_small:](#)
-
-
-
-## [get_lighting_color](#get_lighting_color)
-
-### Description
-Gets a value of the global lighting color
-
-### Lua Example
-`local integerValue = get_lighting_color(index)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u8 get_lighting_color(u8 index);`
-
-[:arrow_up_small:](#)
-
-
-
-## [get_lighting_color_ambient](#get_lighting_color_ambient)
-
-### Description
-Gets a value of the global ambient lighting color
-
-### Lua Example
-`local integerValue = get_lighting_color_ambient(index)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u8 get_lighting_color_ambient(u8 index);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_lighting_color](#set_lighting_color)
-
-### Description
-Sets a value of the global lighting color
-
-### Lua Example
-`set_lighting_color(index, value)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-| value | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_lighting_color(u8 index, u8 value);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_lighting_color_ambient](#set_lighting_color_ambient)
-
-### Description
-Sets a value of the global lighting color (run this after `set_lighting_color` for the ambient color to not be overriden)
-
-### Lua Example
-`set_lighting_color_ambient(index, value)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-| value | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_lighting_color_ambient(u8 index, u8 value);`
-
-[:arrow_up_small:](#)
-
-
-
-## [get_vertex_color](#get_vertex_color)
-
-### Description
-Gets a value of the global vertex shading color
-
-### Lua Example
-`local integerValue = get_vertex_color(index)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u8 get_vertex_color(u8 index);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_vertex_color](#set_vertex_color)
-
-### Description
-Sets a value of the global vertex shading color
-
-### Lua Example
-`set_vertex_color(index, value)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-| value | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_vertex_color(u8 index, u8 value);`
-
-[:arrow_up_small:](#)
-
-
-
-## [get_fog_color](#get_fog_color)
-
-### Description
-Gets a value of the global fog color
-
-### Lua Example
-`local integerValue = get_fog_color(index)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u8 get_fog_color(u8 index);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_fog_color](#set_fog_color)
-
-### Description
-Sets a value of the global fog color
-
-### Lua Example
-`set_fog_color(index, value)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-| value | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_fog_color(u8 index, u8 value);`
-
-[:arrow_up_small:](#)
-
-
-
-## [get_fog_intensity](#get_fog_intensity)
-
-### Description
-Gets the intensity of the fog
-
-### Lua Example
-`local numberValue = get_fog_intensity()`
-
-### Parameters
-- None
-
-### Returns
-- `number`
-
-### C Prototype
-`f32 get_fog_intensity(void);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_fog_intensity](#set_fog_intensity)
-
-### Description
-Sets the intensity of the fog (this value scales very quickly, 1.0 to 1.1 is a desirable range)
-
-### Lua Example
-`set_fog_intensity(intensity)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| intensity | `number` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_fog_intensity(f32 intensity);`
-
-[:arrow_up_small:](#)
-
-
-
-## [get_skybox](#get_skybox)
-
-### Description
-Gets the current skybox
-
-### Lua Example
-`local integerValue = get_skybox()`
-
-### Parameters
-- None
-
-### Returns
-- `integer`
-
-### C Prototype
-`s8 get_skybox(void);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_override_skybox](#set_override_skybox)
-
-### Description
-Sets the override skybox
-
-### Lua Example
-`set_override_skybox(background)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| background | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_override_skybox(s8 background);`
-
-[:arrow_up_small:](#)
-
-
-
-## [get_skybox_color](#get_skybox_color)
-
-### Description
-Gets a value of the global skybox color
-
-### Lua Example
-`local integerValue = get_skybox_color(index)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u8 get_skybox_color(u8 index);`
-
-[:arrow_up_small:](#)
-
-
-
-## [set_skybox_color](#set_skybox_color)
-
-### Description
-Sets a value of the global skybox color
-
-### Lua Example
-`set_skybox_color(index, value)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| index | `integer` |
-| value | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void set_skybox_color(u8 index, u8 value);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_parse](#gfx_parse)
-
-### Description
-Traverses a display list. Takes a Lua function as a parameter, which is called back for each command in the display list with the parameters `cmd` (display list pointer), and `op`
-
-### Lua Example
-`gfx_parse(cmd, func)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| cmd | `Pointer` <`Gfx`> |
-| func | `Lua Function` () |
-
-### Returns
-- None
-
-### C Prototype
-`void gfx_parse(Gfx *cmd, LuaFunction func);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_op](#gfx_get_op)
-
-### Description
-Gets the op of the display list command
-
-### Lua Example
-`local integerValue = gfx_get_op(cmd)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| cmd | `Pointer` <`Gfx`> |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u32 gfx_get_op(Gfx *cmd);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_display_list](#gfx_get_display_list)
-
-### Description
-Gets the display list from a display list command if it has the op `G_DL`
-
-### Lua Example
-`local pointerValue = gfx_get_display_list(cmd)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| cmd | `Pointer` <`Gfx`> |
-
-### Returns
-- `Pointer` <`Gfx`>
-
-### C Prototype
-`Gfx *gfx_get_display_list(Gfx *cmd);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_vertex_buffer](#gfx_get_vertex_buffer)
-
-### Description
-Gets the vertex buffer from a display list command if it has the op `G_VTX`
-
-### Lua Example
-`local pointerValue = gfx_get_vertex_buffer(cmd)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| cmd | `Pointer` <`Gfx`> |
-
-### Returns
-- `Pointer` <`Vtx`>
-
-### C Prototype
-`Vtx *gfx_get_vertex_buffer(Gfx *cmd);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_vertex_count](#gfx_get_vertex_count)
-
-### Description
-Gets the number of vertices from a display list command if it has the op `G_VTX`
-
-### Lua Example
-`local integerValue = gfx_get_vertex_count(cmd)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| cmd | `Pointer` <`Gfx`> |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u16 gfx_get_vertex_count(Gfx *cmd);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_texture](#gfx_get_texture)
-
-### Description
-Gets the texture from a display list command if it has an image related op
-
-### Lua Example
-`local pointerValue = gfx_get_texture(cmd)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| cmd | `Pointer` <`Gfx`> |
-
-### Returns
-- `Pointer` <`Texture`>
-
-### C Prototype
-`Texture *gfx_get_texture(Gfx *cmd);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_from_name](#gfx_get_from_name)
-
-### Description
-Gets a display list of the current mod from its name. Returns a pointer to the display list and its length
-
-### Lua Example
-`local pointerValue, length = gfx_get_from_name(name)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| name | `string` |
-
-### Returns
-- `Pointer` <`Gfx`>
-- `integer`
-
-### C Prototype
-`Gfx *gfx_get_from_name(const char *name, RET u32 *length);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_name](#gfx_get_name)
-
-### Description
-Gets the name of a display list
-
-### Lua Example
-`local stringValue = gfx_get_name(gfx)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| gfx | `Pointer` <`Gfx`> |
-
-### Returns
-- `string`
-
-### C Prototype
-`const char *gfx_get_name(Gfx *gfx);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_length](#gfx_get_length)
-
-### Description
-Gets the max length of a display list
-
-### Lua Example
-`local integerValue = gfx_get_length(gfx)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| gfx | `Pointer` <`Gfx`> |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u32 gfx_get_length(Gfx *gfx);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_command](#gfx_get_command)
-
-### Description
-Gets a command of a display list at position `offset`
-
-### Lua Example
-`local pointerValue = gfx_get_command(gfx, offset)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| gfx | `Pointer` <`Gfx`> |
-| offset | `integer` |
-
-### Returns
-- `Pointer` <`Gfx`>
-
-### C Prototype
-`Gfx *gfx_get_command(Gfx *gfx, u32 offset);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_get_next_command](#gfx_get_next_command)
-
-### Description
-Gets the next command of a given display list pointer. Intended to use in a for loop
-
-### Lua Example
-`local pointerValue = gfx_get_next_command(gfx)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| gfx | `Pointer` <`Gfx`> |
-
-### Returns
-- `Pointer` <`Gfx`>
-
-### C Prototype
-`Gfx *gfx_get_next_command(Gfx *gfx);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_copy](#gfx_copy)
-
-### Description
-Copies `length` commands from display list `src` to display list `dest`
-
-### Lua Example
-`gfx_copy(dest, src, length)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| dest | `Pointer` <`Gfx`> |
-| src | `Pointer` <`Gfx`> |
-| length | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void gfx_copy(Gfx *dest, Gfx *src, u32 length);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_create](#gfx_create)
-
-### Description
-Creates a new named display list of `length` commands
-
-### Lua Example
-`local pointerValue = gfx_create(name, length)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| name | `string` |
-| length | `integer` |
-
-### Returns
-- `Pointer` <`Gfx`>
-
-### C Prototype
-`Gfx *gfx_create(const char *name, u32 length);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_resize](#gfx_resize)
-
-### Description
-Resizes a display list created by `gfx_create`
-
-### Lua Example
-`gfx_resize(gfx, newLength)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| gfx | `Pointer` <`Gfx`> |
-| newLength | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void gfx_resize(Gfx *gfx, u32 newLength);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_delete](#gfx_delete)
-
-### Description
-Deletes a display list created by `gfx_create`
-
-### Lua Example
-`gfx_delete(gfx)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| gfx | `Pointer` <`Gfx`> |
-
-### Returns
-- None
-
-### C Prototype
-`void gfx_delete(Gfx *gfx);`
-
-[:arrow_up_small:](#)
-
-
-
-## [gfx_delete_all](#gfx_delete_all)
-
-### Description
-Deletes all display lists created by `gfx_create`
-
-### Lua Example
-`gfx_delete_all()`
-
-### Parameters
-- None
-
-### Returns
-- None
-
-### C Prototype
-`void gfx_delete_all();`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_get_from_name](#vtx_get_from_name)
-
-### Description
-Gets a vertex buffer of the current mod from its name. Returns a pointer to the vertex buffering and its vertex count
-
-### Lua Example
-`local pointerValue, count = vtx_get_from_name(name)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| name | `string` |
-
-### Returns
-- `Pointer` <`Vtx`>
-- `integer`
-
-### C Prototype
-`Vtx *vtx_get_from_name(const char *name, RET u32 *count);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_get_name](#vtx_get_name)
-
-### Description
-Gets the name of a vertex buffer
-
-### Lua Example
-`local stringValue = vtx_get_name(vtx)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| vtx | `Pointer` <`Vtx`> |
-
-### Returns
-- `string`
-
-### C Prototype
-`const char *vtx_get_name(Vtx *vtx);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_get_count](#vtx_get_count)
-
-### Description
-Gets the max count of vertices of a vertex buffer
-
-### Lua Example
-`local integerValue = vtx_get_count(vtx)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| vtx | `Pointer` <`Vtx`> |
-
-### Returns
-- `integer`
-
-### C Prototype
-`u32 vtx_get_count(Vtx *vtx);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_get_vertex](#vtx_get_vertex)
-
-### Description
-Gets a vertex of a vertex buffer at position `offset`
-
-### Lua Example
-`local pointerValue = vtx_get_vertex(vtx, offset)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| vtx | `Pointer` <`Vtx`> |
-| offset | `integer` |
-
-### Returns
-- `Pointer` <`Vtx`>
-
-### C Prototype
-`Vtx *vtx_get_vertex(Vtx *vtx, u32 offset);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_get_next_vertex](#vtx_get_next_vertex)
-
-### Description
-Gets the next vertex of a given vertex pointer. Intended to use in a for loop
-
-### Lua Example
-`local pointerValue = vtx_get_next_vertex(vtx)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| vtx | `Pointer` <`Vtx`> |
-
-### Returns
-- `Pointer` <`Vtx`>
-
-### C Prototype
-`Vtx *vtx_get_next_vertex(Vtx *vtx);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_copy](#vtx_copy)
-
-### Description
-Copies `count` vertices from vertex buffer `src` to vertex buffer `dest`
-
-### Lua Example
-`vtx_copy(dest, src, count)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| dest | `Pointer` <`Vtx`> |
-| src | `Pointer` <`Vtx`> |
-| count | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void vtx_copy(Vtx *dest, Vtx *src, u32 count);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_create](#vtx_create)
-
-### Description
-Creates a new named vertex buffer of `count` vertices
-
-### Lua Example
-`local pointerValue = vtx_create(name, count)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| name | `string` |
-| count | `integer` |
-
-### Returns
-- `Pointer` <`Vtx`>
-
-### C Prototype
-`Vtx *vtx_create(const char *name, u32 count);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_resize](#vtx_resize)
-
-### Description
-Resizes a vertex buffer created by `vtx_create`
-
-### Lua Example
-`vtx_resize(vtx, newCount)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| vtx | `Pointer` <`Vtx`> |
-| newCount | `integer` |
-
-### Returns
-- None
-
-### C Prototype
-`void vtx_resize(Vtx *vtx, u32 newCount);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_delete](#vtx_delete)
-
-### Description
-Deletes a vertex buffer created by `vtx_create`
-
-### Lua Example
-`vtx_delete(vtx)`
-
-### Parameters
-| Field | Type |
-| ----- | ---- |
-| vtx | `Pointer` <`Vtx`> |
-
-### Returns
-- None
-
-### C Prototype
-`void vtx_delete(Vtx *vtx);`
-
-[:arrow_up_small:](#)
-
-
-
-## [vtx_delete_all](#vtx_delete_all)
-
-### Description
-Deletes all vertex buffers created by `vtx_create`
-
-### Lua Example
-`vtx_delete_all()`
-
-### Parameters
-- None
-
-### Returns
-- None
-
-### C Prototype
-`void vtx_delete_all();`
-
-[:arrow_up_small:](#)
-
-
---
[< prev](functions-5.md) | [1](functions.md) | [2](functions-2.md) | [3](functions-3.md) | [4](functions-4.md) | [5](functions-5.md) | 6 | [7](functions-7.md) | [next >](functions-7.md)]
diff --git a/docs/lua/functions-7.md b/docs/lua/functions-7.md
index 1dd27c2d7..dd24bd958 100644
--- a/docs/lua/functions-7.md
+++ b/docs/lua/functions-7.md
@@ -5,6 +5,1322 @@
[< prev](functions-6.md) | [1](functions.md) | [2](functions-2.md) | [3](functions-3.md) | [4](functions-4.md) | [5](functions-5.md) | [6](functions-6.md) | 7]
+---
+# functions from smlua_gfx_utils.h
+
+
+
+
+## [set_override_fov](#set_override_fov)
+
+### Description
+Sets the override FOV
+
+### Lua Example
+`set_override_fov(fov)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| fov | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_override_fov(f32 fov);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_override_near](#set_override_near)
+
+### Description
+Sets the override near plane
+
+### Lua Example
+`set_override_near(near)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| near | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_override_near(f32 near);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_override_far](#set_override_far)
+
+### Description
+Sets the override far plane
+
+### Lua Example
+`set_override_far(far)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| far | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_override_far(f32 far);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_lighting_dir](#get_lighting_dir)
+
+### Description
+Gets a value of the global lighting direction
+
+### Lua Example
+`local numberValue = get_lighting_dir(index)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+
+### Returns
+- `number`
+
+### C Prototype
+`f32 get_lighting_dir(u8 index);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_lighting_dir](#set_lighting_dir)
+
+### Description
+Sets a value of the global lighting direction
+
+### Lua Example
+`set_lighting_dir(index, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+| value | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_lighting_dir(u8 index, f32 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_lighting_color](#get_lighting_color)
+
+### Description
+Gets a value of the global lighting color
+
+### Lua Example
+`local integerValue = get_lighting_color(index)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u8 get_lighting_color(u8 index);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_lighting_color_ambient](#get_lighting_color_ambient)
+
+### Description
+Gets a value of the global ambient lighting color
+
+### Lua Example
+`local integerValue = get_lighting_color_ambient(index)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u8 get_lighting_color_ambient(u8 index);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_lighting_color](#set_lighting_color)
+
+### Description
+Sets a value of the global lighting color
+
+### Lua Example
+`set_lighting_color(index, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_lighting_color(u8 index, u8 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_lighting_color_ambient](#set_lighting_color_ambient)
+
+### Description
+Sets a value of the global lighting color (run this after `set_lighting_color` for the ambient color to not be overriden)
+
+### Lua Example
+`set_lighting_color_ambient(index, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_lighting_color_ambient(u8 index, u8 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_vertex_color](#get_vertex_color)
+
+### Description
+Gets a value of the global vertex shading color
+
+### Lua Example
+`local integerValue = get_vertex_color(index)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u8 get_vertex_color(u8 index);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_vertex_color](#set_vertex_color)
+
+### Description
+Sets a value of the global vertex shading color
+
+### Lua Example
+`set_vertex_color(index, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_vertex_color(u8 index, u8 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_fog_color](#get_fog_color)
+
+### Description
+Gets a value of the global fog color
+
+### Lua Example
+`local integerValue = get_fog_color(index)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u8 get_fog_color(u8 index);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_fog_color](#set_fog_color)
+
+### Description
+Sets a value of the global fog color
+
+### Lua Example
+`set_fog_color(index, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_fog_color(u8 index, u8 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_fog_intensity](#get_fog_intensity)
+
+### Description
+Gets the intensity of the fog
+
+### Lua Example
+`local numberValue = get_fog_intensity()`
+
+### Parameters
+- None
+
+### Returns
+- `number`
+
+### C Prototype
+`f32 get_fog_intensity(void);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_fog_intensity](#set_fog_intensity)
+
+### Description
+Sets the intensity of the fog (this value scales very quickly, 1.0 to 1.1 is a desirable range)
+
+### Lua Example
+`set_fog_intensity(intensity)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| intensity | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_fog_intensity(f32 intensity);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_skybox](#get_skybox)
+
+### Description
+Gets the current skybox
+
+### Lua Example
+`local integerValue = get_skybox()`
+
+### Parameters
+- None
+
+### Returns
+- `integer`
+
+### C Prototype
+`s8 get_skybox(void);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_override_skybox](#set_override_skybox)
+
+### Description
+Sets the override skybox
+
+### Lua Example
+`set_override_skybox(background)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| background | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_override_skybox(s8 background);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_skybox_color](#get_skybox_color)
+
+### Description
+Gets a value of the global skybox color
+
+### Lua Example
+`local integerValue = get_skybox_color(index)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u8 get_skybox_color(u8 index);`
+
+[:arrow_up_small:](#)
+
+
+
+## [set_skybox_color](#set_skybox_color)
+
+### Description
+Sets a value of the global skybox color
+
+### Lua Example
+`set_skybox_color(index, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| index | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void set_skybox_color(u8 index, u8 value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_parse](#gfx_parse)
+
+### Description
+Traverses a display list. Takes a Lua function as a parameter, which is called back for each command in the display list with the parameters `cmd` (display list pointer), and `op`
+
+### Lua Example
+`gfx_parse(cmd, func)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| cmd | `Pointer` <`Gfx`> |
+| func | `Lua Function` () |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_parse(Gfx *cmd, LuaFunction func);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_op](#gfx_get_op)
+
+### Description
+Gets the op of the display list command
+
+### Lua Example
+`local integerValue = gfx_get_op(cmd)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| cmd | `Pointer` <`Gfx`> |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u32 gfx_get_op(Gfx *cmd);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_display_list](#gfx_get_display_list)
+
+### Description
+Gets the display list from a display list command if it has the op `G_DL`
+
+### Lua Example
+`local pointerValue = gfx_get_display_list(cmd)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| cmd | `Pointer` <`Gfx`> |
+
+### Returns
+- `Pointer` <`Gfx`>
+
+### C Prototype
+`Gfx *gfx_get_display_list(Gfx *cmd);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_vertex_buffer](#gfx_get_vertex_buffer)
+
+### Description
+Gets the vertex buffer from a display list command if it has the op `G_VTX`
+
+### Lua Example
+`local pointerValue = gfx_get_vertex_buffer(cmd)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| cmd | `Pointer` <`Gfx`> |
+
+### Returns
+- `Pointer` <`Vtx`>
+
+### C Prototype
+`Vtx *gfx_get_vertex_buffer(Gfx *cmd);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_vertex_count](#gfx_get_vertex_count)
+
+### Description
+Gets the number of vertices from a display list command if it has the op `G_VTX`
+
+### Lua Example
+`local integerValue = gfx_get_vertex_count(cmd)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| cmd | `Pointer` <`Gfx`> |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u16 gfx_get_vertex_count(Gfx *cmd);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_texture](#gfx_get_texture)
+
+### Description
+Gets the texture from a display list command if it has an image related op
+
+### Lua Example
+`local pointerValue = gfx_get_texture(cmd)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| cmd | `Pointer` <`Gfx`> |
+
+### Returns
+- `Pointer` <`Texture`>
+
+### C Prototype
+`Texture *gfx_get_texture(Gfx *cmd);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_from_name](#gfx_get_from_name)
+
+### Description
+Gets a display list of the current mod from its name. Returns a pointer to the display list and its length
+
+### Lua Example
+`local pointerValue, length = gfx_get_from_name(name)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| name | `string` |
+
+### Returns
+- `Pointer` <`Gfx`>
+- `integer`
+
+### C Prototype
+`Gfx *gfx_get_from_name(const char *name, RET u32 *length);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_name](#gfx_get_name)
+
+### Description
+Gets the name of a display list
+
+### Lua Example
+`local stringValue = gfx_get_name(gfx)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| gfx | `Pointer` <`Gfx`> |
+
+### Returns
+- `string`
+
+### C Prototype
+`const char *gfx_get_name(Gfx *gfx);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_length](#gfx_get_length)
+
+### Description
+Gets the max length of a display list
+
+### Lua Example
+`local integerValue = gfx_get_length(gfx)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| gfx | `Pointer` <`Gfx`> |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u32 gfx_get_length(Gfx *gfx);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_command](#gfx_get_command)
+
+### Description
+Gets a command of a display list at position `offset`
+
+### Lua Example
+`local pointerValue = gfx_get_command(gfx, offset)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| gfx | `Pointer` <`Gfx`> |
+| offset | `integer` |
+
+### Returns
+- `Pointer` <`Gfx`>
+
+### C Prototype
+`Gfx *gfx_get_command(Gfx *gfx, u32 offset);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_next_command](#gfx_get_next_command)
+
+### Description
+Gets the next command of a given display list pointer. Intended to use in a for loop
+
+### Lua Example
+`local pointerValue = gfx_get_next_command(gfx)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| gfx | `Pointer` <`Gfx`> |
+
+### Returns
+- `Pointer` <`Gfx`>
+
+### C Prototype
+`Gfx *gfx_get_next_command(Gfx *gfx);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_copy](#gfx_copy)
+
+### Description
+Copies `length` commands from display list `src` to display list `dest`
+
+### Lua Example
+`gfx_copy(dest, src, length)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| dest | `Pointer` <`Gfx`> |
+| src | `Pointer` <`Gfx`> |
+| length | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_copy(Gfx *dest, Gfx *src, u32 length);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_create](#gfx_create)
+
+### Description
+Creates a new named display list of `length` commands
+
+### Lua Example
+`local pointerValue = gfx_create(name, length)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| name | `string` |
+| length | `integer` |
+
+### Returns
+- `Pointer` <`Gfx`>
+
+### C Prototype
+`Gfx *gfx_create(const char *name, u32 length);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_resize](#gfx_resize)
+
+### Description
+Resizes a display list created by `gfx_create`
+
+### Lua Example
+`gfx_resize(gfx, newLength)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| gfx | `Pointer` <`Gfx`> |
+| newLength | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_resize(Gfx *gfx, u32 newLength);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_delete](#gfx_delete)
+
+### Description
+Deletes a display list created by `gfx_create`
+
+### Lua Example
+`gfx_delete(gfx)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| gfx | `Pointer` <`Gfx`> |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_delete(Gfx *gfx);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_delete_all](#gfx_delete_all)
+
+### Description
+Deletes all display lists created by `gfx_create`
+
+### Lua Example
+`gfx_delete_all()`
+
+### Parameters
+- None
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_delete_all();`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_reload_shaders](#gfx_reload_shaders)
+
+### Description
+Reloads all shaders
+
+### Lua Example
+`gfx_reload_shaders()`
+
+### Parameters
+- None
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_reload_shaders();`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_color_combiner_get_features](#gfx_color_combiner_get_features)
+
+### Description
+Gets features from a color combiner.
+
+### Lua Example
+`local cCFeaturesValue = gfx_color_combiner_get_features(cc)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| cc | [ColorCombiner](structs.md#ColorCombiner) |
+
+### Returns
+- [CCFeatures](structs.md#CCFeatures)
+
+### C Prototype
+`struct CCFeatures *gfx_color_combiner_get_features(struct ColorCombiner *cc);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_get_program_id_from_shader_index](#gfx_get_program_id_from_shader_index)
+
+### Description
+Gets a program id from the shader index.
+
+### Lua Example
+`local integerValue = gfx_get_program_id_from_shader_index(shaderIndex)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| shaderIndex | `integer` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u32 gfx_get_program_id_from_shader_index(u8 shaderIndex);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_use_program](#gfx_use_program)
+
+### Description
+Uses a specific program. Required for setting uniforms.
+
+### Lua Example
+`gfx_use_program(program)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| program | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_use_program(u32 program);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_shader_get_uniform_location](#gfx_shader_get_uniform_location)
+
+### Description
+Gets the location of a shader uniform in a program for modification.
+
+### Lua Example
+`local integerValue = gfx_shader_get_uniform_location(program, name)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| program | `integer` |
+| name | `string` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`int gfx_shader_get_uniform_location(u32 program, const char* name);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_shader_set_int](#gfx_shader_set_int)
+
+### Description
+Sets the value of a shader uniform of type int.
+
+### Lua Example
+`gfx_shader_set_int(loc, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| loc | `integer` |
+| value | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_shader_set_int(int loc, int value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_shader_set_float](#gfx_shader_set_float)
+
+### Description
+Sets the value of a shader uniform of type float.
+
+### Lua Example
+`gfx_shader_set_float(loc, value)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| loc | `integer` |
+| value | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_shader_set_float(int loc, float value);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_shader_set_vec2](#gfx_shader_set_vec2)
+
+### Description
+Sets the value of a shader uniform of type vec2.
+
+### Lua Example
+`gfx_shader_set_vec2(loc, x, y)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| loc | `integer` |
+| x | `number` |
+| y | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_shader_set_vec2(int loc, float x, float y);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_shader_set_vec3](#gfx_shader_set_vec3)
+
+### Description
+Sets the value of a shader uniform of type vec3.
+
+### Lua Example
+`gfx_shader_set_vec3(loc, x, y, z)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| loc | `integer` |
+| x | `number` |
+| y | `number` |
+| z | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_shader_set_vec3(int loc, float x, float y, float z);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_shader_set_vec4](#gfx_shader_set_vec4)
+
+### Description
+Sets the value of a shader uniform of type vec4.
+
+### Lua Example
+`gfx_shader_set_vec4(loc, w, x, y, z)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| loc | `integer` |
+| w | `number` |
+| x | `number` |
+| y | `number` |
+| z | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_shader_set_vec4(int loc, float w, float x, float y, float z);`
+
+[:arrow_up_small:](#)
+
+
+
+## [gfx_shader_set_mat4](#gfx_shader_set_mat4)
+
+### Description
+Sets the value of a shader uniform of type mat4.
+
+### Lua Example
+`gfx_shader_set_mat4(loc, mat)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| loc | `integer` |
+| mat | [Mat4](structs.md#Mat4) |
+
+### Returns
+- None
+
+### C Prototype
+`void gfx_shader_set_mat4(int loc, const Mat4 mat);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_get_from_name](#vtx_get_from_name)
+
+### Description
+Gets a vertex buffer of the current mod from its name. Returns a pointer to the vertex buffering and its vertex count
+
+### Lua Example
+`local pointerValue, count = vtx_get_from_name(name)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| name | `string` |
+
+### Returns
+- `Pointer` <`Vtx`>
+- `integer`
+
+### C Prototype
+`Vtx *vtx_get_from_name(const char *name, RET u32 *count);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_get_name](#vtx_get_name)
+
+### Description
+Gets the name of a vertex buffer
+
+### Lua Example
+`local stringValue = vtx_get_name(vtx)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| vtx | `Pointer` <`Vtx`> |
+
+### Returns
+- `string`
+
+### C Prototype
+`const char *vtx_get_name(Vtx *vtx);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_get_count](#vtx_get_count)
+
+### Description
+Gets the max count of vertices of a vertex buffer
+
+### Lua Example
+`local integerValue = vtx_get_count(vtx)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| vtx | `Pointer` <`Vtx`> |
+
+### Returns
+- `integer`
+
+### C Prototype
+`u32 vtx_get_count(Vtx *vtx);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_get_vertex](#vtx_get_vertex)
+
+### Description
+Gets a vertex of a vertex buffer at position `offset`
+
+### Lua Example
+`local pointerValue = vtx_get_vertex(vtx, offset)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| vtx | `Pointer` <`Vtx`> |
+| offset | `integer` |
+
+### Returns
+- `Pointer` <`Vtx`>
+
+### C Prototype
+`Vtx *vtx_get_vertex(Vtx *vtx, u32 offset);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_get_next_vertex](#vtx_get_next_vertex)
+
+### Description
+Gets the next vertex of a given vertex pointer. Intended to use in a for loop
+
+### Lua Example
+`local pointerValue = vtx_get_next_vertex(vtx)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| vtx | `Pointer` <`Vtx`> |
+
+### Returns
+- `Pointer` <`Vtx`>
+
+### C Prototype
+`Vtx *vtx_get_next_vertex(Vtx *vtx);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_copy](#vtx_copy)
+
+### Description
+Copies `count` vertices from vertex buffer `src` to vertex buffer `dest`
+
+### Lua Example
+`vtx_copy(dest, src, count)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| dest | `Pointer` <`Vtx`> |
+| src | `Pointer` <`Vtx`> |
+| count | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void vtx_copy(Vtx *dest, Vtx *src, u32 count);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_create](#vtx_create)
+
+### Description
+Creates a new named vertex buffer of `count` vertices
+
+### Lua Example
+`local pointerValue = vtx_create(name, count)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| name | `string` |
+| count | `integer` |
+
+### Returns
+- `Pointer` <`Vtx`>
+
+### C Prototype
+`Vtx *vtx_create(const char *name, u32 count);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_resize](#vtx_resize)
+
+### Description
+Resizes a vertex buffer created by `vtx_create`
+
+### Lua Example
+`vtx_resize(vtx, newCount)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| vtx | `Pointer` <`Vtx`> |
+| newCount | `integer` |
+
+### Returns
+- None
+
+### C Prototype
+`void vtx_resize(Vtx *vtx, u32 newCount);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_delete](#vtx_delete)
+
+### Description
+Deletes a vertex buffer created by `vtx_create`
+
+### Lua Example
+`vtx_delete(vtx)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| vtx | `Pointer` <`Vtx`> |
+
+### Returns
+- None
+
+### C Prototype
+`void vtx_delete(Vtx *vtx);`
+
+[:arrow_up_small:](#)
+
+
+
+## [vtx_delete_all](#vtx_delete_all)
+
+### Description
+Deletes all vertex buffers created by `vtx_create`
+
+### Lua Example
+`vtx_delete_all()`
+
+### Parameters
+- None
+
+### Returns
+- None
+
+### C Prototype
+`void vtx_delete_all();`
+
+[:arrow_up_small:](#)
+
+
+
---
# functions from smlua_level_utils.h
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index b463ac63e..411effb19 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -1926,51 +1926,62 @@
- smlua_gfx_utils.h
- - [set_override_fov](functions-6.md#set_override_fov)
- - [set_override_near](functions-6.md#set_override_near)
- - [set_override_far](functions-6.md#set_override_far)
- - [get_lighting_dir](functions-6.md#get_lighting_dir)
- - [set_lighting_dir](functions-6.md#set_lighting_dir)
- - [get_lighting_color](functions-6.md#get_lighting_color)
- - [get_lighting_color_ambient](functions-6.md#get_lighting_color_ambient)
- - [set_lighting_color](functions-6.md#set_lighting_color)
- - [set_lighting_color_ambient](functions-6.md#set_lighting_color_ambient)
- - [get_vertex_color](functions-6.md#get_vertex_color)
- - [set_vertex_color](functions-6.md#set_vertex_color)
- - [get_fog_color](functions-6.md#get_fog_color)
- - [set_fog_color](functions-6.md#set_fog_color)
- - [get_fog_intensity](functions-6.md#get_fog_intensity)
- - [set_fog_intensity](functions-6.md#set_fog_intensity)
- - [get_skybox](functions-6.md#get_skybox)
- - [set_override_skybox](functions-6.md#set_override_skybox)
- - [get_skybox_color](functions-6.md#get_skybox_color)
- - [set_skybox_color](functions-6.md#set_skybox_color)
- - [gfx_parse](functions-6.md#gfx_parse)
- - [gfx_get_op](functions-6.md#gfx_get_op)
- - [gfx_get_display_list](functions-6.md#gfx_get_display_list)
- - [gfx_get_vertex_buffer](functions-6.md#gfx_get_vertex_buffer)
- - [gfx_get_vertex_count](functions-6.md#gfx_get_vertex_count)
- - [gfx_get_texture](functions-6.md#gfx_get_texture)
- - [gfx_get_from_name](functions-6.md#gfx_get_from_name)
- - [gfx_get_name](functions-6.md#gfx_get_name)
- - [gfx_get_length](functions-6.md#gfx_get_length)
- - [gfx_get_command](functions-6.md#gfx_get_command)
- - [gfx_get_next_command](functions-6.md#gfx_get_next_command)
- - [gfx_copy](functions-6.md#gfx_copy)
- - [gfx_create](functions-6.md#gfx_create)
- - [gfx_resize](functions-6.md#gfx_resize)
- - [gfx_delete](functions-6.md#gfx_delete)
- - [gfx_delete_all](functions-6.md#gfx_delete_all)
- - [vtx_get_from_name](functions-6.md#vtx_get_from_name)
- - [vtx_get_name](functions-6.md#vtx_get_name)
- - [vtx_get_count](functions-6.md#vtx_get_count)
- - [vtx_get_vertex](functions-6.md#vtx_get_vertex)
- - [vtx_get_next_vertex](functions-6.md#vtx_get_next_vertex)
- - [vtx_copy](functions-6.md#vtx_copy)
- - [vtx_create](functions-6.md#vtx_create)
- - [vtx_resize](functions-6.md#vtx_resize)
- - [vtx_delete](functions-6.md#vtx_delete)
- - [vtx_delete_all](functions-6.md#vtx_delete_all)
+ - [set_override_fov](functions-7.md#set_override_fov)
+ - [set_override_near](functions-7.md#set_override_near)
+ - [set_override_far](functions-7.md#set_override_far)
+ - [get_lighting_dir](functions-7.md#get_lighting_dir)
+ - [set_lighting_dir](functions-7.md#set_lighting_dir)
+ - [get_lighting_color](functions-7.md#get_lighting_color)
+ - [get_lighting_color_ambient](functions-7.md#get_lighting_color_ambient)
+ - [set_lighting_color](functions-7.md#set_lighting_color)
+ - [set_lighting_color_ambient](functions-7.md#set_lighting_color_ambient)
+ - [get_vertex_color](functions-7.md#get_vertex_color)
+ - [set_vertex_color](functions-7.md#set_vertex_color)
+ - [get_fog_color](functions-7.md#get_fog_color)
+ - [set_fog_color](functions-7.md#set_fog_color)
+ - [get_fog_intensity](functions-7.md#get_fog_intensity)
+ - [set_fog_intensity](functions-7.md#set_fog_intensity)
+ - [get_skybox](functions-7.md#get_skybox)
+ - [set_override_skybox](functions-7.md#set_override_skybox)
+ - [get_skybox_color](functions-7.md#get_skybox_color)
+ - [set_skybox_color](functions-7.md#set_skybox_color)
+ - [gfx_parse](functions-7.md#gfx_parse)
+ - [gfx_get_op](functions-7.md#gfx_get_op)
+ - [gfx_get_display_list](functions-7.md#gfx_get_display_list)
+ - [gfx_get_vertex_buffer](functions-7.md#gfx_get_vertex_buffer)
+ - [gfx_get_vertex_count](functions-7.md#gfx_get_vertex_count)
+ - [gfx_get_texture](functions-7.md#gfx_get_texture)
+ - [gfx_get_from_name](functions-7.md#gfx_get_from_name)
+ - [gfx_get_name](functions-7.md#gfx_get_name)
+ - [gfx_get_length](functions-7.md#gfx_get_length)
+ - [gfx_get_command](functions-7.md#gfx_get_command)
+ - [gfx_get_next_command](functions-7.md#gfx_get_next_command)
+ - [gfx_copy](functions-7.md#gfx_copy)
+ - [gfx_create](functions-7.md#gfx_create)
+ - [gfx_resize](functions-7.md#gfx_resize)
+ - [gfx_delete](functions-7.md#gfx_delete)
+ - [gfx_delete_all](functions-7.md#gfx_delete_all)
+ - [gfx_reload_shaders](functions-7.md#gfx_reload_shaders)
+ - [gfx_color_combiner_get_features](functions-7.md#gfx_color_combiner_get_features)
+ - [gfx_get_program_id_from_shader_index](functions-7.md#gfx_get_program_id_from_shader_index)
+ - [gfx_use_program](functions-7.md#gfx_use_program)
+ - [gfx_shader_get_uniform_location](functions-7.md#gfx_shader_get_uniform_location)
+ - [gfx_shader_set_int](functions-7.md#gfx_shader_set_int)
+ - [gfx_shader_set_float](functions-7.md#gfx_shader_set_float)
+ - [gfx_shader_set_vec2](functions-7.md#gfx_shader_set_vec2)
+ - [gfx_shader_set_vec3](functions-7.md#gfx_shader_set_vec3)
+ - [gfx_shader_set_vec4](functions-7.md#gfx_shader_set_vec4)
+ - [gfx_shader_set_mat4](functions-7.md#gfx_shader_set_mat4)
+ - [vtx_get_from_name](functions-7.md#vtx_get_from_name)
+ - [vtx_get_name](functions-7.md#vtx_get_name)
+ - [vtx_get_count](functions-7.md#vtx_get_count)
+ - [vtx_get_vertex](functions-7.md#vtx_get_vertex)
+ - [vtx_get_next_vertex](functions-7.md#vtx_get_next_vertex)
+ - [vtx_copy](functions-7.md#vtx_copy)
+ - [vtx_create](functions-7.md#vtx_create)
+ - [vtx_resize](functions-7.md#vtx_resize)
+ - [vtx_delete](functions-7.md#vtx_delete)
+ - [vtx_delete_all](functions-7.md#vtx_delete_all)
diff --git a/docs/lua/guides/hooks.md b/docs/lua/guides/hooks.md
index 07d522650..51d27b7de 100644
--- a/docs/lua/guides/hooks.md
+++ b/docs/lua/guides/hooks.md
@@ -143,7 +143,7 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
| HOOK_ON_GEO_PROCESS | Called when a GeoLayout is processed **Note:** You must set the `hookProcess` field of the graph node to a non-zero value | [GraphNode](../structs.md#GraphNode) graphNode, `integer` matStackIndex |
| HOOK_BEFORE_GEO_PROCESS | Called before a GeoLayout is processed **Note:** You must set the `hookProcess` field of the graph node to a non-zero value | [GraphNode](../structs.md#GraphNode) graphNode, `integer` matStackIndex |
| HOOK_ON_GEO_PROCESS_CHILDREN | Called when the children of a GeoLayout node is processed **Note:** You must set the `hookProcess` field of the parent graph node to a non-zero value | [GraphNode](../structs.md#GraphNode) graphNode, `integer` matStackIndex |
-| HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS | Called before running Mario's geometry input logic, return `false` to not run it. | [MarioState](../structs.md) m |
+| HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS | Called before running Mario's geometry input logic, return `false` to not run it. | [MarioState](../structs.md) m |
| HOOK_ON_INTERACTIONS | Called when the Mario interactions are processed | [MarioState](../structs.md#MarioState) mario |
| HOOK_ALLOW_FORCE_WATER_ACTION | Called when executing a non-water action while under the water's surface, or vice versa. Return `false` to prevent the player from being forced out of the action at the water's surface | [MarioState](../structs.md#MarioState) mario, `boolean` isInWaterAction |
| HOOK_BEFORE_WARP | Called before the local player warps. Return a table with `destLevel`, `destArea`, `destWarpNode`, to override the warp | `integer` destLevel, `integer` destArea, `integer` destWarpNode, `integer` arg |
@@ -157,6 +157,9 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
| HOOK_ON_FIND_WATER_LEVEL | Called after water level detection completes. Return a number to override the water level | `number` x, `number` z, `number` waterLevel |
| HOOK_ON_FIND_POISON_GAS_LEVEL | Called after poison gas level detection completes. Return a number to override the gas level | `number` x, `number` z, `number` gasLevel |
| HOOK_ON_FIND_SURFACE_ON_RAY | Called after ray-surface intersection completes. Return `surface` to override the hit surface, or `surface, hitPos` to override both | `Vec3f` orig, `Vec3f` dir, [Surface](../structs.md#Surface) hitSurface, `Vec3f` hitPos |
+| HOOK_ON_REFRESH_SHADERS | Called when a shader is refreshed | |
+| HOOK_ON_VERTEX_SHADER_CREATE | Called when a vertex shader is created. Return a string to override the shader | [ColorCombiner](../structs.md#ColorCombiner) cc, `integer` shaderIndex |
+| HOOK_ON_FRAGMENT_SHADER_CREATE | Called when a fragment shader is created. Return a string to override the shader | [ColorCombiner](../structs.md#ColorCombiner) cc, `integer` shaderIndex |
### Parameters
diff --git a/docs/lua/structs.md b/docs/lua/structs.md
index 79c6d19ff..a17c84677 100644
--- a/docs/lua/structs.md
+++ b/docs/lua/structs.md
@@ -7,10 +7,13 @@
- [BehaviorDialogs](#BehaviorDialogs)
- [BehaviorTrajectories](#BehaviorTrajectories)
- [BehaviorValues](#BehaviorValues)
+- [CCFeatures](#CCFeatures)
- [Camera](#Camera)
- [ChainSegment](#ChainSegment)
- [Character](#Character)
- [Color](#Color)
+- [ColorCombiner](#ColorCombiner)
+- [CombineMode](#CombineMode)
- [Controller](#Controller)
- [CustomLevelInfo](#CustomLevelInfo)
- [DateTime](#DateTime)
@@ -77,6 +80,7 @@
- [RayIntersectionInfo](#RayIntersectionInfo)
- [RomhackCameraSettings](#RomhackCameraSettings)
- [ServerSettings](#ServerSettings)
+- [ShaderProgram](#ShaderProgram)
- [SpawnInfo](#SpawnInfo)
- [SpawnParticlesInfo](#SpawnParticlesInfo)
- [StarPositions](#StarPositions)
@@ -345,6 +349,22 @@
+## [CCFeatures](#CCFeatures)
+
+| Field | Type | Access |
+| ----- | ---- | ------ |
+| used_textures | `Array` <`boolean`> | |
+| num_inputs | `integer` | |
+| do_single | `Array` <`boolean`> | |
+| do_multiply | `Array` <`boolean`> | |
+| do_mix | `Array` <`boolean`> | |
+| color_alpha_same | `Array` <`boolean`> | |
+| do_noise | `boolean` | |
+
+[:arrow_up_small:](#)
+
+
+
## [Camera](#Camera)
| Field | Type | Access |
@@ -679,6 +699,38 @@
+## [ColorCombiner](#ColorCombiner)
+
+| Field | Type | Access |
+| ----- | ---- | ------ |
+| cm | [CombineMode](structs.md#CombineMode) | read-only |
+| prg | [ShaderProgram](structs.md#ShaderProgram) | |
+| shader_input_mapping | `Array` <`integer`> | |
+| shader_input_mapping_as_u64 | `Array` <`integer`> | |
+| shader_commands | `Array` <`integer`> | |
+| shader_commands_as_u64 | `Array` <`integer`> | |
+| hash | `integer` | |
+
+[:arrow_up_small:](#)
+
+
+
+## [CombineMode](#CombineMode)
+
+| Field | Type | Access |
+| ----- | ---- | ------ |
+| rgb1 | `integer` | |
+| alpha1 | `integer` | |
+| rgb2 | `integer` | |
+| alpha2 | `integer` | |
+| all_values | `Array` <`integer`> | |
+| flags | `integer` | |
+| hash | `integer` | |
+
+[:arrow_up_small:](#)
+
+
+
## [Controller](#Controller)
| Field | Type | Access |
@@ -2839,6 +2891,26 @@
+## [ShaderProgram](#ShaderProgram)
+
+| Field | Type | Access |
+| ----- | ---- | ------ |
+| hash | `integer` | |
+| opengl_program_id | `integer` | |
+| num_inputs | `integer` | |
+| used_textures | `Array` <`boolean`> | |
+| num_floats | `integer` | |
+| attrib_locations | `Array` <`integer`> | |
+| uniform_locations | `Array` <`integer`> | |
+| attrib_sizes | `Array` <`integer`> | |
+| num_attribs | `integer` | |
+| used_noise | `boolean` | |
+| used_lightmap | `boolean` | |
+
+[:arrow_up_small:](#)
+
+
+
## [SpawnInfo](#SpawnInfo)
| Field | Type | Access |
diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c
index 43c3c1f0e..2debef69b 100644
--- a/src/game/rendering_graph_node.c
+++ b/src/game/rendering_graph_node.c
@@ -184,7 +184,7 @@ LookAt lookAt;
static struct GraphNodePerspective *sPerspectiveNode = NULL;
static Gfx* sPerspectivePos = NULL;
-static Mtx* sPerspectiveMtx = NULL;
+static Mtx* sPerspectiveMtx = NULL;
static f32 sPerspectiveAspect = 0;
static Vp* sViewport = NULL;
@@ -200,6 +200,8 @@ static struct GraphNodeBackground* sBackgroundNode = NULL;
static struct GraphNodeRoot* sBackgroundNodeRoot = NULL;
static struct GraphNodeCamera* sCameraNode = NULL;
+Mtx gInverseCameraMatrix = { 0 };
+
static struct GrowingArray* sShadowInterp = NULL;
struct ShadowInterp* gShadowInterpCurrent = NULL;
@@ -350,6 +352,7 @@ void patch_mtx_interpolated(f32 delta) {
delta_interpolate_vec3f(focusInterp, sCameraNode->prevFocus, sCameraNode->focus, delta);
mtxf_lookat(camInterp.m, posInterp, focusInterp, sCameraNode->roll);
mtxf_to_mtx(&camInterp, camInterp.m);
+ mtxf_inverse(gInverseCameraMatrix.m, camInterp.m);
}
for (u32 i = 0; i < sMtxTbl->count; i++) {
diff --git a/src/game/rendering_graph_node.h b/src/game/rendering_graph_node.h
index f30ea4a5d..66444816c 100644
--- a/src/game/rendering_graph_node.h
+++ b/src/game/rendering_graph_node.h
@@ -20,6 +20,9 @@ extern struct GraphNodePerspective *gCurGraphNodeCamFrustum;
extern struct GraphNodeCamera *gCurGraphNodeCamera;
extern struct GraphNodeObject *gCurGraphNodeObject;
extern struct GraphNodeHeldObject *gCurGraphNodeHeldObject;
+
+extern Mtx gInverseCameraMatrix;
+
extern u16 gAreaUpdateCounter;
extern struct Object* gCurGraphNodeProcessingObject;
diff --git a/src/game/skybox.c b/src/game/skybox.c
index 424c58ab1..5d73341ff 100644
--- a/src/game/skybox.c
+++ b/src/game/skybox.c
@@ -209,10 +209,10 @@ Vtx *make_skybox_rect(s32 tileRow, s32 tileCol, s8 colorIndex, s32 row, s32 col)
f32 g = gSkyboxColor[1] / 255.0f;
f32 b = gSkyboxColor[2] / 255.0f;
u8 *colors = sSkyboxColors[colorIndex];
- make_vertex(verts, 0, x, y, -1, 0, 0, colors[0] * r, colors[1] * g, colors[2] * b, 255);
- make_vertex(verts, 1, x, y - SKYBOX_TILE_HEIGHT, -1, 0, 31 << 5, colors[0] * r, colors[1] * g, colors[2] * b, 255);
- make_vertex(verts, 2, x + SKYBOX_TILE_WIDTH, y - SKYBOX_TILE_HEIGHT, -1, 31 << 5, 31 << 5, colors[0] * r, colors[1] * g, colors[2] * b, 255);
- make_vertex(verts, 3, x + SKYBOX_TILE_WIDTH, y, -1, 31 << 5, 0, colors[0] * r, colors[1] * g, colors[2] * b, 255);
+ make_vertex(verts, 0, x, y, -2, 0, 0, colors[0] * r, colors[1] * g, colors[2] * b, 255);
+ make_vertex(verts, 1, x, y - SKYBOX_TILE_HEIGHT, -2, 0, 31 << 5, colors[0] * r, colors[1] * g, colors[2] * b, 255);
+ make_vertex(verts, 2, x + SKYBOX_TILE_WIDTH, y - SKYBOX_TILE_HEIGHT, -2, 31 << 5, 31 << 5, colors[0] * r, colors[1] * g, colors[2] * b, 255);
+ make_vertex(verts, 3, x + SKYBOX_TILE_WIDTH, y, -2, 31 << 5, 0, colors[0] * r, colors[1] * g, colors[2] * b, 255);
}
return verts;
}
diff --git a/src/pc/gfx/gfx_cc.h b/src/pc/gfx/gfx_cc.h
index 336a237b5..69d136547 100644
--- a/src/pc/gfx/gfx_cc.h
+++ b/src/pc/gfx/gfx_cc.h
@@ -1,10 +1,11 @@
#ifndef GFX_CC_H
#define GFX_CC_H
+#include
#include
#include
-enum {
+enum ColorCombinerSource {
CC_0,
CC_TEXEL0,
CC_TEXEL1,
@@ -24,7 +25,7 @@ enum {
CC_ENUM_MAX,
};
-enum {
+enum ShaderInput {
SHADER_0,
SHADER_INPUT_1,
SHADER_INPUT_2,
@@ -59,47 +60,57 @@ struct CCFeatures {
bool do_noise;
};
+enum CombineModeFlags {
+ USE_ALPHA = 1 << 0,
+ USE_FOG = 1 << 1,
+ TEXTURE_EDGE = 1 << 2,
+ USE_DITHER = 1 << 3,
+ USE_2CYCLE = 1 << 4,
+ LIGHT_MAP = 1 << 5
+};
+
#pragma pack(1)
struct CombineMode {
union {
struct {
- uint32_t rgb1;
- uint32_t alpha1;
- uint32_t rgb2;
- uint32_t alpha2;
+ u32 rgb1;
+ u32 alpha1;
+ u32 rgb2;
+ u32 alpha2;
};
- uint8_t all_values[16];
+ u8 all_values[16];
};
union {
struct {
- uint8_t use_alpha : 1;
- uint8_t use_fog : 1;
- uint8_t texture_edge : 1;
- uint8_t use_dither : 1;
- uint8_t use_2cycle : 1;
- uint8_t light_map : 1;
+ u8 use_alpha : 1;
+ u8 use_fog : 1;
+ u8 texture_edge : 1;
+ u8 use_dither : 1;
+ u8 use_2cycle : 1;
+ u8 light_map : 1;
};
- uint32_t flags;
+ u32 flags;
};
- uint64_t hash;
+ s64 hash;
};
#pragma pack()
#define SHADER_CMD_LENGTH 16
#define CC_MAX_SHADERS 64
+#define CC_MAX_INPUTS 8
struct ColorCombiner {
struct CombineMode cm;
struct ShaderProgram *prg;
union {
- uint8_t shader_input_mapping[16];
- uint64_t shader_input_mapping_as_u64[8];
+ u8 shader_input_mapping[16];
+ u64 shader_input_mapping_as_u64[8];
};
union {
- uint8_t shader_commands[16];
- uint64_t shader_commands_as_u64[8];
+ u8 shader_commands[16];
+ u64 shader_commands_as_u64[8];
};
- uint64_t hash;
+ u64 hash;
};
#ifdef __cplusplus
diff --git a/src/pc/gfx/gfx_direct3d11.cpp b/src/pc/gfx/gfx_direct3d11.cpp
index 69796c45e..619b90292 100644
--- a/src/pc/gfx/gfx_direct3d11.cpp
+++ b/src/pc/gfx/gfx_direct3d11.cpp
@@ -77,12 +77,12 @@ struct ShaderProgramD3D11 {
static struct {
HMODULE d3d11_module;
PFN_D3D11_CREATE_DEVICE D3D11CreateDevice;
-
+
HMODULE d3dcompiler_module;
pD3DCompile D3DCompile;
-
+
D3D_FEATURE_LEVEL feature_level;
-
+
ComPtr device;
ComPtr swap_chain;
ComPtr context;
@@ -324,6 +324,9 @@ static void gfx_d3d11_load_shader(struct ShaderProgram *new_prg) {
d3d.shader_program = (struct ShaderProgramD3D11 *)new_prg;
}
+static void gfx_d3d11_remove_shaders(void) {
+}
+
static struct ShaderProgram *gfx_d3d11_create_and_load_new_shader(struct ColorCombiner* cc) {
CCFeatures cc_features = { 0 };
gfx_cc_get_features(cc, &cc_features);
@@ -425,6 +428,11 @@ static struct ShaderProgram *gfx_d3d11_lookup_shader(struct ColorCombiner* cc) {
return nullptr;
}
+static struct ShaderProgram *gfx_d3d11_lookup_shader_using_index(u8 shaderIndex) {
+ if (shaderIndex >= d3d.shader_program_pool_size) return nullptr;
+ return (struct ShaderProgram *)&d3d.shader_program_pool[i];
+}
+
static void gfx_d3d11_shader_get_info(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) {
struct ShaderProgramD3D11 *p = (struct ShaderProgramD3D11 *)prg;
@@ -719,8 +727,10 @@ struct GfxRenderingAPI gfx_direct3d11_api = {
gfx_d3d11_z_is_from_0_to_1,
gfx_d3d11_unload_shader,
gfx_d3d11_load_shader,
+ gfx_d3d11_remove_shaders,
gfx_d3d11_create_and_load_new_shader,
gfx_d3d11_lookup_shader,
+ gfx_d3d11_lookup_shader_using_index,
gfx_d3d11_shader_get_info,
gfx_d3d11_new_texture,
gfx_d3d11_select_texture,
diff --git a/src/pc/gfx/gfx_dummy.c b/src/pc/gfx/gfx_dummy.c
index 135ca2e3d..0d9cf46e8 100644
--- a/src/pc/gfx/gfx_dummy.c
+++ b/src/pc/gfx/gfx_dummy.c
@@ -129,6 +129,9 @@ static void gfx_dummy_renderer_unload_shader(UNUSED struct ShaderProgram *old_pr
static void gfx_dummy_renderer_load_shader(UNUSED struct ShaderProgram *new_prg) {
}
+static void gfx_dummy_renderer_remove_shaders(void) {
+}
+
static struct ShaderProgram *gfx_dummy_renderer_create_and_load_new_shader(UNUSED struct ColorCombiner* cc) {
return NULL;
}
@@ -137,6 +140,10 @@ static struct ShaderProgram *gfx_dummy_renderer_lookup_shader(UNUSED struct Colo
return NULL;
}
+static struct ShaderProgram *gfx_dummy_renderer_lookup_shader_using_index(u8 shaderIndex) {
+ return NULL;
+}
+
static void gfx_dummy_renderer_shader_get_info(UNUSED struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) {
*num_inputs = 0;
used_textures[0] = false;
@@ -223,8 +230,10 @@ struct GfxRenderingAPI gfx_dummy_renderer_api = {
gfx_dummy_renderer_z_is_from_0_to_1,
gfx_dummy_renderer_unload_shader,
gfx_dummy_renderer_load_shader,
+ gfx_dummy_renderer_remove_shaders,
gfx_dummy_renderer_create_and_load_new_shader,
gfx_dummy_renderer_lookup_shader,
+ gfx_dummy_renderer_lookup_shader_using_index,
gfx_dummy_renderer_shader_get_info,
gfx_dummy_renderer_new_texture,
gfx_dummy_renderer_select_texture,
diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c
index c33cb8b5b..b8a5c986d 100644
--- a/src/pc/gfx/gfx_opengl.c
+++ b/src/pc/gfx/gfx_opengl.c
@@ -40,23 +40,12 @@
#include "gfx_cc.h"
#include "gfx_rendering_api.h"
#include "gfx_pc.h"
+#include "gfx_opengl.h"
+#include "pc/lua/smlua.h"
+#include "game/rendering_graph_node.h"
#define TEX_CACHE_STEP 512
-struct ShaderProgram {
- uint64_t hash;
- GLuint opengl_program_id;
- uint8_t num_inputs;
- bool used_textures[2];
- uint8_t num_floats;
- GLint attrib_locations[7];
- GLint uniform_locations[7];
- uint8_t attrib_sizes[7];
- uint8_t num_attribs;
- bool used_noise;
- bool used_lightmap;
-};
-
struct GLTexture {
GLuint gltex;
GLfloat size[2];
@@ -66,6 +55,7 @@ struct GLTexture {
static struct ShaderProgram shader_program_pool[CC_MAX_SHADERS];
static uint8_t shader_program_pool_size = 0;
static uint8_t shader_program_pool_index = 0;
+
static GLuint opengl_vbo;
static GLuint opengl_vao;
@@ -95,13 +85,16 @@ static void gfx_opengl_vertex_array_set_attribs(struct ShaderProgram *prg) {
}
static inline void gfx_opengl_set_shader_uniforms(struct ShaderProgram *prg) {
- if (prg->used_noise) { glUniform1f(prg->uniform_locations[4], (float)frame_count); }
- if (prg->used_lightmap) { glUniform3f(prg->uniform_locations[5], gVertexColor[0] / 255.0f, gVertexColor[1] / 255.0f, gVertexColor[2] / 255.0f); }
+ glUniform1f(prg->uniform_locations[4], (float)frame_count);
+ glUniform3f(prg->uniform_locations[5], gVertexColor[0] / 255.0f, gVertexColor[1] / 255.0f, gVertexColor[2] / 255.0f);
glUniform1i(prg->uniform_locations[6], configFiltering);
+ glUniformMatrix4fv(prg->uniform_locations[7], 1, GL_FALSE, (const GLfloat *)rsp.modelview_matrix_stack[rsp.modelview_matrix_stack_size - 1]);
+ glUniformMatrix4fv(prg->uniform_locations[8], 1, GL_FALSE, (const GLfloat *)rsp.P_matrix);
+ glUniformMatrix4fv(prg->uniform_locations[9], 1, GL_FALSE, (const GLfloat *)gInverseCameraMatrix.m);
}
static inline void gfx_opengl_set_texture_uniforms(struct ShaderProgram *prg, const int tile) {
- if (prg->used_textures[tile] && opengl_tex[tile]) {
+ if (opengl_tex[tile]) {
glUniform2f(prg->uniform_locations[tile*2 + 0], opengl_tex[tile]->size[0], opengl_tex[tile]->size[1]);
glUniform1i(prg->uniform_locations[tile*2 + 1], opengl_tex[tile]->filter);
}
@@ -127,6 +120,16 @@ static void gfx_opengl_load_shader(struct ShaderProgram *new_prg) {
gfx_opengl_set_texture_uniforms(new_prg, 1);
}
+static void gfx_opengl_remove_shaders(void) {
+ for (int i = 0; i < CC_MAX_SHADERS; i++) {
+ gfx_opengl_unload_shader(&shader_program_pool[i]);
+ memset(&shader_program_pool[i], 0, sizeof(shader_program_pool[i]));
+ }
+
+ shader_program_pool_index = 0;
+ shader_program_pool_size = 0;
+}
+
static void append_str(char *buf, size_t *len, const char *str) {
while (*str != '\0') buf[(*len)++] = *str++;
}
@@ -136,7 +139,7 @@ static void append_line(char *buf, size_t *len, const char *str) {
buf[(*len)++] = '\n';
}
-static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_alpha, bool inputs_have_alpha, bool hint_single_element) {
+static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_alpha, bool hint_single_element) {
if (!only_alpha) {
switch (item) {
case SHADER_0:
@@ -144,21 +147,21 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_
case SHADER_1:
return with_alpha ? "vec4(1.0, 1.0, 1.0, 1.0)" : "vec3(1.0, 1.0, 1.0)";
case SHADER_INPUT_1:
- return with_alpha || !inputs_have_alpha ? "vInput1" : "vInput1.rgb";
+ return with_alpha ? "vInput1" : "vInput1.rgb";
case SHADER_INPUT_2:
- return with_alpha || !inputs_have_alpha ? "vInput2" : "vInput2.rgb";
+ return with_alpha ? "vInput2" : "vInput2.rgb";
case SHADER_INPUT_3:
- return with_alpha || !inputs_have_alpha ? "vInput3" : "vInput3.rgb";
+ return with_alpha ? "vInput3" : "vInput3.rgb";
case SHADER_INPUT_4:
- return with_alpha || !inputs_have_alpha ? "vInput4" : "vInput4.rgb";
+ return with_alpha ? "vInput4" : "vInput4.rgb";
case SHADER_INPUT_5:
- return with_alpha || !inputs_have_alpha ? "vInput5" : "vInput5.rgb";
+ return with_alpha ? "vInput5" : "vInput5.rgb";
case SHADER_INPUT_6:
- return with_alpha || !inputs_have_alpha ? "vInput6" : "vInput6.rgb";
+ return with_alpha ? "vInput6" : "vInput6.rgb";
case SHADER_INPUT_7:
- return with_alpha || !inputs_have_alpha ? "vInput7" : "vInput7.rgb";
+ return with_alpha ? "vInput7" : "vInput7.rgb";
case SHADER_INPUT_8:
- return with_alpha || !inputs_have_alpha ? "vInput8" : "vInput8.rgb";
+ return with_alpha ? "vInput8" : "vInput8.rgb";
case SHADER_TEXEL0:
return with_alpha ? "texVal0" : "texVal0.rgb";
case SHADER_TEXEL0A:
@@ -218,30 +221,30 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_
return "unknown";
}
-static void append_formula(char *buf, size_t *len, uint8_t* cmd, bool do_single, bool do_multiply, bool do_mix, bool with_alpha, bool only_alpha, bool opt_alpha) {
+static void append_formula(char *buf, size_t *len, uint8_t* cmd, bool do_single, bool do_multiply, bool do_mix, bool with_alpha, bool only_alpha) {
if (do_single) {
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 3], with_alpha, only_alpha, opt_alpha, false));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 3], with_alpha, only_alpha, false));
} else if (do_multiply) {
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, false));
append_str(buf, len, " * ");
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, true));
} else if (do_mix) {
append_str(buf, len, "mix(");
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 1], with_alpha, only_alpha, opt_alpha, false));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 1], with_alpha, only_alpha, false));
append_str(buf, len, ", ");
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, false));
append_str(buf, len, ", ");
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, true));
append_str(buf, len, ")");
} else {
append_str(buf, len, "(");
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, false));
append_str(buf, len, " - ");
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 1], with_alpha, only_alpha, opt_alpha, false));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 1], with_alpha, only_alpha, false));
append_str(buf, len, ") * ");
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, true));
append_str(buf, len, " + ");
- append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 3], with_alpha, only_alpha, opt_alpha, false));
+ append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 3], with_alpha, only_alpha, false));
}
}
@@ -265,48 +268,45 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
char fs_buf[2048];
size_t vs_len = 0;
size_t fs_len = 0;
- size_t num_floats = 4;
+ size_t num_floats = 0;
// Vertex shader
#ifdef USE_GLES
- append_line(vs_buf, &vs_len, "#version 100");
+ append_line(vs_buf, &vs_len, "#version 300 es");
#else
- append_line(vs_buf, &vs_len, "#version 120");
+ append_line(vs_buf, &vs_len, "#version 150");
#endif
- append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;");
- if (ccf.used_textures[0] || ccf.used_textures[1]) {
- append_line(vs_buf, &vs_len, "attribute vec2 aTexCoord;");
- append_line(vs_buf, &vs_len, "varying vec2 vTexCoord;");
- num_floats += 2;
- }
- if (opt_fog) {
- append_line(vs_buf, &vs_len, "attribute vec4 aFog;");
- append_line(vs_buf, &vs_len, "varying vec4 vFog;");
+ append_line(vs_buf, &vs_len, "in vec4 aVtxPos;");
+ num_floats += 4;
+ append_line(vs_buf, &vs_len, "in vec2 aTexCoord;");
+ append_line(vs_buf, &vs_len, "out vec2 vTexCoord;");
+ num_floats += 2;
+ append_line(vs_buf, &vs_len, "in vec4 aFog;");
+ append_line(vs_buf, &vs_len, "out vec4 vFog;");
+ num_floats += 4;
+ append_line(vs_buf, &vs_len, "in vec2 aLightMap;");
+ append_line(vs_buf, &vs_len, "out vec2 vLightMap;");
+ num_floats += 2;
+ for (int i = 0; i < CC_MAX_INPUTS; i++) {
+ vs_len += sprintf(vs_buf + vs_len, "in vec4 aInput%d;\n", i + 1);
+ vs_len += sprintf(vs_buf + vs_len, "out vec4 vInput%d;\n", i + 1);
num_floats += 4;
}
- if (opt_light_map) {
- append_line(vs_buf, &vs_len, "attribute vec2 aLightMap;");
- append_line(vs_buf, &vs_len, "varying vec2 vLightMap;");
- num_floats += 2;
- }
- for (int i = 0; i < ccf.num_inputs; i++) {
- vs_len += sprintf(vs_buf + vs_len, "attribute vec%d aInput%d;\n", opt_alpha ? 4 : 3, i + 1);
- vs_len += sprintf(vs_buf + vs_len, "varying vec%d vInput%d;\n", opt_alpha ? 4 : 3, i + 1);
- num_floats += opt_alpha ? 4 : 3;
- }
+ append_line(vs_buf, &vs_len, "in vec3 aNormal;");
+ append_line(vs_buf, &vs_len, "out vec3 vNormal;");
+ num_floats += 3;
+ append_line(vs_buf, &vs_len, "in vec3 aBarycentric;");
+ append_line(vs_buf, &vs_len, "out vec3 vBarycentric;");
+ num_floats += 3;
append_line(vs_buf, &vs_len, "void main() {");
- if (ccf.used_textures[0] || ccf.used_textures[1]) {
- append_line(vs_buf, &vs_len, "vTexCoord = aTexCoord;");
- }
- if (opt_fog) {
- append_line(vs_buf, &vs_len, "vFog = aFog;");
- }
- if (opt_light_map) {
- append_line(vs_buf, &vs_len, "vLightMap = aLightMap;");
- }
- for (int i = 0; i < ccf.num_inputs; i++) {
+ append_line(vs_buf, &vs_len, "vTexCoord = aTexCoord;");
+ append_line(vs_buf, &vs_len, "vFog = aFog;");
+ append_line(vs_buf, &vs_len, "vLightMap = aLightMap;");
+ for (int i = 0; i < CC_MAX_INPUTS; i++) {
vs_len += sprintf(vs_buf + vs_len, "vInput%d = aInput%d;\n", i + 1, i + 1);
}
+ append_line(vs_buf, &vs_len, "vNormal = aNormal;");
+ append_line(vs_buf, &vs_len, "vBarycentric = aBarycentric;");
append_line(vs_buf, &vs_len, "gl_Position = aVtxPos;");
append_line(vs_buf, &vs_len, "}");
@@ -315,20 +315,16 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(fs_buf, &fs_len, "#version 100");
append_line(fs_buf, &fs_len, "precision mediump float;");
#else
- append_line(fs_buf, &fs_len, "#version 120");
+ append_line(fs_buf, &fs_len, "#version 150");
#endif
- if (ccf.used_textures[0] || ccf.used_textures[1]) {
- append_line(fs_buf, &fs_len, "varying vec2 vTexCoord;");
- }
- if (opt_fog) {
- append_line(fs_buf, &fs_len, "varying vec4 vFog;");
- }
- if (opt_light_map) {
- append_line(fs_buf, &fs_len, "varying vec2 vLightMap;");
- }
- for (int i = 0; i < ccf.num_inputs; i++) {
- fs_len += sprintf(fs_buf + fs_len, "varying vec%d vInput%d;\n", opt_alpha ? 4 : 3, i + 1);
+ append_line(fs_buf, &fs_len, "out vec4 fragColor;");
+
+ append_line(fs_buf, &fs_len, "in vec2 vTexCoord;");
+ append_line(fs_buf, &fs_len, "in vec4 vFog;");
+ append_line(fs_buf, &fs_len, "in vec2 vLightMap;");
+ for (int i = 0; i < CC_MAX_INPUTS; i++) {
+ fs_len += sprintf(fs_buf + fs_len, "in vec4 vInput%d;\n", i + 1);
}
if (ccf.used_textures[0]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;");
@@ -345,7 +341,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
// Original author: ArthurCarvalho
// Modified GLSL implementation by twinaphex, mupen64plus-libretro project.
if (ccf.used_textures[0] || ccf.used_textures[1]) {
- append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)");
+ append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture(tex, texCoord - (off)/texSize)");
append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {");
append_line(fs_buf, &fs_len, " vec2 offset = fract(texCoord*texSize - vec2(0.5));");
append_line(fs_buf, &fs_len, " offset -= step(1.0, offset.x + offset.y);");
@@ -354,11 +350,11 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(fs_buf, &fs_len, " vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)));");
append_line(fs_buf, &fs_len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);");
append_line(fs_buf, &fs_len, "}");
- append_line(fs_buf, &fs_len, "vec4 sampleTex(in sampler2D tex, in vec2 uv, in vec2 texSize, in bool dofilter, in int filter) {");
- append_line(fs_buf, &fs_len, " if (dofilter && filter == 2)");
+ append_line(fs_buf, &fs_len, "vec4 sampleTex(in sampler2D tex, in vec2 uv, in vec2 texSize, in bool dofilter, in int filterType) {");
+ append_line(fs_buf, &fs_len, " if (dofilter && filterType == 2)");
append_line(fs_buf, &fs_len, " return filter3point(tex, uv, texSize);");
append_line(fs_buf, &fs_len, " else");
- append_line(fs_buf, &fs_len, " return texture2D(tex, uv);");
+ append_line(fs_buf, &fs_len, " return texture(tex, uv);");
append_line(fs_buf, &fs_len, "}");
}
@@ -401,12 +397,12 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
u8* cmd = &cc->shader_commands[i * 8];
if (!ccf.color_alpha_same[i] && opt_alpha) {
append_str(fs_buf, &fs_len, "vec4(");
- append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+0], ccf.do_multiply[i*2+0], ccf.do_mix[i*2+0], false, false, true);
+ append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+0], ccf.do_multiply[i*2+0], ccf.do_mix[i*2+0], false, false);
append_str(fs_buf, &fs_len, ", ");
- append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+1], ccf.do_multiply[i*2+1], ccf.do_mix[i*2+1], true, true, true);
+ append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+1], ccf.do_multiply[i*2+1], ccf.do_mix[i*2+1], true, true);
append_str(fs_buf, &fs_len, ")");
} else {
- append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+0], ccf.do_multiply[i*2+0], ccf.do_mix[i*2+0], opt_alpha, false, opt_alpha);
+ append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+0], ccf.do_multiply[i*2+0], ccf.do_mix[i*2+0], opt_alpha, false);
}
append_line(fs_buf, &fs_len, ";");
@@ -434,9 +430,9 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
}
if (opt_alpha) {
- append_line(fs_buf, &fs_len, "gl_FragColor = texel;");
+ append_line(fs_buf, &fs_len, "fragColor = texel;");
} else {
- append_line(fs_buf, &fs_len, "gl_FragColor = vec4(texel, 1.0);");
+ append_line(fs_buf, &fs_len, "fragColor = vec4(texel, 1.0);");
}
append_line(fs_buf, &fs_len, "}");
@@ -449,8 +445,19 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
puts(fs_buf);
puts("End");*/
- const GLchar *sources[2] = { vs_buf, fs_buf };
- const GLint lengths[2] = { vs_len, fs_len };
+ const char* vertexShader = vs_buf;
+ bool usingCustomVertexShader = false;
+ const char* fragmentShader = fs_buf;
+ bool usingCustomFragmentShader = false;
+
+ smlua_call_event_hooks(HOOK_ON_VERTEX_SHADER_CREATE, cc, shader_program_pool_index, &vertexShader);
+ smlua_call_event_hooks(HOOK_ON_FRAGMENT_SHADER_CREATE, cc, shader_program_pool_index, &fragmentShader);
+
+ if (strcmp(vertexShader, vs_buf) != 0) usingCustomVertexShader = true;
+ if (strcmp(fragmentShader, fs_buf) != 0) usingCustomFragmentShader = true;
+
+ const GLchar *sources[2] = { vertexShader, fragmentShader };
+ GLint lengths[2] = { strlen(vertexShader), strlen(fragmentShader) };
GLint success;
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
@@ -461,10 +468,26 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
GLint max_length = 0;
glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &max_length);
char error_log[1024];
- fprintf(stderr, "Vertex shader compilation failed\n");
glGetShaderInfoLog(vertex_shader, max_length, &max_length, &error_log[0]);
- fprintf(stderr, "%s\n", &error_log[0]);
- sys_fatal("vertex shader compilation failed (see terminal)");
+ if (!usingCustomVertexShader) {
+ fprintf(stderr, "Vertex shader compilation failed\n");
+ fprintf(stderr, "%s\n", &error_log[0]);
+ sys_fatal("vertex shader compilation failed (see terminal)");
+ } else {
+ LOG_LUA_LINE("Vertex Shader: %s", error_log);
+ }
+ usingCustomVertexShader = false;
+ sources[0] = vs_buf;
+ lengths[0] = vs_len;
+ glShaderSource(vertex_shader, 1, &sources[0], &lengths[0]);
+ glCompileShader(vertex_shader);
+ glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ fprintf(stderr, "Vertex shader compilation failed\n");
+ glGetShaderInfoLog(vertex_shader, max_length, &max_length, &error_log[0]);
+ fprintf(stderr, "%s\n", &error_log[0]);
+ sys_fatal("vertex shader compilation failed (see terminal)");
+ }
}
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
@@ -475,10 +498,26 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
GLint max_length = 0;
glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &max_length);
char error_log[1024];
- fprintf(stderr, "Fragment shader compilation failed\n");
glGetShaderInfoLog(fragment_shader, max_length, &max_length, &error_log[0]);
- fprintf(stderr, "%s\n", &error_log[0]);
- sys_fatal("fragment shader compilation failed (see terminal)");
+ if (!usingCustomFragmentShader) {
+ fprintf(stderr, "Fragment shader compilation failed\n");
+ fprintf(stderr, "%s\n", &error_log[0]);
+ sys_fatal("fragment shader compilation failed (see terminal)");
+ } else {
+ LOG_LUA_LINE("Fragment Shader: %s", &error_log[0]);
+ }
+ usingCustomFragmentShader = false;
+ sources[1] = fs_buf;
+ lengths[1] = fs_len;
+ glShaderSource(fragment_shader, 1, &sources[1], &lengths[1]);
+ glCompileShader(fragment_shader);
+ glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ fprintf(stderr, "Fragment shader compilation failed\n");
+ glGetShaderInfoLog(fragment_shader, max_length, &max_length, &error_log[0]);
+ fprintf(stderr, "%s\n", &error_log[0]);
+ sys_fatal("fragment shader compilation failed (see terminal)");
+ }
}
GLuint shader_program = glCreateProgram();
@@ -496,31 +535,33 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
prg->attrib_sizes[cnt] = 4;
++cnt;
- if (ccf.used_textures[0] || ccf.used_textures[1]) {
- prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aTexCoord");
- prg->attrib_sizes[cnt] = 2;
- ++cnt;
- }
+ prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aTexCoord");
+ prg->attrib_sizes[cnt] = 2;
+ ++cnt;
- if (opt_fog) {
- prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aFog");
+ prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aFog");
+ prg->attrib_sizes[cnt] = 4;
+ ++cnt;
+
+ prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aLightMap");
+ prg->attrib_sizes[cnt] = 2;
+ ++cnt;
+
+ for (int i = 0; i < CC_MAX_INPUTS; i++) {
+ char name[16];
+ sprintf(name, "aInput%d", i + 1);
+ prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, name);
prg->attrib_sizes[cnt] = 4;
++cnt;
}
- if (opt_light_map) {
- prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aLightMap");
- prg->attrib_sizes[cnt] = 2;
- ++cnt;
- }
+ prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aNormal");
+ prg->attrib_sizes[cnt] = 3;
+ ++cnt;
- for (int i = 0; i < ccf.num_inputs; i++) {
- char name[16];
- sprintf(name, "aInput%d", i + 1);
- prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, name);
- prg->attrib_sizes[cnt] = opt_alpha ? 4 : 3;
- ++cnt;
- }
+ prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aBarycentric");
+ prg->attrib_sizes[cnt] = 3;
+ ++cnt;
prg->hash = cc->hash;
prg->opengl_program_id = shader_program;
@@ -532,34 +573,32 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
gfx_opengl_load_shader(prg);
- if (ccf.used_textures[0]) {
- GLint sampler_location = glGetUniformLocation(shader_program, "uTex0");
- prg->uniform_locations[0] = glGetUniformLocation(shader_program, "uTex0Size");
- prg->uniform_locations[1] = glGetUniformLocation(shader_program, "uTex0Filter");
- glUniform1i(sampler_location, 0);
- }
- if (ccf.used_textures[1]) {
- GLint sampler_location = glGetUniformLocation(shader_program, "uTex1");
- prg->uniform_locations[2] = glGetUniformLocation(shader_program, "uTex1Size");
- prg->uniform_locations[3] = glGetUniformLocation(shader_program, "uTex1Filter");
- glUniform1i(sampler_location, 1);
- }
+ GLint sampler_location = glGetUniformLocation(shader_program, "uTex0");
+ prg->uniform_locations[0] = glGetUniformLocation(shader_program, "uTex0Size");
+ prg->uniform_locations[1] = glGetUniformLocation(shader_program, "uTex0Filter");
+ glUniform1i(sampler_location, 0);
+ sampler_location = glGetUniformLocation(shader_program, "uTex1");
+ prg->uniform_locations[2] = glGetUniformLocation(shader_program, "uTex1Size");
+ prg->uniform_locations[3] = glGetUniformLocation(shader_program, "uTex1Filter");
+ glUniform1i(sampler_location, 1);
+
+ prg->uniform_locations[4] = glGetUniformLocation(shader_program, "uFrameCount");
if ((opt_alpha && opt_dither) || ccf.do_noise) {
- prg->uniform_locations[4] = glGetUniformLocation(shader_program, "uFrameCount");
prg->used_noise = true;
} else {
prg->used_noise = false;
}
- if (opt_light_map) {
- prg->uniform_locations[5] = glGetUniformLocation(shader_program, "uLightmapColor");
- prg->used_lightmap = true;
- } else {
- prg->used_lightmap = false;
- }
+ prg->uniform_locations[5] = glGetUniformLocation(shader_program, "uLightmapColor");
+ prg->used_lightmap = opt_light_map;
+
+ // hah
prg->uniform_locations[6] = glGetUniformLocation(shader_program, "uFilter");
+ prg->uniform_locations[7] = glGetUniformLocation(shader_program, "uModelViewMatrix");
+ prg->uniform_locations[8] = glGetUniformLocation(shader_program, "uProjectionMatrix");
+ prg->uniform_locations[9] = glGetUniformLocation(shader_program, "uInverseViewMatrix");
return prg;
}
@@ -573,6 +612,11 @@ static struct ShaderProgram *gfx_opengl_lookup_shader(struct ColorCombiner* cc)
return NULL;
}
+static struct ShaderProgram* gfx_opengl_lookup_shader_using_index(uint8_t shaderIndex) {
+ if (shaderIndex >= shader_program_pool_size) return NULL;
+ return &shader_program_pool[shaderIndex];
+}
+
static void gfx_opengl_shader_get_info(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) {
*num_inputs = prg->num_inputs;
used_textures[0] = prg->used_textures[0];
@@ -744,8 +788,10 @@ struct GfxRenderingAPI gfx_opengl_api = {
gfx_opengl_z_is_from_0_to_1,
gfx_opengl_unload_shader,
gfx_opengl_load_shader,
+ gfx_opengl_remove_shaders,
gfx_opengl_create_and_load_new_shader,
gfx_opengl_lookup_shader,
+ gfx_opengl_lookup_shader_using_index,
gfx_opengl_shader_get_info,
gfx_opengl_new_texture,
gfx_opengl_select_texture,
diff --git a/src/pc/gfx/gfx_opengl.h b/src/pc/gfx/gfx_opengl.h
index 95be897a2..77f702cbb 100644
--- a/src/pc/gfx/gfx_opengl.h
+++ b/src/pc/gfx/gfx_opengl.h
@@ -3,6 +3,24 @@
#include "gfx_rendering_api.h"
+#define MAX_SHADER_TEXTURES 2
+#define MAX_SHADER_ATTRIBUTES 24
+#define MAX_SHADER_UNIFORMS 24
+
+struct ShaderProgram {
+ u64 hash;
+ u32 opengl_program_id;
+ u8 num_inputs;
+ bool used_textures[MAX_SHADER_TEXTURES];
+ u8 num_floats;
+ u32 attrib_locations[MAX_SHADER_ATTRIBUTES];
+ u32 uniform_locations[MAX_SHADER_UNIFORMS];
+ u8 attrib_sizes[MAX_SHADER_ATTRIBUTES];
+ u8 num_attribs;
+ bool used_noise;
+ bool used_lightmap;
+};
+
extern struct GfxRenderingAPI gfx_opengl_api;
#endif
diff --git a/src/pc/gfx/gfx_opengl_legacy.c b/src/pc/gfx/gfx_opengl_legacy.c
index b3153af7f..4172db8b7 100644
--- a/src/pc/gfx/gfx_opengl_legacy.c
+++ b/src/pc/gfx/gfx_opengl_legacy.c
@@ -246,6 +246,9 @@ static void gfx_opengl_load_shader(struct ShaderProgram *new_prg) {
cur_shader->enabled = false;
}
+static void gfx_opengl_remove_shaders(void) {
+}
+
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorCombiner* cc) {
struct ShaderProgram *prg = &shader_program_pool[shader_program_pool_size++];
@@ -292,6 +295,11 @@ static struct ShaderProgram *gfx_opengl_lookup_shader(struct ColorCombiner* cc)
return NULL;
}
+static struct ShaderProgram *gfx_opengl_lookup_shader_using_index(u8 shaderIndex) {
+ if (shaderIndex >= shader_program_pool_size) return NULL;
+ return &shader_program_pool[shaderIndex];
+}
+
static void gfx_opengl_shader_get_info(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) {
*num_inputs = prg->num_inputs;
used_textures[0] = prg->texture_used[0];
@@ -568,8 +576,10 @@ struct GfxRenderingAPI gfx_opengl_api = {
gfx_opengl_z_is_from_0_to_1,
gfx_opengl_unload_shader,
gfx_opengl_load_shader,
+ gfx_opengl_remove_shaders,
gfx_opengl_create_and_load_new_shader,
gfx_opengl_lookup_shader,
+ gfx_opengl_lookup_shader_using_index,
gfx_opengl_shader_get_info,
gfx_opengl_new_texture,
gfx_opengl_select_texture,
diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c
index 1184eaba1..150552485 100644
--- a/src/pc/gfx/gfx_pc.c
+++ b/src/pc/gfx/gfx_pc.c
@@ -53,29 +53,7 @@ static struct ColorCombiner color_combiner_pool[CC_MAX_SHADERS] = { 0 };
static uint8_t color_combiner_pool_size = 0;
static uint8_t color_combiner_pool_index = 0;
-static struct RSP {
- ALIGNED16 Mat4 MP_matrix;
- ALIGNED16 Mat4 P_matrix;
- ALIGNED16 Mat4 modelview_matrix_stack[MAX_MATRIX_STACK_SIZE];
- uint32_t modelview_matrix_stack_size;
-
- uint32_t geometry_mode;
- int16_t fog_mul, fog_offset;
- int16_t fresnel_scale, fresnel_offset;
-
- struct {
- // U0.16
- uint16_t s, t;
- } texture_scaling_factor;
-
- bool lights_changed;
- uint8_t current_num_lights; // includes ambient light
- Vec3f current_lights_coeffs[MAX_LIGHTS];
- Vec3f current_lookat_coeffs[2]; // lookat_x, lookat_y
- Light_t current_lights[MAX_LIGHTS + 1];
-
- struct GfxVertex loaded_vertices[MAX_VERTICES + 4];
-} rsp;
+struct RSP rsp = { 0 };
static struct RDP {
const uint8_t *palette;
@@ -108,7 +86,7 @@ struct GfxDimensions gfx_current_dimensions = { 0 };
static bool dropped_frame = false;
-static float buf_vbo[MAX_BUFFERED * (26 * 3)] = { 0.0f }; // 3 vertices in a triangle and 26 floats per vtx
+static float buf_vbo[MAX_BUFFERED * ((18 + (CC_MAX_INPUTS * 4)) * 3)] = { 0.0f }; // 3 vertices in a triangle and 18 floats per verticies plus the 4 floats per input for verticies
static size_t buf_vbo_len = 0;
static size_t buf_vbo_num_tris = 0;
@@ -126,8 +104,8 @@ Color gFogColor = { 0xFF, 0xFF, 0xFF };
f32 gFogIntensity = 1;
// need inverse camera matrix to compute world space for lighting engine
-static Mat4 sInverseCameraMatrix;
-static bool sHasInverseCameraMatrix = false;
+Mat4 sInverseCameraMatrix;
+bool sHasInverseCameraMatrix = false;
// 4x4 pink-black checkerboard texture to indicate missing textures
#define MISSING_W 4
@@ -1156,6 +1134,7 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t
bool z_is_from_0_to_1 = gfx_rapi->z_is_from_0_to_1();
for (int32_t i = 0; i < 3; i++) {
+ // send triangle data
float z = v_arr[i]->z, w = v_arr[i]->w;
if (z_is_from_0_to_1) {
z = (z + w) / 2.0f;
@@ -1165,95 +1144,112 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t
buf_vbo[buf_vbo_len++] = z;
buf_vbo[buf_vbo_len++] = w;
- if (use_texture) {
- float u = (v_arr[i]->u - rdp.texture_tile.uls * 8) / 32.0f;
- float v = (v_arr[i]->v - rdp.texture_tile.ult * 8) / 32.0f;
- if ((rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT) {
- // Linear filter adds 0.5f to the coordinates (why?)
- u += 0.5f;
- v += 0.5f;
- }
- buf_vbo[buf_vbo_len++] = u / tex_width;
- buf_vbo[buf_vbo_len++] = v / tex_height;
+ // send texture info
+ float u = (v_arr[i]->u - rdp.texture_tile.uls * 8) / 32.0f;
+ float v = (v_arr[i]->v - rdp.texture_tile.ult * 8) / 32.0f;
+ if ((rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT) {
+ // Linear filter adds 0.5f to the coordinates (why?)
+ u += 0.5f;
+ v += 0.5f;
}
+ buf_vbo[buf_vbo_len++] = u / tex_width;
+ buf_vbo[buf_vbo_len++] = v / tex_height;
- if (cm->use_fog) {
- f32 r = gFogColor[0] / 255.0f;
- f32 g = gFogColor[1] / 255.0f;
- f32 b = gFogColor[2] / 255.0f;
- buf_vbo[buf_vbo_len++] = (rdp.fog_color.r / 255.0f) * r;
- buf_vbo[buf_vbo_len++] = (rdp.fog_color.g / 255.0f) * g;
- buf_vbo[buf_vbo_len++] = (rdp.fog_color.b / 255.0f) * b;
- buf_vbo[buf_vbo_len++] = v_arr[i]->fog_z / 255.0f; // fog factor (not alpha)
- }
+ // send fog data
+ f32 r = gFogColor[0] / 255.0f;
+ f32 g = gFogColor[1] / 255.0f;
+ f32 b = gFogColor[2] / 255.0f;
+ buf_vbo[buf_vbo_len++] = (rdp.fog_color.r / 255.0f) * r;
+ buf_vbo[buf_vbo_len++] = (rdp.fog_color.g / 255.0f) * g;
+ buf_vbo[buf_vbo_len++] = (rdp.fog_color.b / 255.0f) * b;
+ buf_vbo[buf_vbo_len++] = v_arr[i]->fog_z / 255.0f; // fog factor (not alpha)
- if (cm->light_map) {
- struct RGBA* col = &v_arr[i]->color;
- buf_vbo[buf_vbo_len++] = ( (((uint16_t)col->g) << 8) | ((uint16_t)col->r) ) / 65535.0f;
- buf_vbo[buf_vbo_len++] = 1.0f - (( (((uint16_t)col->a) << 8) | ((uint16_t)col->b) ) / 65535.0f);
- }
+ // send lightmap info
+ struct RGBA* col = &v_arr[i]->color;
+ buf_vbo[buf_vbo_len++] = ( (((uint16_t)col->g) << 8) | ((uint16_t)col->r) ) / 65535.0f;
+ buf_vbo[buf_vbo_len++] = 1.0f - (( (((uint16_t)col->a) << 8) | ((uint16_t)col->b) ) / 65535.0f);
- for (int j = 0; j < num_inputs; j++) {
+ for (int j = 0; j < CC_MAX_INPUTS; j++) {
struct RGBA *color = NULL;
struct RGBA tmp = { 0 };
- for (int a = 0; a < (cm->use_alpha ? 2 : 1 ); a++) {
- u8 mapping = comb->shader_input_mapping[j];
- switch (mapping) {
- case CC_PRIM:
- color = &rdp.prim_color;
- break;
- case CC_SHADE:
- color = &v_arr[i]->color;
- break;
- case CC_ENV:
- color = &rdp.env_color;
- break;
- case CC_PRIMA:
- memset(&tmp, rdp.prim_color.a, sizeof(tmp));
- color = &tmp;
- break;
- case CC_SHADEA:
- memset(&tmp, v_arr[i]->color.a, sizeof(tmp));
- color = &tmp;
- break;
- case CC_ENVA:
- memset(&tmp, rdp.env_color.a, sizeof(tmp));
- color = &tmp;
- break;
- case CC_LOD:
- {
- float distance_frac = (v1->w - 3000.0f) / 3000.0f;
- if (distance_frac < 0.0f) distance_frac = 0.0f;
- if (distance_frac > 1.0f) distance_frac = 1.0f;
- tmp.r = tmp.g = tmp.b = tmp.a = distance_frac * 255.0f;
- color = &tmp;
- break;
- }
- default:
- memset(&tmp, 0, sizeof(tmp));
- color = &tmp;
- break;
+ u8 mapping = (j < num_inputs) ? comb->shader_input_mapping[j] : 255;
+
+ switch (mapping) {
+ case CC_PRIM: color = &rdp.prim_color; break;
+ case CC_SHADE: color = &v_arr[i]->color; break;
+ case CC_ENV: color = &rdp.env_color; break;
+ case CC_PRIMA:
+ memset(&tmp, rdp.prim_color.a, sizeof(tmp));
+ color = &tmp;
+ break;
+ case CC_SHADEA:
+ memset(&tmp, v_arr[i]->color.a, sizeof(tmp));
+ color = &tmp;
+ break;
+ case CC_ENVA:
+ memset(&tmp, rdp.env_color.a, sizeof(tmp));
+ color = &tmp;
+ break;
+ case CC_LOD: {
+ float distance_frac = (v_arr[i]->w - 3000.0f) / 3000.0f;
+ if (distance_frac < 0.0f) distance_frac = 0.0f;
+ if (distance_frac > 1.0f) distance_frac = 1.0f;
+ tmp.r = tmp.g = tmp.b = tmp.a = distance_frac * 255.0f;
+ color = &tmp;
+ break;
}
- if (a == 0) {
- buf_vbo[buf_vbo_len++] = color->r / 255.0f;
- buf_vbo[buf_vbo_len++] = color->g / 255.0f;
- buf_vbo[buf_vbo_len++] = color->b / 255.0f;
+ default:
+ memset(&tmp, 0, sizeof(tmp));
+ color = &tmp;
+ break;
+ }
+
+ // send over input colors
+ buf_vbo[buf_vbo_len++] = color->r / 255.0f;
+ buf_vbo[buf_vbo_len++] = color->g / 255.0f;
+ buf_vbo[buf_vbo_len++] = color->b / 255.0f;
+
+ if (cm->use_alpha) {
+ if (cm->use_fog && (color == &v_arr[i]->color || cm->light_map)) {
+ buf_vbo[buf_vbo_len++] = 1.0f;
} else {
- if (cm->use_fog && (color == &v_arr[i]->color || cm->light_map)) {
- // Shade alpha is 100% for fog
- buf_vbo[buf_vbo_len++] = 1.0f;
- } else {
- buf_vbo[buf_vbo_len++] = color->a / 255.0f;
- }
+ buf_vbo[buf_vbo_len++] = color->a / 255.0f;
}
+ } else {
+ buf_vbo[buf_vbo_len++] = 1.0f;
}
}
- /*struct RGBA *color = &v_arr[i]->color;
- buf_vbo[buf_vbo_len++] = color->r / 255.0f;
- buf_vbo[buf_vbo_len++] = color->g / 255.0f;
- buf_vbo[buf_vbo_len++] = color->b / 255.0f;
- buf_vbo[buf_vbo_len++] = color->a / 255.0f;*/
+
+ // calculate normal
+ f32 ux = v2->x - v1->x;
+ f32 uy = v2->y - v1->y;
+ f32 uz = v2->z - v1->z;
+
+ f32 vx = v3->x - v1->x;
+ f32 vy = v3->y - v1->y;
+ f32 vz = v3->z - v1->z;
+
+ f32 nx = uy * vz - uz * vy;
+ f32 ny = uz * vx - ux * vz;
+ f32 nz = ux * vy - uy * vx;
+
+ float len = sqrtf(nx*nx + ny*ny + nz*nz);
+ if (len > 0.0f) {
+ nx /= len;
+ ny /= len;
+ nz /= len;
+ }
+
+ // send normal
+ buf_vbo[buf_vbo_len++] = nx;
+ buf_vbo[buf_vbo_len++] = ny;
+ buf_vbo[buf_vbo_len++] = nz;
+
+ // send barycentric coords
+ buf_vbo[buf_vbo_len++] = i == 0 ? 1.0f : 0.0f;
+ buf_vbo[buf_vbo_len++] = i == 1 ? 1.0f : 0.0f;
+ buf_vbo[buf_vbo_len++] = i == 2 ? 1.0f : 0.0f;
}
if (++buf_vbo_num_tris == MAX_BUFFERED) {
gfx_flush();
@@ -2064,6 +2060,15 @@ void gfx_shutdown(void) {
gGfxInited = false;
}
+void gfx_remove_all_color_combiners() {
+ for (int i = 0; i < CC_MAX_SHADERS; i++) {
+ memset(&color_combiner_pool[i], 0, sizeof(color_combiner_pool[i]));
+ }
+
+ color_combiner_pool_index = 0;
+ color_combiner_pool_size = 0;
+}
+
/////////////////////////
// v custom for djui v //
/////////////////////////
diff --git a/src/pc/gfx/gfx_pc.h b/src/pc/gfx/gfx_pc.h
index 97fdca0cc..3b3344cb4 100644
--- a/src/pc/gfx/gfx_pc.h
+++ b/src/pc/gfx/gfx_pc.h
@@ -7,12 +7,41 @@
struct GfxRenderingAPI;
struct GfxWindowManagerAPI;
+struct RSP {
+ ALIGNED16 Mat4 MP_matrix;
+ ALIGNED16 Mat4 P_matrix;
+ ALIGNED16 Mat4 modelview_matrix_stack[MAX_MATRIX_STACK_SIZE];
+ uint32_t modelview_matrix_stack_size;
+
+ uint32_t geometry_mode;
+ int16_t fog_mul, fog_offset;
+ int16_t fresnel_scale, fresnel_offset;
+
+ struct {
+ // U0.16
+ uint16_t s, t;
+ } texture_scaling_factor;
+
+ bool lights_changed;
+ uint8_t current_num_lights; // includes ambient light
+ Vec3f current_lights_coeffs[MAX_LIGHTS];
+ Vec3f current_lookat_coeffs[2]; // lookat_x, lookat_y
+ Light_t current_lights[MAX_LIGHTS + 1];
+
+ struct GfxVertex loaded_vertices[MAX_VERTICES + 4];
+};
+
+extern struct RSP rsp;
+
extern Vec3f gLightingDir;
extern Color gLightingColor[2];
extern Color gVertexColor;
extern Color gFogColor;
extern f32 gFogIntensity;
+extern Mat4 sInverseCameraMatrix;
+extern bool sHasInverseCameraMatrix;
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -25,6 +54,7 @@ void gfx_end_frame_render(void);
void gfx_display_frame(void);
void gfx_end_frame(void);
void gfx_shutdown(void);
+void gfx_remove_all_color_combiners(void);
void gfx_pc_precomp_shader(uint32_t rgb1, uint32_t alpha1, uint32_t rgb2, uint32_t alpha2, uint32_t flags);
#ifdef __cplusplus
diff --git a/src/pc/gfx/gfx_rendering_api.h b/src/pc/gfx/gfx_rendering_api.h
index 064d8de5e..b1b3f6032 100644
--- a/src/pc/gfx/gfx_rendering_api.h
+++ b/src/pc/gfx/gfx_rendering_api.h
@@ -12,8 +12,10 @@ struct GfxRenderingAPI {
bool (*z_is_from_0_to_1)(void);
void (*unload_shader)(struct ShaderProgram *old_prg);
void (*load_shader)(struct ShaderProgram *new_prg);
+ void (*remove_shaders)(void);
struct ShaderProgram *(*create_and_load_new_shader)(struct ColorCombiner* cc);
struct ShaderProgram *(*lookup_shader)(struct ColorCombiner* cc);
+ struct ShaderProgram *(*lookup_shader_using_index)(uint8_t shaderIndex);
void (*shader_get_info)(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]);
uint32_t (*new_texture)(void);
void (*select_texture)(int tile, uint32_t texture_id);
diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c
index ce5959290..b3a89bfdf 100644
--- a/src/pc/gfx/gfx_sdl2.c
+++ b/src/pc/gfx/gfx_sdl2.c
@@ -134,6 +134,10 @@ static void gfx_sdl_init(const char *window_title) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); // These attributes allow for hardware acceleration on RPis.
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+#else
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#endif
int xpos = (configWindow.x == WAPI_WIN_CENTERPOS) ? SDL_WINDOWPOS_CENTERED : configWindow.x;
diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c
index 83f3e1542..c122fb994 100644
--- a/src/pc/lua/smlua_cobject.c
+++ b/src/pc/lua/smlua_cobject.c
@@ -83,6 +83,8 @@ static const char *sLuaLvtNames[] = {
[LVT_S16_P] = "s16 pointer",
[LVT_S32] = "s32",
[LVT_S32_P] = "s32 pointer",
+ [LVT_S64] = "s64",
+ [LVT_S64_P] = "s64 pointer",
[LVT_F32] = "f32",
[LVT_F32_P] = "f32 pointer",
[LVT_U64] = "u64",
@@ -377,6 +379,7 @@ static bool smlua_push_field(lua_State* L, u8* p, struct LuaObjectField *data) {
case LVT_S8: lua_pushinteger(L, *(s8* )p); break;
case LVT_S16: lua_pushinteger(L, *(s16*)p); break;
case LVT_S32: lua_pushinteger(L, *(s32*)p); break;
+ case LVT_S64: lua_pushinteger(L, *(s64*)p); break;
case LVT_F32: lua_pushnumber( L, *(f32*)p); break;
case LVT_U64: lua_pushinteger(L, *(u64*)p); break;
case LVT_COBJECT: smlua_push_object(L, data->lot, p, NULL); break;
@@ -392,6 +395,7 @@ static bool smlua_push_field(lua_State* L, u8* p, struct LuaObjectField *data) {
case LVT_S8_P:
case LVT_S16_P:
case LVT_S32_P:
+ case LVT_S64_P:
case LVT_F32_P:
case LVT_U64_P:
case LVT_BEHAVIORSCRIPT_P:
@@ -419,6 +423,7 @@ static bool smlua_set_field(lua_State* L, u8* p, struct LuaObjectField *data) {
case LVT_S8: *(s8*) p = smlua_to_integer(L, 3); break;
case LVT_S16: *(s16*)p = smlua_to_integer(L, 3); break;
case LVT_S32: *(s32*)p = smlua_to_integer(L, 3); break;
+ case LVT_S64: *(s64*)p = smlua_to_integer(L, 3); break;
case LVT_F32: *(f32*)p = smlua_to_number(L, 3); break;
case LVT_U64: *(s64*)p = smlua_to_integer(L, 3); break;
@@ -441,6 +446,7 @@ static bool smlua_set_field(lua_State* L, u8* p, struct LuaObjectField *data) {
case LVT_S8_P:
case LVT_S16_P:
case LVT_S32_P:
+ case LVT_S64_P:
case LVT_F32_P:
case LVT_U64_P:
case LVT_BEHAVIORSCRIPT_P:
diff --git a/src/pc/lua/smlua_cobject.h b/src/pc/lua/smlua_cobject.h
index 83cac836d..69bb196cf 100644
--- a/src/pc/lua/smlua_cobject.h
+++ b/src/pc/lua/smlua_cobject.h
@@ -18,6 +18,8 @@ enum LuaValueType {
LVT_S16_P,
LVT_S32,
LVT_S32_P,
+ LVT_S64,
+ LVT_S64_P,
LVT_F32,
LVT_F32_P,
LVT_U64,
diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c
index 35a3ce52d..ff56a28ed 100644
--- a/src/pc/lua/smlua_cobject_autogen.c
+++ b/src/pc/lua/smlua_cobject_autogen.c
@@ -25,6 +25,8 @@
#include "src/pc/lua/utils/smlua_audio_utils.h"
#include "src/game/paintings.h"
#include "src/pc/djui/djui_types.h"
+#include "src/pc/gfx/gfx_cc.h"
+#include "src/pc/gfx/gfx_opengl.h"
#include "src/game/first_person_cam.h"
#include "src/game/player_palette.h"
#include "src/engine/graph_node.h"
@@ -377,6 +379,17 @@ static struct LuaObjectField sBehaviorValuesFields[LUA_BEHAVIOR_VALUES_FIELD_COU
{ "trajectories", LVT_COBJECT, offsetof(struct BehaviorValues, trajectories), true, LOT_BEHAVIORTRAJECTORIES, 1, sizeof(struct BehaviorTrajectories) },
};
+#define LUA_CCFEATURES_FIELD_COUNT 7
+static struct LuaObjectField sCCFeaturesFields[LUA_CCFEATURES_FIELD_COUNT] = {
+ { "color_alpha_same", LVT_BOOL, offsetof(struct CCFeatures, color_alpha_same), false, LOT_NONE, 2, sizeof(bool) },
+ { "do_mix", LVT_BOOL, offsetof(struct CCFeatures, do_mix), false, LOT_NONE, 4, sizeof(bool) },
+ { "do_multiply", LVT_BOOL, offsetof(struct CCFeatures, do_multiply), false, LOT_NONE, 4, sizeof(bool) },
+ { "do_noise", LVT_BOOL, offsetof(struct CCFeatures, do_noise), false, LOT_NONE, 1, sizeof(bool) },
+ { "do_single", LVT_BOOL, offsetof(struct CCFeatures, do_single), false, LOT_NONE, 4, sizeof(bool) },
+ { "num_inputs", LVT_S32, offsetof(struct CCFeatures, num_inputs), false, LOT_NONE, 1, sizeof(int) },
+ { "used_textures", LVT_BOOL, offsetof(struct CCFeatures, used_textures), false, LOT_NONE, 2, sizeof(bool) },
+};
+
#define LUA_CAMERA_FIELD_COUNT 15
static struct LuaObjectField sCameraFields[LUA_CAMERA_FIELD_COUNT] = {
{ "areaCenX", LVT_F32, offsetof(struct Camera, areaCenX), false, LOT_NONE, 1, sizeof(f32) },
@@ -684,6 +697,34 @@ static struct LuaObjectField sCharacterFields[LUA_CHARACTER_FIELD_COUNT] = {
{ "type", LVT_S32, offsetof(struct Character, type), true, LOT_NONE, 1, sizeof(enum CharacterType) },
};
+#define LUA_COLOR_COMBINER_FIELD_COUNT 7
+static struct LuaObjectField sColorCombinerFields[LUA_COLOR_COMBINER_FIELD_COUNT] = {
+ { "cm", LVT_COBJECT, offsetof(struct ColorCombiner, cm), true, LOT_COMBINEMODE, 1, sizeof(struct CombineMode) },
+ { "hash", LVT_U64, offsetof(struct ColorCombiner, hash), false, LOT_NONE, 1, sizeof(u64) },
+ { "prg", LVT_COBJECT_P, offsetof(struct ColorCombiner, prg), false, LOT_SHADERPROGRAM, 1, sizeof(struct ShaderProgram*) },
+ { "shader_commands", LVT_U8, offsetof(struct ColorCombiner, shader_commands), false, LOT_NONE, 16, sizeof(u8) },
+ { "shader_commands_as_u64", LVT_U64, offsetof(struct ColorCombiner, shader_commands_as_u64), false, LOT_NONE, 8, sizeof(u64) },
+ { "shader_input_mapping", LVT_U8, offsetof(struct ColorCombiner, shader_input_mapping), false, LOT_NONE, 16, sizeof(u8) },
+ { "shader_input_mapping_as_u64", LVT_U64, offsetof(struct ColorCombiner, shader_input_mapping_as_u64), false, LOT_NONE, 8, sizeof(u64) },
+};
+
+#define LUA_COMBINE_MODE_FIELD_COUNT 7
+static struct LuaObjectField sCombineModeFields[LUA_COMBINE_MODE_FIELD_COUNT] = {
+// { "1", LVT_???, offsetof(struct CombineMode, 1), false, LOT_???, 1, sizeof(u8 use_alpha :) }, <--- UNIMPLEMENTED
+// { "1", LVT_???, offsetof(struct CombineMode, 1), false, LOT_???, 1, sizeof(u8 use_fog :) }, <--- UNIMPLEMENTED
+// { "1", LVT_???, offsetof(struct CombineMode, 1), false, LOT_???, 1, sizeof(u8 texture_edge :) }, <--- UNIMPLEMENTED
+// { "1", LVT_???, offsetof(struct CombineMode, 1), false, LOT_???, 1, sizeof(u8 use_dither :) }, <--- UNIMPLEMENTED
+// { "1", LVT_???, offsetof(struct CombineMode, 1), false, LOT_???, 1, sizeof(u8 use_2cycle :) }, <--- UNIMPLEMENTED
+// { "1", LVT_???, offsetof(struct CombineMode, 1), false, LOT_???, 1, sizeof(u8 light_map :) }, <--- UNIMPLEMENTED
+ { "all_values", LVT_U8, offsetof(struct CombineMode, all_values), false, LOT_NONE, 16, sizeof(u8) },
+ { "alpha1", LVT_U32, offsetof(struct CombineMode, alpha1), false, LOT_NONE, 1, sizeof(u32) },
+ { "alpha2", LVT_U32, offsetof(struct CombineMode, alpha2), false, LOT_NONE, 1, sizeof(u32) },
+ { "flags", LVT_U32, offsetof(struct CombineMode, flags), false, LOT_NONE, 1, sizeof(u32) },
+ { "hash", LVT_S64, offsetof(struct CombineMode, hash), false, LOT_NONE, 1, sizeof(s64) },
+ { "rgb1", LVT_U32, offsetof(struct CombineMode, rgb1), false, LOT_NONE, 1, sizeof(u32) },
+ { "rgb2", LVT_U32, offsetof(struct CombineMode, rgb2), false, LOT_NONE, 1, sizeof(u32) },
+};
+
#define LUA_CONTROLLER_FIELD_COUNT 11
static struct LuaObjectField sControllerFields[LUA_CONTROLLER_FIELD_COUNT] = {
{ "buttonDown", LVT_U16, offsetof(struct Controller, buttonDown), false, LOT_NONE, 1, sizeof(u16) },
@@ -2501,6 +2542,21 @@ static struct LuaObjectField sServerSettingsFields[LUA_SERVER_SETTINGS_FIELD_COU
{ "stayInLevelAfterStar", LVT_U8, offsetof(struct ServerSettings, stayInLevelAfterStar), false, LOT_NONE, 1, sizeof(u8) },
};
+#define LUA_SHADER_PROGRAM_FIELD_COUNT 11
+static struct LuaObjectField sShaderProgramFields[LUA_SHADER_PROGRAM_FIELD_COUNT] = {
+ { "attrib_locations", LVT_U32, offsetof(struct ShaderProgram, attrib_locations), false, LOT_NONE, MAX_SHADER_ATTRIBUTES, sizeof(u32) },
+ { "attrib_sizes", LVT_U8, offsetof(struct ShaderProgram, attrib_sizes), false, LOT_NONE, MAX_SHADER_ATTRIBUTES, sizeof(u8) },
+ { "hash", LVT_U64, offsetof(struct ShaderProgram, hash), false, LOT_NONE, 1, sizeof(u64) },
+ { "num_attribs", LVT_U8, offsetof(struct ShaderProgram, num_attribs), false, LOT_NONE, 1, sizeof(u8) },
+ { "num_floats", LVT_U8, offsetof(struct ShaderProgram, num_floats), false, LOT_NONE, 1, sizeof(u8) },
+ { "num_inputs", LVT_U8, offsetof(struct ShaderProgram, num_inputs), false, LOT_NONE, 1, sizeof(u8) },
+ { "opengl_program_id", LVT_U32, offsetof(struct ShaderProgram, opengl_program_id), false, LOT_NONE, 1, sizeof(u32) },
+ { "uniform_locations", LVT_U32, offsetof(struct ShaderProgram, uniform_locations), false, LOT_NONE, MAX_SHADER_UNIFORMS, sizeof(u32) },
+ { "used_lightmap", LVT_BOOL, offsetof(struct ShaderProgram, used_lightmap), false, LOT_NONE, 1, sizeof(bool) },
+ { "used_noise", LVT_BOOL, offsetof(struct ShaderProgram, used_noise), false, LOT_NONE, 1, sizeof(bool) },
+ { "used_textures", LVT_BOOL, offsetof(struct ShaderProgram, used_textures), false, LOT_NONE, MAX_SHADER_TEXTURES, sizeof(bool) },
+};
+
#define LUA_SPAWN_INFO_FIELD_COUNT 8
static struct LuaObjectField sSpawnInfoFields[LUA_SPAWN_INFO_FIELD_COUNT] = {
{ "activeAreaIndex", LVT_S8, offsetof(struct SpawnInfo, activeAreaIndex), false, LOT_NONE, 1, sizeof(s8) },
@@ -2679,9 +2735,12 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN]
{ LOT_BEHAVIORDIALOGS, sBehaviorDialogsFields, LUA_BEHAVIOR_DIALOGS_FIELD_COUNT },
{ LOT_BEHAVIORTRAJECTORIES, sBehaviorTrajectoriesFields, LUA_BEHAVIOR_TRAJECTORIES_FIELD_COUNT },
{ LOT_BEHAVIORVALUES, sBehaviorValuesFields, LUA_BEHAVIOR_VALUES_FIELD_COUNT },
+ { LOT_CCFEATURES, sCCFeaturesFields, LUA_CCFEATURES_FIELD_COUNT },
{ LOT_CAMERA, sCameraFields, LUA_CAMERA_FIELD_COUNT },
{ LOT_CHAINSEGMENT, sChainSegmentFields, LUA_CHAIN_SEGMENT_FIELD_COUNT },
{ LOT_CHARACTER, sCharacterFields, LUA_CHARACTER_FIELD_COUNT },
+ { LOT_COLORCOMBINER, sColorCombinerFields, LUA_COLOR_COMBINER_FIELD_COUNT },
+ { LOT_COMBINEMODE, sCombineModeFields, LUA_COMBINE_MODE_FIELD_COUNT },
{ LOT_CONTROLLER, sControllerFields, LUA_CONTROLLER_FIELD_COUNT },
{ LOT_CUSTOMLEVELINFO, sCustomLevelInfoFields, LUA_CUSTOM_LEVEL_INFO_FIELD_COUNT },
{ LOT_DATETIME, sDateTimeFields, LUA_DATE_TIME_FIELD_COUNT },
@@ -2747,6 +2806,7 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN]
{ LOT_RAYINTERSECTIONINFO, sRayIntersectionInfoFields, LUA_RAY_INTERSECTION_INFO_FIELD_COUNT },
{ LOT_ROMHACKCAMERASETTINGS, sRomhackCameraSettingsFields, LUA_ROMHACK_CAMERA_SETTINGS_FIELD_COUNT },
{ LOT_SERVERSETTINGS, sServerSettingsFields, LUA_SERVER_SETTINGS_FIELD_COUNT },
+ { LOT_SHADERPROGRAM, sShaderProgramFields, LUA_SHADER_PROGRAM_FIELD_COUNT },
{ LOT_SPAWNINFO, sSpawnInfoFields, LUA_SPAWN_INFO_FIELD_COUNT },
{ LOT_SPAWNPARTICLESINFO, sSpawnParticlesInfoFields, LUA_SPAWN_PARTICLES_INFO_FIELD_COUNT },
{ LOT_STARPOSITIONS, sStarPositionsFields, LUA_STAR_POSITIONS_FIELD_COUNT },
@@ -2784,9 +2844,12 @@ const char *sLuaLotNames[] = {
[LOT_BEHAVIORDIALOGS] = "BehaviorDialogs",
[LOT_BEHAVIORTRAJECTORIES] = "BehaviorTrajectories",
[LOT_BEHAVIORVALUES] = "BehaviorValues",
+ [LOT_CCFEATURES] = "CCFeatures",
[LOT_CAMERA] = "Camera",
[LOT_CHAINSEGMENT] = "ChainSegment",
[LOT_CHARACTER] = "Character",
+ [LOT_COLORCOMBINER] = "ColorCombiner",
+ [LOT_COMBINEMODE] = "CombineMode",
[LOT_CONTROLLER] = "Controller",
[LOT_CUSTOMLEVELINFO] = "CustomLevelInfo",
[LOT_DATETIME] = "DateTime",
@@ -2852,6 +2915,7 @@ const char *sLuaLotNames[] = {
[LOT_RAYINTERSECTIONINFO] = "RayIntersectionInfo",
[LOT_ROMHACKCAMERASETTINGS] = "RomhackCameraSettings",
[LOT_SERVERSETTINGS] = "ServerSettings",
+ [LOT_SHADERPROGRAM] = "ShaderProgram",
[LOT_SPAWNINFO] = "SpawnInfo",
[LOT_SPAWNPARTICLESINFO] = "SpawnParticlesInfo",
[LOT_STARPOSITIONS] = "StarPositions",
diff --git a/src/pc/lua/smlua_cobject_autogen.h b/src/pc/lua/smlua_cobject_autogen.h
index d034ce9f7..c18155fe9 100644
--- a/src/pc/lua/smlua_cobject_autogen.h
+++ b/src/pc/lua/smlua_cobject_autogen.h
@@ -29,9 +29,12 @@ enum LuaObjectAutogenType {
LOT_BEHAVIORDIALOGS,
LOT_BEHAVIORTRAJECTORIES,
LOT_BEHAVIORVALUES,
+ LOT_CCFEATURES,
LOT_CAMERA,
LOT_CHAINSEGMENT,
LOT_CHARACTER,
+ LOT_COLORCOMBINER,
+ LOT_COMBINEMODE,
LOT_CONTROLLER,
LOT_CUSTOMLEVELINFO,
LOT_DATETIME,
@@ -97,6 +100,7 @@ enum LuaObjectAutogenType {
LOT_RAYINTERSECTIONINFO,
LOT_ROMHACKCAMERASETTINGS,
LOT_SERVERSETTINGS,
+ LOT_SHADERPROGRAM,
LOT_SPAWNINFO,
LOT_SPAWNPARTICLESINFO,
LOT_STARPOSITIONS,
diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c
index de7da771c..9275002f2 100644
--- a/src/pc/lua/smlua_constants_autogen.c
+++ b/src/pc/lua/smlua_constants_autogen.c
@@ -1595,6 +1595,53 @@ char gSmluaConstants[] = ""
"BACKGROUND_ABOVE_CLOUDS=8\n"
"BACKGROUND_PURPLE_SKY=9\n"
"BACKGROUND_CUSTOM=10\n"
+"CC_0=0\n"
+"CC_TEXEL0=1\n"
+"CC_TEXEL1=2\n"
+"CC_PRIM=3\n"
+"CC_SHADE=4\n"
+"CC_ENV=5\n"
+"CC_TEXEL0A=6\n"
+"CC_LOD=7\n"
+"CC_1=8\n"
+"CC_TEXEL1A=9\n"
+"CC_COMBINED=10\n"
+"CC_COMBINEDA=11\n"
+"CC_PRIMA=12\n"
+"CC_SHADEA=13\n"
+"CC_ENVA=14\n"
+"CC_NOISE=15\n"
+"CC_ENUM_MAX=16\n"
+"SHADER_0=0\n"
+"SHADER_INPUT_1=1\n"
+"SHADER_INPUT_2=2\n"
+"SHADER_INPUT_3=3\n"
+"SHADER_INPUT_4=4\n"
+"SHADER_INPUT_5=5\n"
+"SHADER_INPUT_6=6\n"
+"SHADER_INPUT_7=7\n"
+"SHADER_INPUT_8=8\n"
+"SHADER_TEXEL0=9\n"
+"SHADER_TEXEL0A=10\n"
+"SHADER_TEXEL1=11\n"
+"SHADER_TEXEL1A=12\n"
+"SHADER_1=13\n"
+"SHADER_COMBINED=14\n"
+"SHADER_COMBINEDA=15\n"
+"SHADER_NOISE=16\n"
+"SHADER_OPT_ALPHA=(1 << 24)\n"
+"SHADER_OPT_FOG=(1 << 25)\n"
+"SHADER_OPT_TEXTURE_EDGE=(1 << 26)\n"
+"SHADER_OPT_NOISE=(1 << 27)\n"
+"USE_ALPHA=1 << 0\n"
+"USE_FOG=1 << 1\n"
+"TEXTURE_EDGE=1 << 2\n"
+"USE_DITHER=1 << 3\n"
+"USE_2CYCLE=1 << 4\n"
+"LIGHT_MAP=1 << 5\n"
+"SHADER_CMD_LENGTH=16\n"
+"CC_MAX_SHADERS=64\n"
+"CC_MAX_INPUTS=8\n"
"GRAPH_RENDER_ACTIVE=(1 << 0)\n"
"GRAPH_RENDER_CHILDREN_FIRST=(1 << 1)\n"
"GRAPH_RENDER_BILLBOARD=(1 << 2)\n"
@@ -3553,7 +3600,10 @@ char gSmluaConstants[] = ""
"HOOK_ON_FIND_WATER_LEVEL=63\n"
"HOOK_ON_FIND_POISON_GAS_LEVEL=64\n"
"HOOK_ON_FIND_SURFACE_ON_RAY=65\n"
-"HOOK_MAX=66\n"
+"HOOK_ON_REFRESH_SHADERS=66\n"
+"HOOK_ON_VERTEX_SHADER_CREATE=67\n"
+"HOOK_ON_FRAGMENT_SHADER_CREATE=68\n"
+"HOOK_MAX=69\n"
"MAX_HOOKED_BEHAVIORS=1024\n"
"HUD_DISPLAY_LIVES=0\n"
"HUD_DISPLAY_COINS=1\n"
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index 54bb0672b..2c59b5915 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -32547,6 +32547,219 @@ int smlua_func_gfx_delete_all(UNUSED lua_State* L) {
return 1;
}
+int smlua_func_gfx_reload_shaders(UNUSED lua_State* L) {
+ 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", "gfx_reload_shaders", 0, top);
+ return 0;
+ }
+
+
+ gfx_reload_shaders();
+
+ return 1;
+}
+
+int smlua_func_gfx_color_combiner_get_features(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", "gfx_color_combiner_get_features", 1, top);
+ return 0;
+ }
+
+ struct ColorCombiner* cc = (struct ColorCombiner*)smlua_to_cobject(L, 1, LOT_COLORCOMBINER);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_color_combiner_get_features"); return 0; }
+
+ smlua_push_object(L, LOT_CCFEATURES, gfx_color_combiner_get_features(cc), NULL);
+
+ return 1;
+}
+
+int smlua_func_gfx_get_program_id_from_shader_index(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", "gfx_get_program_id_from_shader_index", 1, top);
+ return 0;
+ }
+
+ u8 shaderIndex = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_program_id_from_shader_index"); return 0; }
+
+ lua_pushinteger(L, gfx_get_program_id_from_shader_index(shaderIndex));
+
+ return 1;
+}
+
+int smlua_func_gfx_use_program(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", "gfx_use_program", 1, top);
+ return 0;
+ }
+
+ u32 program = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_use_program"); return 0; }
+
+ gfx_use_program(program);
+
+ return 1;
+}
+
+int smlua_func_gfx_shader_get_uniform_location(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 2) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_shader_get_uniform_location", 2, top);
+ return 0;
+ }
+
+ u32 program = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_shader_get_uniform_location"); return 0; }
+ const char* name = smlua_to_string(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_shader_get_uniform_location"); return 0; }
+
+ lua_pushinteger(L, gfx_shader_get_uniform_location(program, name));
+
+ return 1;
+}
+
+int smlua_func_gfx_shader_set_int(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 2) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_shader_set_int", 2, top);
+ return 0;
+ }
+
+ int loc = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_shader_set_int"); return 0; }
+ int value = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_shader_set_int"); return 0; }
+
+ gfx_shader_set_int(loc, value);
+
+ return 1;
+}
+
+int smlua_func_gfx_shader_set_float(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 2) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_shader_set_float", 2, top);
+ return 0;
+ }
+
+ int loc = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_shader_set_float"); return 0; }
+ float value = smlua_to_number(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_shader_set_float"); return 0; }
+
+ gfx_shader_set_float(loc, value);
+
+ return 1;
+}
+
+int smlua_func_gfx_shader_set_vec2(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 3) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_shader_set_vec2", 3, top);
+ return 0;
+ }
+
+ int loc = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_shader_set_vec2"); return 0; }
+ float x = smlua_to_number(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_shader_set_vec2"); return 0; }
+ float y = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "gfx_shader_set_vec2"); return 0; }
+
+ gfx_shader_set_vec2(loc, x, y);
+
+ return 1;
+}
+
+int smlua_func_gfx_shader_set_vec3(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 4) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_shader_set_vec3", 4, top);
+ return 0;
+ }
+
+ int loc = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_shader_set_vec3"); return 0; }
+ float x = smlua_to_number(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_shader_set_vec3"); return 0; }
+ float y = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "gfx_shader_set_vec3"); return 0; }
+ float z = smlua_to_number(L, 4);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "gfx_shader_set_vec3"); return 0; }
+
+ gfx_shader_set_vec3(loc, x, y, z);
+
+ return 1;
+}
+
+int smlua_func_gfx_shader_set_vec4(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 5) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_shader_set_vec4", 5, top);
+ return 0;
+ }
+
+ int loc = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_shader_set_vec4"); return 0; }
+ float w = smlua_to_number(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_shader_set_vec4"); return 0; }
+ float x = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "gfx_shader_set_vec4"); return 0; }
+ float y = smlua_to_number(L, 4);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "gfx_shader_set_vec4"); return 0; }
+ float z = smlua_to_number(L, 5);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "gfx_shader_set_vec4"); return 0; }
+
+ gfx_shader_set_vec4(loc, w, x, y, z);
+
+ return 1;
+}
+
+int smlua_func_gfx_shader_set_mat4(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 2) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_shader_set_mat4", 2, top);
+ return 0;
+ }
+
+ int loc = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_shader_set_mat4"); return 0; }
+
+ Mat4 mat;
+ smlua_get_mat4(mat, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_shader_set_mat4"); return 0; }
+
+ gfx_shader_set_mat4(loc, mat);
+
+ return 1;
+}
+
int smlua_func_vtx_get_from_name(lua_State* L) {
if (L == NULL) { return 0; }
@@ -38616,6 +38829,17 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "gfx_resize", smlua_func_gfx_resize);
smlua_bind_function(L, "gfx_delete", smlua_func_gfx_delete);
smlua_bind_function(L, "gfx_delete_all", smlua_func_gfx_delete_all);
+ smlua_bind_function(L, "gfx_reload_shaders", smlua_func_gfx_reload_shaders);
+ smlua_bind_function(L, "gfx_color_combiner_get_features", smlua_func_gfx_color_combiner_get_features);
+ smlua_bind_function(L, "gfx_get_program_id_from_shader_index", smlua_func_gfx_get_program_id_from_shader_index);
+ smlua_bind_function(L, "gfx_use_program", smlua_func_gfx_use_program);
+ smlua_bind_function(L, "gfx_shader_get_uniform_location", smlua_func_gfx_shader_get_uniform_location);
+ smlua_bind_function(L, "gfx_shader_set_int", smlua_func_gfx_shader_set_int);
+ smlua_bind_function(L, "gfx_shader_set_float", smlua_func_gfx_shader_set_float);
+ smlua_bind_function(L, "gfx_shader_set_vec2", smlua_func_gfx_shader_set_vec2);
+ smlua_bind_function(L, "gfx_shader_set_vec3", smlua_func_gfx_shader_set_vec3);
+ smlua_bind_function(L, "gfx_shader_set_vec4", smlua_func_gfx_shader_set_vec4);
+ smlua_bind_function(L, "gfx_shader_set_mat4", smlua_func_gfx_shader_set_mat4);
smlua_bind_function(L, "vtx_get_from_name", smlua_func_vtx_get_from_name);
smlua_bind_function(L, "vtx_get_name", smlua_func_vtx_get_name);
smlua_bind_function(L, "vtx_get_count", smlua_func_vtx_get_count);
diff --git a/src/pc/lua/smlua_hook_events.inl b/src/pc/lua/smlua_hook_events.inl
index 71f4a915c..de0e48001 100644
--- a/src/pc/lua/smlua_hook_events.inl
+++ b/src/pc/lua/smlua_hook_events.inl
@@ -64,3 +64,6 @@ SMLUA_EVENT_HOOK(HOOK_ON_FIND_FLOOR, _, f32 posX, f32 posY, f32 posZ, struct Sur
SMLUA_EVENT_HOOK(HOOK_ON_FIND_WATER_LEVEL, _, f32 x, f32 z, f32 *waterLevel) // Manually defined hook
SMLUA_EVENT_HOOK(HOOK_ON_FIND_POISON_GAS_LEVEL, _, f32 x, f32 z, f32 *gasLevel) // Manually defined hook
SMLUA_EVENT_HOOK(HOOK_ON_FIND_SURFACE_ON_RAY, _, Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos) // Manually defined hook
+SMLUA_EVENT_HOOK(HOOK_ON_REFRESH_SHADERS, HOOK_RETURN_NEVER)
+SMLUA_EVENT_HOOK(HOOK_ON_VERTEX_SHADER_CREATE, HOOK_RETURN_ON_OUTPUT_SET, struct ColorCombiner *cc, u8 shaderIndex, OUTPUT const char **vertexShader)
+SMLUA_EVENT_HOOK(HOOK_ON_FRAGMENT_SHADER_CREATE, HOOK_RETURN_ON_OUTPUT_SET, struct ColorCombiner *cc, u8 shaderIndex, OUTPUT const char **fragmentShader)
diff --git a/src/pc/lua/smlua_hook_events_autogen.inl b/src/pc/lua/smlua_hook_events_autogen.inl
index 8468eb4b8..01680a292 100644
--- a/src/pc/lua/smlua_hook_events_autogen.inl
+++ b/src/pc/lua/smlua_hook_events_autogen.inl
@@ -1863,3 +1863,97 @@ bool smlua_call_event_hooks_HOOK_ON_PACKET_BYTESTRING_RECEIVE(s32 modIndex, s32
}
return hookResult;
}
+
+bool smlua_call_event_hooks_HOOK_ON_REFRESH_SHADERS() {
+ lua_State *L = gLuaState;
+ if (L == NULL) { return false; }
+ bool hookResult = false;
+
+ struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_REFRESH_SHADERS];
+ for (int i = 0; i < hook->count; i++) {
+ s32 prevTop = lua_gettop(L);
+
+ // push the callback onto the stack
+ lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
+
+ // call the callback
+ if (0 != smlua_call_hook(L, 0, 0, 0, hook->mod[i], hook->modFile[i])) {
+ LOG_LUA("Failed to call the callback for hook %s - '%s/%s'", sLuaHookedEventTypeName[HOOK_ON_REFRESH_SHADERS], hook->mod[i]->relativePath, hook->modFile[i]->relativePath);
+ continue;
+ }
+ hookResult = true;
+
+ lua_settop(L, prevTop);
+ }
+ return hookResult;
+}
+
+bool smlua_call_event_hooks_HOOK_ON_VERTEX_SHADER_CREATE(struct ColorCombiner *cc, u8 shaderIndex, const char **vertexShader) {
+ lua_State *L = gLuaState;
+ if (L == NULL) { return false; }
+
+ struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_VERTEX_SHADER_CREATE];
+ for (int i = 0; i < hook->count; i++) {
+ s32 prevTop = lua_gettop(L);
+
+ // push the callback onto the stack
+ lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
+
+ // push cc
+ smlua_push_object(L, LOT_COLORCOMBINER, cc, NULL);
+
+ // push shaderIndex
+ lua_pushinteger(L, shaderIndex);
+
+ // call the callback
+ if (0 != smlua_call_hook(L, 2, 1, 0, hook->mod[i], hook->modFile[i])) {
+ LOG_LUA("Failed to call the callback for hook %s - '%s/%s'", sLuaHookedEventTypeName[HOOK_ON_VERTEX_SHADER_CREATE], hook->mod[i]->relativePath, hook->modFile[i]->relativePath);
+ continue;
+ }
+
+ // return vertexShader
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ *vertexShader = smlua_to_string(L, -1);
+ lua_settop(L, prevTop);
+ return true;
+ }
+
+ lua_settop(L, prevTop);
+ }
+ return false;
+}
+
+bool smlua_call_event_hooks_HOOK_ON_FRAGMENT_SHADER_CREATE(struct ColorCombiner *cc, u8 shaderIndex, const char **fragmentShader) {
+ lua_State *L = gLuaState;
+ if (L == NULL) { return false; }
+
+ struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_FRAGMENT_SHADER_CREATE];
+ for (int i = 0; i < hook->count; i++) {
+ s32 prevTop = lua_gettop(L);
+
+ // push the callback onto the stack
+ lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
+
+ // push cc
+ smlua_push_object(L, LOT_COLORCOMBINER, cc, NULL);
+
+ // push shaderIndex
+ lua_pushinteger(L, shaderIndex);
+
+ // call the callback
+ if (0 != smlua_call_hook(L, 2, 1, 0, hook->mod[i], hook->modFile[i])) {
+ LOG_LUA("Failed to call the callback for hook %s - '%s/%s'", sLuaHookedEventTypeName[HOOK_ON_FRAGMENT_SHADER_CREATE], hook->mod[i]->relativePath, hook->modFile[i]->relativePath);
+ continue;
+ }
+
+ // return fragmentShader
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ *fragmentShader = smlua_to_string(L, -1);
+ lua_settop(L, prevTop);
+ return true;
+ }
+
+ lua_settop(L, prevTop);
+ }
+ return false;
+}
diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c
index 0984c8223..a68d68694 100644
--- a/src/pc/lua/smlua_hooks.c
+++ b/src/pc/lua/smlua_hooks.c
@@ -21,6 +21,7 @@
#include "pc/configfile.h"
#include "pc/utils/misc.h"
#include "pc/lua/utils/smlua_model_utils.h"
+#include "pc/gfx/gfx_cc.h"
#include "../mods/mods.h"
#include "game/print.h"
diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h
index c814c73e9..d755eff16 100644
--- a/src/pc/lua/smlua_hooks.h
+++ b/src/pc/lua/smlua_hooks.h
@@ -7,6 +7,7 @@
#include "smlua.h"
#include "pc/mods/mod.h"
#include "pc/lua/utils/smlua_model_utils.h"
+#include "pc/gfx/gfx_cc.h"
// forward declare
struct Camera;
@@ -82,6 +83,9 @@ enum LuaHookedEventType {
HOOK_ON_FIND_WATER_LEVEL,
HOOK_ON_FIND_POISON_GAS_LEVEL,
HOOK_ON_FIND_SURFACE_ON_RAY,
+ HOOK_ON_REFRESH_SHADERS,
+ HOOK_ON_VERTEX_SHADER_CREATE,
+ HOOK_ON_FRAGMENT_SHADER_CREATE,
HOOK_MAX,
};
diff --git a/src/pc/lua/utils/smlua_gfx_utils.c b/src/pc/lua/utils/smlua_gfx_utils.c
index 78a3679b1..b93e2ce1e 100644
--- a/src/pc/lua/utils/smlua_gfx_utils.c
+++ b/src/pc/lua/utils/smlua_gfx_utils.c
@@ -1,4 +1,26 @@
+#if defined(__MINGW32__) || defined(OSX_BUILD)
+# define GLEW_STATIC
+# include
+#endif
+
+#define GL_GLEXT_PROTOTYPES 1
+
+#ifdef WAPI_SDL2
+# include
+# ifdef USE_GLES
+# include
+# else
+# include
+# endif
+#elif defined(WAPI_SDL1)
+# include
+# ifndef GLEW_STATIC
+# include
+# endif
+#endif
+
#include "smlua_gfx_utils.h"
+#include "pc/pc_main.h"
#include "pc/gfx/gfx_pc.h"
#include "game/rendering_graph_node.h"
#include "game/skybox.h"
@@ -360,6 +382,69 @@ void gfx_delete_all() {
dynos_gfx_delete_all();
}
+void gfx_reload_shaders() {
+ gfx_remove_all_color_combiners();
+ RAPI.remove_shaders();
+ smlua_call_event_hooks(HOOK_ON_REFRESH_SHADERS);
+}
+
+struct CCFeatures *gfx_color_combiner_get_features(struct ColorCombiner *cc) {
+ static struct CCFeatures sCcf = { 0 };
+ gfx_cc_get_features(cc, &sCcf);
+ return &sCcf;
+}
+
+
+u32 gfx_get_program_id_from_shader_index(u8 shaderIndex) {
+ struct ShaderProgram* program = RAPI.lookup_shader_using_index(shaderIndex);
+ if (!program) return 0;
+ return program->opengl_program_id;
+}
+
+void gfx_use_program(u32 program) {
+ glUseProgram(program);
+}
+
+int gfx_shader_get_uniform_location(u32 program, const char* name) {
+ return glGetUniformLocation(program, name);
+}
+
+void gfx_shader_set_int(int loc, int value) {
+ if (loc != -1) {
+ glUniform1i(loc, value);
+ }
+}
+
+void gfx_shader_set_float(int loc, float value) {
+ if (loc != -1) {
+ glUniform1f(loc, value);
+ }
+}
+
+void gfx_shader_set_vec2(int loc, float x, float y) {
+ if (loc != -1) {
+ glUniform2f(loc, x, y);
+ }
+}
+
+void gfx_shader_set_vec3(int loc, float x, float y, float z) {
+ if (loc != -1) {
+ glUniform3f(loc, x, y, z);
+ }
+}
+
+void gfx_shader_set_vec4(int loc, float x, float y, float z, float w) {
+ if (loc != -1) {
+ glUniform4f(loc, x, y, z, w);
+ }
+}
+
+void gfx_shader_set_mat4(int loc, const Mat4 mat) {
+ if (loc != -1) {
+ glUniformMatrix4fv(loc, 1, GL_FALSE, (const GLfloat*)mat);
+ }
+}
+
Vtx *vtx_get_from_name(const char *name, RET u32 *count) {
*count = 0;
return dynos_vtx_get(name, count);
diff --git a/src/pc/lua/utils/smlua_gfx_utils.h b/src/pc/lua/utils/smlua_gfx_utils.h
index d49ebed34..4c62c40ea 100644
--- a/src/pc/lua/utils/smlua_gfx_utils.h
+++ b/src/pc/lua/utils/smlua_gfx_utils.h
@@ -92,6 +92,28 @@ void gfx_resize(Gfx *gfx, u32 newLength);
void gfx_delete(Gfx *gfx);
/* |description|Deletes all display lists created by `gfx_create`|descriptionEnd| */
void gfx_delete_all();
+/* |description|Reloads all shaders|descriptionEnd| */
+void gfx_reload_shaders();
+/* |description|Gets features from a color combiner.|descriptionEnd| */
+struct CCFeatures *gfx_color_combiner_get_features(struct ColorCombiner *cc);
+/* |description|Gets a program id from the shader index.|descriptionEnd| */
+u32 gfx_get_program_id_from_shader_index(u8 shaderIndex);
+/* |description|Uses a specific program. Required for setting uniforms.|descriptionEnd| */
+void gfx_use_program(u32 program);
+/* |description|Gets the location of a shader uniform in a program for modification.|descriptionEnd| */
+int gfx_shader_get_uniform_location(u32 program, const char* name);
+/* |description|Sets the value of a shader uniform of type int.|descriptionEnd| */
+void gfx_shader_set_int(int loc, int value);
+/* |description|Sets the value of a shader uniform of type float.|descriptionEnd| */
+void gfx_shader_set_float(int loc, float value);
+/* |description|Sets the value of a shader uniform of type vec2.|descriptionEnd| */
+void gfx_shader_set_vec2(int loc, float x, float y);
+/* |description|Sets the value of a shader uniform of type vec3.|descriptionEnd| */
+void gfx_shader_set_vec3(int loc, float x, float y, float z);
+/* |description|Sets the value of a shader uniform of type vec4.|descriptionEnd| */
+void gfx_shader_set_vec4(int loc, float w, float x, float y, float z);
+/* |description|Sets the value of a shader uniform of type mat4.|descriptionEnd| */
+void gfx_shader_set_mat4(int loc, const Mat4 mat);
/* |description|
diff --git a/src/pc/network/network.c b/src/pc/network/network.c
index 6bd1d4882..d25a9e943 100644
--- a/src/pc/network/network.c
+++ b/src/pc/network/network.c
@@ -773,6 +773,8 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup, bool reconnect
first_person_reset();
le_shutdown();
+ gfx_remove_all_color_combiners();
+ RAPI.remove_shaders();
extern void save_file_load_all(UNUSED u8 reload);
save_file_load_all(TRUE);