第 20 课:Procedural Sky
实现
uniform float iTime;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
varying vec2 vUv;
varying vec3 vPos;
float noise(vec2 p) {
return textureLod(iChannel0, fract(p), 0.01).r;
}
float fbm(vec2 st) {
const int octaves = 4;
float lacunarity = 2.0;
float gain = 0.5;
float amplitude = 1.0;
float frequency = 1.0;
float y = 0.0;
float normalization = 0.0;
for (int i = 0; i < octaves; i++) {
y += amplitude * noise(frequency * st);
normalization += amplitude;
frequency *= lacunarity;
amplitude *= gain;
}
return y / normalization;
}
float domainWrapping(vec2 uv) {
vec2 a_uv = uv * 5.0 + vec2(iTime * 0.01, 0.0);
float a = fbm(a_uv);
vec2 c_uv = uv;
c_uv = (c_uv + vec2(iTime * 0.01, 0.0));
c_uv += vec2(a * 0.025);
float c = fbm(c_uv);
return c;
}
void main() {
vec3 n = normalize(vPos.xyz);
// Spherical Coordinates
float u = atan(n.x, n.z) / (6.28) + 0.5;
float v = n.y * 0.5 + 0.5;
vec2 uv = vec2(u, v);
uv.y = (uv.y - 0.3) / 0.7;
uv.x = fract(uv.x * 2.0);
float cloud = domainWrapping(uv);
cloud = smoothstep(0.2, 0.35, uv.y) * cloud; // skyline
//cloud = pow(cloud, 0.9 + sin(iTime * 0.5) + 1.0); // dencity
cloud = pow(cloud, 1.15);
vec3 skyColorBottom = vec3(0.8, 0.7, 0.5);
vec3 skyColorTop = vec3(0.27, 0.6, 0.5);
vec3 sky = mix(skyColorBottom, skyColorTop, (uv.y - 0.5) * 2.0);
vec3 result = mix(vec3(0.1, 0.1, 0.15), skyColorBottom, cloud * cloud * 2.0 * uv.y);
result = mix(sky, result, smoothstep(0.2, 0.5, cloud));
gl_FragColor = vec4(result, 1.0);
}