From 6be18a5c997b3cbe5ae2cbfb8b76480d879a8465 Mon Sep 17 00:00:00 2001 From: Frederic Bouvier Date: Tue, 1 May 2012 08:47:38 +0200 Subject: [PATCH] Add the ability to record depth in color buffer. This should solve depth buffer resolution problem for older NVidia cards. --- Effects/tree.eff | 1 + Shaders/deferred-gbuffer.frag | 16 ++++----- Shaders/deferred-gbuffer.vert | 8 ++--- Shaders/deferred-tree.frag | 8 ++--- Shaders/fog.frag | 8 ++--- Shaders/gbuffer-functions.frag | 57 ++++++++++++++++++++++++++++++- Shaders/light-point.frag | 4 +-- Shaders/light-spot.frag | 4 +-- Shaders/sunlight-nofiltering.frag | 4 +-- Shaders/sunlight-simple.frag | 4 +-- Shaders/sunlight.frag | 4 +-- Shaders/ubershader-gbuffer.frag | 6 ++-- Shaders/urban-gbuffer.frag | 7 ++-- preferences.xml | 1 + 14 files changed, 88 insertions(+), 44 deletions(-) diff --git a/Effects/tree.eff b/Effects/tree.eff index 18599aa5d..ad27ae4f4 100644 --- a/Effects/tree.eff +++ b/Effects/tree.eff @@ -67,6 +67,7 @@ Shaders/deferred-tree.vert Shaders/deferred-tree.frag + Shaders/gbuffer-functions.frag texture diff --git a/Shaders/deferred-gbuffer.frag b/Shaders/deferred-gbuffer.frag index e1d3b4cf9..3ffce50f1 100644 --- a/Shaders/deferred-gbuffer.frag +++ b/Shaders/deferred-gbuffer.frag @@ -1,15 +1,15 @@ #extension GL_EXT_gpu_shader4 : enable +// -*- mode: C; -*- +// Licence: GPL v2 +// Author: Frederic Bouvier. // -// attachment 0: normal.x | normal.x | normal.y | normal.y -// attachment 1: diffuse.r | diffuse.g | diffuse.b | material Id -// attachment 2: specular.l | shininess | emission.l | unused -// + varying vec3 ecNormal; varying float alpha; uniform int materialID; uniform sampler2D texture; -vec2 normal_encode(vec3 n); +void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth); void main() { vec4 texel = texture2D(texture, gl_TexCoord[0].st); @@ -19,8 +19,6 @@ void main() { float shininess = gl_FrontMaterial.shininess; float emission = dot( gl_FrontLightModelProduct.sceneColor.rgb, vec3( 0.3, 0.59, 0.11 ) ); - vec3 normal2 = normalize( (2.0 * gl_Color.a - 1.0) * ecNormal ); - gl_FragData[0] = vec4( normal_encode(normal2), 0.0, 1.0 ); - gl_FragData[1] = vec4( gl_Color.rgb * texel.rgb, float( materialID ) / 255.0 ); - gl_FragData[2] = vec4( specular, shininess / 128.0, emission, 1.0 ); + vec3 normal2 = normalize( (2.0 * gl_Color.a - 1.0) * ecNormal ); + encode_gbuffer(normal2, gl_Color.rgb * texel.rgb, materialID, specular, shininess, emission, gl_FragCoord.z); } diff --git a/Shaders/deferred-gbuffer.vert b/Shaders/deferred-gbuffer.vert index 4ab618936..ca8e4549d 100644 --- a/Shaders/deferred-gbuffer.vert +++ b/Shaders/deferred-gbuffer.vert @@ -1,8 +1,8 @@ +// -*- mode: C; -*- +// Licence: GPL v2 +// Author: Frederic Bouvier. // -// attachment 0: normal.x | normal.x | normal.y | normal.y -// attachment 1: diffuse.r | diffuse.g | diffuse.b | material Id -// attachment 2: specular.l | shininess | emission.l | unused -// + varying vec3 ecNormal; varying float alpha; void main() { diff --git a/Shaders/deferred-tree.frag b/Shaders/deferred-tree.frag index 8c416240c..5d94da809 100644 --- a/Shaders/deferred-tree.frag +++ b/Shaders/deferred-tree.frag @@ -6,6 +6,7 @@ // uniform int materialID; uniform sampler2D texture; +void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth); void main() { vec4 texel = texture2D(texture, gl_TexCoord[0].st); if (texel.a < 0.1) @@ -14,9 +15,6 @@ void main() { float shininess = 0.1; float emission = 0.0; - // Normal is straight towards the viewer. - vec3 normal2 = vec3(0.0, 0.0, 0.0); - gl_FragData[0] = vec4( 0.5, 0.5, 0.0, 1.0 ); - gl_FragData[1] = vec4( gl_Color.rgb * texel.rgb, float( materialID ) / 255.0 ); - gl_FragData[2] = vec4( specular, shininess / 255.0, emission, 1.0 ); + // Normal is straight towards the viewer. (FB: Are they really billboards ? ) + encode_gbuffer(vec3(0.5, 0.5, 0.0), gl_Color.rgb * texel.rgb, materialID, specular, shininess, emission, gl_FragCoord.z); } diff --git a/Shaders/fog.frag b/Shaders/fog.frag index 09280db14..3ae150fc5 100644 --- a/Shaders/fog.frag +++ b/Shaders/fog.frag @@ -7,7 +7,7 @@ uniform float fg_FogDensity; uniform vec3 fg_Planes; varying vec3 ray; -vec3 position( vec3 viewdir, float depth ); +vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex ); void main() { vec2 coords = gl_TexCoord[0].xy; @@ -15,11 +15,7 @@ void main() { if ( initialized < 0.1 ) discard; vec3 normal; - normal.xy = texture2D( normal_tex, coords ).rg * 2.0 - vec2(1.0,1.0); - normal.z = sqrt( 1.0 - dot( normal.xy, normal.xy ) ); - float len = length(normal); - normal /= len; - vec3 pos = position( normalize(ray), texture2D( depth_tex, coords ).r ); + vec3 pos = position( normalize(ray), coords, depth_tex ); float fogFactor = 0.0; const float LOG2 = 1.442695; diff --git a/Shaders/gbuffer-functions.frag b/Shaders/gbuffer-functions.frag index 5b8addee6..871a209ef 100644 --- a/Shaders/gbuffer-functions.frag +++ b/Shaders/gbuffer-functions.frag @@ -1,4 +1,9 @@ +// -*- mode: C; -*- +// Licence: GPL v2 +// Author: Frederic Bouvier. + uniform vec3 fg_Planes; +uniform bool fg_DepthInColor; // normal compression functions from // http://aras-p.info/texts/CompactNormalStorage.html#method04spheremap @@ -19,10 +24,60 @@ vec3 normal_decode(vec2 enc) return n; } +// depth to color encoding and decoding functions from +// Deferred Shading Tutorial by Fabio Policarpo and Francisco Fonseca +// (corrected by Frederic Bouvier) +vec3 float_to_color(in float f) +{ + vec3 color; + f *= 255.0; + color.x = floor(f); + f = (f-color.x)*255.0; + color.y = floor(f); + color.z = f-color.y; + color.xy /= 255.0; + return color; +} + +float color_to_float(vec3 color) +{ + const vec3 byte_to_float = vec3(1.0, 1.0/255.0, 1.0/(255.0*255.0)); + return dot(color,byte_to_float); +} + vec3 position( vec3 viewDir, float depth ) { vec3 pos; pos.z = - fg_Planes.y / (fg_Planes.x + depth * fg_Planes.z); pos.xy = viewDir.xy / viewDir.z * pos.z; - return pos; + return pos; +} + +vec3 position( vec3 viewDir, vec3 depthColor ) +{ + return position( viewDir, color_to_float(depthColor) ); +} + +vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex ) +{ + float depth; + if (fg_DepthInColor) + depth = color_to_float( texture2D( depth_tex, coords ).rgb ); + else + depth = texture2D( depth_tex, coords ).r; + return position( viewDir, depth ); +} + +// attachment 0: normal.x | normal.y | 0.0 | 1.0 +// attachment 1: diffuse.r | diffuse.g | diffuse.b | material Id +// attachment 2: specular.l | shininess | emission.l | unused +// attachment 3: ---------- depth ------------ | unused (optional) +// +void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth) +{ + gl_FragData[0] = vec4( normal_encode(normal), 0.0, 1.0 ); + gl_FragData[1] = vec4( color, float( mId ) / 255.0 ); + gl_FragData[2] = vec4( specular, shininess / 128.0, emission, 1.0 ); + if (fg_DepthInColor) + gl_FragData[3] = vec4(float_to_color(depth), 1.0); } diff --git a/Shaders/light-point.frag b/Shaders/light-point.frag index f71a40600..739017278 100644 --- a/Shaders/light-point.frag +++ b/Shaders/light-point.frag @@ -15,7 +15,7 @@ uniform float Far; varying vec4 ecPosition; -vec3 position( vec3 viewdir, float depth ); +vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex ); vec3 normal_decode(vec2 enc); void main() { @@ -27,7 +27,7 @@ void main() { vec3 normal = normal_decode(texture2D( normal_tex, coords ).rg); vec4 spec_emis = texture2D( spec_emis_tex, coords ); - vec3 pos = position(viewDir, texture2D( depth_tex, coords ).r); + vec3 pos = position(viewDir, coords, depth_tex); if ( pos.z < ecPos3.z ) // Negative direction in z discard; // Don't light surface outside the light volume diff --git a/Shaders/light-spot.frag b/Shaders/light-spot.frag index 7371eec6f..a4bdd7231 100644 --- a/Shaders/light-spot.frag +++ b/Shaders/light-spot.frag @@ -19,7 +19,7 @@ uniform float Far; varying vec4 ecPosition; -vec3 position( vec3 viewdir, float depth ); +vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex ); vec3 normal_decode(vec2 enc); void main() { @@ -31,7 +31,7 @@ void main() { vec3 normal = normal_decode(texture2D( normal_tex, coords ).rg); vec4 spec_emis = texture2D( spec_emis_tex, coords ); - vec3 pos = position(viewDir, texture2D( depth_tex, coords ).r); + vec3 pos = position(viewDir, coords, depth_tex); if ( pos.z < ecPos3.z ) // Negative direction in z discard; // Don't light surface outside the light volume diff --git a/Shaders/sunlight-nofiltering.frag b/Shaders/sunlight-nofiltering.frag index 80ea77f54..aacfd9d3c 100644 --- a/Shaders/sunlight-nofiltering.frag +++ b/Shaders/sunlight-nofiltering.frag @@ -12,7 +12,7 @@ uniform int fg_ShadowNumber; uniform vec4 fg_ShadowDistances; varying vec3 ray; -vec3 position( vec3 viewdir, float depth ); +vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex ); vec3 normal_decode(vec2 enc); vec4 DynamicShadow( in vec4 ecPosition, out vec4 tint ) @@ -57,7 +57,7 @@ void main() { float len = length(normal); normal /= len; vec3 viewDir = normalize(ray); - vec3 pos = position( viewDir, texture2D( depth_tex, coords ).r ); + vec3 pos = position( viewDir, coords, depth_tex ); vec4 tint; float shadow = shadow2DProj( shadow_tex, DynamicShadow( vec4( pos, 1.0 ), tint ) ).r; diff --git a/Shaders/sunlight-simple.frag b/Shaders/sunlight-simple.frag index 4a354c02b..e6d38deb7 100644 --- a/Shaders/sunlight-simple.frag +++ b/Shaders/sunlight-simple.frag @@ -17,7 +17,7 @@ varying vec4 eyePlaneT; varying vec4 eyePlaneR; varying vec4 eyePlaneQ; -vec3 position( vec3 viewdir, float depth ); +vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex ); vec3 normal_decode(vec2 enc); vec4 DynamicShadow( in vec4 ecPosition, out vec4 tint ) @@ -43,7 +43,7 @@ void main() { float len = length(normal); normal /= len; vec3 viewDir = normalize(ray); - vec3 pos = position( viewDir, texture2D( depth_tex, coords ).r ); + vec3 pos = position( viewDir, coords, depth_tex ); vec4 tint; float shadow; diff --git a/Shaders/sunlight.frag b/Shaders/sunlight.frag index 6f5578342..1d79c94db 100644 --- a/Shaders/sunlight.frag +++ b/Shaders/sunlight.frag @@ -14,7 +14,7 @@ uniform vec4 fg_ShadowDistances; uniform int filtering; varying vec3 ray; -vec3 position( vec3 viewdir, float depth ); +vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex ); vec3 normal_decode(vec2 enc); vec4 DynamicShadow( in vec4 ecPosition, out vec4 tint ) @@ -59,7 +59,7 @@ void main() { float len = length(normal); normal /= len; vec3 viewDir = normalize(ray); - vec3 pos = position( viewDir, texture2D( depth_tex, coords ).r ); + vec3 pos = position( viewDir, coords, depth_tex ); vec4 tint; float shadow = 0.0; diff --git a/Shaders/ubershader-gbuffer.frag b/Shaders/ubershader-gbuffer.frag index ff6c48a3a..be75f8c96 100644 --- a/Shaders/ubershader-gbuffer.frag +++ b/Shaders/ubershader-gbuffer.frag @@ -56,7 +56,7 @@ uniform vec3 dirt_g_color; uniform vec3 dirt_b_color; //uniform vec4 fg_SunAmbientColor; -vec2 normal_encode(vec3 n); +void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth); ///fog include////////////////////// uniform int fogType; @@ -180,7 +180,5 @@ void main (void) // END lightmap ///////////////////////////////////////////////////////////////////// - gl_FragData[0]=vec4(normal_encode(N), 0.0, 1.0); - gl_FragData[1]=vec4(fragColor.rgb,1.0/255.0); - gl_FragData[2]=vec4(specular, gl_FrontMaterial.shininess/128.0, emission, 1.0); + encode_gbuffer(N, fragColor.rgb, 1, specular, gl_FrontMaterial.shininess, emission, gl_FragCoord.z); } \ No newline at end of file diff --git a/Shaders/urban-gbuffer.frag b/Shaders/urban-gbuffer.frag index c28959996..f182347ee 100644 --- a/Shaders/urban-gbuffer.frag +++ b/Shaders/urban-gbuffer.frag @@ -37,7 +37,7 @@ int linear_search_steps = 10; int GlobalIterationCount = 0; int gIterationCap = 64; -vec2 normal_encode(vec3 n); +void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth); void QDM(inout vec3 p, inout vec3 v) { @@ -190,7 +190,6 @@ void main (void) N.z = sqrt(1.0 - min(1.0,dot(N.xy, N.xy))); float Nz = N.z; N = normalize(N.x * tangent + N.y * binormal + N.z * normal); - gl_FragData[0] = vec4( normal_encode(N), 0.0, 1.0 ); vec4 ambient_light = constantColor + vec4(gl_Color.rgb, 1.0); @@ -216,9 +215,6 @@ void main (void) vec4 p = vec4( ecPos3 + tile_size * V * (d-1.0) * depth_factor / s.z, 1.0 ); - gl_FragData[1] = vec4( finalColor.rgb, 1.0 / 255.0 ); - gl_FragData[2] = vec4( dot(specular.xyz,vec3(0.3, 0.59, 0.11 )), specular.w/128.0, 0.0, 1.0 ); - if (dot(normal,-V) > 0.1) { vec4 iproj = gl_ProjectionMatrix * p; iproj /= iproj.w; @@ -226,4 +222,5 @@ void main (void) } else { gl_FragDepth = gl_FragCoord.z; } + encode_gbuffer(N, finalColor.rgb, 1, dot(specular.xyz,vec3(0.3, 0.59, 0.11 )), specular.w, 0.0, gl_FragDepth); } diff --git a/preferences.xml b/preferences.xml index 987dd0c9c..2e90f8e6a 100644 --- a/preferences.xml +++ b/preferences.xml @@ -68,6 +68,7 @@ Started September 2000 by David Megginson, david@megginson.com true false 1.0 + false false 5 8