terrain.glsl (2459B)
1 struct VSOut { 2 vec4 view_position; 3 vec3 world_position; 4 }; 5 6 #ifdef VERTEX_SHADER 7 8 in vec3 position; 9 out VSOut v2f; 10 11 layout( std140 ) uniform view { 12 mat4 V; 13 mat4 P; 14 }; 15 16 void main() { 17 v2f.world_position = position; 18 v2f.view_position = V * vec4( position, 1.0 ); 19 gl_Position = P * v2f.view_position; 20 } 21 22 #else 23 24 in VSOut v2f; 25 out vec4 colour; 26 27 layout( std140 ) uniform sun { 28 vec3 sun_dir; 29 float sun_angle; 30 }; 31 32 uniform sampler2D normals; 33 uniform sampler2D horizons; 34 uniform sampler2D blue_noise; 35 36 // uniform usamplerBuffer point_light_counts_and_offsets; 37 // uniform usamplerBuffer point_light_indices; 38 uniform samplerBuffer point_light_origins; 39 uniform samplerBuffer point_light_colours; 40 41 void main() { 42 vec2 world_pos = mod( v2f.world_position.xy, textureSize( normals, 0 ) - ivec2( 1, 1 ) ); 43 44 vec3 normal = normalize( texture( normals, world_pos / textureSize( normals, 0 ) ).xyz ); 45 float horizon_angle = texture( horizons, world_pos / textureSize( horizons, 0 ) ).r; 46 47 // ground colour 48 vec3 ground; 49 if( v2f.world_position.z > 175 ) { 50 // snow/rocks 51 if( normal.z > 0.5 ) { 52 ground = vec3( 0.8, 0.8, 0.8 ); 53 } 54 else { 55 ground = vec3( 0.6, 0.6, 0.6 ); 56 } 57 } 58 else if( v2f.world_position.z < 5 ) { 59 ground = vec3( 0.0, 0.25, 1.0 ); 60 } 61 else { 62 if( normal.z > 0.8 ) { 63 ground = vec3( 0.4, 1.0, 0.4 ); 64 } 65 else { 66 ground = vec3( 0.7, 0.7, 0.5 ); 67 } 68 } 69 70 // sunlight + sky ambient lighting 71 // area of a chord is somewhat similar to smoothstep 72 float sun_visible_fraction = smoothstep( -0.2, 0.2, sun_angle - horizon_angle ); 73 float sunlight_lambert = max( 0, dot( normal, sun_dir ) ); 74 vec3 sunlight = sun_visible_fraction * sunlight_lambert * vec3( 0.9, 0.9, 0.5 ); 75 vec3 ambient = vec3( 0.05, 0.05, 0.15 ); 76 77 vec3 c = ( sunlight + ambient ) * ground; 78 79 // lights 80 for( int i = 0; i < 5; i++ ) { 81 vec3 light_position = texelFetch( point_light_origins, i ).xyz; 82 vec3 light_colour = texelFetch( point_light_colours, i ).rgb; 83 float light_sqdistance = dot( light_position - v2f.world_position, light_position - v2f.world_position ); 84 vec3 light_direction = normalize( light_position - v2f.world_position ); 85 float lambert_scale = dot( light_direction, normal ); 86 float distance_scale = 1.0 / light_sqdistance; 87 c += vec3( light_colour * lambert_scale * distance_scale ) * ground; 88 } 89 90 // fog 91 c = apply_fog( c, length( v2f.view_position ) ); 92 93 colour = vec4( linear_to_srgb( c + get_dither_noise( blue_noise ) ), 1.0 ); 94 } 95 96 #endif