How to use LUTs in shader to simulate day and night?
Asked Answered
W

5

0

I'd like to create a day night effect like in graveyard keeper: https://www.gamedeveloper.com/programming/graveyard-keeper-how-the-graphics-effects-are-made

They said they used a look up table, presumably in the shader, to color shift each pixel based on the day night cycle.

Can this be done in Godot?

Could I use a sampler2d as the look up table some how? I cant seem to find references for the shader data types...

Maybe a texture will work? Can a texture take an RGB float input and output an RGB value?

Wordless answered 2/10, 2021 at 15:40 Comment(0)
J
0

They packed slices of a 3d texture into 2d texture. It can be done in shader without any problems. Just calculate texture's UV coordinates from input RGB values and read the remapped RGB from that coordinates

Jocosity answered 2/10, 2021 at 15:52 Comment(0)
F
0

Yes, this can be done in Godot. The LUT is just a texture, and you can pass it to the shader as a sampler2d.

Fionafionna answered 2/10, 2021 at 16:54 Comment(0)
W
0

@cybereality @xyz thanks for the response. Can you guys point me to any documentation on sampler2d? is it an array? is it some other kind of data structure? What are the parameters it accepts and how does it store data? How is it related to the texture function and what does the texture function do?

Is it in the godot documentation and I'm just blind?

I searched everywhere and cant find any info on it...

Wordless answered 2/10, 2021 at 18:25 Comment(0)
J
0

There's not much to it really. It's basically like GLSL sampler2d type.

You can look at it as a handle to a 2d texture, like ID number. It doesn't store any data. It just points to texture data. You supply this id whenever you want to read from texture in the shader. And there are only few functions that read from texture: texture(), textureSize(), textureProj() and texelFetch().

The main one is texture(). It takes as arguments a handle to the texture (that is sampler2d) and UV coordinates in range 0-1 of the texel you want to read. And it returns vec4 with RGBA values from the texture. That's basically it.

uniform sampler2D myTexture;

void fragment(){
	vec4 colorFromTexture = texture(myTexture, UV); 
}

Of course you need to set this uniform from a script using set_shader_param() method of the material object:

material.set_shader_param("myTexture", textureObject)

You can find some of info in Shading Language reference in Godot docs: https://docs.godotengine.org/en/stable/tutorials/shading/shading_reference/shading_language.html?highlight=shading%20language

Jocosity answered 2/10, 2021 at 18:51 Comment(0)
J
0

@itgiawa Also note that texture() does not return exact pixel value from the texture bitmap. It rather "samples" the texture. Since uv coordinates are normalized and don't correspond to pixels, your sampling position will likely be off the exact pixel center and sampling with do bilinear or mipmap filtering, averaging neighboring pixels into the return value. That's why you see "blurry" textures on 3d models when texture resolution is low.

Notice that I didn't use texture() in example I posted in your other question, where texture is used to encode vectors. There you need to read exact pixel values, without filtering. Otherwise your data will be corrupted by filtering. So that's what texelFetch() function is for. It's similar to texture() but returns exact pixel value. Uv coordinates you supply at input are actual pixel coordinates, not normalized position inside the texture. The uv argument is thus not of type vec2, but rather ivec2 (integer vec2)

Jocosity answered 2/10, 2021 at 20:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.