diff options
| author | tech kaczynski <tk@techkaczynski.dev> | 2026-09-22 22:38:57 +1000 |
|---|---|---|
| committer | tech kaczynski <tk@techkaczynski.dev> | 2026-09-22 22:38:57 +1000 |
| commit | 08cb8d6a585dd552b69a488d9db1be123f01467a (patch) | |
| tree | 77d50ce30bbc102b08486929ba654b5bef70af43 /res/sdr | |
initial commit.
Diffstat (limited to 'res/sdr')
| -rw-r--r-- | res/sdr/mdl_lit.fs | 69 | ||||
| -rw-r--r-- | res/sdr/mdl_lit.vs | 28 | ||||
| -rw-r--r-- | res/sdr/mdl_vtx_lit.fs | 29 | ||||
| -rw-r--r-- | res/sdr/mdl_vtx_lit.vs | 64 | ||||
| -rw-r--r-- | res/sdr/ocean.fs | 264 | ||||
| -rw-r--r-- | res/sdr/ocean.vs | 16 | ||||
| -rw-r--r-- | res/sdr/sky.fs | 72 | ||||
| -rw-r--r-- | res/sdr/sky_halo_old.fs | 279 | ||||
| -rw-r--r-- | res/sdr/sky_old.fs | 92 |
9 files changed, 913 insertions, 0 deletions
diff --git a/res/sdr/mdl_lit.fs b/res/sdr/mdl_lit.fs new file mode 100644 index 0000000..f3a51c6 --- /dev/null +++ b/res/sdr/mdl_lit.fs @@ -0,0 +1,69 @@ +#version 330 + +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +uniform vec3 sun_direction; +uniform vec3 sun_colour; +uniform float sun_intensity; + +uniform vec3 moon_direction; +uniform vec3 moon_colour; +uniform float moon_intensity; + +uniform vec3 ambient_colour; +uniform float ambient_intensity; + +in vec2 frag_texcoord; +in vec4 frag_colour; +in vec3 frag_world_normal; + +out vec4 finalColor; + +void +main() +{ + vec3 normal = normalize(frag_world_normal); + + // float sun_diffuse = max( + // dot(normal, sun_direction), + // 0.0 + // ); + + // half lambert + float sun_diffuse = dot(normal, sun_direction) * 0.5 + 0.5; + sun_diffuse *= sun_diffuse; + + float moon_diffuse = max( + dot(normal, moon_direction), + 0.0 + ); + + vec3 ambient_light = + ambient_colour * ambient_intensity; + + vec3 sun_light = + sun_colour * + sun_intensity * + sun_diffuse; + + vec3 moon_light = + moon_colour * + moon_intensity * + moon_diffuse; + + vec3 lighting = + ambient_light + + sun_light + + moon_light; + + vec4 texel = + texture(texture0, frag_texcoord) * + colDiffuse * + frag_colour; + + finalColor = vec4( + texel.rgb * max(lighting, vec3(0.0)), + texel.a + ); +} diff --git a/res/sdr/mdl_lit.vs b/res/sdr/mdl_lit.vs new file mode 100644 index 0000000..eb13a28 --- /dev/null +++ b/res/sdr/mdl_lit.vs @@ -0,0 +1,28 @@ +#version 330 + +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; + +uniform mat4 mvp; +uniform mat4 matNormal; + +out vec2 frag_texcoord; +out vec4 frag_colour; +out vec3 frag_world_normal; + +void +main() { + frag_texcoord = vertexTexCoord; + frag_colour = vertexColor; + + /* + * Do not necessarily normalize here. Interpolation changes the + * length, so the fragment shader must normalize it regardless. + */ + frag_world_normal = + (matNormal * vec4(vertexNormal, 0.0)).xyz; + + gl_Position = mvp * vec4(vertexPosition, 1.0); +} diff --git a/res/sdr/mdl_vtx_lit.fs b/res/sdr/mdl_vtx_lit.fs new file mode 100644 index 0000000..d2320c9 --- /dev/null +++ b/res/sdr/mdl_vtx_lit.fs @@ -0,0 +1,29 @@ +#version 330 + +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +in vec2 frag_texcoord; +in vec4 frag_colour; +in vec3 frag_lighting; + +out vec4 finalColor; + +void +main() { + vec4 texel = + texture(texture0, frag_texcoord) * + // colDiffuse * + frag_colour + + colDiffuse; + + vec3 lighting = max( + frag_lighting, + vec3(0.0) + ); + + finalColor = vec4( + texel.rgb * lighting, + texel.a + ); +} diff --git a/res/sdr/mdl_vtx_lit.vs b/res/sdr/mdl_vtx_lit.vs new file mode 100644 index 0000000..c69cb3d --- /dev/null +++ b/res/sdr/mdl_vtx_lit.vs @@ -0,0 +1,64 @@ +#version 330 + +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; + +uniform mat4 mvp; +uniform mat4 matNormal; + +uniform vec3 sun_direction; +uniform vec3 sun_colour; +uniform float sun_intensity; + +uniform vec3 moon_direction; +uniform vec3 moon_colour; +uniform float moon_intensity; + +uniform vec3 ambient_colour; +uniform float ambient_intensity; + +out vec2 frag_texcoord; +out vec4 frag_colour; +out vec3 frag_lighting; + +void +main() { + vec3 world_normal = normalize( + (matNormal * vec4(vertexNormal, 0.0)).xyz + ); + + float sun_diffuse = max( + dot(world_normal, sun_direction), + 0.0 + ); + + float moon_diffuse = max( + dot(world_normal, moon_direction), + 0.0 + ); + + vec3 ambient_light = + ambient_colour * ambient_intensity; + + vec3 sun_light = + sun_colour * + sun_intensity * + sun_diffuse; + + vec3 moon_light = + moon_colour * + moon_intensity * + moon_diffuse; + + frag_lighting = + ambient_light + + sun_light + + moon_light; + + frag_texcoord = vertexTexCoord; + frag_colour = vertexColor; + + gl_Position = mvp * vec4(vertexPosition, 1.0); +} diff --git a/res/sdr/ocean.fs b/res/sdr/ocean.fs new file mode 100644 index 0000000..53b81f5 --- /dev/null +++ b/res/sdr/ocean.fs @@ -0,0 +1,264 @@ +#version 330 + +in vec3 world_position; + +uniform float time; +uniform vec3 camera_position; + +uniform vec3 sun_direction; +uniform vec3 moon_direction; +uniform vec3 sun_colour; +uniform vec3 moon_colour; +uniform vec3 ambient_colour; +uniform vec3 horizon_colour; +uniform vec3 zenith_colour; + +uniform float sun_intensity; +uniform float moon_intensity; +uniform float ambient_intensity; + +out vec4 finalColor; + +float +hash12(vec2 position) { + vec3 hash_value = fract(position.xyx * 0.1031); + hash_value += dot(hash_value, hash_value.yzx + vec3(33.33)); + + return fract((hash_value.x + hash_value.y) * hash_value.z); +} + +float +noise2(vec2 position) { + vec2 cell = floor(position); + vec2 fraction = fract(position); + vec2 curve = fraction * fraction * + (vec2(3.0) - 2.0 * fraction); + + float a = hash12(cell); + float b = hash12(cell + vec2(1.0, 0.0)); + float c = hash12(cell + vec2(0.0, 1.0)); + float d = hash12(cell + vec2(1.0, 1.0)); + + return mix( + mix(a, b, curve.x), + mix(c, d, curve.x), + curve.y + ); +} + +float +fbm(vec2 position) { + vec2 sample_position = position; + float value = 0.0; + + value += noise2(sample_position) * 0.500; + sample_position *= 2.02; + + value += noise2(sample_position) * 0.250; + sample_position *= 2.03; + + value += noise2(sample_position) * 0.125; + sample_position *= 2.01; + + value += noise2(sample_position) * 0.0625; + + return value; +} + +float +wave_height(vec2 position) { + vec2 domain = position * 0.008; + + vec2 warp = vec2( + fbm(domain * 0.8 + vec2(time * 0.030, 0.0)), + fbm(domain * 0.8 + vec2(7.3, time * 0.024)) + ); + + domain += (warp - vec2(0.5)) * 1.8; + + float wave_a = sin(dot(domain, normalize(vec2(1.0, 0.28))) * + 7.0 + time * 0.45); + + float wave_b = sin(dot(domain, normalize(vec2(-0.42, 1.0))) * + 11.0 + time * 0.72); + + float wave_c = sin(dot(domain, normalize(vec2(0.75, 0.63))) * + 15.0 - time * 0.95); + + float wave_d = sin(dot(domain, normalize(vec2(-0.88, 0.18))) * + 5.0 + time * 0.28); + + return wave_a * 0.50 + wave_b * 0.25 + + wave_c * 0.15 + wave_d * 0.10; +} + +vec3 +wave_normal(vec2 position) { + const float offset = 2.0; + + float height = wave_height(position); + float height_x = wave_height(position + vec2(offset, 0.0)); + float height_z = wave_height(position + vec2(0.0, offset)); + + return normalize(vec3( + height - height_x, + 0.55, + height - height_z + )); +} + +float +light_glint(vec3 normal, vec3 view_direction, + vec3 light_direction, float power) { + vec3 half_direction = normalize( + light_direction + view_direction + ); + + return pow(max(dot(normal, half_direction), 0.0), power); +} + +void +main() { + vec2 position = world_position.xz; + + vec3 normal = wave_normal(position); + vec3 view_direction = normalize( + camera_position - world_position + ); + + /* Large-scale irregular turquoise/blue variation. */ + float patch_a = fbm( + position * 0.0025 + vec2(time * 0.010, 3.1) + ); + + float patch_b = fbm( + position * 0.0013 + vec2(-2.7, time * 0.006) + ); + + float water_patch = clamp( + patch_a * 0.65 + patch_b * 0.35, + 0.0, 1.0 + ); + + vec3 deep_blue = vec3(0.02, 0.42, 0.70); + vec3 turquoise = vec3(0.03, 0.73, 0.74); + vec3 aqua = vec3(0.16, 0.78, 0.88); + + vec3 base_colour = mix( + deep_blue, turquoise, water_patch + ); + + base_colour = mix( + base_colour, + aqua, + smoothstep(0.72, 1.0, water_patch) + ); + + /* + * Actually light the base water using the current environment. + * During the day this stays bright; at night it becomes properly + * dark and takes on the ambient sky colour. + */ + vec3 ambient_light = + vec3(0.10) + + ambient_colour * ambient_intensity * 1.8; + + vec3 colour = base_colour * ambient_light; + + /* + * Fake reflected sky. The reflected wave normal determines + * whether we see more horizon or zenith colour. + */ + float facing = max(dot(normal, view_direction), 0.0); + float fresnel = 1.0 - facing; + fresnel *= fresnel; + fresnel *= fresnel; + + vec3 reflected_direction = reflect( + -view_direction, + normal + ); + + float sky_height = smoothstep( + -0.12, 0.70, reflected_direction.y + ); + + vec3 reflected_sky = mix( + horizon_colour, + zenith_colour, + sky_height + ); + + colour = mix( + colour, + reflected_sky, + 0.18 + fresnel * 0.45 + ); + + /* Sun and moon glints. */ + float sun_glint = light_glint( + normal, + view_direction, + normalize(sun_direction), + 24.0 + ); + + float moon_glint = light_glint( + normal, + view_direction, + normalize(moon_direction), + 20.0 + ); + + colour += sun_colour * sun_glint * + sun_intensity * 0.30; + + colour += moon_colour * moon_glint * + moon_intensity * 0.18; + + /* Irregular whitecaps. */ + float cap_a = fbm( + position * 0.020 + + vec2(time * 0.080, -time * 0.050) + ); + + float cap_b = fbm( + position * 0.045 + + vec2(-4.0, time * 0.110) + ); + + float cap_field = cap_a * 0.55 + cap_b * 0.45; + + float crest = wave_height( + position * 1.35 + vec2(17.0, -9.0) + ) * 0.5 + 0.5; + + float steepness = clamp( + 1.0 - normal.y, + 0.0, 1.0 + ); + + float whitecap = + smoothstep(0.72, 0.86, cap_field) * + smoothstep(0.58, 0.80, crest) * + smoothstep(0.02, 0.10, steepness); + + /* + * Foam also receives environment lighting rather than remaining + * glowing white at night. + */ + vec3 foam_colour = vec3(0.92, 0.98, 0.98); + foam_colour *= vec3(0.18) + + ambient_colour * ambient_intensity * 1.5; + + foam_colour += sun_colour * + sun_intensity * 0.25; + + colour = mix( + colour, + foam_colour, + whitecap * 0.90 + ); + + finalColor = vec4(0.03, 0.73, 0.74, 1.0); +} diff --git a/res/sdr/ocean.vs b/res/sdr/ocean.vs new file mode 100644 index 0000000..517d0aa --- /dev/null +++ b/res/sdr/ocean.vs @@ -0,0 +1,16 @@ +#version 330 + +in vec3 vertexPosition; + +uniform mat4 mvp; +uniform mat4 matModel; + +out vec3 world_position; + +void +main() { + vec4 world = matModel * vec4(vertexPosition, 1.0); + world_position = world.xyz; + + gl_Position = mvp * vec4(vertexPosition, 1.0); +} diff --git a/res/sdr/sky.fs b/res/sdr/sky.fs new file mode 100644 index 0000000..8fde0f2 --- /dev/null +++ b/res/sdr/sky.fs @@ -0,0 +1,72 @@ +#version 330 + +uniform vec2 resolution; + +uniform vec3 camera_forward; +uniform vec3 camera_right; +uniform vec3 camera_up; +uniform vec3 sun_direction; + +uniform vec3 horizon_colour; +uniform vec3 zenith_colour; + +uniform float day_amount; +uniform float twilight_amount; +uniform float tan_half_fovy; + +out vec4 finalColor; + +void +main() { + vec2 ndc = gl_FragCoord.xy / resolution * 2.0 - 1.0; + float aspect_ratio = resolution.x / resolution.y; + + vec3 view_direction = normalize( + camera_forward + + camera_right * ndc.x * aspect_ratio * tan_half_fovy + + camera_up * ndc.y * tan_half_fovy + ); + + float height = smoothstep(-0.20, 0.80, view_direction.y); + float horizon = 1.0 - smoothstep(0.0, 0.35, abs(view_direction.y)); + + vec3 sky = mix(horizon_colour, zenith_colour, height); + + float sun_alignment = dot(view_direction, sun_direction); + float sun_facing = max(sun_alignment, 0.0); + float sun_facing_2 = sun_facing * sun_facing; + float sun_facing_4 = sun_facing_2 * sun_facing_2; + + sky += vec3(0.65, 0.16, 0.035) * + horizon * twilight_amount * sun_facing_4; + + float sun_wide = smoothstep(0.9510565, 0.9986295, sun_alignment); + float sun_core = smoothstep(0.9925462, 0.9998477, sun_alignment); + + float moon_alignment = -sun_alignment; + float moon_wide = smoothstep(0.9702957, 0.9993908, moon_alignment); + float moon_core = smoothstep(0.9961947, 0.9999619, moon_alignment); + + float sun_visibility = smoothstep(-0.12, 0.04, sun_direction.y); + float moon_visibility = smoothstep(-0.10, 0.04, -sun_direction.y); + + vec3 sun_glow_colour = mix( + vec3(1.00, 0.82, 0.38), + vec3(1.00, 0.25, 0.035), + twilight_amount + ); + + vec3 moon_glow_colour = vec3(0.32, 0.46, 0.82); + + float sun_glow = + (sun_wide * 0.13 + sun_core * 0.32) * sun_visibility; + + float moon_glow = + (moon_wide * 0.08 + moon_core * 0.17) * + moon_visibility * (1.0 - day_amount); + + sky += (1.0 - sky) * sun_glow_colour * sun_glow; + sky += (1.0 - sky) * moon_glow_colour * moon_glow; + + finalColor = vec4(clamp(sky, 0.0, 1.0), 1.0); +} diff --git a/res/sdr/sky_halo_old.fs b/res/sdr/sky_halo_old.fs new file mode 100644 index 0000000..50f2002 --- /dev/null +++ b/res/sdr/sky_halo_old.fs @@ -0,0 +1,279 @@ +#version 330 + +uniform vec2 resolution; + +uniform vec3 camera_forward; +uniform vec3 camera_right; +uniform vec3 camera_up; + +uniform vec3 sun_direction; + +uniform float aspect_ratio; +uniform float tan_half_fovy; + +out vec4 finalColor; + +void +main() +{ + /* + * Reconstruct a world-space direction for this screen pixel. + */ + vec2 screen = gl_FragCoord.xy / resolution; + vec2 ndc = screen * 2.0 - 1.0; + + vec3 view_direction = normalize( + camera_forward + + camera_right * ndc.x * aspect_ratio * tan_half_fovy + + camera_up * ndc.y * tan_half_fovy + ); + + vec3 moon_direction = -sun_direction; + + /* + * Vertical sky gradient. + */ + float height = smoothstep( + -0.20, + 0.80, + view_direction.y + ); + + /* + * Day/night transition based on the sun's elevation. + */ + float day_amount = smoothstep( + -0.10, + 0.12, + sun_direction.y + ); + + float night_amount = 1.0 - day_amount; + + vec3 night_horizon = vec3( + 0.055, + 0.045, + 0.110 + ); + + vec3 night_zenith = vec3( + 0.005, + 0.008, + 0.025 + ); + + vec3 day_horizon = vec3( + 0.620, + 0.780, + 0.920 + ); + + vec3 day_zenith = vec3( + 0.080, + 0.280, + 0.620 + ); + + vec3 night_sky = mix( + night_horizon, + night_zenith, + height + ); + + vec3 day_sky = mix( + day_horizon, + day_zenith, + height + ); + + vec3 sky = mix( + night_sky, + day_sky, + day_amount + ); + + /* + * Sunrise and sunset colouring. + */ + float horizon = + 1.0 - + smoothstep( + 0.0, + 0.35, + abs(view_direction.y) + ); + + float twilight = + 1.0 - + smoothstep( + 0.02, + 0.28, + abs(sun_direction.y) + ); + + float sun_alignment = dot( + view_direction, + sun_direction + ); + + float sun_facing = max( + sun_alignment, + 0.0 + ); + + /* + * Avoid pow(): x^4 is sufficient for the broad sunset effect. + */ + float sun_facing_2 = sun_facing * sun_facing; + float sun_facing_4 = sun_facing_2 * sun_facing_2; + + vec3 sunset_colour = vec3( + 0.65, + 0.16, + 0.035 + ); + + sky += + sunset_colour * + horizon * + twilight * + sun_facing_4; + + /* + * Sun halo. + * + * The values are precalculated cosine values. Since both + * view_direction and sun_direction are normalized, their dot + * product is the cosine of the angle between them. + * + * Wide halo: + * outer edge: 18 degrees + * inner edge: 3 degrees + * + * Core halo: + * outer edge: 7 degrees + * inner edge: 1 degree + */ + float sun_wide = smoothstep( + 0.9510565, + 0.9986295, + sun_alignment + ); + + float sun_core = smoothstep( + 0.9925462, + 0.9998477, + sun_alignment + ); + + /* + * Moon halo. + * + * Because the moon is directly opposite the sun in this model, + * its alignment is the negative sun alignment. + * + * Wide halo: + * outer edge: 14 degrees + * inner edge: 2 degrees + * + * Core halo: + * outer edge: 5 degrees + * inner edge: 0.5 degrees + */ + float moon_alignment = -sun_alignment; + + float moon_wide = smoothstep( + 0.9702957, + 0.9993908, + moon_alignment + ); + + float moon_core = smoothstep( + 0.9961947, + 0.9999619, + moon_alignment + ); + + /* + * Fade each halo near and below the horizon. + * + * These ranges are deliberately broader than the symbol fade so + * the surrounding light disappears gradually. + */ + float sun_above_horizon = smoothstep( + -0.12, + 0.04, + sun_direction.y + ); + + float moon_above_horizon = smoothstep( + -0.10, + 0.04, + moon_direction.y + ); + + /* + * Warm the sun halo around sunrise and sunset. + */ + vec3 daylight_glow = vec3( + 1.00, + 0.82, + 0.38 + ); + + vec3 sunset_glow = vec3( + 1.00, + 0.25, + 0.035 + ); + + vec3 sun_glow_colour = mix( + daylight_glow, + sunset_glow, + twilight + ); + + vec3 moon_glow_colour = vec3( + 0.32, + 0.46, + 0.82 + ); + + /* + * Broad component blends the sprite into the sky. + * Core component makes the centre appear luminous. + */ + float sun_glow = + ( + sun_wide * 0.13 + + sun_core * 0.32 + ) * + sun_above_horizon; + + float moon_glow = + ( + moon_wide * 0.08 + + moon_core * 0.17 + ) * + moon_above_horizon * + night_amount; + + /* + * Soft screen-like blending. This brightens the sky without + * immediately clipping bright daytime colours to white. + */ + sky += + (1.0 - sky) * + sun_glow_colour * + sun_glow; + + sky += + (1.0 - sky) * + moon_glow_colour * + moon_glow; + + finalColor = vec4( + clamp(sky, 0.0, 1.0), + 1.0 + ); +} diff --git a/res/sdr/sky_old.fs b/res/sdr/sky_old.fs new file mode 100644 index 0000000..039691c --- /dev/null +++ b/res/sdr/sky_old.fs @@ -0,0 +1,92 @@ +#version 330 + +uniform vec2 resolution; +uniform vec3 camera_forward; +uniform vec3 camera_right; +uniform vec3 camera_up; + +uniform vec3 sun_direction; + +uniform float aspect_ratio; +uniform float tan_half_fovy; + +out vec4 finalColor; + +float +angular_halo(float alignment, float outer_cos, float inner_cos) { + /* + * alignment is 1.0 while looking directly at the celestial body. + * + * outer_cos = cos(outer halo angle) + * inner_cos = cos(inner halo angle) + */ + return smoothstep( + outer_cos, + inner_cos, + alignment + ); +} + +void +main() { + vec2 screen = gl_FragCoord.xy / resolution; + vec2 ndc = screen * 2.0 - 1.0; + + vec3 view_direction = normalize( + camera_forward + + camera_right * ndc.x * aspect_ratio * tan_half_fovy + + camera_up * ndc.y * tan_half_fovy + ); + + /* + * Controls the vertical gradient. + * + * -0.2 includes some colour below the horizon so the transition + * remains smooth while looking downward. + */ + float height = smoothstep(-0.20, 0.80, view_direction.y); + + /* + * The world becomes mostly daylight shortly after the sun crosses + * the horizon, and mostly night shortly after it sets. + */ + float day_amount = smoothstep(-0.10, 0.12, sun_direction.y); + + vec3 night_horizon = vec3(0.055, 0.045, 0.110); + vec3 night_zenith = vec3(0.005, 0.008, 0.025); + + vec3 day_horizon = vec3(0.620, 0.780, 0.920); + vec3 day_zenith = vec3(0.080, 0.280, 0.620); + + vec3 night_sky = mix(night_horizon, night_zenith, height); + vec3 day_sky = mix(day_horizon, day_zenith, height); + + vec3 sky = mix(night_sky, day_sky, day_amount); + + /* + * Stylized sunrise/sunset colour. + * + * This is strongest: + * - near the horizon; + * - while the sun is near the horizon; + * - while looking toward the sun. + */ + float horizon = + 1.0 - smoothstep(0.0, 0.35, abs(view_direction.y)); + + float twilight = + 1.0 - smoothstep(0.02, 0.28, abs(sun_direction.y)); + + float sun_facing = max(dot(view_direction, sun_direction), 0.0); + float sun_facing_2 = sun_facing * sun_facing; + float sun_facing_4 = sun_facing_2 * sun_facing_2; + + vec3 sunset_colour = vec3(0.65, 0.16, 0.035); + + sky += sunset_colour * + horizon * + twilight * + sun_facing_4; + + finalColor = vec4(min(sky, vec3(1.0)), 1.0); +} |
