From b857fb2d7c8b630a7cf9242e957f05df7404edc1 Mon Sep 17 00:00:00 2001 From: Frederic Bouvier Date: Mon, 9 Apr 2012 18:52:24 +0200 Subject: [PATCH] Rembrandt: convert urban effect --- Effects/urban.eff | 339 +++++++++++++++++++++++++++++++++++++ Shaders/urban-gbuffer.frag | 219 ++++++++++++++++++++++++ Shaders/urban-gbuffer.vert | 30 ++++ 3 files changed, 588 insertions(+) create mode 100644 Shaders/urban-gbuffer.frag create mode 100644 Shaders/urban-gbuffer.vert diff --git a/Effects/urban.eff b/Effects/urban.eff index ef4defa74..a214a112b 100644 --- a/Effects/urban.eff +++ b/Effects/urban.eff @@ -39,6 +39,345 @@ 6 7 + + + + /sim/rendering/rembrandt + /sim/rendering/shaders/urban + + 4.0 + /sim/rendering/shaders/urban + + + + 2.0 + + + + GL_ARB_shader_objects + GL_ARB_shading_language_100 + GL_ARB_vertex_shader + GL_ARB_fragment_shader + + + + GL_ATI_shader_texture_lod + GL_ARB_shader_texture_lod + GL_EXT_gpu_shader4 + + + + + false + + + material/ambient + + + material/diffuse + + + material/specular + + ambient-and-diffuse + + false + false + smooth + back + + 0 + RenderBin + + + 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-gbuffer.vert + Shaders/urban-gbuffer.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 + + + + quality_level + float + + quality-level + + + + snowlevel + float + + snow-level + + + + max_lod_level + float + + max-lod-level + + + + + + + + /sim/rendering/rembrandt + /sim/rendering/shaders/urban + + 1.0 + /sim/rendering/shaders/urban + + + + 2.0 + + + + GL_ARB_shader_objects + GL_ARB_shading_language_100 + GL_ARB_vertex_shader + GL_ARB_fragment_shader + + + + + + + false + + + material/ambient + + + material/diffuse + + + material/specular + + ambient-and-diffuse + + false + false + smooth + back + + 0 + RenderBin + + + 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 + noise + + + Shaders/urban-gbuffer.vert + Shaders/urban-gbuffer.frag + + tangent + 6 + + + binormal + 7 + + + normal + 15 + + + + BaseTex + sampler-2d + 0 + + + NormalTex + sampler-2d + 1 + + + NoiseTex + sampler-3d + 2 + + + depth_factor + float + + depth-factor + + + + tile_size + float + + xsize + + + + night_color + float-vec3 + + night-color + + + + quality_level + float + + quality-level + + + + snowlevel + float + + snow-level + + + + diff --git a/Shaders/urban-gbuffer.frag b/Shaders/urban-gbuffer.frag new file mode 100644 index 000000000..a3349d8a4 --- /dev/null +++ b/Shaders/urban-gbuffer.frag @@ -0,0 +1,219 @@ +// -*- mode: C; -*- +// 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 + +#extension GL_ATI_shader_texture_lod : enable +#extension GL_ARB_shader_texture_lod : enable + +#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; +varying vec3 VTangent; +varying vec3 VBinormal; +varying vec3 Normal; +varying vec4 constantColor; +varying vec4 specular; + +uniform sampler3D NoiseTex; +uniform sampler2D BaseTex; +uniform sampler2D NormalTex; +uniform sampler2D QDMTex; +uniform float depth_factor; +uniform float tile_size; +uniform float quality_level; +uniform float snowlevel; + +const float scale = 1.0; +int linear_search_steps = 10; +int GlobalIterationCount = 0; +int gIterationCap = 64; + +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; + float best_depth = 1.0; + + for(int i = 0; i < linear_search_steps - 1; ++i) + { + depth += size; + float t = step(0.95, texture2D(NormalTex, dp + ds * depth).a); + if(best_depth > 0.996) + if(depth >= t) + best_depth = depth; + } + depth = best_depth; + + const int binary_search_steps = 5; + + for(int i = 0; i < binary_search_steps; ++i) + { + size *= 0.5; + float t = step(0.95, texture2D(NormalTex, dp + ds * depth).a); + if(depth >= t) + { + best_depth = depth; + depth -= 2.0 * size; + } + depth += size; + } + + 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.0 ) { + 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); + + vec2 uv = dp + ds * d; + vec3 N = texture2D(NormalTex, uv).xyz * 2.0 - 1.0; + + + float emis = N.z; + N.z = sqrt(1.0 - min(1.0,dot(N.xy, N.xy))); + float Nz = N.z; + N = normalize(N.x * VTangent + N.y * VBinormal + N.z * VNormal); + gl_FragData[0] = vec4( (N.xy + vec2(1.0,1.0)) * 0.5, 0.0, 1.0 ); + + vec4 ambient_light = constantColor + vec4(gl_Color.rgb, 1.0); + + vec4 noisevec = texture3D(NoiseTex, (rawpos.xyz)*0.01*scale); + vec4 nvL = texture3D(NoiseTex, (rawpos.xyz)*0.00066*scale); + + float n=0.06; + n += nvL[0]*0.4; + n += nvL[1]*0.6; + n += nvL[2]*2.0; + n += nvL[3]*4.0; + n += noisevec[0]*0.1; + n += noisevec[1]*0.4; + + n += noisevec[2]*0.8; + n += noisevec[3]*2.1; + n = mix(0.6, n, length(ecPosition.xyz) ); + + vec4 finalColor = texture2D(BaseTex, uv); + finalColor = mix(finalColor, clamp(n+nvL[2]*4.1+vec4(0.1, 0.1, nvL[2]*2.2, 1.0), 0.7, 1.0), + step(0.8,Nz)*(1.0-emis)*smoothstep(snowlevel+300.0, snowlevel+360.0, (rawpos.z)+nvL[1]*3000.0)); + finalColor *= ambient_light; + + vec4 p = vec4( ecPos3 + tile_size * V * (d-1.0) * depth_factor / s.z, 1.0 ); + vec4 iproj = gl_ProjectionMatrix * p; + iproj /= iproj.w; + + 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, 0.0, 1.0 ); + + gl_FragDepth = (iproj.z + 1.0) / 2.0; +} diff --git a/Shaders/urban-gbuffer.vert b/Shaders/urban-gbuffer.vert new file mode 100644 index 000000000..285abb533 --- /dev/null +++ b/Shaders/urban-gbuffer.vert @@ -0,0 +1,30 @@ +// -*- mode: C; -*- +// Licence: GPL v2 +// Author: Frederic Bouvier + +varying vec4 rawpos; +varying vec4 ecPosition; +varying vec3 VNormal; +varying vec3 Normal; +varying vec3 VTangent; +varying vec3 VBinormal; +varying vec4 constantColor; +varying vec4 specular; + +attribute vec3 tangent, binormal; + +void main(void) +{ + rawpos = gl_Vertex; + ecPosition = gl_ModelViewMatrix * gl_Vertex; + VNormal = normalize(gl_NormalMatrix * gl_Normal); + Normal = normalize(gl_Normal); + VTangent = gl_NormalMatrix * tangent; + VBinormal = gl_NormalMatrix * binormal; + gl_FrontColor = gl_Color; + constantColor = gl_FrontMaterial.emission + + gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient); + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + specular = vec4( gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess ); +}