From d723b0b518312f5b2d11e3004046fd8840a40122 Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Wed, 10 Nov 2021 22:58:44 +0000 Subject: [PATCH] WS30 - Uniform Arrays and lighting model Use Uniform Arrays instead of Texture1D. Use ambient/diffuse/specular/shininess material properties consistently across all WS30 shaders. Use consistent shading model for photoscenery vs. landclass to minimize visual difference. --- Effects/ws30.eff | 125 +++--------------- Shaders/HDR/ws30.frag | 52 +++++--- Shaders/ws30-ALS-detailed.frag | 75 ++++++----- .../ws30-ALS-landclass-search-functions.frag | 12 +- Shaders/ws30-ALS-ultra.frag | 70 ++++++---- Shaders/ws30-ALS.frag | 101 +++++++------- Shaders/ws30-ALS.vert | 7 +- Shaders/ws30-q1.frag | 81 +++++++++--- Shaders/ws30.frag | 79 ++++++++--- Shaders/ws30.vert | 7 + 10 files changed, 327 insertions(+), 282 deletions(-) diff --git a/Effects/ws30.eff b/Effects/ws30.eff index bff135719..89107e5bd 100644 --- a/Effects/ws30.eff +++ b/Effects/ws30.eff @@ -779,21 +779,6 @@ sampler-2d 1 - - dimensionsArray - sampler-1d - 2 - - - diffuseArray - sampler-1d - 3 - - - specularArray - sampler-1d - 4 - perlin sampler-2d @@ -1127,21 +1112,6 @@ sampler-2d 1 - - dimensionsArray - sampler-1d - 2 - - - diffuseArray - sampler-1d - 3 - - - specularArray - sampler-1d - 4 - perlin sampler-2d @@ -1152,12 +1122,6 @@ int xsize - - colorMode - int - 2 - - shadow_tex @@ -1403,33 +1367,7 @@ sampler-2d 1 - - dimensionsArray - sampler-1d - 2 - - - diffuseArray - sampler-1d - 3 - - - specularArray - sampler-1d - 4 - - - perlin - sampler-2d - 6 - - - colorMode - int - 2 - - shadow_tex @@ -1538,9 +1476,13 @@ + Shaders/include_fog.vert + Shaders/shadows-include.vert Shaders/ws30.vert Shaders/include_fog.frag Shaders/ws30-q1.frag + Shaders/shadows-include.frag + Shaders/clustered-include.frag @@ -1554,25 +1496,16 @@ 1 - dimensionsArray - sampler-1d - 2 + perlin + sampler-2d + 6 - diffuseArray - sampler-1d - 3 + colorMode + int + 2 + - - specularArray - sampler-1d - 4 - - - perlin - sampler-2d - 6 - @@ -1637,9 +1570,13 @@ + Shaders/include_fog.vert + Shaders/shadows-include.vert Shaders/ws30.vert Shaders/include_fog.frag Shaders/ws30.frag + Shaders/shadows-include.frag + Shaders/clustered-include.frag @@ -1653,19 +1590,10 @@ 1 - dimensionsArray - sampler-1d - 2 - - - diffuseArray - sampler-1d - 3 - - - specularArray - sampler-1d - 4 + colorMode + int + 2 + @@ -1758,21 +1686,6 @@ sampler-2d 1 - - dimensionsArray - sampler-1d - 2 - - - diffuseArray - sampler-1d - 3 - - - specularArray - sampler-1d - 4 - perlin sampler-2d diff --git a/Shaders/HDR/ws30.frag b/Shaders/HDR/ws30.frag index ff0be9861..b824668e9 100644 --- a/Shaders/HDR/ws30.frag +++ b/Shaders/HDR/ws30.frag @@ -9,42 +9,52 @@ in vec2 texCoord; uniform sampler2D landclass; uniform sampler2DArray atlas; -uniform sampler1D dimensionsArray; -uniform sampler1D diffuseArray; -uniform sampler1D specularArray; uniform sampler2D perlin; // Passed from VPBTechnique, not the Effect uniform float tile_width; uniform float tile_height; +uniform vec4 dimensionsArray[128]; +uniform vec4 ambientArray[128]; +uniform vec4 diffuseArray[128]; +uniform vec4 specularArray[128]; + vec2 encodeNormal(vec3 n); vec3 decodeSRGB(vec3 screenRGB); void main() { - // The Landclass for this particular fragment. This can be used to - // index into the atlas textures. - int lc = int(texture(landclass, texCoord).g * 255.0 + 0.5); + vec3 texel; - // Different textures have different have different dimensions. - // Dimensions array is scaled to fit in [0...1.0] in the texture1D, so has to be scaled back up here. - vec4 color = texture(diffuseArray, float(lc)/512.0); - vec4 specular = texture(specularArray, float(lc)/512.0); - vec2 atlas_dimensions = 10000.0 * texture(dimensionsArray, float(lc)/512.0).st; - vec2 atlas_scale = vec2(tile_width / atlas_dimensions.s, tile_height / atlas_dimensions.t ); - vec2 st = atlas_scale * texCoord; + if (photoScenery) { + texel = decodeSRGB(texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)).rgb); + } else { - // Rotate texture using the perlin texture as a mask to reduce tiling - if (step(0.5, texture(perlin, atlas_scale * texCoord / 8.0).r) == 1.0) { - st = vec2(atlas_scale.s * texCoord.t, atlas_scale.t * texCoord.s); + // The Landclass for this particular fragment. This can be used to + // index into the atlas textures. + int lc = int(texture2D(landclass, gl_TexCoord[0].st).g * 255.0 + 0.5); + + color = ambientArray[lc] + diffuseArray[lc] * NdotL * gl_LightSource[0].diffuse; + specular = specularArray[lc]; + + // Different textures have different have different dimensions. + vec2 atlas_dimensions = dimensionsArray[lc].st; + vec2 atlas_scale = vec2(tile_width / atlas_dimensions.s, tile_height / atlas_dimensions.t ); + vec2 st = atlas_scale * gl_TexCoord[0].st; + + // Rotate texture using the perlin texture as a mask to reduce tiling + if (step(0.5, texture(perlin, atlas_scale * gl_TexCoord[0].st / 8.0).r) == 1.0) { + st = vec2(atlas_scale.s * gl_TexCoord[0].t, atlas_scale.t * gl_TexCoord[0].s); + } + + if (step(0.5, texture(perlin, - atlas_scale * gl_TexCoord[0].st / 16.0).r) == 1.0) { + st = -st; + } + + texel = decodeSRGB(texture(atlas, vec3(st, lc)).rgb); } - if (step(0.5, texture(perlin, - atlas_scale * texCoord / 16.0).r) == 1.0) { - st = -st; - } - - vec3 texel = decodeSRGB(texture(atlas, vec3(st, lc)).rgb); float specularity = clamp(dot(specular.rgb, vec3(0.333)), 0.0, 1.0); outGBuffer0.rg = encodeNormal(normalVS); diff --git a/Shaders/ws30-ALS-detailed.frag b/Shaders/ws30-ALS-detailed.frag index 9723d5d24..33b7565f3 100644 --- a/Shaders/ws30-ALS-detailed.frag +++ b/Shaders/ws30-ALS-detailed.frag @@ -53,9 +53,6 @@ varying vec4 eyePos; uniform sampler2D landclass; uniform sampler2DArray textureArray; -uniform sampler1D dimensionsArray; -uniform sampler1D diffuseArray; -uniform sampler1D specularArray; uniform sampler2D perlin; //varying float yprime_alt; @@ -88,6 +85,10 @@ uniform int tquality_level; // Passed from VPBTechnique, not the Effect uniform bool photoScenery; +uniform vec4 dimensionsArray[128]; +uniform vec4 ambientArray[128]; +uniform vec4 diffuseArray[128]; +uniform vec4 specularArray[128]; const float EarthRadius = 5800000.0; const float terminator_width = 200000.0; @@ -153,8 +154,7 @@ int get_random_landclass(in vec2 co, in vec2 tile_size); // the stretching of different textures, so that the correct mip-map level is looked // up and there are no seams. -vec4 lookup_ground_texture_array(in float index, in vec2 tile_coord, in int landclass_id, - in vec2 dx, in vec2 dy); +vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id, in vec2 dx, in vec2 dy); // Look up the landclass id [0 .. 255] for this particular fragment. @@ -283,12 +283,11 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0); float index = float(lc)/512.0; vec4 index_n = vec4(lc_n)/512.0; - float mat_shininess = texture(dimensionsArray, index).z; - vec4 mat_diffuse = texture(diffuseArray, index); - vec4 mat_specular = texture(specularArray, index); + float mat_shininess = dimensionsArray[lc].z; + vec4 mat_ambient = ambientArray[lc]; + vec4 mat_diffuse = diffuseArray[lc]; + vec4 mat_specular = specularArray[lc]; - vec4 color = gl_Color; - color.a = 1.0; @@ -298,26 +297,37 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0); // color.rgb = color.rgb+0.00001*float(get_random_landclass(tile_coord.st, tile_size)); - - - // Look up ground textures by indexing into the texture array. - // Different textures are stretched along the ground to different - // lengths along each axes as set by and - // regional definitions parameters - - // Look up texture coordinates and scale of ground textures - - // Landclass for this fragment if (photoScenery) { + // In the photoscenery case we don't have landclass or materials available, so we + // just use constants for the material properties. + mat_ambient = vec4(0.2,0.2,0.2,1.0); + mat_diffuse = vec4(0.8,0.8,0.8,1.0); + mat_specular = vec4(0.0,0.0,0.0,1.0); + texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)); } else { - texel = lookup_ground_texture_array(index, tile_coord, lc, dx, dy); + // Color Mode is always AMBIENT_AND_DIFFUSE, which means + // using a base colour of white for ambient/diffuse, + // rather than the material color from ambientArray/diffuseArray. + mat_ambient = vec4(1.0,1.0,1.0,1.0); + mat_diffuse = vec4(1.0,1.0,1.0,1.0); + mat_specular = specularArray[lc]; + mat_shininess = dimensionsArray[lc].z; + + // Look up ground textures by indexing into the texture array. + // Different textures are stretched along the ground to different + // lengths along each axes as set by and + // regional definitions parameters + + // Look up texture coordinates and scale of ground textures + // Landclass for this fragment + texel = lookup_ground_texture_array(tile_coord, lc, dx, dy); // Mix texels - to work consistently it needs a more preceptual interpolation than mix() if (num_unique_neighbors != 0) { // Closest neighbor landclass - vec4 texel_closest = lookup_ground_texture_array(index_n[0], tile_coord, lc_n[0], dx, dy); + vec4 texel_closest = lookup_ground_texture_array(tile_coord, lc_n[0], dx, dy); // Neighbor contributions vec4 texel_nc=texel_closest; @@ -325,7 +335,7 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0); if (num_unique_neighbors > 1) { // 2nd Closest neighbor landclass - vec4 texel_2nd_closest = lookup_ground_texture_array(index_n[1], tile_coord, lc_n[1], + vec4 texel_2nd_closest = lookup_ground_texture_array(tile_coord, lc_n[1], dx, dy); texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]); @@ -335,6 +345,9 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0); } } + vec4 color = gl_Color * mat_ambient; + color.a = 1.0; + // Testing code: mix with green to show values of variables at each point //vec4 green = vec4(0.0, 0.5, 0.0, 0.0); //texel = mix(texel, green, (mfact[2])); @@ -348,16 +361,12 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0); float local_autumn_factor = texel.a; -/* - if (orthophotoAvailable) { - vec4 sat_texel = texture2D(orthophotoTexture, orthoTexCoord); - if (sat_texel.a > 0) { - texel.rgb = sat_texel.rgb; - flag = 0; - mix_flag = 0; - } - } -*/ + + if (photoScenery) { + flag = 0; + mix_flag = 0; + } + float distortion_factor = 1.0; vec2 stprime; diff --git a/Shaders/ws30-ALS-landclass-search-functions.frag b/Shaders/ws30-ALS-landclass-search-functions.frag index 447c7d826..2e8da28ca 100644 --- a/Shaders/ws30-ALS-landclass-search-functions.frag +++ b/Shaders/ws30-ALS-landclass-search-functions.frag @@ -227,15 +227,13 @@ uniform sampler2D landclass; uniform sampler2DArray textureArray; -uniform sampler1D dimensionsArray; -uniform sampler1D diffuseArray; -uniform sampler1D specularArray; uniform sampler2D perlin; // Passed from VPBTechnique, not the Effect uniform int tile_level; uniform float tile_width; uniform float tile_height; +uniform vec4 dimensionsArray[128]; // These should be sent as uniforms @@ -259,12 +257,12 @@ int get_random_landclass(in vec2 co, in vec2 tile_size) // Look up texture coordinates and stretching scale of ground textures -void get_ground_texture_data(in float textureIndex, in vec2 tile_coord, +void get_ground_texture_data(in int textureIndex, in vec2 tile_coord, out vec2 st, out vec2 g_texture_scale, inout vec2 dx, inout vec2 dy) { // Look up stretching dimensions of ground textures in m - scaled to // fit in [0..1], so rescale - vec2 g_texture_stretch_dim = 10000.0 * texture(dimensionsArray, textureIndex).st; + vec2 g_texture_stretch_dim = dimensionsArray[textureIndex].st; g_texture_scale = tile_size.xy / g_texture_stretch_dim.xy; // Correct partial derivatives to account for stretching of different textures dx = dx * g_texture_scale; @@ -335,7 +333,7 @@ vec2 detile_texcoords_with_perlin_noise(in vec2 st, in vec2 ground_texture_scale // the stretching of different textures, so that the correct mip-map level is looked // up and there are no seams. -vec4 lookup_ground_texture_array(in float index, in vec2 tile_coord, in int landclass_id, +vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id, in vec2 dx, in vec2 dy) { // Testing: may be able to save 1 or 2 op slots by combining dx/dy in a vec4 and @@ -346,7 +344,7 @@ vec4 lookup_ground_texture_array(in float index, in vec2 tile_coord, in int land vec4 texel; int lc = landclass_id; - get_ground_texture_data(index, tile_coord, st, g_texture_scale, dx, dy); + get_ground_texture_data(lc, tile_coord, st, g_texture_scale, dx, dy); st = detile_texcoords_with_perlin_noise(st, g_texture_scale, tile_coord, dx, dy); diff --git a/Shaders/ws30-ALS-ultra.frag b/Shaders/ws30-ALS-ultra.frag index c1a6f2343..126431e1e 100644 --- a/Shaders/ws30-ALS-ultra.frag +++ b/Shaders/ws30-ALS-ultra.frag @@ -55,9 +55,6 @@ varying vec4 ecPosition; uniform sampler2D landclass; uniform sampler2DArray textureArray; -uniform sampler1D dimensionsArray; -uniform sampler1D diffuseArray; -uniform sampler1D specularArray; uniform sampler2D perlin; @@ -109,6 +106,10 @@ uniform int swatch_size; //in metres, typically 1000 or 2000 // Passed from VPBTechnique, not the Effect uniform bool photoScenery; +uniform vec4 dimensionsArray[128]; +uniform vec4 ambientArray[128]; +uniform vec4 diffuseArray[128]; +uniform vec4 specularArray[128]; const float EarthRadius = 5800000.0; const float terminator_width = 200000.0; @@ -181,7 +182,7 @@ int get_random_landclass(in vec2 co, in vec2 tile_size); // the stretching of different textures, so that the correct mip-map level is looked // up and there are no seams. -vec4 lookup_ground_texture_array(in float index, in vec2 tile_coord, in int landclass_id, +vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id, in vec2 dx, in vec2 dy); @@ -377,12 +378,10 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness), float index = float(lc)/512.0; vec4 index_n = vec4(lc_n)/512.0; - float mat_shininess = texture(dimensionsArray, index).z; - vec4 mat_diffuse = texture(diffuseArray, index); - vec4 mat_specular = texture(specularArray, index); - - vec4 color = gl_Color; - color.a = 1.0; + float mat_shininess = dimensionsArray[lc].z; + vec4 mat_ambient = ambientArray[lc]; + vec4 mat_diffuse = diffuseArray[lc]; + vec4 mat_specular = specularArray[lc]; @@ -391,28 +390,44 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness), // so any performance difference between the two is due to the texture lookup // color.rgb = color.rgb+0.00001*float(get_random_landclass(tile_coord.st, tile_size)); - - - - - // Look up ground textures by indexing into the texture array. - // Different textures are stretched along the ground to different - // lengths along each axes as set by and - // regional definitions parameters - - // Look up texture coordinates and scale of ground textures - - // Landclass for this fragment if (photoScenery) { + // In the photoscenery case we don't have landclass or materials available, so we + // just use constants for the material properties. + mat_ambient = vec4(0.2,0.2,0.2,1.0); + mat_diffuse = vec4(0.8,0.8,0.8,1.0); + mat_specular = vec4(0.0,0.0,0.0,1.0); + texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)); + + // Do not attempt any mixing + flag = 0; + mix_flag = 0; } else { - texel = lookup_ground_texture_array(index, tile_coord, lc, dx, dy); + // Color Mode is always AMBIENT_AND_DIFFUSE, which means + // using a base colour of white for ambient/diffuse, + // rather than the material color from ambientArray/diffuseArray. + mat_ambient = vec4(1.0,1.0,1.0,1.0); + mat_diffuse = vec4(1.0,1.0,1.0,1.0); + mat_specular = specularArray[lc]; + mat_shininess = dimensionsArray[lc].z; + + + // Look up ground textures by indexing into the texture array. + // Different textures are stretched along the ground to different + // lengths along each axes as set by and + // regional definitions parameters + + // Look up texture coordinates and scale of ground textures + + // Landclass for this fragment + + texel = lookup_ground_texture_array(tile_coord, lc, dx, dy); // Mix texels - to work consistently it needs a more preceptual interpolation than mix() if (num_unique_neighbors != 0) { // Closest neighbor landclass - vec4 texel_closest = lookup_ground_texture_array(index_n[0], tile_coord, lc_n[0], dx, dy); + vec4 texel_closest = lookup_ground_texture_array(tile_coord, lc_n[0], dx, dy); // Neighbor contributions vec4 texel_nc=texel_closest; @@ -420,8 +435,7 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness), if (num_unique_neighbors > 1) { // 2nd Closest neighbor landclass - vec4 texel_2nd_closest = lookup_ground_texture_array(index_n[1], tile_coord, lc_n[1], - dx, dy); + vec4 texel_2nd_closest = lookup_ground_texture_array(tile_coord, lc_n[1], dx, dy); texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]); } @@ -430,6 +444,10 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness), } } + + vec4 color = gl_Color; + color.a = 1.0; + // Testing code: mix with green to show values of variables at each point //vec4 green = vec4(0.0, 0.5, 0.0, 0.0); //texel = mix(texel, green, (mfact[2])); diff --git a/Shaders/ws30-ALS.frag b/Shaders/ws30-ALS.frag index d9a6fe25d..64ad3ebd2 100644 --- a/Shaders/ws30-ALS.frag +++ b/Shaders/ws30-ALS.frag @@ -46,10 +46,6 @@ varying vec3 relPos; uniform sampler2D landclass; uniform sampler2DArray textureArray; -uniform sampler1D dimensionsArray; -uniform sampler1D diffuseArray; -uniform sampler1D specularArray; -uniform sampler2D perlin; varying float yprime_alt; varying float mie_angle; @@ -70,6 +66,10 @@ uniform int tile_level; uniform float tile_width; uniform float tile_height; uniform bool photoScenery; +uniform vec4 dimensionsArray[128]; +uniform vec4 ambientArray[128]; +uniform vec4 diffuseArray[128]; +uniform vec4 specularArray[128]; const float EarthRadius = 5800000.0; const float terminator_width = 200000.0; @@ -140,8 +140,7 @@ int get_random_landclass(in vec2 co, in vec2 tile_size); // the stretching of different textures, so that the correct mip-map level is looked // up and there are no seams. -vec4 lookup_ground_texture_array(in float index, in vec2 tile_coord, in int landclass_id, - in vec2 dx, in vec2 dy); +vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id, in vec2 dx, in vec2 dy); // Look up the landclass id [0 .. 255] for this particular fragment. @@ -222,11 +221,58 @@ void main() float index = float(lc)/512.0; vec4 index_n = vec4(lc_n)/512.0; - float mat_shininess = texture(dimensionsArray, index).z; - vec4 mat_diffuse = texture(diffuseArray, index); - vec4 mat_specular = texture(specularArray, index); + // Material properties. + vec4 mat_diffuse, mat_ambient, mat_specular; + float mat_shininess; - vec4 color = gl_Color; + if (photoScenery) { + mat_ambient = vec4(1.0,1.0,1.0,1.0); + mat_diffuse = vec4(1.0,1.0,1.0,1.0); + mat_specular = vec4(0.1, 0.1, 0.1, 1.0); + mat_shininess = 1.2; + + texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)); + } else { + // Color Mode is always AMBIENT_AND_DIFFUSE, which means + // using a base colour of white for ambient/diffuse, + // rather than the material color from ambientArray/diffuseArray. + mat_ambient = vec4(1.0,1.0,1.0,1.0); + mat_diffuse = vec4(1.0,1.0,1.0,1.0); + mat_specular = specularArray[lc]; + mat_shininess = dimensionsArray[lc].z; + + // Look up ground textures by indexing into the texture array. + // Different textures are stretched along the ground to different + // lengths along each axes as set by and + // regional definitions parameters + + // Look up texture coordinates and scale of ground textures + // Landclass for this fragment + texel = lookup_ground_texture_array(tile_coord, lc, dx, dy); + + // Mix texels - to work consistently it needs a more preceptual interpolation than mix() + if (num_unique_neighbors != 0) + { + // Closest neighbor landclass + vec4 texel_closest = lookup_ground_texture_array(tile_coord, lc_n[0], dx, dy); + + // Neighbor contributions + vec4 texel_nc=texel_closest; + + if (num_unique_neighbors > 1) + { + // 2nd Closest neighbor landclass + vec4 texel_2nd_closest = lookup_ground_texture_array(tile_coord, lc_n[1], + dx, dy); + + texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]); + } + + texel = mix(texel, texel_nc, mfact[0]); + } + } + + vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient); // Testing code: // Use rlc even when looking up textures to recreate the extra performance hit @@ -263,41 +309,6 @@ void main() color = clamp(color, 0.0, 1.0); - // Look up ground textures by indexing into the texture array. - // Different textures are stretched along the ground to different - // lengths along each axes as set by and - // regional definitions parameters - - // Look up texture coordinates and scale of ground textures - - if (photoScenery) { - texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)); - } else { - // Landclass for this fragment - texel = lookup_ground_texture_array(index, tile_coord, lc, dx, dy); - - // Mix texels - to work consistently it needs a more preceptual interpolation than mix() - if (num_unique_neighbors != 0) - { - // Closest neighbor landclass - vec4 texel_closest = lookup_ground_texture_array(index_n[0], tile_coord, lc_n[0], dx, dy); - - // Neighbor contributions - vec4 texel_nc=texel_closest; - - if (num_unique_neighbors > 1) - { - // 2nd Closest neighbor landclass - vec4 texel_2nd_closest = lookup_ground_texture_array(index_n[1], tile_coord, lc_n[1], - dx, dy); - - texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]); - } - - texel = mix(texel, texel_nc, mfact[0]); - } - } - // Testing code: mix with green to show values of variables at each point //vec4 green = vec4(0.0, 0.5, 0.0, 0.0); //texel = mix(texel, green, (mfact[2])); diff --git a/Shaders/ws30-ALS.vert b/Shaders/ws30-ALS.vert index d31a3520e..57739ab45 100644 --- a/Shaders/ws30-ALS.vert +++ b/Shaders/ws30-ALS.vert @@ -16,8 +16,6 @@ #define MODE_DIFFUSE 1 #define MODE_AMBIENT_AND_DIFFUSE 2 -attribute vec2 orthophotoTexCoord; - // The constant term of the lighting equation that doesn't depend on // the surface normal is passed in gl_{Front,Back}Color. The alpha // component is set to 1 for front, 0 for back in order to work around @@ -25,7 +23,6 @@ attribute vec2 orthophotoTexCoord; varying vec4 light_diffuse_comp; varying vec3 normal; varying vec3 relPos; -varying vec2 orthoTexCoord; varying vec4 ecPosition; varying float yprime_alt; @@ -82,7 +79,6 @@ void main() ecPosition = gl_ModelViewMatrix * gl_Vertex; gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - orthoTexCoord = orthophotoTexCoord; normal = gl_NormalMatrix * gl_Normal; // here start computations for the haze layer @@ -225,8 +221,7 @@ else // the faster, full-day version without lightfields // Emission is all set to the default of vec4(0.0, 0.0, 0.0, 1.0) //To do: Fix this once ambient colour becomes available in the fragment shaders. //const vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0); - const vec4 ambient_color = vec4(1.0); - vec4 constant_term = ambient_color * (gl_LightModel.ambient + light_ambient); + vec4 constant_term = gl_LightModel.ambient + light_ambient; // Another hack for supporting two-sided lighting without using // gl_FrontFacing in the fragment shader. gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0; diff --git a/Shaders/ws30-q1.frag b/Shaders/ws30-q1.frag index 962535180..d4eadb263 100644 --- a/Shaders/ws30-q1.frag +++ b/Shaders/ws30-q1.frag @@ -5,51 +5,67 @@ #extension GL_EXT_texture_array : enable varying vec3 normal; +varying vec4 ecPosition; uniform sampler2D landclass; uniform sampler2DArray atlas; -uniform sampler1D dimensionsArray; -uniform sampler1D diffuseArray; -uniform sampler1D specularArray; uniform sampler2D perlin; // Passed from VPBTechnique, not the Effect uniform float tile_width; uniform float tile_height; uniform bool photoScenery; +uniform vec4 dimensionsArray[128]; +uniform vec4 ambientArray[128]; +uniform vec4 diffuseArray[128]; +uniform vec4 specularArray[128]; // See include_fog.frag uniform int fogType; vec3 fog_Func(vec3 color, int type); +// See Shaders/shadows-include.frag +float getShadowing(); + +// See Shaders/clustered-include.frag +vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel); + void main() { + float NdotL, NdotHV, fogFactor; vec3 lightDir = gl_LightSource[0].position.xyz; - vec3 halfVector = gl_LightSource[0].halfVector.xyz; - vec4 texel; - vec4 fragColor; - vec4 color = vec4(0.9, 0.9, 0.9, 1.0); - vec4 specular = vec4(0.1, 0.1, 0.1, 1.0); + vec3 halfVector = gl_LightSource[0].halfVector.xyz; + vec4 texel; + vec4 fragColor; + vec4 specular = vec4(0.0); - // If gl_Color.a == 0, this is a back-facing polygon and the - // normal should be reversed. - vec3 n = (2.0 * gl_Color.a - 1.0) * normal; - n = normalize(n); - float NdotL = dot(n, lightDir); - float NdotHV = max(dot(n, halfVector), 0.0); + // Material properties. + // Material properties. + vec4 mat_diffuse, mat_ambient, mat_specular; + float mat_shininess; if (photoScenery) { + mat_ambient = vec4(1.0,1.0,1.0,1.0); + mat_diffuse = vec4(1.0,1.0,1.0,1.0); + mat_specular = vec4(0.1, 0.1, 0.1, 1.0); + mat_shininess = 1.2; + texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)); } else { // The Landclass for this particular fragment. This can be used to // index into the atlas textures. int lc = int(texture2D(landclass, gl_TexCoord[0].st).g * 255.0 + 0.5); + // Color Mode is always AMBIENT_AND_DIFFUSE, which means + // using a base colour of white for ambient/diffuse, + // rather than the material color from ambientArray/diffuseArray. + mat_ambient = vec4(1.0,1.0,1.0,1.0); + mat_diffuse = vec4(1.0,1.0,1.0,1.0); + mat_specular = specularArray[lc]; + mat_shininess = dimensionsArray[lc].z; + // Different textures have different have different dimensions. - // Dimensions array is scaled to fit in [0...1.0] in the texture1D, so has to be scaled back up here. - //color = texture(diffuseArray, float(lc)/512.0) * (gl_LightSource[0].ambient + NdotL * gl_LightSource[0].diffuse); - //specular = texture(specularArray, float(lc)/512.0); - vec2 atlas_dimensions = 10000.0 * texture(dimensionsArray, float(lc)/512.0).st; + vec2 atlas_dimensions = dimensionsArray[lc].st; vec2 atlas_scale = vec2(tile_width / atlas_dimensions.s, tile_height / atlas_dimensions.t ); vec2 st = atlas_scale * gl_TexCoord[0].st; @@ -65,7 +81,34 @@ void main() texel = texture(atlas, vec3(st, lc)); } - fragColor = color * texel + pow(NdotHV, gl_FrontMaterial.shininess) * gl_LightSource[0].specular * specular; + vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient); + + // If gl_Color.a == 0, this is a back-facing polygon and the + // normal should be reversed. + vec3 n = (2.0 * gl_Color.a - 1.0) * normal; + n = normalize(n); + NdotL = dot(n, lightDir); + + if (NdotL > 0.0) { + float shadowmap = getShadowing(); + color += mat_diffuse * NdotL * shadowmap; + NdotHV = max(dot(n, halfVector), 0.0); + if (mat_shininess > 0.0) + specular.rgb = (mat_specular.rgb + * gl_LightSource[0].specular.rgb + * pow(NdotHV, mat_shininess) + * shadowmap); + } + color.a = mat_diffuse.a; + + // This shouldn't be necessary, but our lighting becomes very + // saturated. Clamping the color before modulating by the texture + // is closer to what the OpenGL fixed function pipeline does. + color = clamp(color, 0.0, 1.0); + + + fragColor = color * texel + specular; + fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb); fragColor.rgb = fog_Func(fragColor.rgb, fogType); gl_FragColor = fragColor; diff --git a/Shaders/ws30.frag b/Shaders/ws30.frag index 5bb8248b0..07fc8e163 100644 --- a/Shaders/ws30.frag +++ b/Shaders/ws30.frag @@ -5,56 +5,97 @@ #extension GL_EXT_texture_array : enable varying vec3 normal; +varying vec4 ecPosition; uniform sampler2D landclass; uniform sampler2DArray atlas; -uniform sampler1D dimensionsArray; -uniform sampler1D diffuseArray; -uniform sampler1D specularArray; // Passed from VPBTechnique, not the Effect uniform float tile_width; uniform float tile_height; uniform bool photoScenery; +uniform vec4 dimensionsArray[128]; +uniform vec4 ambientArray[128]; +uniform vec4 diffuseArray[128]; +uniform vec4 specularArray[128]; // See include_fog.frag uniform int fogType; vec3 fog_Func(vec3 color, int type); +// See Shaders/shadows-include.frag +float getShadowing(); + +// See Shaders/clustered-include.frag +vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel); + void main() { + float NdotL, NdotHV, fogFactor; vec3 lightDir = gl_LightSource[0].position.xyz; - vec3 halfVector = gl_LightSource[0].halfVector.xyz; - vec4 texel; - vec4 fragColor; - vec4 color = vec4(0.9, 0.9, 0.9, 1.0); - vec4 specular = vec4(0.1, 0.1, 0.1, 1.0); + vec3 halfVector = gl_LightSource[0].halfVector.xyz; + vec4 texel; + vec4 fragColor; + vec4 specular = vec4(0.0); - // If gl_Color.a == 0, this is a back-facing polygon and the - // normal should be reversed. - vec3 n = (2.0 * gl_Color.a - 1.0) * normal; - n = normalize(n); - float NdotL = dot(n, lightDir); - float NdotHV = max(dot(n, halfVector), 0.0); + // Material properties. + vec4 mat_diffuse, mat_ambient, mat_specular; + float mat_shininess; if (photoScenery) { + mat_ambient = vec4(1.0,1.0,1.0,1.0); + mat_diffuse = vec4(1.0,1.0,1.0,1.0); + mat_specular = vec4(0.1, 0.1, 0.1, 1.0); + mat_shininess = 1.2; + texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)); } else { // The Landclass for this particular fragment. This can be used to // index into the atlas textures. int lc = int(texture2D(landclass, gl_TexCoord[0].st).g * 255.0 + 0.5); + // Color Mode is always AMBIENT_AND_DIFFUSE, which means + // using a base colour of white for ambient/diffuse, + // rather than the material color from ambientArray/diffuseArray. + mat_ambient = vec4(1.0,1.0,1.0,1.0); + mat_diffuse = vec4(1.0,1.0,1.0,1.0); + mat_specular = specularArray[lc]; + mat_shininess = dimensionsArray[lc].z; + // Different textures have different have different dimensions. - // Dimensions array is scaled to fit in [0...1.0] in the texture1D, so has to be scaled back up here. - //color = texture(diffuseArray, float(lc)/512.0) * (gl_LightSource[0].ambient + NdotL * gl_LightSource[0].diffuse); - //specular = texture(specularArray, float(lc)/512.0); - vec2 atlas_dimensions = 10000.0 * texture(dimensionsArray, float(lc)/512.0).st; + vec2 atlas_dimensions = dimensionsArray[lc].st; vec2 atlas_scale = vec2(tile_width / atlas_dimensions.s, tile_height / atlas_dimensions.t ); texel = texture(atlas, vec3(atlas_scale * gl_TexCoord[0].st, lc)); } - fragColor = color * texel + pow(NdotHV, gl_FrontMaterial.shininess) * gl_LightSource[0].specular * specular; + vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient); + + // If gl_Color.a == 0, this is a back-facing polygon and the + // normal should be reversed. + vec3 n = (2.0 * gl_Color.a - 1.0) * normal; + n = normalize(n); + NdotL = dot(n, lightDir); + + if (NdotL > 0.0) { + float shadowmap = getShadowing(); + color += mat_diffuse * NdotL * shadowmap; + NdotHV = max(dot(n, halfVector), 0.0); + if (mat_shininess > 0.0) + specular.rgb = (mat_specular.rgb + * gl_LightSource[0].specular.rgb + * pow(NdotHV, mat_shininess) + * shadowmap); + } + color.a = mat_diffuse.a; + + // This shouldn't be necessary, but our lighting becomes very + // saturated. Clamping the color before modulating by the texture + // is closer to what the OpenGL fixed function pipeline does. + color = clamp(color, 0.0, 1.0); + + fragColor = color * texel + specular; + fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb); fragColor.rgb = fog_Func(fragColor.rgb, fogType); gl_FragColor = fragColor; diff --git a/Shaders/ws30.vert b/Shaders/ws30.vert index 46ad783dc..7ea64847b 100644 --- a/Shaders/ws30.vert +++ b/Shaders/ws30.vert @@ -21,10 +21,16 @@ // component is set to 1 for front, 0 for back in order to work around // bugs with gl_FrontFacing in the fragment shader. varying vec3 normal; +varying vec4 ecPosition; + +// See Shaders/shadows-include.vert +void setupShadows(vec4 eyeSpacePos); void main() { gl_Position = ftransform(); + ecPosition = gl_ModelViewMatrix * gl_Vertex; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; normal = gl_NormalMatrix * gl_Normal; @@ -32,6 +38,7 @@ void main() // gl_FrontFacing in the fragment shader. gl_FrontColor.a = 1.0; gl_BackColor.a = 0.0; + setupShadows(ecPosition); }