contrails: rewrite shader with world-space wispy cloud noise

This commit is contained in:
Richard Zink committed 2026-10-12 20:29:25 +02:00
1 parent b76b4fe4f2
commit dd36976712
1 file changed
+28 -16
+28 -16
View File
@@ -5440,6 +5440,8 @@ var CT2_FRAG_SRC = [
'precision mediump float;', 'precision mediump float;',
'uniform float uDay;', 'uniform float uDay;',
'uniform float uNight;', 'uniform float uNight;',
'uniform float uTime;',
'uniform vec3 uCamPos;',
'varying float vU;', 'varying float vU;',
'varying float vV;', 'varying float vV;',
'varying float vS;', 'varying float vS;',
@@ -5467,23 +5469,31 @@ var CT2_FRAG_SRC = [
'return v;', 'return v;',
'}', '}',
'void main() {', 'void main() {',
'float cDist = length(vWorld - uCamPos);',
'float cSoft = smoothstep(8.0, 24.0, cDist);',
'vec2 q = vec2(',
'vWorld.x * 0.28 + vWorld.z * 0.19 + uTime * 0.015,',
'vWorld.y * 0.55 + vWorld.z * 0.11 - uTime * 0.008',
');',
'float side = abs(vV);', 'float side = abs(vV);',
'float edgeNoise = fbm2(vec2(vU * 18.0, vV * 5.0));', 'float edgeBase = fbm2(q * 1.15 + vec2(vU * 2.0, vV * 0.35));',
'float clumpNoise = fbm2(vec2(vU * 43.0 + 11.0, vV * 11.0 - 3.0));', 'float edgeFine = noise2(q * 7.0 + vec2(vU * 12.0, vV * 2.5));',
'float wob = 0.30 + 0.72 * edgeNoise;', 'float wob = 0.22 + 0.86 * edgeBase;',
'float raggedSide = side + (clumpNoise - 0.5) * 0.42;', 'float ragged = side + (edgeFine - 0.5) * 0.65 + (edgeBase - 0.5) * 0.25;',
'float edge = 1.0 - smoothstep(wob * 0.10, wob, raggedSide);', 'float edge = 1.0 - smoothstep(wob * 0.06, wob, ragged);',
'edge *= 0.32 + 0.68 * pow(vU, 0.55);', 'edge *= 0.25 + 0.75 * pow(vU, 0.45);',
'float dens = fbm2(vec2(vU * 31.0 + vV * 2.0, vU * 7.0 - vV * 4.0));', 'float cloud = fbm2(q * 2.2 + vec2(vU * 3.5, vV * 0.8));',
'dens = 0.35 + 0.75 * smoothstep(0.12, 0.78, dens);', 'float wisps = noise2(q * 9.0 + vec2(vU * 18.0, vV * 3.0));',
'float streak = 0.65 + 0.35 * noise2(vec2(vU * 90.0, vV * 2.0));', 'float dens = smoothstep(0.14, 0.74, cloud) * (0.45 + 0.85 * wisps);',
'float head = 0.32 + 0.68 * vU;', 'dens = mix(dens, 0.55, cSoft);',
'float a = clamp(vS * (0.25 + edge * head * dens * streak), 0.0, 0.95);', 'float head = 0.25 + 0.75 * vU;',
'if (a <= 0.002) discard;', 'float a = clamp(vS * edge * head * (0.18 + 1.05 * dens), 0.0, 0.95);',
'vec3 dayCol = mix(vec3(0.82, 0.84, 0.88), vec3(1.0, 1.0, 1.0), dens);', 'if (a <= 0.003) discard;',
'vec3 nightCol = mix(vec3(0.30, 0.38, 0.55), vec3(0.58, 0.68, 0.88), dens);', 'float shade = 0.62 + 0.48 * cloud;',
'vec3 dayCol = vec3(0.88, 0.90, 0.94) * shade;',
'vec3 nightCol = vec3(0.28, 0.36, 0.52) * shade;',
'vec3 col = mix(nightCol, dayCol, clamp(uDay, 0.0, 1.0));', 'vec3 col = mix(nightCol, dayCol, clamp(uDay, 0.0, 1.0));',
'col *= 0.32 + 0.68 * clamp(uDay + uNight, 0.0, 1.0);', 'col *= 0.30 + 0.70 * clamp(uDay + uNight, 0.0, 1.0);',
'gl_FragColor = vec4(col, a);', 'gl_FragColor = vec4(col, a);',
'}' '}'
].join('\n'); ].join('\n');
@@ -6965,7 +6975,8 @@ window.clouds3dRender = function(target) {
earthRadius: gl.getUniformLocation(c2p, 'uEarthRadius'), earthRadius: gl.getUniformLocation(c2p, 'uEarthRadius'),
curvatureOn: gl.getUniformLocation(c2p, 'uCurvatureOn'), curvatureOn: gl.getUniformLocation(c2p, 'uCurvatureOn'),
day: gl.getUniformLocation(c2p, 'uDay'), day: gl.getUniformLocation(c2p, 'uDay'),
night: gl.getUniformLocation(c2p, 'uNight') night: gl.getUniformLocation(c2p, 'uNight'),
time: gl.getUniformLocation(c2p, 'uTime')
}; };
} }
} }
@@ -6978,6 +6989,7 @@ window.clouds3dRender = function(target) {
gl.uniform1f(ct2U.curvatureOn, CURVATURE_ON ? 1.0 : 0.0); gl.uniform1f(ct2U.curvatureOn, CURVATURE_ON ? 1.0 : 0.0);
gl.uniform1f(ct2U.day, dayf); gl.uniform1f(ct2U.day, dayf);
gl.uniform1f(ct2U.night, carNight); gl.uniform1f(ct2U.night, carNight);
gl.uniform1f(ct2U.time, now);
gl.enableVertexAttribArray(ct2A.pos); gl.enableVertexAttribArray(ct2A.pos);
gl.vertexAttribPointer(ct2A.pos, 3, gl.FLOAT, false, 24, 0); gl.vertexAttribPointer(ct2A.pos, 3, gl.FLOAT, false, 24, 0);
gl.enableVertexAttribArray(ct2A.u); gl.enableVertexAttribArray(ct2A.u);