跳到主要内容
← Noise

Noise

Procedural Sky

shader-learning 自学第 20 课:Procedural Sky

实时渲染 · 网格 GLSL

第 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);
}