Skip to content

Commit 0fe53a3

Browse files
committed
Add ability to transform scene color in shaders.
1 parent 81d62d0 commit 0fe53a3

File tree

10 files changed

+104
-2
lines changed

10 files changed

+104
-2
lines changed

builtin/game/features.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ core.features = {
4747
particle_blend_clip = true,
4848
remove_item_match_meta = true,
4949
httpfetch_additional_methods = true,
50+
vision_color_transform = true,
5051
}
5152

5253
function core.has_feature(arg)

builtin/game/misc_s.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ core.protocol_versions = {
130130
["5.10.0"] = 46,
131131
["5.11.0"] = 47,
132132
["5.12.0"] = 48,
133+
["5.13.0"] = 49,
133134
}
134135

135136
setmetatable(core.protocol_versions, {__newindex = function()

client/shaders/second_stage/opengl_fragment.glsl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ centroid varying vec2 varTexCoord;
3131
varying float exposure; // linear exposure factor, see vertex shader
3232
#endif
3333

34+
uniform mat3 colorTransformMatrix;
35+
3436
#ifdef ENABLE_BLOOM
3537

3638
vec4 applyBloom(vec4 color, vec2 uv)
@@ -103,6 +105,12 @@ vec3 screen_space_dither(highp vec2 frag_coord) {
103105
}
104106
#endif
105107

108+
vec4 applyColorVision(vec4 color)
109+
{
110+
vec3 transformedColor = colorTransformMatrix * color.rgb;
111+
return vec4(transformedColor, color.a);
112+
}
113+
106114
void main(void)
107115
{
108116
vec2 uv = varTexCoord.st;
@@ -133,6 +141,7 @@ void main(void)
133141
color = applyBloom(color, uv);
134142
#endif
135143

144+
color = applyColorVision(color);
136145

137146
color.rgb = clamp(color.rgb, vec3(0.), vec3(1.));
138147

doc/lua_api.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5810,6 +5810,8 @@ Utilities
58105810
remove_item_match_meta = true,
58115811
-- The HTTP API supports the HEAD and PATCH methods (5.12.0)
58125812
httpfetch_additional_methods = true,
5813+
-- Scene color can be transformed by transform matrix (5.13.0)
5814+
vision_color_transform = true,
58135815
}
58145816
```
58155817

@@ -9048,6 +9050,20 @@ child will follow movement and rotation of that bone.
90489050
* Currently, bloom `intensity` and `strength_factor` affect volumetric
90499051
lighting `strength` and vice versa. This behavior is to be changed
90509052
in the future, do not rely on it.
9053+
* `vision_effects`: is a table that controls vision effects
9054+
* `color_transform_matrix`: is a matrix with default value (identity matrix):
9055+
```lua
9056+
{ {1.0, 0.0, 0.0},
9057+
{0.0, 1.0, 0.0},
9058+
{0.0, 0.0, 1.0}}
9059+
```
9060+
* can be used for creation color blind effect, base for night vision effect etc.
9061+
```lua
9062+
-- example of night vision like transform
9063+
{ {0.0, 0.0, 0.0},
9064+
{1.0, 9.0, 1.0},
9065+
{0.0, 0.0, 0.0}}
9066+
```
90519067

90529068
* `get_lighting()`: returns the current state of lighting for the player.
90539069
* Result is a table with the same fields as `light_definition` in `set_lighting`.

src/client/game.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,9 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter
231231
CachedPixelShaderSetting<float>
232232
m_volumetric_light_strength_pixel{"volumetricLightStrength"};
233233

234+
CachedPixelShaderSetting<float, 9>
235+
m_color_transform_matrix{"colorTransformMatrix"};
236+
234237
static constexpr std::array<const char*, 1> SETTING_CALLBACKS = {
235238
"exposure_compensation",
236239
};
@@ -321,6 +324,8 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter
321324
m_bloom_radius_pixel.set(&radius, services);
322325
}
323326

327+
m_color_transform_matrix.set(lighting.vision_effects.color_transform_matrix.data(), services);
328+
324329
float saturation = lighting.saturation;
325330
m_saturation_pixel.set(&saturation, services);
326331

src/lighting.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@ struct AutoExposure
4040
{}
4141
};
4242

43+
struct VisionEffects
44+
{
45+
std::array<float, 9> color_transform_matrix;
46+
47+
constexpr VisionEffects()
48+
: color_transform_matrix{
49+
1.0f, 0.0f, 0.0f,
50+
0.0f, 1.0f, 0.0f,
51+
0.0f, 0.0f, 1.0f}
52+
{}
53+
};
54+
4355
/** Describes ambient light settings for a player
4456
*/
4557
struct Lighting
@@ -52,4 +64,5 @@ struct Lighting
5264
float bloom_intensity {0.05f};
5365
float bloom_strength_factor {1.0f};
5466
float bloom_radius {1.0f};
67+
VisionEffects vision_effects;
5568
};

src/network/clientpackethandler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,4 +1794,9 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
17941794
>> lighting.bloom_strength_factor
17951795
>> lighting.bloom_radius;
17961796
}
1797+
if (pkt->getRemainingBytes() >= 36) {
1798+
for (int i = 0; i < 9; ++i) {
1799+
*pkt >> lighting.vision_effects.color_transform_matrix[i];
1800+
}
1801+
}
17971802
}

src/network/networkprotocol.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,13 @@
6565
PROTOCOL VERSION 48
6666
Add compression to some existing packets
6767
[scheduled bump for 5.12.0]
68+
PROTOCOL VERSION 49
69+
Add "vision_effects" to TOCLIENT_SET_LIGHTING packet
70+
[scheduled bump for 5.13.0]
6871
*/
6972

7073
// Note: Also update core.protocol_versions in builtin when bumping
71-
const u16 LATEST_PROTOCOL_VERSION = 48;
74+
const u16 LATEST_PROTOCOL_VERSION = 49;
7275

7376
// See also formspec [Version History] in doc/lua_api.md
7477
const u16 FORMSPEC_API_VERSION = 9;

src/script/lua_api/l_object.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2694,7 +2694,39 @@ int ObjectRef::l_set_lighting(lua_State *L)
26942694
lighting.bloom_radius = getfloatfield_default(L, -1, "radius", lighting.bloom_radius);
26952695
}
26962696
lua_pop(L, 1); // bloom
2697-
}
2697+
2698+
lua_getfield(L, 2, "vision_effects");
2699+
if (!lua_isnoneornil(L, -1)) {
2700+
if (!lua_istable(L, -1))
2701+
throw LuaError("vision_effects is not a table");
2702+
2703+
lua_getfield(L, 3, "color_transform_matrix");
2704+
2705+
// if none or nil, keep color transform matrix unchanged
2706+
if (!lua_isnoneornil(L, -1)) {
2707+
if (!lua_istable(L, -1))
2708+
throw LuaError("vision_effects.color_transform_matrix is not a table");
2709+
2710+
for (int row = 1; row <= 3; ++row) {
2711+
lua_rawgeti(L, -1, row);
2712+
if (!lua_istable(L, -1))
2713+
throw LuaError("color_transform_matrix should be in format {{a, b, c},{d, e, f},{g, a, h}}");
2714+
2715+
for (int col = 1; col <= 3; ++col) {
2716+
lua_rawgeti(L, -1, col);
2717+
if (!lua_isnumber(L, -1))
2718+
throw LuaError("color_transform_matrix should be in format {{a, b, c},{d, e, f},{g, a, h}}");
2719+
2720+
lighting.vision_effects.color_transform_matrix[(row - 1) * 3 + (col - 1)] = (float)lua_tonumber(L, -1);
2721+
lua_pop(L, 1); // Pop the value at [row][col]
2722+
}
2723+
lua_pop(L, 1); // Pop the row table
2724+
}
2725+
}
2726+
lua_pop(L, 1); // color_transform_matrix
2727+
}
2728+
lua_pop(L, 1); // vision_effects
2729+
}
26982730

26992731
getServer(L)->setLighting(player, lighting);
27002732
return 0;
@@ -2746,6 +2778,19 @@ int ObjectRef::l_get_lighting(lua_State *L)
27462778
lua_pushnumber(L, lighting.bloom_radius);
27472779
lua_setfield(L, -2, "radius");
27482780
lua_setfield(L, -2, "bloom");
2781+
lua_newtable(L); // "vision_effects"
2782+
lua_newtable(L); // "color_transform_matrix"
2783+
// Create the nested table structure {{a, b, c}, {d, e, f}, {g, h, i}}
2784+
for (int row = 0; row < 3; row++) {
2785+
lua_newtable(L); // Create inner row table
2786+
for (int col = 0; col < 3; col++) {
2787+
lua_pushnumber(L, lighting.vision_effects.color_transform_matrix[row * 3 + col]); // Push the value
2788+
lua_rawseti(L, -2, col + 1); // Set value in inner table with 1-based indexing
2789+
}
2790+
lua_rawseti(L, -2, row + 1); // Set inner table in the outer matrix table
2791+
}
2792+
lua_setfield(L, -2, "color_transform_matrix");
2793+
lua_setfield(L, -2, "vision_effects");
27492794
return 1;
27502795
}
27512796

src/server.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,6 +1953,10 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
19531953
pkt << lighting.bloom_intensity << lighting.bloom_strength_factor <<
19541954
lighting.bloom_radius;
19551955

1956+
for (int i = 0; i < 9; ++i) {
1957+
pkt << lighting.vision_effects.color_transform_matrix[i];
1958+
}
1959+
19561960
Send(&pkt);
19571961
}
19581962

0 commit comments

Comments
 (0)