diff options
| author | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2025-02-12 18:05:18 +1100 |
|---|---|---|
| committer | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2025-02-12 18:05:18 +1100 |
| commit | 1cc08c51eb4b0f95c30c0a98ad1fc5ad3459b2df (patch) | |
| tree | 222dfcd07a1e40716127a347bbfd7119ce3d0984 /res/shaders/framebuffer.fs | |
initial commit
Diffstat (limited to 'res/shaders/framebuffer.fs')
| -rw-r--r-- | res/shaders/framebuffer.fs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/res/shaders/framebuffer.fs b/res/shaders/framebuffer.fs new file mode 100644 index 0000000..b644980 --- /dev/null +++ b/res/shaders/framebuffer.fs @@ -0,0 +1,100 @@ +#version 420 core + +in vec2 _f_texture; + +layout(binding = 2) uniform sampler2D main_colour; +layout(binding = 3) uniform sampler2D main_depth; +layout(binding = 4) uniform sampler2D water_colour; +layout(binding = 5) uniform sampler2D water_depth; + +layout(std140, binding = 0) uniform _u_globals { + mat4 proj; + mat4 view; + vec4 frustum[6]; + float znear; + float zfar; + float xfov; + float yfov; + int time; + float xwindow; + float ywindow; +}; + +uniform bool _u_is_underwater; + +const vec3 fog_colour = vec3(0.5f, 0.7f, 0.9f); +const vec3 underwater_fog_colour = vec3(0.137f, 0.275f, 0.694f); + +out vec4 _o_colour; + +vec4 texture_sample(const sampler2D sampler, const vec2 coord) { + return texture(sampler, coord); +} + +float depth_sample(const sampler2D sampler, const vec2 coord) { + return texture(sampler, coord).r; +} + +float linearise_depth(const float depth) { + const float z = depth * 2.0f - 1.0f; // normalised device coordinates + const float linear_depth = + (2.0 * znear * zfar) / (zfar + znear - (z * (zfar - znear))); + // Usually we would just return linear depth, but this is incorrect! We need + // to account for the additional distance of the frustum away from the + // center of the screen. Just some trigonomety + + const float xsigma = tan(xfov * 0.5) * zfar * _f_texture.x; + const float ysigma = tan(yfov * 0.5) * zfar * _f_texture.y; + const float dist = sqrt(xsigma * xsigma + ysigma * ysigma) / zfar; + + const float o_dist = linear_depth * dist; + return sqrt(o_dist * o_dist + linear_depth * linear_depth); +} + +float get_fog_intensity(const float distance) { + return clamp(pow((1.0f / (zfar * 0.6f)) * distance, 3.0f), 0.0f, 1.0f); +} + +float get_water_intensity(const float distance) { + return 1.0f - exp(0.5 * distance); +} + +void main() { + // We recycle the coordinates of our position into our texture coordinates. + const vec2 coords = + vec2((_f_texture.x + 1.0f) / 2.0f, (_f_texture.y + 1.0f) / 2.0f); + + const float main_depth = depth_sample(main_depth, coords); + const float main_distance = linearise_depth(main_depth); + const float water_depth = depth_sample(water_depth, coords); + const float water_distance = linearise_depth(water_depth); + + _o_colour = texture_sample(main_colour, coords); + if (!_u_is_underwater) { + if (water_depth < main_depth) { + _o_colour = + vec4(mix(vec3(_o_colour.rgb), + texture_sample(water_colour, coords).rgb, + get_water_intensity(water_distance - main_distance)), + 1.0f); + } + _o_colour = + vec4(mix(vec3(_o_colour.rgb), fog_colour, + get_fog_intensity(min(main_distance, water_distance))), + 1.0f); + } else { + _o_colour = vec4(mix(vec3(_o_colour.rgb), fog_colour, + get_fog_intensity(main_distance)), + 1.0f); + if (water_depth < main_depth) { + _o_colour = vec4(mix(vec3(_o_colour.rgb), + texture_sample(water_colour, coords).rgb, + get_water_intensity(-water_distance)), + 1.0f); + } else { + _o_colour = vec4(mix(vec3(_o_colour.rgb), underwater_fog_colour, + get_water_intensity(-main_distance)), + 1.0f); + } + } +} |
