fragmentShader top-level property

String fragmentShader
final

Implementation

final String fragmentShader = '''
  // Terrain generation parameters
  varying vec3 vWorldPosition; // Receive from Vertex
  uniform int type;
  uniform float radius;
  uniform float amplitude;
  uniform float sharpness;
  uniform float offset;
  uniform float period;
  uniform float persistence;
  uniform float lacunarity;
  uniform int octaves;

  // Layer colors
  uniform vec3 color1;
  uniform vec3 color2;
  uniform vec3 color3;
  uniform vec3 color4;
  uniform vec3 color5;

  // Transition points for each layer
  uniform float transition2;
  uniform float transition3;
  uniform float transition4;
  uniform float transition5;

  // Amount of blending between each layer
  uniform float blend12;
  uniform float blend23;
  uniform float blend34;
  uniform float blend45;

  // Bump mapping parameters
  uniform float bumpStrength;
  uniform float bumpOffset;

  // Lighting parameters
  uniform float ambientIntensity;
  uniform float diffuseIntensity;
  uniform float specularIntensity;
  uniform float shininess;
  uniform vec3 lightDirection;
  uniform vec3 lightColor;

  varying vec3 fragPosition;
  varying vec3 fragNormal;
  varying vec3 fragTangent;
  varying vec3 fragBitangent;

  varying float vHeight; // Receiving from Vertex

  void main() {
    float dist = distance(cameraPosition, vWorldPosition);
    float smoothLod = float(octaves);
    if (dist > 1000.0) {
      // Linear interpolation of the octave count
      float t = clamp((dist - 1000.0) / 300.0, 0.0, 1.0);
      smoothLod = mix(float(octaves), 2.0, t);
    }

    float h = terrainHeight(type, fragPosition, amplitude, sharpness, offset, period, persistence, lacunarity, smoothLod);

    vec3 dx = bumpOffset * fragTangent;
    float h_dx = terrainHeight(type, fragPosition + dx, amplitude, sharpness, offset, period, persistence, lacunarity, smoothLod);

    vec3 dy = bumpOffset * fragBitangent;
    float h_dy = terrainHeight(type, fragPosition + dy, amplitude, sharpness, offset, period, persistence, lacunarity, smoothLod);

    vec3 pos = fragPosition * (radius + h);
    vec3 pos_dx = (fragPosition + dx) * (radius + h_dx);
    vec3 pos_dy = (fragPosition + dy) * (radius + h_dy);
    vec3 N = normalize(mix(fragNormal, normalize(cross(pos_dx - pos, pos_dy - pos)), bumpStrength));

    vec3 L = normalize(-lightDirection);
    vec3 V = normalize(cameraPosition - pos);
    vec3 R = normalize(reflect(L, N));

    float diffuse = diffuseIntensity * max(0.0, dot(N, -L));
    float specularFalloff = clamp((transition3 - h) / transition3, 0.0, 1.0);
    float specular = max(0.0, specularFalloff * specularIntensity * pow(dot(V, R), shininess));
    float light = ambientIntensity + diffuse + specular;

    vec3 finalColor;
    if (h < transition2 + blend12) {
        finalColor = mix(color1, color2, smoothstep(transition2 - blend12, transition2 + blend12, h));
    } else if (h < transition3 + blend23) {
        finalColor = mix(color2, color3, smoothstep(transition3 - blend23, transition3 + blend23, h));
    } else if (h < transition4 + blend34) {
        finalColor = mix(color3, color4, smoothstep(transition4 - blend34, transition4 + blend34, h));
    } else {
        finalColor = mix(color4, color5, smoothstep(transition5 - blend45, transition5 + blend45, h));
    }

    gl_FragColor = vec4(light * finalColor * lightColor, 1.0);
}
''';