Sharpen the static ice surface
Ridged grain replaces the smooth swells, and two families of fracture lines step the height, so the refracted sheets break across hard seams instead of drifting. The height field stays time-independent: only the plasma moves. Grazing rays at a step are clamped so the sheets never smear off the atlas.
This commit is contained in:
+26
-3
@@ -24,14 +24,29 @@ float fbm(vec2 p) {
|
|||||||
for (int i = 0; i < 3; i++) { sum += amp * noise(p); p = mat2(1.62, 1.17, -1.17, 1.62) * p; amp *= 0.5; }
|
for (int i = 0; i < 3; i++) { sum += amp * noise(p); p = mat2(1.62, 1.17, -1.17, 1.62) * p; amp *= 0.5; }
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
float fbm2(vec2 p) {
|
||||||
|
return 0.5 * noise(p) + 0.25 * noise(mat2(1.62, 1.17, -1.17, 1.62) * p);
|
||||||
|
}
|
||||||
vec2 atlasUV(vec2 world, float layer) {
|
vec2 atlasUV(vec2 world, float layer) {
|
||||||
vec2 uv = world / (2.0 * EXTENT) + 0.5;
|
vec2 uv = world / (2.0 * EXTENT) + 0.5;
|
||||||
uv = clamp(uv, 0.5 / u_tile_res, 1.0 - 0.5 / u_tile_res); // keep bilinear taps inside the tile
|
uv = clamp(uv, 0.5 / u_tile_res, 1.0 - 0.5 / u_tile_res); // keep bilinear taps inside the tile
|
||||||
return (vec2(mod(layer, 4.0), floor(layer / 4.0)) + uv) / vec2(4.0, 2.0);
|
return (vec2(mod(layer, 4.0), floor(layer / 4.0)) + uv) / vec2(4.0, 2.0);
|
||||||
}
|
}
|
||||||
// Smooth frozen surface: two octaves, no bubbles, no grain.
|
// The slab's fracture lines: two families of long, slightly wandering cracks. Shared
|
||||||
|
// by the height field and the sheen, so each crack is both a bright seam and a step.
|
||||||
|
vec2 fracture(vec2 x) {
|
||||||
|
float d = fbm(x * 0.62 + 3.0) - 0.5; // zero set: long winding cracks
|
||||||
|
float e = fbm(x * 1.35 - 7.0) - 0.5; // a sparser second family
|
||||||
|
return vec2(d, e);
|
||||||
|
}
|
||||||
|
// Frozen surface: fine ridged grain over the plates the cracks have lifted apart.
|
||||||
|
// Static in world space; only the plasma behind it moves.
|
||||||
float height(vec2 x) {
|
float height(vec2 x) {
|
||||||
return 0.15 * fbm(x * 1.3 + 2.0) + 0.05 * fbm(x * 3.7 - 5.0);
|
vec2 fr = fracture(x);
|
||||||
|
return 0.085 * (1.0 - abs(2.0 * fbm2(x * 1.9 + 2.0) - 1.0))
|
||||||
|
+ 0.030 * (1.0 - abs(2.0 * fbm2(x * 4.6 - 5.0) - 1.0))
|
||||||
|
+ 0.020 * clamp(fr.x * 60.0, -1.0, 1.0) // the slab sits at a different level
|
||||||
|
+ 0.012 * clamp(fr.y * 60.0, -1.0, 1.0); // on each side of a crack
|
||||||
}
|
}
|
||||||
void main() {
|
void main() {
|
||||||
vec2 screen = gl_FragCoord.xy / u_res;
|
vec2 screen = gl_FragCoord.xy / u_res;
|
||||||
@@ -57,7 +72,7 @@ void main() {
|
|||||||
vec2 shearR = (refract(ray, normal, 1.0 / (IOR - 0.012)) - inside).xy;
|
vec2 shearR = (refract(ray, normal, 1.0 / (IOR - 0.012)) - inside).xy;
|
||||||
vec2 shearB = (refract(ray, normal, 1.0 / (IOR + 0.016)) - inside).xy;
|
vec2 shearB = (refract(ray, normal, 1.0 / (IOR + 0.016)) - inside).xy;
|
||||||
inside = normalize(inside);
|
inside = normalize(inside);
|
||||||
if (inside.z > -0.05) inside = vec3(0.0, 0.0, -1.0);
|
inside.z = min(inside.z, -0.50); // bound grazing rays at the crack steps
|
||||||
|
|
||||||
// Recentre the parallax on the middle of the sheet stack: near and far sheets
|
// Recentre the parallax on the middle of the sheet stack: near and far sheets
|
||||||
// then slide past each other at different rates as the pointer moves.
|
// then slide past each other at different rates as the pointer moves.
|
||||||
@@ -89,6 +104,14 @@ void main() {
|
|||||||
float fresnel = pow(1.0 - facing, 5.0);
|
float fresnel = pow(1.0 - facing, 5.0);
|
||||||
vec3 sky = mix(vec3(0.004, 0.016, 0.030), vec3(0.075, 0.220, 0.320), normal.y * 0.5 + 0.5);
|
vec3 sky = mix(vec3(0.004, 0.016, 0.030), vec3(0.075, 0.220, 0.320), normal.y * 0.5 + 0.5);
|
||||||
col += sky * (fresnel * 1.2 + bevel * 0.03);
|
col += sky * (fresnel * 1.2 + bevel * 0.03);
|
||||||
|
// Steep faces of the crests catch a thin sheen: the edge of the frozen surface,
|
||||||
|
// painted only where the ice actually tilts, so the open water stays black.
|
||||||
|
float tilt = smoothstep(0.45, 0.95, length(slope));
|
||||||
|
col += vec3(0.030, 0.085, 0.105) * tilt;
|
||||||
|
vec2 fr = fracture(hit.xy);
|
||||||
|
float crack = (1.0 - smoothstep(0.0, 0.006, abs(fr.x)))
|
||||||
|
+ (1.0 - smoothstep(0.0, 0.006, abs(fr.y)));
|
||||||
|
col += vec3(0.020, 0.055, 0.070) * crack * smoothstep(0.58, 0.80, fbm2(hit.xy * 0.30 + 21.0));
|
||||||
|
|
||||||
gl_FragColor = vec4(pow(clamp(col, 0.0, 1.0), vec3(0.4545)), 1.0);
|
gl_FragColor = vec4(pow(clamp(col, 0.0, 1.0), vec3(0.4545)), 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user