From 7c608c20032624c2f6ef43d8005ec176c63c79ca Mon Sep 17 00:00:00 2001 From: Frederic Bouvier Date: Tue, 2 Nov 2010 22:31:39 +0100 Subject: [PATCH] Restore QDM urban shader technique for quality level >= 4 --- Effects/urban.eff | 143 +++++++++++++++++++++++++++++++++++++++++++++ Shaders/urban.frag | 112 +++++++++++++++++++++++++++++++++-- 2 files changed, 250 insertions(+), 5 deletions(-) diff --git a/Effects/urban.eff b/Effects/urban.eff index f8eecd141..1f43cbb73 100644 --- a/Effects/urban.eff +++ b/Effects/urban.eff @@ -13,6 +13,149 @@ 6 7 + + + + /sim/rendering/urban-shader + /sim/rendering/shader-effects + + 4.0 + /sim/rendering/quality-level + + + + 2.0 + + + + GL_ARB_shader_objects + GL_ARB_shading_language_100 + GL_ARB_vertex_shader + GL_ARB_fragment_shader + + + + + + true + + material/ambient + material/diffuse + material/specular + ambient-and-diffuse + + transparent + transparent + smooth + back + + render-bin/bin-number + render-bin/bin-name + + + 0 + texture[0]/image + texture[0]/filter + texture[0]/wrap-s + texture[0]/wrap-t + + texture[0]/internal-format + + + + 1 + texture[2]/image + texture[2]/filter + texture[2]/wrap-s + texture[2]/wrap-t + texture[2]/internal-format + + + 2 + texture[2]/image + nearest-mipmap-nearest + texture[2]/wrap-s + texture[2]/wrap-t + texture[2]/internal-format + + average + average + average + min + + + + 3 + noise + + + Shaders/urban.vert + Shaders/urban.frag + + tangent + 6 + + + binormal + 7 + + + normal + 15 + + + + BaseTex + sampler-2d + 0 + + + NormalTex + sampler-2d + 1 + + + QDMTex + sampler-2d + 2 + + + NoiseTex + sampler-3d + 3 + + + depth_factor + float + depth-factor + + + tile_size + float + xsize + + + night_color + float-vec3 + night-color + + + quality_level + float + quality-level + + + snowlevel + float + snow-level + + + max_lod_level + float + max-lod-level + + + diff --git a/Shaders/urban.frag b/Shaders/urban.frag index 7e207cf44..addceb67c 100644 --- a/Shaders/urban.frag +++ b/Shaders/urban.frag @@ -5,6 +5,11 @@ #version 120 +#define TEXTURE_MIP_LEVELS 10 +#define TEXTURE_PIX_COUNT 1024 //pow(2,TEXTURE_MIP_LEVELS) +#define BINARY_SEARCH_COUNT 10 +#define BILINEAR_SMOOTH_FACTOR 2.0 + varying vec4 rawpos; varying vec4 ecPosition; varying vec3 VNormal; @@ -16,6 +21,7 @@ varying vec4 constantColor; uniform sampler3D NoiseTex; uniform sampler2D BaseTex; uniform sampler2D NormalTex; +uniform sampler2D QDMTex; uniform float depth_factor; uniform float tile_size; uniform float quality_level; // From /sim/rendering/quality-level @@ -24,8 +30,96 @@ uniform vec3 night_color; const float scale = 1.0; int linear_search_steps = 10; +int GlobalIterationCount = 0; +int gIterationCap = 64; -float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds) +void QDM(inout vec3 p, inout vec3 v) +{ + const int MAX_LEVEL = TEXTURE_MIP_LEVELS; + const float NODE_COUNT = TEXTURE_PIX_COUNT; + const float TEXEL_SPAN_HALF = 1.0 / NODE_COUNT / 2.0; + + float fDeltaNC = TEXEL_SPAN_HALF * depth_factor; + + vec3 p2 = p; + float level = MAX_LEVEL; + vec2 dirSign = (sign(v.xy) + 1.0) * 0.5; + GlobalIterationCount = 0; + float d = 0.0; + + while (level >= 0.0 && GlobalIterationCount < gIterationCap) + { + vec4 uv = vec4(p2.xyz, level); + d = texture2DLod(QDMTex, uv.xy, uv.w).w; + + if (d > p2.z) + { + //predictive point of ray traversal + vec3 tmpP2 = p + v * d; + + //current node count + float nodeCount = pow(2.0, (MAX_LEVEL - level)); + //current and predictive node ID + vec4 nodeID = floor(vec4(p2.xy, tmpP2.xy)*nodeCount); + + //check if we are crossing the current cell + if (nodeID.x != nodeID.z || nodeID.y != nodeID.w) + { + //calculate distance to nearest bound + vec2 a = p2.xy - p.xy; + vec2 p3 = (nodeID.xy + dirSign) / nodeCount; + vec2 b = p3.xy - p.xy; + + vec2 dNC = (b.xy * p2.z) / a.xy; + //take the nearest cell + d = min(d,min(dNC.x, dNC.y))+fDeltaNC; + + level++; + + //use additional convergence speed-up + #ifdef USE_QDM_ASCEND_INTERVAL + if(frac(level*0.5) > EPSILON) + level++; + #elseif USE_QDM_ASCEND_CONST + level++; + #endif + } + p2 = p + v * d; + } + level--; + GlobalIterationCount++; + } + + // + // Manual Bilinear filtering + // + float rayLength = length(p2.xy - p.xy) + fDeltaNC; + + float dA = p2.z * (rayLength - BILINEAR_SMOOTH_FACTOR * TEXEL_SPAN_HALF) / rayLength; + float dB = p2.z * (rayLength + BILINEAR_SMOOTH_FACTOR * TEXEL_SPAN_HALF) / rayLength; + + vec4 p2a = vec4(p + v * dA, 0.0); + vec4 p2b = vec4(p + v * dB, 0.0); + dA = texture2DLod(NormalTex, p2a.xy, p2a.w).w; + dB = texture2DLod(NormalTex, p2b.xy, p2b.w).w; + + dA = abs(p2a.z - dA); + dB = abs(p2b.z - dB); + + p2 = mix(p2a.xyz, p2b.xyz, dA / (dA + dB)); + + p = p2; +} + +float ray_intersect_QDM(vec2 dp, vec2 ds) +{ + vec3 p = vec3( dp, 0.0 ); + vec3 v = vec3( ds, 1.0 ); + QDM( p, v ); + return p.z; +} + +float ray_intersect_relief(vec2 dp, vec2 ds) { float size = 1.0 / float(linear_search_steps); float depth = 0.0; @@ -34,7 +128,7 @@ float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds) for(int i = 0; i < linear_search_steps - 1; ++i) { depth += size; - float t = step(0.95, texture2D(reliefMap, dp + ds * depth).a); + float t = step(0.95, texture2D(NormalTex, dp + ds * depth).a); if(best_depth > 0.996) if(depth >= t) best_depth = depth; @@ -46,7 +140,7 @@ float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds) for(int i = 0; i < binary_search_steps; ++i) { size *= 0.5; - float t = step(0.95, texture2D(reliefMap, dp + ds * depth).a); + float t = step(0.95, texture2D(NormalTex, dp + ds * depth).a); if(depth >= t) { best_depth = depth; @@ -58,6 +152,14 @@ float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds) return(best_depth); } +float ray_intersect(vec2 dp, vec2 ds) +{ + if ( quality_level >= 4.0 ) + return ray_intersect_QDM( dp, ds ); + else + return ray_intersect_relief( dp, ds ); +} + void main (void) { if ( quality_level >= 3.5 ) { @@ -68,7 +170,7 @@ void main (void) vec3 s = vec3(dot(V, VTangent), dot(V, VBinormal), dot(VNormal, -V)); vec2 ds = s.xy * depth_factor / s.z; vec2 dp = gl_TexCoord[0].st - ds; - float d = ray_intersect(NormalTex, dp, ds); + float d = ray_intersect(dp, ds); vec2 uv = dp + ds * d; vec3 N = texture2D(NormalTex, uv).xyz * 2.0 - 1.0; @@ -89,7 +191,7 @@ void main (void) vec3 sl = normalize( vec3( dot( l, VTangent ), dot( l, VBinormal ), dot( -l, VNormal ) ) ); ds = sl.xy * depth_factor / sl.z; dp -= ds * d; - float dl = ray_intersect(NormalTex, dp, ds); + float dl = ray_intersect(dp, ds); if ( dl < d - 0.05 ) shadow_factor = dot( constantColor.xyz, vec3( 1.0, 1.0, 1.0 ) ) * 0.25; }