diff --git a/Effects/urban.eff b/Effects/urban.eff index d73d5b2ea..f8eecd141 100644 --- a/Effects/urban.eff +++ b/Effects/urban.eff @@ -7,7 +7,6 @@ 0.008 0.75 0.59 0.05 /sim/rendering/quality-level - 10 15 @@ -69,24 +68,12 @@ texture[2]/filter texture[2]/wrap-s texture[2]/wrap-t - texture[2]/internal-format + + 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 @@ -115,15 +102,10 @@ sampler-2d 1 - - QDMTex - sampler-2d - 2 - NoiseTex sampler-3d - 3 + 2 depth_factor @@ -150,11 +132,6 @@ float snow-level - - max_lod_level - float - max-lod-level - diff --git a/Shaders/urban.frag b/Shaders/urban.frag index f61faa35a..7e207cf44 100644 --- a/Shaders/urban.frag +++ b/Shaders/urban.frag @@ -2,15 +2,9 @@ // Licence: GPL v2 // Author: Frederic Bouvier. // Adapted from the paper by F. Policarpo et al. : Real-time Relief Mapping on Arbitrary Polygonal Surfaces -// Adapted from the paper and sources by M. Drobot in GPU Pro : Quadtree Displacement Mapping with Height Blending #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; @@ -22,7 +16,6 @@ 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 @@ -30,103 +23,52 @@ uniform float snowlevel; // From /sim/rendering/snow-level-m uniform vec3 night_color; const float scale = 1.0; -int GlobalIterationCount = 0; -int gIterationCap = 64; +int linear_search_steps = 10; -void QDM(inout vec3 p, inout vec3 v) +float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds) { - 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 size = 1.0 / float(linear_search_steps); + float depth = 0.0; + float best_depth = 1.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; - - while (level >= 0 && GlobalIterationCount < gIterationCap) + for(int i = 0; i < linear_search_steps - 1; ++i) { - vec4 uv = vec4(p2.xyz, level); - d = texture2DLod(QDMTex, uv.xy, uv.w).w; + depth += size; + float t = step(0.95, texture2D(reliefMap, dp + ds * depth).a); + if(best_depth > 0.996) + if(depth >= t) + best_depth = depth; + } + depth = best_depth; - if (d > p2.z) + const int binary_search_steps = 5; + + for(int i = 0; i < binary_search_steps; ++i) + { + size *= 0.5; + float t = step(0.95, texture2D(reliefMap, dp + ds * depth).a); + if(depth >= t) { - //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; + best_depth = depth; + depth -= 2.0 * size; } - level--; - GlobalIterationCount++; + depth += size; } - // - // 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); - vec4 p2b = vec4(p + v * dB, 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(vec2 dp, vec2 ds) -{ - vec3 p = vec3( dp, 0.0 ); - vec3 v = vec3( ds, 1.0 ); - QDM( p, v ); - return p.z; + return(best_depth); } void main (void) { + if ( quality_level >= 3.5 ) { + linear_search_steps = 20; + } vec3 ecPos3 = ecPosition.xyz / ecPosition.w; vec3 V = normalize(ecPos3); 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(dp, ds); + float d = ray_intersect(NormalTex, dp, ds); vec2 uv = dp + ds * d; vec3 N = texture2D(NormalTex, uv).xyz * 2.0 - 1.0; @@ -147,7 +89,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(dp, ds); + float dl = ray_intersect(NormalTex, dp, ds); if ( dl < d - 0.05 ) shadow_factor = dot( constantColor.xyz, vec3( 1.0, 1.0, 1.0 ) ) * 0.25; }