WS30: Improved shoreline rendering
This commit is contained in:
parent
c032a41cd6
commit
467edf2bb6
4 changed files with 103 additions and 79 deletions
|
@ -35,14 +35,6 @@
|
|||
<wrap-t>repeat</wrap-t>
|
||||
<internal-format>normalized</internal-format>
|
||||
</texture>
|
||||
<texture n="8">
|
||||
<image>Textures/Terrain/sand6.png</image>
|
||||
<type>2d</type>
|
||||
<filter>nearest</filter>
|
||||
<wrap-s>repeat</wrap-s>
|
||||
<wrap-t>repeat</wrap-t>
|
||||
<internal-format>normalized</internal-format>
|
||||
</texture>
|
||||
<texture n="10">
|
||||
<image>Textures/Terrain/snow3.png</image>
|
||||
<type>2d</type>
|
||||
|
@ -859,11 +851,6 @@
|
|||
<name>coastline</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">7</value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>sand</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">8</value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>swatch_size</name>
|
||||
|
@ -1289,11 +1276,6 @@
|
|||
<type>sampler-2d</type>
|
||||
<value type="int">7</value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>sand</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">8</value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>swatch_size</name>
|
||||
<type>int</type>
|
||||
|
|
|
@ -29,17 +29,13 @@
|
|||
// End of test phase controls
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Constants controlling the transition from water
|
||||
// to terrain depending on the terrain normal
|
||||
// A normal of 1.0 is completely horizontal.
|
||||
const float WATER_START = 0.995; // Deeper water.
|
||||
const float WATER_BEACH_TO_WATER = 0.99; // Transition point between the shoreline and the shallow water
|
||||
const float WATER_STEEP_TO_BEACH = 0.985; // The transition point between the shoreline and the land
|
||||
const float WATER_STEEP = 0.98; // Anything with less than this value is considered not water or shoreline
|
||||
|
||||
// written by Thorsten Renk, Oct 2011, based on default.frag
|
||||
// Ambient term comes in gl_Color.rgb.
|
||||
|
@ -101,8 +97,8 @@ uniform vec3 fg_modelOffset;
|
|||
// Coastline texture - generated from VPBTechnique
|
||||
uniform sampler2D coastline;
|
||||
|
||||
// Sand texture
|
||||
uniform sampler2D sand;
|
||||
// Index into the material definition for shorelines
|
||||
uniform int fg_shoreAtlasIndex;
|
||||
|
||||
const float EarthRadius = 5800000.0;
|
||||
const float terminator_width = 200000.0;
|
||||
|
@ -321,7 +317,8 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
|
|||
// Mix factor of base textures for 2 neighbour landclass(es)
|
||||
vec4 mfact;
|
||||
|
||||
bool water = false;
|
||||
bool water_lc = false;
|
||||
bool mix_water_texel = false;
|
||||
|
||||
// Partial derivatives of s and t of ground texture coords for this fragment,
|
||||
// with respect to window (screen space) x and y axes.
|
||||
|
@ -332,35 +329,37 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
|
|||
|
||||
get_landclass_id(tile_coord, dxdy_gc, lc, lc_n, num_unique_neighbors, mfact);
|
||||
get_material(lc, ground_tex_coord, dxdy_gc, mat_shininess, mat_ambient, mat_diffuse, mat_specular, dxdy, st);
|
||||
vec4 coast = texture2D(coastline, tile_coord);
|
||||
|
||||
if (fg_photoScenery) {
|
||||
texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t));
|
||||
water = (texture(coastline, vec2(tile_coord.s, tile_coord.t)).r > 0.1);
|
||||
} else if (coast.g > 0.1) {
|
||||
texel = lookup_ground_texture_array(0, tile_coord, lc, dxdy);
|
||||
water = texture(landclass, vec2(tile_coord.s, tile_coord.t)).z > 0.9;
|
||||
water_lc = (texture(coastline, vec2(tile_coord.s, tile_coord.t)).r > 0.1);
|
||||
} else {
|
||||
// Lookup the base texture texel for this fragment and any neighbors, with mixing
|
||||
texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
|
||||
water = texture(landclass, vec2(tile_coord.s, tile_coord.t)).z > 0.9;
|
||||
water_lc = texture(landclass, vec2(tile_coord.s, tile_coord.t)).z > 0.9;
|
||||
}
|
||||
|
||||
float steep = 0.9;
|
||||
float steepToBeach = 0.93;
|
||||
float beachToWater = 0.95;
|
||||
float waterStart = 0.97;
|
||||
float steepness_modifier = texture2D(coastline, tile_coord).g * 0.1;
|
||||
bool water = water_lc || texture2D(coastline, tile_coord).b > 0.05;
|
||||
|
||||
if ((water_shader == 1) && ((coast.b > 0.05) || (water && steepness < (waterStart + 0.02)))) {
|
||||
if ((water_shader == 1) && (water && (steepness + steepness_modifier)< WATER_START)) {
|
||||
|
||||
// This is a water fragment, so calculate the fragment color procedurally, but mix in the steep and beach
|
||||
vec4 steep_texel = lookup_ground_texture_array(2, ground_tex_coord, lc, dxdy_gc); // Uses the same index as the gradient texture, which it is
|
||||
vec4 beach_texel = texture2D(sand, ground_tex_coord); // Use the dot texture, which is overloaded to be the beach texture
|
||||
texel = mix(steep_texel, beach_texel, smoothstep(steep, steepToBeach, steepness));
|
||||
fragColor = mix(texel, generateWaterTexel(), smoothstep(beachToWater,waterStart,steepness));
|
||||
if (water_lc) {
|
||||
lc = fg_shoreAtlasIndex;
|
||||
get_material(lc, ground_tex_coord, dxdy_gc, mat_shininess, mat_ambient, mat_diffuse, mat_specular, dxdy, st);
|
||||
}
|
||||
|
||||
fragColor.rgb += getClusteredLightsContribution(eyePos.xyz, n, fragColor.rgb);
|
||||
} else if ((water_shader == 1) && water) {
|
||||
vec4 steep_texel = lookup_ground_texture_array(0, ground_tex_coord, lc, dxdy_gc); // Uses the same index as the gradient texture, which it is
|
||||
vec4 beach_texel = lookup_ground_texture_array(0, ground_tex_coord, fg_shoreAtlasIndex, dxdy_gc); // Use the shore texture
|
||||
texel = mix(steep_texel, beach_texel, smoothstep(WATER_STEEP, WATER_STEEP_TO_BEACH, steepness + steepness_modifier));
|
||||
|
||||
// Flag that we need to mix in a water texel later if appropriate.
|
||||
mix_water_texel = (steepness + steepness_modifier > WATER_BEACH_TO_WATER);
|
||||
water = false;
|
||||
}
|
||||
|
||||
if ((water_shader == 1) && water) {
|
||||
fragColor = generateWaterTexel();
|
||||
fragColor.rgb += getClusteredLightsContribution(eyePos.xyz, n, fragColor.rgb);
|
||||
} else {
|
||||
|
@ -602,6 +601,9 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
|
|||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
fragColor = color * texel + specular;
|
||||
|
||||
if (mix_water_texel) { fragColor = mix(fragColor, generateWaterTexel(), smoothstep(WATER_BEACH_TO_WATER, WATER_START, steepness + steepness_modifier)); }
|
||||
|
||||
fragColor.rgb += getClusteredLightsContribution(eyePos.xyz, n, texel.rgb);
|
||||
}
|
||||
|
||||
|
|
|
@ -528,6 +528,13 @@ int read_landclass_id(in vec2 tile_coord)
|
|||
return lc;
|
||||
}
|
||||
|
||||
// Landclass sources: texture or random
|
||||
ivec2 read_landclass_id_and_water(in vec2 tile_coord)
|
||||
{
|
||||
int lc = (int(texture2D(landclass, tile_coord.st).g * 255.0 + 0.5));
|
||||
return ivec2(lc, (texture2D(landclass, tile_coord.st).b > 0.9) ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
int read_landclass_id_non_pixelated(in vec2 tile_coord,
|
||||
const in float landclass_texel_size_m)
|
||||
|
@ -991,8 +998,8 @@ if ( (enable_large_scale_transition_search == 1) &&
|
|||
|
||||
for (int i=1;i<=n;i++) {
|
||||
vec2 c = c0+float(i)*dir;
|
||||
int v = read_landclass_id(c);
|
||||
if ((v != lc) && (mi[0] > n)) {l[0] = v; mi[0] = i; }
|
||||
ivec2 v = read_landclass_id_and_water(c);
|
||||
if ((v[0] != lc) && (v[1] != 1) && (mi[0] > n)) {l[0] = v[0]; mi[0] = i; }
|
||||
}
|
||||
|
||||
|
||||
|
@ -1001,8 +1008,8 @@ if ( (enable_large_scale_transition_search == 1) &&
|
|||
for (int i=1;i<=n;i++)
|
||||
{
|
||||
vec2 c = c0+float(i)*dir;
|
||||
int v = read_landclass_id(c);
|
||||
if ((v != lc) && (mi[1] > n)) {l[1] = v; mi[1] = i; }
|
||||
ivec2 v = read_landclass_id_and_water(c);
|
||||
if ((v[0] != lc) && (v[1] != 1) && (mi[1] > n)) {l[1] = v[0]; mi[1] = i; }
|
||||
}
|
||||
|
||||
|
||||
|
@ -1011,8 +1018,8 @@ if ( (enable_large_scale_transition_search == 1) &&
|
|||
for (int i=1;i<=n;i++)
|
||||
{
|
||||
vec2 c = c0+float(i)*dir;
|
||||
int v = read_landclass_id(c);
|
||||
if ((v != lc) && (mi[2] > n)) {l[2] = v; mi[2] = i; }
|
||||
ivec2 v = read_landclass_id_and_water(c);
|
||||
if ((v[0] != lc) && (v[1] != 1) && (mi[2] > n)) {l[2] = v[0]; mi[2] = i; }
|
||||
}
|
||||
|
||||
|
||||
|
@ -1021,8 +1028,8 @@ if ( (enable_large_scale_transition_search == 1) &&
|
|||
for (int i=1;i<=n;i++)
|
||||
{
|
||||
vec2 c = c0+float(i)*dir;
|
||||
int v = read_landclass_id(c);
|
||||
if ((v != lc) && (mi[3] > n)) {l[3] = v; mi[3] = i; }
|
||||
ivec2 v = read_landclass_id_and_water(c);
|
||||
if ((v[0] != lc) && (v[1] != 1) && (mi[3] > n)) {l[3] = v[0]; mi[3] = i; }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,15 @@ const int randomise_texture_lookups = 0;
|
|||
// Use built-in water shader. Use for testing impact of ws30-water.frag
|
||||
const int water_shader = 1;
|
||||
|
||||
|
||||
// Constants controlling the transition from water
|
||||
// to terrain depending on the terrain normal
|
||||
// A normal of 1.0 is completely horizontal.
|
||||
const float WATER_START = 0.995; // Deeper water.
|
||||
const float WATER_BEACH_TO_WATER = 0.99; // Transition point between the shoreline and the shallow water
|
||||
const float WATER_STEEP_TO_BEACH = 0.985; // The transition point between the shoreline and the land
|
||||
const float WATER_STEEP = 0.98; // Anything with less than this value is considered not water or shoreline
|
||||
|
||||
//
|
||||
// End of test phase controls
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
@ -103,6 +112,9 @@ uniform vec4 fg_materialParams1[128];
|
|||
uniform vec4 fg_materialParams2[128];
|
||||
uniform vec4 fg_materialParams3[128];
|
||||
|
||||
// Index into the material definition for shorelines
|
||||
uniform int fg_shoreAtlasIndex;
|
||||
|
||||
// Coastline texture - generated from VPBTechnique
|
||||
uniform sampler2D coastline;
|
||||
|
||||
|
@ -417,7 +429,8 @@ void main()
|
|||
// Mix factor of base textures for 2 neighbour landclass(es)
|
||||
vec4 mfact;
|
||||
|
||||
bool water = false;
|
||||
bool water_lc = false;
|
||||
bool mix_water_texel = false;
|
||||
|
||||
// Partial derivatives of s and t of ground texture coords for this fragment,
|
||||
// with respect to window (screen space) x and y axes.
|
||||
|
@ -428,24 +441,20 @@ void main()
|
|||
|
||||
get_landclass_id(tile_coord, dxdy_gc, lc, lc_n, num_unique_neighbors, mfact);
|
||||
get_material(lc, ground_tex_coord, dxdy_gc, mat_shininess, mat_ambient, mat_diffuse, mat_specular, dxdy, st);
|
||||
vec4 coast = texture2D(coastline, tile_coord);
|
||||
|
||||
if (fg_photoScenery) {
|
||||
// The photoscenery orthophotos are stored in the landclass texture
|
||||
// and use normalised tile coordinates
|
||||
texel = texture(landclass, vec2(tile_coord.s, 1.0 - tile_coord.t));
|
||||
water = (texture(coastline, vec2(tile_coord.s, tile_coord.t)).r > 0.1);
|
||||
water_lc = (texture(coastline, vec2(tile_coord.s, tile_coord.t)).r > 0.1);
|
||||
|
||||
// Do not attempt any mixing
|
||||
flag = 0;
|
||||
mix_flag = 0;
|
||||
} else if (coast.g > 0.1) {
|
||||
texel = lookup_ground_texture_array(0, tile_coord, lc, dxdy);
|
||||
water = texture(landclass, vec2(tile_coord.s, tile_coord.t)).z > 0.9;
|
||||
} else {
|
||||
// Lookup the base texture texel for this fragment and any neighbors, with mixing
|
||||
texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
|
||||
water = texture(landclass, vec2(tile_coord.s, tile_coord.t)).z > 0.9;
|
||||
water_lc = texture(landclass, vec2(tile_coord.s, tile_coord.t)).b > 0.5;
|
||||
}
|
||||
|
||||
vec4 color = gl_Color * mat_ambient;
|
||||
|
@ -455,20 +464,41 @@ void main()
|
|||
//vec4 green = vec4(0.0, 0.5, 0.0, 0.0);
|
||||
//texel = mix(texel, green, (mfact[2]));
|
||||
|
||||
float steep = 0.9;
|
||||
float steepToBeach = 0.93;
|
||||
float beachToWater = 0.95;
|
||||
float waterStart = 0.97;
|
||||
// The coastline BLUE channel provides a higher detail level for waters. The coastline G channel provides a
|
||||
// steepness modified that is used so that rivers and lakes are displayed with water on more angled surfaces. Otherwise
|
||||
// rivers tend to just be sand, as they flow downhill.
|
||||
float steepness_modifier = texture2D(coastline, tile_coord).g * 0.1;
|
||||
bool water = water_lc || texture2D(coastline, tile_coord).b > 0.05;
|
||||
if (water && (steepness + steepness_modifier < WATER_START)) {
|
||||
// For water surfaces that are simply too steep to be plausible we look for an adjacent landclass and mix it with
|
||||
// a possible shoreline
|
||||
if (water_lc) {
|
||||
if (lc == lc_n[0]) {
|
||||
// Default to the shore material definition
|
||||
lc = fg_shoreAtlasIndex;
|
||||
} else {
|
||||
lc = lc_n[0];
|
||||
}
|
||||
}
|
||||
|
||||
if ((coast.b > 0.05) || (water && steepness < (waterStart + 0.02))) {
|
||||
float waterline_min_steepness = fg_materialParams3[lc].y;
|
||||
float waterline_max_steepness = fg_materialParams3[lc].z;
|
||||
vec4 steep_texel = lookup_ground_texture_array(2, ground_tex_coord, lc, dxdy_gc); // Uses the same index as the gradient texture, which it is
|
||||
vec4 beach_texel = texture2D(sand, ground_tex_coord); // Use the dot texture, which is overloaded to be the beach texture
|
||||
texel = mix(steep_texel, beach_texel, smoothstep(steep, steepToBeach, steepness));
|
||||
fragColor = mix(texel, generateWaterTexel(), smoothstep(beachToWater,waterStart,steepness));
|
||||
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, fragColor.rgb);
|
||||
} else if (water) {
|
||||
get_material(lc, ground_tex_coord, dxdy_gc, mat_shininess, mat_ambient, mat_diffuse, mat_specular, dxdy, st);
|
||||
vec4 color = gl_Color * mat_ambient;
|
||||
color.a = 1.0;
|
||||
|
||||
vec4 steep_texel = lookup_ground_texture_array(0, ground_tex_coord, lc, dxdy); // look up the secondary texture
|
||||
vec4 beach_texel = lookup_ground_texture_array(0, ground_tex_coord, fg_shoreAtlasIndex, dxdy); // Use the shore texture
|
||||
texel = mix(steep_texel, beach_texel, smoothstep(WATER_STEEP, WATER_STEEP_TO_BEACH, steepness + steepness_modifier));
|
||||
|
||||
// Flag that we need to mix in a water texel later if appropriate.
|
||||
mix_water_texel = (steepness + steepness_modifier > WATER_BEACH_TO_WATER);
|
||||
water = false;
|
||||
}
|
||||
|
||||
// Test code to view the coastline rasters in-sim
|
||||
//texel.r = texture2D(coastline, tile_coord).b;
|
||||
//water = false;
|
||||
|
||||
if (water) {
|
||||
fragColor = generateWaterTexel();
|
||||
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, fragColor.rgb);
|
||||
} else {
|
||||
|
@ -833,6 +863,9 @@ void main()
|
|||
color.rgb += secondary_light * light_distance_fading(dist);
|
||||
|
||||
fragColor = color * texel + specular;
|
||||
|
||||
if (mix_water_texel) { fragColor = mix(fragColor, generateWaterTexel(), smoothstep(WATER_BEACH_TO_WATER, WATER_START, steepness + steepness_modifier)); }
|
||||
|
||||
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue