diff --git a/base/renderprogs/AmbientOcclusion_AO.pixel b/base/renderprogs/AmbientOcclusion_AO.pixel
index ecf92b6a..5399a8b2 100644
--- a/base/renderprogs/AmbientOcclusion_AO.pixel
+++ b/base/renderprogs/AmbientOcclusion_AO.pixel
@@ -60,7 +60,7 @@ const float METERS_TO_DOOM = ( 1.0 / DOOM_TO_METERS ); // meters to doom
/** Used for preventing AO computation on the sky (at infinite depth) and defining the CS Z to bilateral depth key scaling.
This need not match the real far plane but should not be much more than it.*/
-const float FAR_PLANE_Z = -4000.0;
+const float FAR_PLANE_Z = -16000.0;
/** World-space AO radius in scene units (r). e.g., 1.0m */
const float radius = 1.0 * METERS_TO_DOOM;
@@ -71,7 +71,7 @@ const float invRadius2 = 1.0 / radius2;
const float bias = 0.01 * METERS_TO_DOOM;
/** intensity / radius^6 */
-const float intensity = 0.5;
+const float intensity = 0.3;
const float intensityDivR6 = intensity / ( radius* radius* radius* radius* radius* radius );
const float projScale = 300.0;// * METERS_TO_DOOM;
@@ -119,6 +119,19 @@ float CSZToKey( float z )
return clamp( z * ( 1.0 / FAR_PLANE_Z ), 0.0, 1.0 );
}
+/** Used for packing Z into the GB channels */
+void packKey( float key, out float2 p )
+{
+ // Round to the nearest 1/256.0
+ float temp = floor( key * 256.0 );
+
+ // Integer part
+ p.x = temp * ( 1.0 / 256.0 );
+
+ // Fractional part
+ p.y = key * 256.0 - temp;
+}
+
/** Reconstructs screen-space unit normal from screen-space position */
float3 reconstructCSFaceNormal( float3 C )
{
@@ -135,14 +148,23 @@ float3 reconstructNonUnitCSFaceNormal( float3 C )
/** Read the camera-space position of the point at screen-space pixel ssP */
float3 getPosition( float2 ssP, sampler2D cszBuffer )
{
+#if 1
+ // derive clip space from the depth buffer and screen position
+ float windowZ = tex2D( cszBuffer, ssP ).x;
+ float3 ndc = float3( ssP * 2.0 - 1.0, windowZ * 2.0 - 1.0 );
+ //float clipW = -rpProjectionMatrixZ.w / ( -rpProjectionMatrixZ.z - ndc.z );
+ //float4 P = float4( ndc * clipW, clipW );
+ float4 P = float4( ndc, 1.0 );
+#else
float4 P;
P.z = tex2D( cszBuffer, ssP ).r;
P.xy = float2( ssP ); //+ float2( 0.5 ) );
P.w = 1.0;
-
+#endif
// offset to pixel center
//P = reconstructCSPosition( float2( ssP ) + float2( 0.5 ), P.z, projInfo );
+#if 1
float4 csP;
csP.x = dot4( P, rpProjectionMatrixX );
csP.y = dot4( P, rpProjectionMatrixY );
@@ -150,6 +172,7 @@ float3 getPosition( float2 ssP, sampler2D cszBuffer )
csP.w = dot4( P, rpProjectionMatrixW );
csP.xyz /= csP.w;
+#endif
#if 0
float4 wP;
@@ -186,7 +209,17 @@ float3 getOffsetPosition( ivec2 issC, vec2 unitOffset, float ssR, sampler2D cszB
float2 ossC = float2( ssP ) * rpScreenCorrectionFactor.xy;
- P.z = texture( cszBuffer, ossC, 0.0 ).r;
+ float windowZ = texture( cszBuffer, ossC, 0.0 ).r;
+
+#if 1
+ float3 ndc = float3( ossC * 2.0 - 1.0, windowZ * 2.0 - 1.0 );
+ //float clipW = -rpProjectionMatrixZ.w / ( -rpProjectionMatrixZ.z - ndc.z );
+ //P = float4( ndc * clipW, clipW );
+ P = float4( ndc, 1.0 );
+
+ //return P.xyz;
+#else
+
//P.z = texture( cszBuffer, mipP, 0.0 ).r;
//P.z = texture( cszBuffer, mipP, mipLevel ).r;
@@ -194,13 +227,16 @@ float3 getOffsetPosition( ivec2 issC, vec2 unitOffset, float ssR, sampler2D cszB
//P = reconstructCSPosition( ( vec2( ssP ) + vec2( 0.5 ) ) * invCszBufferScale, P.z, projInfo );
P.xy = ossC; //+ float2( 0.5 ) ) * invCszBufferScale;
P.w = 1.0;
+#endif
+#if 1
float4 csP;
csP.x = dot4( P, rpProjectionMatrixX );
csP.y = dot4( P, rpProjectionMatrixY );
csP.z = dot4( P, rpProjectionMatrixZ );
csP.w = dot4( P, rpProjectionMatrixW );
csP.xyz /= csP.w;
+#endif
#if 0
float4 wP;
@@ -294,7 +330,7 @@ float sampleAO( ivec2 issC, in float3 C, in float3 n_C, in float ssDiskRadius, i
const float MIN_RADIUS = 3.0; // pixels
#define visibility result.color.r
-#define bilateralKey result.color.g
+#define bilateralKey result.color.gb
void main( PS_IN fragment, out PS_OUT result )
{
@@ -321,7 +357,8 @@ void main( PS_IN fragment, out PS_OUT result )
vec3 C = getPosition( ssC, CS_Z_buffer );
//float z = length( C - rpGlobalEyePos.xyz );
- bilateralKey = CSZToKey( C.z );
+ //bilateralKey = CSZToKey( C.z );
+ packKey( CSZToKey( C.z ), bilateralKey );
visibility = 0.0;
@@ -406,13 +443,14 @@ void main( PS_IN fragment, out PS_OUT result )
visibility = lerp( 1.0, A, saturate( ssDiskRadius - MIN_RADIUS ) );
//visibility = A;
+#if defined(BRIGHTPASS)
//result.color = float4( visibility, bilateralKey, 0.0, 1.0 );
//result.color = float4( bilateralKey, bilateralKey, bilateralKey, 1.0 );
- //result.color = float4( visibility, visibility, visibility, 1.0 );
+ result.color = float4( visibility, visibility, visibility, 1.0 );
//result.color = float4( n_C * 0.5 + 0.5, 1.0 );
//result.color = float4( n_C, 1.0 );
//result.color = texture( samp0, fragment.texcoord0 ).rgba;
-
+#endif
// derive clip space from the depth buffer and screen position
// float windowZ = tex2D( samp1, fragment.texcoord0 ).x;
// float3 ndc = float3( fragment.texcoord0 * 2.0 - 1.0, windowZ * 2.0 - 1.0 );
diff --git a/base/renderprogs/AmbientOcclusion_blur.pixel b/base/renderprogs/AmbientOcclusion_blur.pixel
index d2113b62..caeaacf1 100644
--- a/base/renderprogs/AmbientOcclusion_blur.pixel
+++ b/base/renderprogs/AmbientOcclusion_blur.pixel
@@ -75,7 +75,7 @@ struct PS_OUT
#define VALUE_IS_KEY 0
/** Channel encoding the bilateral key value (which must not be the same as VALUE_COMPONENTS) */
-#if 0 //NUM_KEY_COMPONENTS == 2
+#if 1 //NUM_KEY_COMPONENTS == 2
#define KEY_COMPONENTS gb
#else
#define KEY_COMPONENTS g
@@ -97,9 +97,9 @@ struct PS_OUT
#define aoResult result.color.VALUE_COMPONENTS
#define keyPassThrough result.color.KEY_COMPONENTS
-#if 0 //NUM_KEY_COMPONENTS == 2
+#if 1 //NUM_KEY_COMPONENTS == 2
/** Returns a number on (0, 1) */
-float unpackKey( vec2 p )
+float unpackKey( float2 p )
{
return p.x * ( 256.0 / 257.0 ) + p.y * ( 1.0 / 257.0 );
}
diff --git a/base/renderprogs/_manifest.lua b/base/renderprogs/_manifest.lua
index 9893a0d6..bedf86aa 100644
--- a/base/renderprogs/_manifest.lua
+++ b/base/renderprogs/_manifest.lua
@@ -8,6 +8,10 @@ return
-- shaders
"ambient_lighting.pixel",
"ambient_lighting.vertex",
+ "AmbientOcclusion_AO.pixel",
+ "AmbientOcclusion_AO.vertex",
+ "AmbientOcclusion_blur.pixel",
+ "AmbientOcclusion_blur.vertex",
"bink.pixel",
"bink.vertex",
"bink_gui.pixel",
diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp
index 3947b273..a73e7dac 100644
--- a/neo/renderer/RenderProgs.cpp
+++ b/neo/renderer/RenderProgs.cpp
@@ -149,6 +149,7 @@ void idRenderProgManager::Init()
{ BUILTIN_SMAA_NEIGHBORHOOD_BLENDING, "SMAA_final", "", 0, false },
{ BUILTIN_AMBIENT_OCCLUSION, "AmbientOcclusion_AO", "", 0, false },
+ { BUILTIN_AMBIENT_OCCLUSION_AND_OUTPUT, "AmbientOcclusion_AO", "_write", BIT( BRIGHTPASS ), false },
{ BUILTIN_AMBIENT_OCCLUSION_BLUR, "AmbientOcclusion_blur", "", 0, false },
{ BUILTIN_AMBIENT_OCCLUSION_BLUR_AND_OUTPUT, "AmbientOcclusion_blur", "_write", BIT( BRIGHTPASS ), false },
// RB end
diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h
index ec8219a4..8f24aa72 100644
--- a/neo/renderer/RenderProgs.h
+++ b/neo/renderer/RenderProgs.h
@@ -458,6 +458,11 @@ public:
BindShader_Builtin( BUILTIN_AMBIENT_OCCLUSION );
}
+ void BindShader_AmbientOcclusionAndOutput()
+ {
+ BindShader_Builtin( BUILTIN_AMBIENT_OCCLUSION_AND_OUTPUT );
+ }
+
void BindShader_AmbientOcclusionBlur()
{
BindShader_Builtin( BUILTIN_AMBIENT_OCCLUSION_BLUR );
@@ -592,6 +597,7 @@ protected:
BUILTIN_SMAA_NEIGHBORHOOD_BLENDING,
BUILTIN_AMBIENT_OCCLUSION,
+ BUILTIN_AMBIENT_OCCLUSION_AND_OUTPUT,
BUILTIN_AMBIENT_OCCLUSION_BLUR,
BUILTIN_AMBIENT_OCCLUSION_BLUR_AND_OUTPUT,
// RB end
diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h
index 4ac72aff..89dc88b3 100644
--- a/neo/renderer/RenderProgs_embedded.h
+++ b/neo/renderer/RenderProgs_embedded.h
@@ -192,6 +192,8 @@ static const cgShaderDef_t cg_renderprogs[] =
"#define PI 3.14159265358979323846\n"
"#endif\n"
"\n"
+ "#define square( x ) ( x * x )\n"
+ "\n"
"#define DEG2RAD( a ) ( ( a ) * PI / 180.0f )\n"
"#define RAD2DEG( a ) ( ( a ) * 180.0f / PI )\n"
"\n"
@@ -1994,6 +1996,936 @@ static const cgShaderDef_t cg_renderprogs[] =
},
+ {
+ "renderprogs/AmbientOcclusion_AO.pixel",
+ "/**\n"
+ " \file AmbientOcclusion_AO.pix\n"
+ " \author Morgan McGuire and Michael Mara, NVIDIA Research\n"
+ "\n"
+ " Reference implementation of the Scalable Ambient Obscurance (AmbientOcclusion) screen-space ambient obscurance algorithm.\n"
+ "\n"
+ " The optimized algorithmic structure of AmbientOcclusion was published in McGuire, Mara, and Luebke, Scalable Ambient Obscurance,\n"
+ " HPG 2012, and was developed at NVIDIA with support from Louis Bavoil.\n"
+ "\n"
+ " The mathematical ideas of AlchemyAO were first described in McGuire, Osman, Bukowski, and Hennessy, The\n"
+ " Alchemy Screen-Space Ambient Obscurance Algorithm, HPG 2011 and were developed at\n"
+ " Vicarious Visions.\n"
+ "\n"
+ " DX11 HLSL port by Leonardo Zide of Treyarch\n"
+ "\n"
+ "
\n"
+ "\n"
+ " Open Source under the \"BSD\" license: http://www.opensource.org/licenses/bsd-license.php\n"
+ "\n"
+ " Copyright (c) 2011-2012, NVIDIA\n"
+ " Copyright (c) 2016 Robert Beckebans ( id Tech 4.x integration )\n"
+ " All rights reserved.\n"
+ "\n"
+ " Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n"
+ "\n"
+ " Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n"
+ " Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n"
+ " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+ "\n"
+ " */\n"
+ "\n"
+ "#include \"renderprogs/global.inc\"\n"
+ "\n"
+ "\n"
+ "\n"
+ "#define DIFFERENT_DEPTH_RESOLUTIONS 0\n"
+ "#define USE_DEPTH_PEEL 0\n"
+ "#define CS_Z_PACKED_TOGETHER 0\n"
+ "#define TEMPORALLY_VARY_SAMPLES 0\n"
+ "#define HIGH_QUALITY 1\n"
+ "\n"
+ "// Total number of direct samples to take at each pixel\n"
+ "#define NUM_SAMPLES 11\n"
+ "\n"
+ "// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent\n"
+ "// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9\n"
+ "#define NUM_SPIRAL_TURNS 7\n"
+ "\n"
+ "// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower\n"
+ "// miplevel to maintain reasonable spatial locality in the cache\n"
+ "// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing.\n"
+ "// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively\n"
+ "#define LOG_MAX_OFFSET (3)\n"
+ "\n"
+ "// This must be less than or equal to the MAX_MIP_LEVEL defined in SAmbientOcclusion.cpp\n"
+ "#define MAX_MIP_LEVEL (5)\n"
+ "\n"
+ "const float DOOM_TO_METERS = 0.0254; // doom to meters\n"
+ "const float METERS_TO_DOOM = ( 1.0 / DOOM_TO_METERS ); // meters to doom\n"
+ "\n"
+ "/** Used for preventing AO computation on the sky (at infinite depth) and defining the CS Z to bilateral depth key scaling.\n"
+ " This need not match the real far plane but should not be much more than it.*/\n"
+ "const float FAR_PLANE_Z = -16000.0;\n"
+ "\n"
+ "/** World-space AO radius in scene units (r). e.g., 1.0m */\n"
+ "const float radius = 1.0 * METERS_TO_DOOM;\n"
+ "const float radius2 = radius * radius;\n"
+ "const float invRadius2 = 1.0 / radius2;\n"
+ "\n"
+ "/** Bias to avoid AO in smooth corners, e.g., 0.01m */\n"
+ "const float bias = 0.01 * METERS_TO_DOOM;\n"
+ "\n"
+ "/** intensity / radius^6 */\n"
+ "const float intensity = 0.3;\n"
+ "const float intensityDivR6 = intensity / ( radius* radius* radius* radius* radius* radius );\n"
+ "\n"
+ "const float projScale = 300.0;// * METERS_TO_DOOM;\n"
+ "\n"
+ "//#expect NUM_SAMPLES \"Integer number of samples to take at each pixels\"\n"
+ "//#expect NUM_SPIRAL_TURNS \"Integer number of turns around the circle that the spiral pattern makes. The G3D::AmbientOcclusion class provides a discrepancy-minimizing value of NUM_SPIRAL_TURNS for eac value of NUM_SAMPLES.\"\n"
+ "//#expect DIFFERENT_DEPTH_RESOLUTIONS \"1 if the peeled depth buffer is at a different resolution than the primary depth buffer\"\n"
+ "//#expect USE_DEPTH_PEEL \"1 to enable, 0 to disable\"\n"
+ "//#expect CS_Z_PACKED_TOGETHER \"1 to enable, 0 to disable\"\n"
+ "//#expect TEMPORALLY_VARY_SAMPLES \"1 to enable, 0 to disable\"\n"
+ "\n"
+ "// *INDENT-OFF*\n"
+ "uniform sampler2D samp0 : register( s0 ); // view color\n"
+ "uniform sampler2D samp1 : register( s1 ); // view depth\n"
+ " \n"
+ "#define CS_Z_buffer samp1\n"
+ " \n"
+ "struct PS_IN\n"
+ "{\n"
+ " float2 texcoord0 : TEXCOORD0_centroid;\n"
+ "};\n"
+ " \n"
+ "struct PS_OUT \n"
+ "{\n"
+ " float4 color : COLOR;\n"
+ "};\n"
+ "// *INDENT-ON*\n"
+ "\n"
+ "/** Returns a unit vector and a screen-space radius for the tap on a unit disk\n"
+ " (the caller should scale by the actual disk radius) */\n"
+ "float2 tapLocation( int sampleNumber, float spinAngle, out float ssR )\n"
+ "{\n"
+ " // Radius relative to ssR\n"
+ " float alpha = float( sampleNumber + 0.5 ) * ( 1.0 / NUM_SAMPLES );\n"
+ " float angle = alpha * ( NUM_SPIRAL_TURNS * 6.28 ) + spinAngle;\n"
+ " \n"
+ " ssR = alpha;\n"
+ " return float2( cos( angle ), sin( angle ) );\n"
+ "}\n"
+ "\n"
+ "\n"
+ "/** Used for packing Z into the GB channels */\n"
+ "float CSZToKey( float z )\n"
+ "{\n"
+ " return clamp( z * ( 1.0 / FAR_PLANE_Z ), 0.0, 1.0 );\n"
+ "}\n"
+ "\n"
+ "/** Used for packing Z into the GB channels */\n"
+ "void packKey( float key, out float2 p )\n"
+ "{\n"
+ " // Round to the nearest 1/256.0\n"
+ " float temp = floor( key * 256.0 );\n"
+ " \n"
+ " // Integer part\n"
+ " p.x = temp * ( 1.0 / 256.0 );\n"
+ " \n"
+ " // Fractional part\n"
+ " p.y = key * 256.0 - temp;\n"
+ "}\n"
+ "\n"
+ "/** Reconstructs screen-space unit normal from screen-space position */\n"
+ "float3 reconstructCSFaceNormal( float3 C )\n"
+ "{\n"
+ " return normalize( cross( dFdy( C ), dFdx( C ) ) );\n"
+ "}\n"
+ "\n"
+ "float3 reconstructNonUnitCSFaceNormal( float3 C )\n"
+ "{\n"
+ " float3 n = cross( dFdy( C ), dFdx( C ) );\n"
+ " //n.z = sqrt( abs( dot( n.xy, n.xy ) - 0.25 ) );\n"
+ " return n;\n"
+ "}\n"
+ "\n"
+ "/** Read the camera-space position of the point at screen-space pixel ssP */\n"
+ "float3 getPosition( float2 ssP, sampler2D cszBuffer )\n"
+ "{\n"
+ "#if 1\n"
+ " // derive clip space from the depth buffer and screen position\n"
+ " float windowZ = tex2D( cszBuffer, ssP ).x;\n"
+ " float3 ndc = float3( ssP * 2.0 - 1.0, windowZ * 2.0 - 1.0 );\n"
+ " //float clipW = -rpProjectionMatrixZ.w / ( -rpProjectionMatrixZ.z - ndc.z );\n"
+ " //float4 P = float4( ndc * clipW, clipW );\n"
+ " float4 P = float4( ndc, 1.0 );\n"
+ "#else\n"
+ " float4 P;\n"
+ " P.z = tex2D( cszBuffer, ssP ).r;\n"
+ " P.xy = float2( ssP ); //+ float2( 0.5 ) );\n"
+ " P.w = 1.0;\n"
+ "#endif\n"
+ " // offset to pixel center\n"
+ " //P = reconstructCSPosition( float2( ssP ) + float2( 0.5 ), P.z, projInfo );\n"
+ " \n"
+ "#if 1\n"
+ " float4 csP;\n"
+ " csP.x = dot4( P, rpProjectionMatrixX );\n"
+ " csP.y = dot4( P, rpProjectionMatrixY );\n"
+ " csP.z = dot4( P, rpProjectionMatrixZ );\n"
+ " csP.w = dot4( P, rpProjectionMatrixW );\n"
+ " \n"
+ " csP.xyz /= csP.w;\n"
+ "#endif\n"
+ " \n"
+ "#if 0\n"
+ " float4 wP;\n"
+ " wP.x = dot4( csP, rpModelMatrixX );\n"
+ " wP.y = dot4( csP, rpModelMatrixY );\n"
+ " wP.z = dot4( csP, rpModelMatrixZ );\n"
+ " wP.w = dot4( csP, rpModelMatrixW );\n"
+ " //wP.xyz /= wP.w;\n"
+ " return wP.xyz;\n"
+ "#endif\n"
+ " \n"
+ " return csP.xyz;\n"
+ "}\n"
+ "\n"
+ "/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1.\n"
+ " Use cszBufferScale if reading from the peeled depth buffer, which has been scaled by (1 / invCszBufferScale) from the original */\n"
+ "float3 getOffsetPosition( ivec2 issC, vec2 unitOffset, float ssR, sampler2D cszBuffer, float invCszBufferScale )\n"
+ "{\n"
+ " // Derivation:\n"
+ " // mipLevel = floor(log(ssR / MAX_OFFSET));\n"
+ "#ifdef GL_EXT_gpu_shader5\n"
+ " int mipLevel = clamp( findMSB( int( ssR ) ) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL );\n"
+ "#else\n"
+ " int mipLevel = clamp( int( floor( log2( ssR ) ) ) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL );\n"
+ "#endif\n"
+ " \n"
+ " ivec2 ssP = ivec2( ssR * unitOffset ) + issC;\n"
+ " \n"
+ " float4 P;\n"
+ " \n"
+ " // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.\n"
+ " // Manually clamp to the texture size because texelFetch bypasses the texture unit\n"
+ " ivec2 mipP = clamp( ssP >> mipLevel, ivec2( 0 ), textureSize( CS_Z_buffer, mipLevel ) - ivec2( 1 ) );\n"
+ " \n"
+ " float2 ossC = float2( ssP ) * rpScreenCorrectionFactor.xy;\n"
+ " \n"
+ " float windowZ = texture( cszBuffer, ossC, 0.0 ).r;\n"
+ " \n"
+ "#if 1\n"
+ " float3 ndc = float3( ossC * 2.0 - 1.0, windowZ * 2.0 - 1.0 );\n"
+ " //float clipW = -rpProjectionMatrixZ.w / ( -rpProjectionMatrixZ.z - ndc.z );\n"
+ " //P = float4( ndc * clipW, clipW );\n"
+ " P = float4( ndc, 1.0 );\n"
+ " \n"
+ " //return P.xyz;\n"
+ "#else\n"
+ " \n"
+ " //P.z = texture( cszBuffer, mipP, 0.0 ).r;\n"
+ " //P.z = texture( cszBuffer, mipP, mipLevel ).r;\n"
+ " \n"
+ " // Offset to pixel center\n"
+ " //P = reconstructCSPosition( ( vec2( ssP ) + vec2( 0.5 ) ) * invCszBufferScale, P.z, projInfo );\n"
+ " P.xy = ossC; //+ float2( 0.5 ) ) * invCszBufferScale;\n"
+ " P.w = 1.0;\n"
+ "#endif\n"
+ " \n"
+ "#if 1\n"
+ " float4 csP;\n"
+ " csP.x = dot4( P, rpProjectionMatrixX );\n"
+ " csP.y = dot4( P, rpProjectionMatrixY );\n"
+ " csP.z = dot4( P, rpProjectionMatrixZ );\n"
+ " csP.w = dot4( P, rpProjectionMatrixW );\n"
+ " csP.xyz /= csP.w;\n"
+ "#endif\n"
+ " \n"
+ "#if 0\n"
+ " float4 wP;\n"
+ " wP.x = dot4( csP, rpModelMatrixX );\n"
+ " wP.y = dot4( csP, rpModelMatrixY );\n"
+ " wP.z = dot4( csP, rpModelMatrixZ );\n"
+ " wP.w = dot4( csP, rpModelMatrixW );\n"
+ " //wP.xyz /= wP.w;\n"
+ " return wP.xyz;\n"
+ "#endif\n"
+ " \n"
+ " return csP.xyz;\n"
+ "}\n"
+ "\n"
+ "float fallOffFunction( float vv, float vn, float epsilon )\n"
+ "{\n"
+ " // A: From the HPG12 paper\n"
+ " // Note large epsilon to avoid overdarkening within cracks\n"
+ " // Assumes the desired result is intensity/radius^6 in main()\n"
+ " // return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6;\n"
+ " \n"
+ " // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]\n"
+ "#if HIGH_QUALITY\n"
+ " // Epsilon inside the sqrt for rsqrt operation\n"
+ " float f = max( 1.0 - vv * invRadius2, 0.0 );\n"
+ " return f * max( ( vn - bias ) * rsqrt( epsilon + vv ), 0.0 );\n"
+ "#else\n"
+ " // Avoid the square root from above.\n"
+ " // Assumes the desired result is intensity/radius^6 in main()\n"
+ " float f = max( radius2 - vv, 0.0 );\n"
+ " return f * f * f * max( ( vn - bias ) / ( epsilon + vv ), 0.0 );\n"
+ "#endif\n"
+ " \n"
+ " // C: Medium contrast (which looks better at high radii), no division. Note that the\n"
+ " // contribution still falls off with radius^2, but we've adjusted the rate in a way that is\n"
+ " // more computationally efficient and happens to be aesthetically pleasing. Assumes\n"
+ " // division by radius^6 in main()\n"
+ " //return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0);\n"
+ " \n"
+ " // D: Low contrast, no division operation\n"
+ " //return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0);\n"
+ "}\n"
+ "\n"
+ "/** Compute the occlusion due to sample point \a Q about camera-space point \a C with unit normal \a n_C */\n"
+ "float aoValueFromPositionsAndNormal( float3 C, float3 n_C, float3 Q )\n"
+ "{\n"
+ " float3 v = Q - C;\n"
+ " //v = normalize( v );\n"
+ " float vv = dot( v, v );\n"
+ " float vn = dot( v, n_C );\n"
+ " const float epsilon = 0.001;\n"
+ " \n"
+ " // Without the angular adjustment term, surfaces seen head on have less AO\n"
+ " return fallOffFunction( vv, vn, epsilon );// * lerp( 1.0, max( 0.0, 1.5 * n_C.z ), 0.35 );\n"
+ "}\n"
+ "\n"
+ "\n"
+ "/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds\n"
+ " to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius\n"
+ "\n"
+ " Note that units of H() in the HPG12 paper are meters, not\n"
+ " unitless. The whole falloff/sampling function is therefore\n"
+ " unitless. In this implementation, we factor out (9 / radius).\n"
+ "\n"
+ " Four versions of the falloff function are implemented below\n"
+ "\n"
+ " When sampling from the peeled depth buffer, make sure ssDiskRadius has been premultiplied by cszBufferScale\n"
+ "*/\n"
+ "float sampleAO( ivec2 issC, in float3 C, in float3 n_C, in float ssDiskRadius, in int tapIndex, in float randomPatternRotationAngle, in sampler2D cszBuffer, in float invCszBufferScale )\n"
+ "{\n"
+ " // Offset on the unit disk, spun for this pixel\n"
+ " float ssR;\n"
+ " float2 unitOffset = tapLocation( tapIndex, randomPatternRotationAngle, ssR );\n"
+ " \n"
+ " // Ensure that the taps are at least 1 pixel away\n"
+ " ssR = max( 0.75, ssR * ssDiskRadius );\n"
+ " \n"
+ "#if (CS_Z_PACKED_TOGETHER != 0)\n"
+ " vec3 Q0, Q1;\n"
+ " getOffsetPositions( ssC, unitOffset, ssR, cszBuffer, Q0, Q1 );\n"
+ " \n"
+ " return max( aoValueFromPositionsAndNormal( C, n_C, Q0 ), aoValueFromPositionsAndNormal( C, n_C, Q1 ) );\n"
+ "#else\n"
+ " // The occluding point in camera space\n"
+ " vec3 Q = getOffsetPosition( issC, unitOffset, ssR, cszBuffer, invCszBufferScale );\n"
+ " \n"
+ " return aoValueFromPositionsAndNormal( C, n_C, Q );\n"
+ "#endif\n"
+ "}\n"
+ "\n"
+ "const float MIN_RADIUS = 3.0; // pixels\n"
+ "\n"
+ "#define visibility result.color.r\n"
+ "#define bilateralKey result.color.gb\n"
+ "\n"
+ "void main( PS_IN fragment, out PS_OUT result )\n"
+ "{\n"
+ " result.color = float4( 1.0, 0.0, 0.0, 1.0 );\n"
+ " \n"
+ "#if 0\n"
+ " if( fragment.texcoord0.x < 0.25 )\n"
+ " {\n"
+ " discard;\n"
+ " }\n"
+ "#endif\n"
+ " \n"
+ " //float3 normal = tex2D( samp0, fragment.texcoord0 ).rgb * 2.0 - 1.0;\n"
+ " //if( length( normal ) < 0.9 )\n"
+ " //{\n"
+ " //discard;\n"
+ " //}\n"
+ " \n"
+ " // Pixel being shaded\n"
+ " float2 ssC = fragment.texcoord0;\n"
+ " ivec2 issC = ivec2( ssC.x * rpScreenCorrectionFactor.z, ssC.y * rpScreenCorrectionFactor.w );\n"
+ " \n"
+ " // World space point being shaded\n"
+ " vec3 C = getPosition( ssC, CS_Z_buffer );\n"
+ " \n"
+ " //float z = length( C - rpGlobalEyePos.xyz );\n"
+ " //bilateralKey = CSZToKey( C.z );\n"
+ " packKey( CSZToKey( C.z ), bilateralKey );\n"
+ " \n"
+ " visibility = 0.0;\n"
+ " \n"
+ "#if 0\n"
+ " //vec3 n_C = texelFetch( normal_buffer, ivec2( gl_FragCoord.xy ), 0 ).xyz;\n"
+ " //n_C = normalize( n_C * normal_readMultiplyFirst.xyz + normal_readAddSecond.xyz );\n"
+ " \n"
+ " float3 n_C = tex2D( samp0, fragment.texcoord0 ).rgb * 2.0 - 1.0;\n"
+ " n_C = normalize( n_C );\n"
+ " //n_C = -n_C;\n"
+ " \n"
+ " if( length( n_C ) < 0.1 )\n"
+ " {\n"
+ " visibility = 1.0;\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ "#else\n"
+ " // Reconstruct normals from positions.\n"
+ " float3 n_C = reconstructNonUnitCSFaceNormal( C );\n"
+ " // Since n_C is computed from the cross product of cmaera-space edge vectors from points at adjacent pixels, its magnitude will be proportional to the square of distance from the camera\n"
+ " if( dot( n_C, n_C ) > ( square( C.z * C.z * 0.00006 ) ) ) // if the threshold # is too big you will see black dots where we used a bad normal at edges, too small -> white\n"
+ " {\n"
+ " // The normals from depth should be very small values before normalization,\n"
+ " // except at depth discontinuities, where they will be large and lead\n"
+ " // to 1-pixel false occlusions because they are not reliable\n"
+ " visibility = 1.0;\n"
+ " //result.color = float4( visibility, visibility, visibility, 1.0 );\n"
+ " return;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " n_C = normalize( -n_C );\n"
+ " }\n"
+ "#endif\n"
+ " \n"
+ " // Hash function used in the HPG12 AlchemyAO paper\n"
+ " float randomPatternRotationAngle = ( ( ( 3 * issC.x ) ^ ( issC.y + issC.x * issC.y ) )\n"
+ "#if TEMPORALLY_VARY_SAMPLES\n"
+ " + rpJitterTexOffset.x\n"
+ "#endif\n"
+ " ) * 10;\n"
+ " \n"
+ " // Choose the screen-space sample radius\n"
+ " // proportional to the projected area of the sphere\n"
+ " float ssDiskRadius = -projScale * radius / C.z;\n"
+ " \n"
+ "#if 1\n"
+ " if( ssDiskRadius <= MIN_RADIUS )\n"
+ " {\n"
+ " // There is no way to compute AO at this radius\n"
+ " visibility = 1.0;\n"
+ " return;\n"
+ " }\n"
+ "#endif\n"
+ " \n"
+ "#if USE_DEPTH_PEEL == 1\n"
+ "#if DIFFERENT_DEPTH_RESOLUTIONS == 1\n"
+ " float unpeeledToPeeledScale = 1.0 / peeledToUnpeeledScale;\n"
+ "#endif\n"
+ "#endif\n"
+ " \n"
+ " float sum = 0.0;\n"
+ " for( int i = 0; i < NUM_SAMPLES; ++i )\n"
+ " {\n"
+ " sum += sampleAO( issC, C, n_C, ssDiskRadius, i, randomPatternRotationAngle, CS_Z_buffer, 1 );\n"
+ " }\n"
+ " \n"
+ "#if HIGH_QUALITY\n"
+ " float A = pow( max( 0.0, 1.0 - sqrt( sum * ( 3.0 / NUM_SAMPLES ) ) ), intensity );\n"
+ "#else\n"
+ " float A = max( 0.0, 1.0 - sum * intensityDivR6 * ( 5.0 / NUM_SAMPLES ) );\n"
+ " // Anti-tone map to reduce contrast and drag dark region farther\n"
+ " // (x^0.2 + 1.2 * x^4)/2.2\n"
+ " //A = ( pow( A, 0.2 ) + 1.2 * A * A * A * A ) / 2.2;\n"
+ "#endif\n"
+ " \n"
+ " // Visualize random spin distribution\n"
+ " //A = mod(randomPatternRotationAngle / (2 * 3.141592653589), 1.0);\n"
+ " \n"
+ " // Fade in as the radius reaches 2 pixels\n"
+ " visibility = lerp( 1.0, A, saturate( ssDiskRadius - MIN_RADIUS ) );\n"
+ " //visibility = A;\n"
+ " \n"
+ "#if defined(BRIGHTPASS)\n"
+ " //result.color = float4( visibility, bilateralKey, 0.0, 1.0 );\n"
+ " //result.color = float4( bilateralKey, bilateralKey, bilateralKey, 1.0 );\n"
+ " result.color = float4( visibility, visibility, visibility, 1.0 );\n"
+ " //result.color = float4( n_C * 0.5 + 0.5, 1.0 );\n"
+ " //result.color = float4( n_C, 1.0 );\n"
+ " //result.color = texture( samp0, fragment.texcoord0 ).rgba;\n"
+ "#endif\n"
+ " // derive clip space from the depth buffer and screen position\n"
+ " // float windowZ = tex2D( samp1, fragment.texcoord0 ).x;\n"
+ " // float3 ndc = float3( fragment.texcoord0 * 2.0 - 1.0, windowZ * 2.0 - 1.0 );\n"
+ " // float clipW = -rpProjectionMatrixZ.w / ( -rpProjectionMatrixZ.z - ndc.z );\n"
+ " \n"
+ " // float4 clip = float4( ndc * clipW, clipW );\n"
+ "}\n"
+ "\n"
+
+ },
+
+ {
+ "renderprogs/AmbientOcclusion_AO.vertex",
+ "/*\n"
+ "===========================================================================\n"
+ "\n"
+ "Doom 3 BFG Edition GPL Source Code\n"
+ "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
+ "\n"
+ "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\"). \n"
+ "\n"
+ "Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation, either version 3 of the License, or\n"
+ "(at your option) any later version.\n"
+ "\n"
+ "Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with Doom 3 BFG Edition Source Code. If not, see .\n"
+ "\n"
+ "In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.\n"
+ "\n"
+ "If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.\n"
+ "\n"
+ "===========================================================================\n"
+ "*/\n"
+ "\n"
+ "#include \"renderprogs/global.inc\"\n"
+ "\n"
+ "struct VS_IN \n"
+ "{\n"
+ " float4 position : POSITION;\n"
+ " float2 texcoord : TEXCOORD0;\n"
+ "};\n"
+ "\n"
+ "struct VS_OUT\n"
+ "{\n"
+ " float4 position : POSITION;\n"
+ " float2 texcoord0 : TEXCOORD0;\n"
+ "};\n"
+ "\n"
+ "void main( VS_IN vertex, out VS_OUT result )\n"
+ "{\n"
+ " result.position = vertex.position;\n"
+ " result.texcoord0 = vertex.texcoord;\n"
+ "}\n"
+
+ },
+
+ {
+ "renderprogs/AmbientOcclusion_blur.pixel",
+ "/**\n"
+ " \file AmbientOcclusion_blur.pix\n"
+ " \author Morgan McGuire and Michael Mara, NVIDIA Research\n"
+ "\n"
+ " \brief 7-tap 1D cross-bilateral blur using a packed depth key\n"
+ "\n"
+ " DX11 HLSL port by Leonardo Zide, Treyarch\n"
+ "\n"
+ " Open Source under the \"BSD\" license: http://www.opensource.org/licenses/bsd-license.php\n"
+ "\n"
+ " Copyright (c) 2011-2012, NVIDIA\n"
+ " Copyright (c) 2016 Robert Beckebans ( id Tech 4.x integration )\n"
+ " All rights reserved.\n"
+ "\n"
+ " Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n"
+ "\n"
+ " Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n"
+ " Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n"
+ " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+ "*/\n"
+ "#include \"renderprogs/global.inc\"\n"
+ "\n"
+ "// *INDENT-OFF*\n"
+ "uniform sampler2D samp0 : register( s0 ); // view color\n"
+ "uniform sampler2D samp1 : register( s1 ); // view depth\n"
+ " \n"
+ "#define source samp0 \n"
+ "#define CS_Z_buffer samp1\n"
+ " \n"
+ "struct PS_IN\n"
+ "{\n"
+ " float2 texcoord0 : TEXCOORD0_centroid;\n"
+ "};\n"
+ " \n"
+ "struct PS_OUT \n"
+ "{\n"
+ " float4 color : COLOR;\n"
+ "};\n"
+ "// *INDENT-ON*\n"
+ "\n"
+ "//////////////////////////////////////////////////////////////////////////////////////////////\n"
+ "// Tunable Parameters:\n"
+ "\n"
+ "//#define NUM_KEY_COMPONENTS 1\n"
+ "\n"
+ "// The other parameters in this section must be passed in as macro values\n"
+ "\n"
+ "/** Increase to make depth edges crisper. Decrease to reduce flicker. */\n"
+ "#define EDGE_SHARPNESS (1.0)\n"
+ "\n"
+ "/** Step in 2-pixel intervals since we already blurred against neighbors in the\n"
+ " first AO pass. This constant can be increased while R decreases to improve\n"
+ " performance at the expense of some dithering artifacts.\n"
+ "\n"
+ " Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was\n"
+ " unobjectionable after shading was applied but eliminated most temporal incoherence\n"
+ " from using small numbers of sample taps.\n"
+ " */\n"
+ "#define SCALE (2)\n"
+ "\n"
+ "/** Filter radius in pixels. This will be multiplied by SCALE. */\n"
+ "#define R (4)\n"
+ "\n"
+ "#define MDB_WEIGHTS 0\n"
+ "//////////////////////////////////////////////////////////////////////////////////////////////\n"
+ "\n"
+ "/** Type of data to read from source. This macro allows\n"
+ " the same blur shader to be used on different kinds of input data. */\n"
+ "#define VALUE_TYPE float\n"
+ "\n"
+ "/** Swizzle to use to extract the channels of source. This macro allows\n"
+ " the same blur shader to be used on different kinds of input data. */\n"
+ "#define VALUE_COMPONENTS r\n"
+ "\n"
+ "#define VALUE_IS_KEY 0\n"
+ "\n"
+ "/** Channel encoding the bilateral key value (which must not be the same as VALUE_COMPONENTS) */\n"
+ "#if 1 //NUM_KEY_COMPONENTS == 2\n"
+ "#define KEY_COMPONENTS gb\n"
+ "#else\n"
+ "#define KEY_COMPONENTS g\n"
+ "#endif\n"
+ "\n"
+ "//#if __VERSION__ >= 330\n"
+ "// Gaussian coefficients\n"
+ "//const float gaussian[R + 1] =\n"
+ "// float[](0.356642, 0.239400, 0.072410, 0.009869);\n"
+ "// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0\n"
+ "// float[]( 0.153170, 0.144893, 0.122649, 0.092902, 0.062970 ); // stddev = 2.0\n"
+ "// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0\n"
+ "//#endif\n"
+ "\n"
+ "/** (1, 0) or (0, 1)*/\n"
+ "//uniform ivec2 axis;\n"
+ "\n"
+ "\n"
+ "#define aoResult result.color.VALUE_COMPONENTS\n"
+ "#define keyPassThrough result.color.KEY_COMPONENTS\n"
+ "\n"
+ "#if 1 //NUM_KEY_COMPONENTS == 2\n"
+ "/** Returns a number on (0, 1) */\n"
+ "float unpackKey( float2 p )\n"
+ "{\n"
+ " return p.x * ( 256.0 / 257.0 ) + p.y * ( 1.0 / 257.0 );\n"
+ "}\n"
+ "#else\n"
+ "/** Returns a number on (0, 1) */\n"
+ "float unpackKey( float p )\n"
+ "{\n"
+ " return p;\n"
+ "}\n"
+ "#endif\n"
+ "\n"
+ "//uniform float4 projInfo;\n"
+ "\n"
+ "float3 reconstructCSPosition( float2 S, float z )\n"
+ "{\n"
+ " float4 P;\n"
+ " P.z = z;\n"
+ " P.xy = S * rpScreenCorrectionFactor.xy;\n"
+ " P.w = 1.0;\n"
+ " \n"
+ " float4 csP;\n"
+ " csP.x = dot4( P, rpProjectionMatrixX );\n"
+ " csP.y = dot4( P, rpProjectionMatrixY );\n"
+ " csP.z = dot4( P, rpProjectionMatrixZ );\n"
+ " csP.w = dot4( P, rpProjectionMatrixW );\n"
+ " \n"
+ " csP.xyz /= csP.w;\n"
+ " \n"
+ " return csP.xyz;\n"
+ "}\n"
+ "\n"
+ "//float3 reconstructCSPosition( float2 ssP ) + float2( 0.5 ), P.z, projInfo );\n"
+ "\n"
+ "/** Used for preventing AO computation on the sky (at infinite depth) and defining the CS Z to bilateral depth key scaling.\n"
+ " This need not match the real far plane but should not be much more than it.*/\n"
+ "const float FAR_PLANE_Z = -4000.0;\n"
+ "\n"
+ "float3 positionFromKey( float key, ivec2 ssC )\n"
+ "{\n"
+ " float z = key * FAR_PLANE_Z;\n"
+ " //float3 C = reconstructCSPosition( vec2( ssC )/* + vec2( 0.5 )*/, z, pInfo );\n"
+ " float3 C = reconstructCSPosition( vec2( ssC ), z );\n"
+ " return C;\n"
+ "}\n"
+ "\n"
+ "#if 0 //def normal_notNull\n"
+ "/** Same size as result buffer, do not offset by guard band when reading from it */\n"
+ "uniform sampler2D normal_buffer;\n"
+ "uniform float4 normal_readMultiplyFirst;\n"
+ "uniform float4 normal_readAddSecond;\n"
+ "#endif\n"
+ "\n"
+ "float calculateBilateralWeight( float key, float tapKey, ivec2 tapLoc, float3 n_C, float3 C )\n"
+ "{\n"
+ " // range domain (the \"bilateral\" weight). As depth difference increases, decrease weight.\n"
+ " float depthWeight = max( 0.0, 1.0 - ( EDGE_SHARPNESS * 2000.0 ) * abs( tapKey - key ) );\n"
+ " float k_normal = 1.0;\n"
+ " float k_plane = 1.0;\n"
+ " \n"
+ " // Prevents blending over creases.\n"
+ " float normalWeight = 1.0;\n"
+ " float planeWeight = 1.0;\n"
+ " \n"
+ "#if 0 //def normal_notNull\n"
+ " float3 tapN_C = texelFetch( normal_buffer, tapLoc, 0 ).xyz;\n"
+ " tapN_C = normalize( tapN_C * normal_readMultiplyFirst.xyz + normal_readAddSecond.xyz );\n"
+ " \n"
+ " float normalError = 1.0 - dot( tapN_C, n_C ) * k_normal;\n"
+ " normalWeight = max( ( 1.0 - EDGE_SHARPNESS * normalError ), 0.00 );\n"
+ " \n"
+ " float lowDistanceThreshold2 = 0.001;\n"
+ " \n"
+ " float3 tapC = positionFromKey( tapKey, tapLoc, projInfo );\n"
+ " \n"
+ " // Change in position in camera space\n"
+ " float3 dq = C - tapC;\n"
+ " \n"
+ " // How far away is this point from the original sample\n"
+ " // in camera space? (Max value is unbounded)\n"
+ " float distance2 = dot( dq, dq );\n"
+ " \n"
+ " // How far off the expected plane (on the perpendicular) is this point? Max value is unbounded.\n"
+ " float planeError = max( abs( dot( dq, tapN_C ) ), abs( dot( dq, n_C ) ) );\n"
+ " \n"
+ " planeWeight = ( distance2 < lowDistanceThreshold2 ) ? 1.0 :\n"
+ " pow( max( 0.0, 1.0 - EDGE_SHARPNESS * 2.0 * k_plane * planeError / sqrt( distance2 ) ), 2.0 );\n"
+ " \n"
+ " \n"
+ "#endif\n"
+ " \n"
+ " //normalWeight = 1.0;\n"
+ " //planeWeight = 1.0;\n"
+ " \n"
+ " return depthWeight * normalWeight * planeWeight;\n"
+ "}\n"
+ "\n"
+ "\n"
+ "void main( PS_IN fragment, out PS_OUT result )\n"
+ "{\n"
+ "\n"
+ "//# if __VERSION__ < 330\n"
+ " float gaussian[R + 1];\n"
+ "// if R == 0, we never call this shader\n"
+ "// # if R == 1 // TODO: Actually calculate gaussian weights... this is just Mike winging it here\n"
+ " // gaussian[0] = 0.5;\n"
+ " // gaussian[1] = 0.25;\n"
+ "// # elif R == 2 // TODO: Actually calculate gaussian weights... this is just Mike winging it here\n"
+ " // gaussian[0] = 0.153170;\n"
+ " // gaussian[1] = 0.144893;\n"
+ " // gaussian[2] = 0.122649;\n"
+ "// # elif R == 3 // TODO: We are losing some base weight here...\n"
+ " // gaussian[0] = 0.153170;\n"
+ " // gaussian[1] = 0.144893;\n"
+ " // gaussian[2] = 0.122649;\n"
+ " // gaussian[3] = 0.092902; // stddev = 2.0\n"
+ "// # elif R == 4\n"
+ " gaussian[0] = 0.153170;\n"
+ " gaussian[1] = 0.144893;\n"
+ " gaussian[2] = 0.122649;\n"
+ " gaussian[3] = 0.092902;\n"
+ " gaussian[4] = 0.062970; // stddev = 2.0\n"
+ "// # elif R == 5 // TODO: We are losing some base weight here...\n"
+ " // gaussian[0] = 0.111220;\n"
+ " // gaussian[1] = 0.107798;\n"
+ " // gaussian[2] = 0.098151;\n"
+ " // gaussian[3] = 0.083953;\n"
+ " // gaussian[4] = 0.067458;\n"
+ " // gaussian[5] = 0.050920;\n"
+ "// # elif R == 6\n"
+ " // gaussian[0] = 0.111220;\n"
+ " // gaussian[1] = 0.107798;\n"
+ " // gaussian[2] = 0.098151;\n"
+ " // gaussian[3] = 0.083953;\n"
+ " // gaussian[4] = 0.067458;\n"
+ " // gaussian[5] = 0.050920;\n"
+ " // gaussian[6] = 0.036108;\n"
+ "// # endif\n"
+ "//# endif\n"
+ "\n"
+ " ivec2 ssC = ivec2( gl_FragCoord.xy );\n"
+ " \n"
+ " float4 temp = texelFetch( source, ssC, 0 );\n"
+ " \n"
+ " keyPassThrough = temp.KEY_COMPONENTS;\n"
+ " float key = unpackKey( keyPassThrough );\n"
+ " \n"
+ " VALUE_TYPE sum = temp.VALUE_COMPONENTS;\n"
+ " \n"
+ "#if 0\n"
+ " if( fragment.texcoord0.x < 0.5 )\n"
+ " {\n"
+ " //discard;\n"
+ " //result.color = float4( temp.rgb, 1.0 );\n"
+ " result.color = float4( float3( keyPassThrough ), 1.0 );\n"
+ " return;\n"
+ " }\n"
+ "#endif\n"
+ " \n"
+ " if( key == 1.0 )\n"
+ " {\n"
+ " // Sky pixel (if you aren't using depth keying, disable this test)\n"
+ " aoResult = sum;\n"
+ "#if defined(BRIGHTPASS)\n"
+ " result.color = float4( aoResult, aoResult, aoResult, 1.0 );\n"
+ "#endif\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " // Base weight for depth falloff. Increase this for more blurriness,\n"
+ " // decrease it for better edge discrimination\n"
+ " float BASE = gaussian[0];\n"
+ " float totalWeight = BASE;\n"
+ " sum *= totalWeight;\n"
+ " float3 n_C;\n"
+ "#if 0 //def normal_notNull\n"
+ " n_C = normalize( texelFetch( normal_buffer, ssC, 0 ).xyz * normal_readMultiplyFirst.xyz + normal_readAddSecond.xyz );\n"
+ "#endif\n"
+ " \n"
+ " float3 C = positionFromKey( key, ssC );\n"
+ " \n"
+ "#if MDB_WEIGHTS == 0\n"
+ " for( int r = -R; r <= R; ++r )\n"
+ " {\n"
+ " // We already handled the zero case above. This loop should be unrolled and the static branch optimized out,\n"
+ " // so the IF statement has no runtime cost\n"
+ " if( r != 0 )\n"
+ " {\n"
+ " ivec2 tapLoc = ssC + ivec2( rpJitterTexScale.xy ) * ( r * SCALE );\n"
+ " temp = texelFetch( source, tapLoc, 0 );\n"
+ " float tapKey = unpackKey( temp.KEY_COMPONENTS );\n"
+ " VALUE_TYPE value = temp.VALUE_COMPONENTS;\n"
+ " \n"
+ " // spatial domain: offset gaussian tap\n"
+ " float weight = 0.3 + gaussian[abs( r )];\n"
+ " \n"
+ " float bilateralWeight = calculateBilateralWeight( key, tapKey, tapLoc, n_C, C );\n"
+ " \n"
+ " weight *= bilateralWeight;\n"
+ " sum += value * weight;\n"
+ " totalWeight += weight;\n"
+ " }\n"
+ " }\n"
+ "#else\n"
+ " \n"
+ " float lastBilateralWeight = 9999.0;\n"
+ " for( int r = -1; r >= -R; --r )\n"
+ " {\n"
+ " ivec2 tapLoc = ssC + ivec2( rpJitterTexScale.xy ) * ( r * SCALE );\n"
+ " temp = texelFetch( source, tapLoc, 0 );\n"
+ " float tapKey = unpackKey( temp.KEY_COMPONENTS );\n"
+ " VALUE_TYPE value = temp.VALUE_COMPONENTS;\n"
+ " \n"
+ " // spatial domain: offset gaussian tap\n"
+ " float weight = 0.3 + gaussian[abs( r )];\n"
+ " \n"
+ " // range domain (the \"bilateral\" weight). As depth difference increases, decrease weight.\n"
+ " float bilateralWeight = calculateBilateralWeight( key, tapKey, tapLoc, n_C, C );\n"
+ " bilateralWeight = min( lastBilateralWeight, bilateralWeight );\n"
+ " lastBilateralWeight = bilateralWeight;\n"
+ " weight *= bilateralWeight;\n"
+ " sum += value * weight;\n"
+ " totalWeight += weight;\n"
+ " }\n"
+ " \n"
+ " lastBilateralWeight = 9999.0;\n"
+ " for( int r = 1; r <= R; ++r )\n"
+ " {\n"
+ " ivec2 tapLoc = ssC + ivec2( rpJitterTexScale.xy ) * ( r * SCALE );\n"
+ " temp = texelFetch( source, tapLoc, 0 );\n"
+ " float tapKey = unpackKey( temp.KEY_COMPONENTS );\n"
+ " VALUE_TYPE value = temp.VALUE_COMPONENTS;\n"
+ " \n"
+ " // spatial domain: offset gaussian tap\n"
+ " float weight = 0.3 + gaussian[abs( r )];\n"
+ " \n"
+ " // range domain (the \"bilateral\" weight). As depth difference increases, decrease weight.\n"
+ " float bilateralWeight = calculateBilateralWeight( key, tapKey, tapLoc, n_C, C );\n"
+ " bilateralWeight = min( lastBilateralWeight, bilateralWeight );\n"
+ " lastBilateralWeight = bilateralWeight;\n"
+ " weight *= bilateralWeight;\n"
+ " sum += value * weight;\n"
+ " totalWeight += weight;\n"
+ " }\n"
+ "#endif\n"
+ " \n"
+ " const float epsilon = 0.0001;\n"
+ " aoResult = sum / ( totalWeight + epsilon );\n"
+ " \n"
+ "#if defined(BRIGHTPASS)\n"
+ " result.color = float4( aoResult, aoResult, aoResult, 1.0 );\n"
+ "#endif\n"
+ "}\n"
+ "\n"
+
+ },
+
+ {
+ "renderprogs/AmbientOcclusion_blur.vertex",
+ "/*\n"
+ "===========================================================================\n"
+ "\n"
+ "Doom 3 BFG Edition GPL Source Code\n"
+ "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
+ "\n"
+ "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\"). \n"
+ "\n"
+ "Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation, either version 3 of the License, or\n"
+ "(at your option) any later version.\n"
+ "\n"
+ "Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with Doom 3 BFG Edition Source Code. If not, see .\n"
+ "\n"
+ "In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.\n"
+ "\n"
+ "If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.\n"
+ "\n"
+ "===========================================================================\n"
+ "*/\n"
+ "\n"
+ "#include \"renderprogs/global.inc\"\n"
+ "\n"
+ "struct VS_IN \n"
+ "{\n"
+ " float4 position : POSITION;\n"
+ " float2 texcoord : TEXCOORD0;\n"
+ "};\n"
+ "\n"
+ "struct VS_OUT\n"
+ "{\n"
+ " float4 position : POSITION;\n"
+ " float2 texcoord0 : TEXCOORD0;\n"
+ "};\n"
+ "\n"
+ "void main( VS_IN vertex, out VS_OUT result )\n"
+ "{\n"
+ " result.position = vertex.position;\n"
+ " result.texcoord0 = vertex.texcoord;\n"
+ "}\n"
+
+ },
+
{
"renderprogs/bink.pixel",
"/*\n"
@@ -4766,6 +5698,278 @@ static const cgShaderDef_t cg_renderprogs[] =
},
+ {
+ "renderprogs/gbuffer.pixel",
+ "/*\n"
+ "===========================================================================\n"
+ "\n"
+ "Doom 3 BFG Edition GPL Source Code\n"
+ "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
+ "Copyright (C) 2016 Robert Beckebans\n"
+ "\n"
+ "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\"). \n"
+ "\n"
+ "Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation, either version 3 of the License, or\n"
+ "(at your option) any later version.\n"
+ "\n"
+ "Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with Doom 3 BFG Edition Source Code. If not, see .\n"
+ "\n"
+ "In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.\n"
+ "\n"
+ "If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.\n"
+ "\n"
+ "===========================================================================\n"
+ "*/\n"
+ "\n"
+ "#include \"renderprogs/global.inc\"\n"
+ "\n"
+ "uniform sampler2D samp0 : register(s0); // normal map\n"
+ "\n"
+ "struct PS_IN\n"
+ "{\n"
+ " float4 position : VPOS;\n"
+ " float2 texcoord0 : TEXCOORD0_centroid;\n"
+ " float3 texcoord1 : TEXCOORD1_centroid;\n"
+ " float3 texcoord2 : TEXCOORD2_centroid;\n"
+ " float3 texcoord3 : TEXCOORD3_centroid;\n"
+ " float3 texcoord4 : TEXCOORD4_centroid;\n"
+ " float4 color : COLOR0;\n"
+ "};\n"
+ "\n"
+ "struct PS_OUT\n"
+ "{\n"
+ " float4 color : COLOR;\n"
+ "};\n"
+ "\n"
+ "void main( PS_IN fragment, out PS_OUT result )\n"
+ "{\n"
+ " float4 bump = tex2D( samp0, fragment.texcoord0 ) * 2.0f - 1.0f;\n"
+ " \n"
+ " // RB begin\n"
+ " float3 localNormal;\n"
+ "#if defined(USE_NORMAL_FMT_RGB8)\n"
+ " localNormal = float3( bump.rg, 0.0f );\n"
+ "#else\n"
+ " localNormal = float3( bump.wy, 0.0f );\n"
+ "#endif\n"
+ " // RB end\n"
+ " localNormal.z = sqrt( 1.0f - dot3( localNormal, localNormal ) );\n"
+ "\n"
+ " float3 globalNormal;\n"
+ "#if 0\n"
+ " globalNormal.x = dot3( localNormal, fragment.texcoord2 );\n"
+ " globalNormal.y = dot3( localNormal, fragment.texcoord3 );\n"
+ " globalNormal.z = dot3( localNormal, fragment.texcoord4 );\n"
+ "#else\n"
+ " // only the normal in view space\n"
+ " globalNormal.x = fragment.texcoord2.z;\n"
+ " globalNormal.y = fragment.texcoord3.z;\n"
+ " globalNormal.z = fragment.texcoord4.z;\n"
+ " //globalNormal.z = fragment.texcoord4.z * -0.001; //sqrt( abs( dot( globalNormal.xy, globalNormal.xy ) - 0.25 ) );\n"
+ " globalNormal = normalize( globalNormal );\n"
+ "#endif\n"
+ "\n"
+ " // RB: rpColor is white and only used to generate the _fa_ uniform array\n"
+ " result.color.rgb = ( globalNormal.xyz * 0.5 + 0.5 ) * fragment.color.rgb;// * rpColor;\n"
+ " //result.color.rgb = ( globalNormal.xyz );// * fragment.color.rgb;// * rpColor;\n"
+ " result.color.a = 1.0;\n"
+ "}\n"
+ "\n"
+
+ },
+
+ {
+ "renderprogs/gbuffer.vertex",
+ "/*\n"
+ "===========================================================================\n"
+ "\n"
+ "Doom 3 BFG Edition GPL Source Code\n"
+ "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
+ "Copyright (C) 2016 Robert Beckebans\n"
+ "\n"
+ "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\"). \n"
+ "\n"
+ "Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation, either version 3 of the License, or\n"
+ "(at your option) any later version.\n"
+ "\n"
+ "Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with Doom 3 BFG Edition Source Code. If not, see .\n"
+ "\n"
+ "In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.\n"
+ "\n"
+ "If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.\n"
+ "\n"
+ "===========================================================================\n"
+ "*/\n"
+ "\n"
+ "#include \"renderprogs/global.inc\"\n"
+ "\n"
+ "#if defined( USE_GPU_SKINNING )\n"
+ "uniform matrices_ubo { float4 matrices[408]; };\n"
+ "#endif\n"
+ "\n"
+ "struct VS_IN {\n"
+ " float4 position : POSITION;\n"
+ " float2 texcoord : TEXCOORD0;\n"
+ " float4 normal : NORMAL;\n"
+ " float4 tangent : TANGENT;\n"
+ " float4 color : COLOR0;\n"
+ " float4 color2 : COLOR1;\n"
+ "};\n"
+ "\n"
+ "struct VS_OUT {\n"
+ " float4 position : POSITION;\n"
+ " float2 texcoord0 : TEXCOORD0;\n"
+ " float3 texcoord1 : TEXCOORD1;\n"
+ " float3 texcoord2 : TEXCOORD2;\n"
+ " float3 texcoord3 : TEXCOORD3;\n"
+ " float3 texcoord4 : TEXCOORD4;\n"
+ " float4 color : COLOR0;\n"
+ "};\n"
+ "\n"
+ "void main( VS_IN vertex, out VS_OUT result ) {\n"
+ " \n"
+ " float4 vNormal = vertex.normal * 2.0 - 1.0;\n"
+ " float4 vTangent = vertex.tangent * 2.0 - 1.0;\n"
+ " float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;\n"
+ "\n"
+ "#if defined( USE_GPU_SKINNING )\n"
+ " //--------------------------------------------------------------\n"
+ " // GPU transformation of the normal / tangent / bitangent\n"
+ " //\n"
+ " // multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )\n"
+ " //--------------------------------------------------------------\n"
+ " const float w0 = vertex.color2.x;\n"
+ " const float w1 = vertex.color2.y;\n"
+ " const float w2 = vertex.color2.z;\n"
+ " const float w3 = vertex.color2.w;\n"
+ "\n"
+ " float4 matX, matY, matZ; // must be float4 for vec4\n"
+ " int joint = int(vertex.color.x * 255.1 * 3.0);\n"
+ " matX = matrices[int(joint+0)] * w0;\n"
+ " matY = matrices[int(joint+1)] * w0;\n"
+ " matZ = matrices[int(joint+2)] * w0;\n"
+ "\n"
+ " joint = int(vertex.color.y * 255.1 * 3.0);\n"
+ " matX += matrices[int(joint+0)] * w1;\n"
+ " matY += matrices[int(joint+1)] * w1;\n"
+ " matZ += matrices[int(joint+2)] * w1;\n"
+ "\n"
+ " joint = int(vertex.color.z * 255.1 * 3.0);\n"
+ " matX += matrices[int(joint+0)] * w2;\n"
+ " matY += matrices[int(joint+1)] * w2;\n"
+ " matZ += matrices[int(joint+2)] * w2;\n"
+ "\n"
+ " joint = int(vertex.color.w * 255.1 * 3.0);\n"
+ " matX += matrices[int(joint+0)] * w3;\n"
+ " matY += matrices[int(joint+1)] * w3;\n"
+ " matZ += matrices[int(joint+2)] * w3;\n"
+ "\n"
+ " float3 normal;\n"
+ " normal.x = dot3( matX, vNormal );\n"
+ " normal.y = dot3( matY, vNormal );\n"
+ " normal.z = dot3( matZ, vNormal );\n"
+ " normal = normalize( normal );\n"
+ "\n"
+ " float3 tangent;\n"
+ " tangent.x = dot3( matX, vTangent );\n"
+ " tangent.y = dot3( matY, vTangent );\n"
+ " tangent.z = dot3( matZ, vTangent );\n"
+ " tangent = normalize( tangent );\n"
+ "\n"
+ " float3 bitangent;\n"
+ " bitangent.x = dot3( matX, vBitangent );\n"
+ " bitangent.y = dot3( matY, vBitangent );\n"
+ " bitangent.z = dot3( matZ, vBitangent );\n"
+ " bitangent = normalize( bitangent );\n"
+ "\n"
+ " float4 modelPosition;\n"
+ " modelPosition.x = dot4( matX, vertex.position );\n"
+ " modelPosition.y = dot4( matY, vertex.position );\n"
+ " modelPosition.z = dot4( matZ, vertex.position );\n"
+ " modelPosition.w = 1.0;\n"
+ "\n"
+ "#else\n"
+ " float4 modelPosition = vertex.position;\n"
+ " float3 normal = vNormal.xyz;\n"
+ " float3 tangent = vTangent.xyz;\n"
+ " float3 bitangent = vBitangent.xyz;\n"
+ "#endif\n"
+ "\n"
+ " result.position.x = dot4( modelPosition, rpMVPmatrixX );\n"
+ " result.position.y = dot4( modelPosition, rpMVPmatrixY );\n"
+ " result.position.z = dot4( modelPosition, rpMVPmatrixZ );\n"
+ " result.position.w = dot4( modelPosition, rpMVPmatrixW );\n"
+ "\n"
+ " // textures 0 takes the base coordinates by the texture matrix\n"
+ " result.texcoord0.x = dot4( vertex.texcoord.xy, rpBumpMatrixS );\n"
+ " result.texcoord0.y = dot4( vertex.texcoord.xy, rpBumpMatrixT );\n"
+ "\n"
+ " //float4 toEye = rpLocalViewOrigin - modelPosition;\n"
+ " //result.texcoord1.x = dot3( toEye, rpModelMatrixX );\n"
+ " //result.texcoord1.y = dot3( toEye, rpModelMatrixY );\n"
+ " //result.texcoord1.z = dot3( toEye, rpModelMatrixZ );\n"
+ "\n"
+ "#if 0\n"
+ " // rotate into world space\n"
+ " result.texcoord2.x = dot3( tangent, rpModelMatrixX );\n"
+ " result.texcoord3.x = dot3( tangent, rpModelMatrixY );\n"
+ " result.texcoord4.x = dot3( tangent, rpModelMatrixZ );\n"
+ "\n"
+ " result.texcoord2.y = dot3( bitangent, rpModelMatrixX );\n"
+ " result.texcoord3.y = dot3( bitangent, rpModelMatrixY );\n"
+ " result.texcoord4.y = dot3( bitangent, rpModelMatrixZ );\n"
+ "\n"
+ " result.texcoord2.z = dot3( normal, rpModelMatrixX );\n"
+ " result.texcoord3.z = dot3( normal, rpModelMatrixY );\n"
+ " result.texcoord4.z = dot3( normal, rpModelMatrixZ ); \n"
+ " \n"
+ "#else\n"
+ " // rotate into view space\n"
+ " result.texcoord2.x = dot3( tangent, rpModelViewMatrixX );\n"
+ " result.texcoord3.x = dot3( tangent, rpModelViewMatrixY );\n"
+ " result.texcoord4.x = dot3( tangent, rpModelViewMatrixZ );\n"
+ "\n"
+ " result.texcoord2.y = dot3( bitangent, rpModelViewMatrixX );\n"
+ " result.texcoord3.y = dot3( bitangent, rpModelViewMatrixY );\n"
+ " result.texcoord4.y = dot3( bitangent, rpModelViewMatrixZ );\n"
+ "\n"
+ " result.texcoord2.z = dot3( normal, rpModelViewMatrixX );\n"
+ " result.texcoord3.z = dot3( normal, rpModelViewMatrixY );\n"
+ " result.texcoord4.z = dot3( normal, rpModelViewMatrixZ ); \n"
+ "#endif\n"
+ "\n"
+ "#if defined( USE_GPU_SKINNING )\n"
+ " // for joint transformation of the tangent space, we use color and\n"
+ " // color2 for weighting information, so hopefully there aren't any\n"
+ " // effects that need vertex color...\n"
+ " result.color = float4( 1.0f, 1.0f, 1.0f, 1.0f );\n"
+ "#else\n"
+ " //# generate the vertex color, which can be 1.0, color, or 1.0 - color\n"
+ " //# for 1.0 : env[16] = 0, env[17] = 1\n"
+ " //# for color : env[16] = 1, env[17] = 0\n"
+ " //# for 1.0-color : env[16] = -1, env[17] = 1 \n"
+ " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n"
+ "#endif\n"
+ "}\n"
+
+ },
+
{
"renderprogs/gui.pixel",
"/*\n"
diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp
index 5313833d..188401cc 100644
--- a/neo/renderer/RenderSystem_init.cpp
+++ b/neo/renderer/RenderSystem_init.cpp
@@ -262,6 +262,7 @@ idCVar r_forceAmbient( "r_forceAmbient", "0.2", CVAR_RENDERER | CVAR_FLOAT, "ren
idCVar r_useSSGI( "r_useSSGI", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use screen space global illumination and reflections" );
idCVar r_ssgiDebug( "r_ssgiDebug", "0", CVAR_RENDERER | CVAR_INTEGER, "" );
+idCVar r_ssaoFiltering( "r_ssaoFiltering", "1", CVAR_RENDERER | CVAR_BOOL, "" );
// RB end
const char* fileExten[3] = { "tga", "png", "jpg" };
diff --git a/neo/renderer/tr_backend_draw.cpp b/neo/renderer/tr_backend_draw.cpp
index 6e2dfe4f..d91f1c4d 100644
--- a/neo/renderer/tr_backend_draw.cpp
+++ b/neo/renderer/tr_backend_draw.cpp
@@ -1841,6 +1841,7 @@ static void RB_AmbientPass( const drawSurf_t* const* drawSurfs, int numDrawSurfs
//}
//else
{
+#if 0
if( r_useSSGI.GetBool() )
{
// fill geometry buffer with normal/roughness information
@@ -1854,6 +1855,7 @@ static void RB_AmbientPass( const drawSurf_t* const* drawSurfs, int numDrawSurfs
}
}
else
+#endif
{
// draw Quake 4 style ambient
if( drawSurf->jointCache )
@@ -2101,6 +2103,7 @@ static void RB_AmbientPass( const drawSurf_t* const* drawSurfs, int numDrawSurfs
renderLog.CloseBlock();
renderLog.CloseMainBlock();
+#if 0
if( r_useSSGI.GetBool() )
{
GL_SelectTexture( 0 );
@@ -2124,6 +2127,7 @@ static void RB_AmbientPass( const drawSurf_t* const* drawSurfs, int numDrawSurfs
globalImages->BindNull();
}
+#endif
}
// RB end
@@ -4614,12 +4618,23 @@ void RB_SSAO()
const bool hdrIsActive = ( r_useHDR.GetBool() && globalFramebuffers.hdrFBO != NULL && globalFramebuffers.hdrFBO->IsBound() );
- globalFramebuffers.ambientOcclusionFBO[0]->Bind();
-
- glClearColor( 1, 0, 0, 1 );
- glClear( GL_COLOR_BUFFER_BIT );
-
- renderProgManager.BindShader_AmbientOcclusion();
+ if( r_ssaoFiltering.GetBool() )
+ {
+ globalFramebuffers.ambientOcclusionFBO[0]->Bind();
+
+ glClearColor( 1, 0, 0, 1 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ renderProgManager.BindShader_AmbientOcclusion();
+ }
+ else
+ {
+ if( r_ssgiDebug.GetInteger() <= 0 )
+ {
+ GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
+ }
+ renderProgManager.BindShader_AmbientOcclusionAndOutput();
+ }
float screenCorrectionParm[4];
screenCorrectionParm[0] = 1.0f / glConfig.nativeScreenWidth;
@@ -4628,10 +4643,7 @@ void RB_SSAO()
screenCorrectionParm[3] = glConfig.nativeScreenHeight;
SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor
- // let the fragment program know how many samples we are going to use
- idVec4 samples( ( float )( 1 << r_motionBlur.GetInteger() ) );
- SetFragmentParm( RENDERPARM_OVERBRIGHT, samples.ToFloatPtr() );
-
+#if 0
// RB: set unprojection matrices so we can convert zbuffer values back to camera and world spaces
idRenderMatrix modelViewMatrix;
idRenderMatrix::Transpose( *( idRenderMatrix* )backEnd.viewDef->worldSpace.modelViewMatrix, modelViewMatrix );
@@ -4643,9 +4655,10 @@ void RB_SSAO()
SetVertexParms( RENDERPARM_MODELMATRIX_X, cameraToWorldMatrix[0], 4 );
//SetVertexParms( RENDERPARM_MODELMATRIX_X, backEnd.viewDef->unprojectionToWorldRenderMatrix[0], 4 );
-
+#endif
SetVertexParms( RENDERPARM_PROJMATRIX_X, backEnd.viewDef->unprojectionToCameraRenderMatrix[0], 4 );
+
float jitterTexOffset[4];
if( r_shadowMapRandomizeJitter.GetBool() )
{
@@ -4669,58 +4682,64 @@ void RB_SSAO()
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
-
- float jitterTexScale[4];
-
- // AO blur X
+ if( r_ssaoFiltering.GetBool() )
+ {
+ float jitterTexScale[4];
+
+ // AO blur X
#if 1
- globalFramebuffers.ambientOcclusionFBO[1]->Bind();
-
- renderProgManager.BindShader_AmbientOcclusionBlur();
-
- //const idScreenRect& viewport = backEnd.viewDef->viewport;
- //globalImages->currentAOImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
-
- // set axis parameter
-
- jitterTexScale[0] = 1;
- jitterTexScale[1] = 0;
- jitterTexScale[2] = 0;
- jitterTexScale[3] = 0;
- SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
-
- GL_SelectTexture( 0 );
- globalImages->ambientOcclusionImage[0]->Bind();
-
- RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
+ globalFramebuffers.ambientOcclusionFBO[1]->Bind();
+
+ renderProgManager.BindShader_AmbientOcclusionBlur();
+
+ //const idScreenRect& viewport = backEnd.viewDef->viewport;
+ //globalImages->currentAOImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
+
+ // set axis parameter
+
+ jitterTexScale[0] = 1;
+ jitterTexScale[1] = 0;
+ jitterTexScale[2] = 0;
+ jitterTexScale[3] = 0;
+ SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
+
+ GL_SelectTexture( 0 );
+ globalImages->ambientOcclusionImage[0]->Bind();
+
+ RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
#endif
-
- // AO blur Y
- if( hdrIsActive )
- {
- globalFramebuffers.hdrFBO->Bind();
+
+ // AO blur Y
+ if( hdrIsActive )
+ {
+ globalFramebuffers.hdrFBO->Bind();
+ }
+ else
+ {
+ Framebuffer::Unbind();
+ }
+
+ if( r_ssgiDebug.GetInteger() <= 0 )
+ {
+ GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
+ }
+
+ //globalImages->currentAOImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
+
+ renderProgManager.BindShader_AmbientOcclusionBlurAndOutput();
+
+ // set axis parameter
+ jitterTexScale[0] = 0;
+ jitterTexScale[1] = 1;
+ jitterTexScale[2] = 0;
+ jitterTexScale[3] = 0;
+ SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
+
+ GL_SelectTexture( 0 );
+ globalImages->ambientOcclusionImage[1]->Bind();
+
+ RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
}
- else
- {
- Framebuffer::Unbind();
- }
-
- //globalImages->currentAOImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
-
- renderProgManager.BindShader_AmbientOcclusionBlurAndOutput();
-
- // set axis parameter
- jitterTexScale[0] = 0;
- jitterTexScale[1] = 1;
- jitterTexScale[2] = 0;
- jitterTexScale[3] = 0;
- SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
-
- GL_SelectTexture( 0 );
- globalImages->ambientOcclusionImage[1]->Bind();
-
- RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
-
GL_CheckErrors();
diff --git a/neo/renderer/tr_local.h b/neo/renderer/tr_local.h
index 94d623f7..54792420 100644
--- a/neo/renderer/tr_local.h
+++ b/neo/renderer/tr_local.h
@@ -1104,6 +1104,7 @@ extern idCVar r_forceAmbient;
extern idCVar r_useSSGI;
extern idCVar r_ssgiDebug;
+extern idCVar r_ssaoFiltering;
// RB end
/*