From 7c608c20032624c2f6ef43d8005ec176c63c79ca Mon Sep 17 00:00:00 2001 From: Frederic Bouvier <fredfgfs01@free.fr> 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 @@ <tangent type="int">6</tangent> <binormal type="int">7</binormal> </generate> + <technique n="8"> + <predicate> + <and> + <property>/sim/rendering/urban-shader</property> + <property>/sim/rendering/shader-effects</property> + <less-equal> + <value type="float">4.0</value> + <float-property>/sim/rendering/quality-level</float-property> + </less-equal> + <or> + <less-equal> + <value type="float">2.0</value> + <glversion/> + </less-equal> + <and> + <extension-supported>GL_ARB_shader_objects</extension-supported> + <extension-supported>GL_ARB_shading_language_100</extension-supported> + <extension-supported>GL_ARB_vertex_shader</extension-supported> + <extension-supported>GL_ARB_fragment_shader</extension-supported> + </and> + </or> + </and> + </predicate> + <pass> + <lighting>true</lighting> + <material> + <ambient><use>material/ambient</use></ambient> + <diffuse><use>material/diffuse</use></diffuse> + <specular><use>material/specular</use></specular> + <color-mode>ambient-and-diffuse</color-mode> + </material> + <blend><use>transparent</use></blend> + <alpha-test><use>transparent</use></alpha-test> + <shade-model>smooth</shade-model> + <cull-face>back</cull-face> + <render-bin> + <bin-number><use>render-bin/bin-number</use></bin-number> + <bin-name><use>render-bin/bin-name</use></bin-name> + </render-bin> + <texture-unit> + <unit>0</unit> + <image><use>texture[0]/image</use></image> + <filter><use>texture[0]/filter</use></filter> + <wrap-s><use>texture[0]/wrap-s</use></wrap-s> + <wrap-t><use>texture[0]/wrap-t</use></wrap-t> + <internal-format> + <use>texture[0]/internal-format</use> + </internal-format> + </texture-unit> + <texture-unit> + <unit>1</unit> + <image><use>texture[2]/image</use></image> + <filter><use>texture[2]/filter</use></filter> + <wrap-s><use>texture[2]/wrap-s</use></wrap-s> + <wrap-t><use>texture[2]/wrap-t</use></wrap-t> + <internal-format><use>texture[2]/internal-format</use></internal-format> + </texture-unit> + <texture-unit> + <unit>2</unit> + <image><use>texture[2]/image</use></image> + <filter>nearest-mipmap-nearest</filter> + <wrap-s><use>texture[2]/wrap-s</use></wrap-s> + <wrap-t><use>texture[2]/wrap-t</use></wrap-t> + <internal-format><use>texture[2]/internal-format</use></internal-format> + <mipmap-control> + <function-r>average</function-r> + <function-g>average</function-g> + <function-b>average</function-b> + <function-a>min</function-a> + </mipmap-control> + </texture-unit> + <texture-unit> + <unit>3</unit> + <type>noise</type> + </texture-unit> + <program> + <vertex-shader>Shaders/urban.vert</vertex-shader> + <fragment-shader>Shaders/urban.frag</fragment-shader> + <attribute> + <name>tangent</name> + <index>6</index> + </attribute> + <attribute> + <name>binormal</name> + <index>7</index> + </attribute> + <attribute> + <name>normal</name> + <index>15</index> + </attribute> + </program> + <uniform> + <name>BaseTex</name> + <type>sampler-2d</type> + <value type="int">0</value> + </uniform> + <uniform> + <name>NormalTex</name> + <type>sampler-2d</type> + <value type="int">1</value> + </uniform> + <uniform> + <name>QDMTex</name> + <type>sampler-2d</type> + <value type="int">2</value> + </uniform> + <uniform> + <name>NoiseTex</name> + <type>sampler-3d</type> + <value type="int">3</value> + </uniform> + <uniform> + <name>depth_factor</name> + <type>float</type> + <value><use>depth-factor</use></value> + </uniform> + <uniform> + <name>tile_size</name> + <type>float</type> + <value><use>xsize</use></value> + </uniform> + <uniform> + <name>night_color</name> + <type>float-vec3</type> + <value><use>night-color</use></value> + </uniform> + <uniform> + <name>quality_level</name> + <type>float</type> + <value><use>quality-level</use></value> + </uniform> + <uniform> + <name>snowlevel</name> + <type>float</type> + <value><use>snow-level</use></value> + </uniform> + <uniform> + <name>max_lod_level</name> + <type>float</type> + <value><use>max-lod-level</use></value> + </uniform> + </pass> + </technique> <technique n="9"> <predicate> <and> 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; }