diff --git a/base/renderprogs/_manifest.lua b/base/renderprogs/_manifest.lua
index 199b53a2..01698ddd 100644
--- a/base/renderprogs/_manifest.lua
+++ b/base/renderprogs/_manifest.lua
@@ -27,6 +27,8 @@ return
"color.vertex",
"colorProcess.pixel",
"colorProcess.vertex",
+ "debug_shadowmap.pixel",
+ "debug_shadowmap.vertex",
"depth.pixel",
"depth.vertex",
"depth_skinned.pixel",
@@ -54,12 +56,12 @@ return
"heatHazeWithMaskAndVertex.vertex",
"interaction.pixel",
"interaction.vertex",
+ "interactionSM.pixel",
+ "interactionSM.vertex",
"interactionAmbient.pixel",
"interactionAmbient.vertex",
"interactionAmbient_skinned.pixel",
"interactionAmbient_skinned.vertex",
- "interaction_skinned.pixel",
- "interaction_skinned.vertex",
"motionBlur.pixel",
"motionBlur.vertex",
"postprocess.pixel",
@@ -91,6 +93,8 @@ return
"texture_color_skinned.vertex",
"texture_color_texgen.pixel",
"texture_color_texgen.vertex",
+ "vertex_color.pixel",
+ "vertex_color.vertex",
"wobblesky.pixel",
"wobblesky.vertex",
"zcullReconstruct.pixel",
diff --git a/base/renderprogs/color.vertex b/base/renderprogs/color.vertex
index e330f16a..f1666b6d 100644
--- a/base/renderprogs/color.vertex
+++ b/base/renderprogs/color.vertex
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -28,21 +29,71 @@ If you have questions concerning this license or the applicable additional terms
#include "global.inc"
+#if defined(USE_GPU_SKINNING)
+uniform matrices_ubo { float4 matrices[408]; };
+#endif
+
struct VS_IN {
float4 position : POSITION;
float2 texcoord : TEXCOORD0;
float4 normal : NORMAL;
float4 tangent : TANGENT;
float4 color : COLOR0;
+ float4 color2 : COLOR1;
};
struct VS_OUT {
float4 position : POSITION;
};
-void main( VS_IN vertex, out VS_OUT result ) {
+void main( VS_IN vertex, out VS_OUT result )
+{
+#if defined(USE_GPU_SKINNING)
+ //--------------------------------------------------------------
+ // GPU transformation of the position
+ //
+ // multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
+ //--------------------------------------------------------------
+ const float w0 = vertex.color2.x;
+ const float w1 = vertex.color2.y;
+ const float w2 = vertex.color2.z;
+ const float w3 = vertex.color2.w;
+
+ float4 matX, matY, matZ; // must be float4 for vec4
+ float joint = vertex.color.x * 255.1 * 3;
+ matX = matrices[int(joint+0)] * w0;
+ matY = matrices[int(joint+1)] * w0;
+ matZ = matrices[int(joint+2)] * w0;
+
+ joint = vertex.color.y * 255.1 * 3;
+ matX += matrices[int(joint+0)] * w1;
+ matY += matrices[int(joint+1)] * w1;
+ matZ += matrices[int(joint+2)] * w1;
+
+ joint = vertex.color.z * 255.1 * 3;
+ matX += matrices[int(joint+0)] * w2;
+ matY += matrices[int(joint+1)] * w2;
+ matZ += matrices[int(joint+2)] * w2;
+
+ joint = vertex.color.w * 255.1 * 3;
+ matX += matrices[int(joint+0)] * w3;
+ matY += matrices[int(joint+1)] * w3;
+ matZ += matrices[int(joint+2)] * w3;
+
+ float4 modelPosition;
+ modelPosition.x = dot4( matX, vertex.position );
+ modelPosition.y = dot4( matY, vertex.position );
+ modelPosition.z = dot4( matZ, vertex.position );
+ modelPosition.w = 1.0;
+
+ result.position.x = dot4( modelPosition, rpMVPmatrixX );
+ result.position.y = dot4( modelPosition, rpMVPmatrixY );
+ result.position.z = dot4( modelPosition, rpMVPmatrixZ );
+ result.position.w = dot4( modelPosition, rpMVPmatrixW );
+#else
result.position.x = dot4( vertex.position, rpMVPmatrixX );
result.position.y = dot4( vertex.position, rpMVPmatrixY );
result.position.z = dot4( vertex.position, rpMVPmatrixZ );
result.position.w = dot4( vertex.position, rpMVPmatrixW );
+#endif
}
\ No newline at end of file
diff --git a/neo/renderer/AutoRenderBink.cpp b/base/renderprogs/debug_shadowmap.pixel
similarity index 76%
rename from neo/renderer/AutoRenderBink.cpp
rename to base/renderprogs/debug_shadowmap.pixel
index 18a0d8e7..422650df 100644
--- a/neo/renderer/AutoRenderBink.cpp
+++ b/base/renderprogs/debug_shadowmap.pixel
@@ -2,9 +2,10 @@
===========================================================================
Doom 3 BFG Edition GPL Source Code
-Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
-This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
+This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,8 +26,27 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
-#pragma hdrstop
-#include "precompiled.h"
-#include "tr_local.h"
-#include "../sound/snd_local.h"
+#include "renderprogs/global.inc"
+
+uniform sampler2DArray samp0 : register(s0);
+
+struct PS_IN
+{
+ float4 position : VPOS;
+ float2 texcoord0 : TEXCOORD0_centroid;
+};
+
+struct PS_OUT
+{
+ float4 color : COLOR;
+};
+
+void main( PS_IN fragment, out PS_OUT result )
+{
+ float3 tc;
+ tc.xy = fragment.texcoord0.xy;
+ tc.z = rpScreenCorrectionFactor.x; // layer
+
+ result.color = texture( samp0, tc );// * rpColor;
+}
\ No newline at end of file
diff --git a/base/renderprogs/debug_shadowmap.vertex b/base/renderprogs/debug_shadowmap.vertex
new file mode 100644
index 00000000..6cad9776
--- /dev/null
+++ b/base/renderprogs/debug_shadowmap.vertex
@@ -0,0 +1,58 @@
+/*
+===========================================================================
+
+Doom 3 BFG Edition GPL Source Code
+Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+
+This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
+
+Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Doom 3 BFG Edition Source Code. If not, see .
+
+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.
+
+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.
+
+===========================================================================
+*/
+
+#include "renderprogs/global.inc"
+
+struct VS_IN {
+ float4 position : POSITION;
+ float2 texcoord : TEXCOORD0;
+ float4 normal : NORMAL;
+ float4 tangent : TANGENT;
+ float4 color : COLOR0;
+};
+
+struct VS_OUT {
+ float4 position : POSITION;
+ float2 texcoord0 : TEXCOORD0;
+};
+
+void main( VS_IN vertex, out VS_OUT result ) {
+ result.position.x = dot4( vertex.position, rpMVPmatrixX );
+ result.position.y = dot4( vertex.position, rpMVPmatrixY );
+ result.position.z = dot4( vertex.position, rpMVPmatrixZ );
+ result.position.w = dot4( vertex.position, rpMVPmatrixW );
+
+ // compute oldschool texgen or multiply by texture matrix
+ BRANCH if ( rpTexGen0Enabled.x > 0.0 ) {
+ result.texcoord0.x = dot4( vertex.position, rpTexGen0S );
+ result.texcoord0.y = dot4( vertex.position, rpTexGen0T );
+ } else {
+ result.texcoord0.x = dot4( vertex.texcoord.xy, rpTextureMatrixS );
+ result.texcoord0.y = dot4( vertex.texcoord.xy, rpTextureMatrixT );
+ }
+}
\ No newline at end of file
diff --git a/base/renderprogs/global.inc b/base/renderprogs/global.inc
index 715776f0..51cac2ab 100644
--- a/base/renderprogs/global.inc
+++ b/base/renderprogs/global.inc
@@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
-Copyright (C) 2013 Robert Beckebans
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -97,6 +97,20 @@ uniform float4 rpOverbright : register(c50);
uniform float4 rpEnableSkinning : register(c51);
uniform float4 rpAlphaTest : register(c52);
+// RB begin
+uniform float4 rpAmbientColor : register(c53);
+uniform float4 rpGlobalLightOrigin : register(c54);
+uniform float4 rpJitterTexScale : register(c55);
+uniform float4 rpJitterTexOffset : register(c56);
+uniform float4 rpCascadeDistances : register(c57);
+
+#if defined( USE_UNIFORM_ARRAYS )
+uniform float4 rpShadowMatrices : register(c58);
+#else
+uniform float4 rpShadowMatrices[6*4] : register(c59);
+#endif
+// RB end
+
static float dot2( float2 a, float2 b ) { return dot( a, b ); }
static float dot3( float3 a, float3 b ) { return dot( a, b ); }
static float dot3( float3 a, float4 b ) { return dot( a, b.xyz ); }
@@ -180,6 +194,5 @@ static float4 idtex2Dproj( sampler2D samp, float4 texCoords ) { return tex2Dproj
static float4 swizzleColor( float4 c ) { return c; }
static float2 vposToScreenPosTexCoord( float2 vpos ) { return vpos.xy * rpWindowCoord.xy; }
-
#define BRANCH
#define IFANY
diff --git a/base/renderprogs/interaction.pixel b/base/renderprogs/interaction.pixel
index 263c4bce..a190a9d1 100644
--- a/base/renderprogs/interaction.pixel
+++ b/base/renderprogs/interaction.pixel
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -26,7 +27,7 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
-#include "global.inc"
+#include "renderprogs/global.inc"
uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map
uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture
@@ -64,15 +65,28 @@ void main( PS_IN fragment, out PS_OUT result ) {
localNormal.xy = bumpMap.wy - 0.5;
localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
localNormal = normalize( localNormal );
+
+ // RB: http://developer.valvesoftware.com/wiki/Half_Lambert
+ float halfLdotN = dot3( localNormal, lightVector ) * 0.5 + 0.5;
+ halfLdotN *= halfLdotN;
+
+ // traditional very dark Lambert light model used in Doom 3
+ //float ldotN = clamp( dot3( localNormal, lightVector ), 0.0, 1.0 );
+ float ldotN = dot3( localNormal, lightVector );
const half specularPower = 10.0f;
half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );
- half3 specularContribution = _half3( pow( hDotN, specularPower ) );
+ // RB: added abs
+ half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );
half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;
half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;
- half3 lightColor = dot3( lightVector, localNormal ) * lightProj.xyz * lightFalloff.xyz;
+ half3 lightColor = lightProj.xyz * lightFalloff.xyz;
+
+ half rim = 1.0f - saturate( hDotN );
+ half rimPower = 16.0f;
+ half3 rimColor = diffuseColor * lightProj.xyz * lightFalloff.xyz * 1.0f * pow( rim, rimPower ) * fragment.color.rgb;// * halfLdotN;
- result.color.xyz = ( diffuseColor + specularColor ) * lightColor * fragment.color.xyz;
+ result.color.xyz = ( diffuseColor + specularColor ) * halfLdotN * lightColor * fragment.color.rgb;// + rimColor;
result.color.w = 1.0;
}
diff --git a/base/renderprogs/interaction.vertex b/base/renderprogs/interaction.vertex
index 0b6e4066..322cde75 100644
--- a/base/renderprogs/interaction.vertex
+++ b/base/renderprogs/interaction.vertex
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -26,7 +27,11 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
-#include "global.inc"
+#include "renderprogs/global.inc"
+
+#if defined( USE_GPU_SKINNING )
+uniform matrices_ubo { float4 matrices[408]; };
+#endif
struct VS_IN {
float4 position : POSITION;
@@ -34,6 +39,7 @@ struct VS_IN {
float4 normal : NORMAL;
float4 tangent : TANGENT;
float4 color : COLOR0;
+ float4 color2 : COLOR1;
};
struct VS_OUT {
@@ -50,24 +56,89 @@ struct VS_OUT {
void main( VS_IN vertex, out VS_OUT result ) {
- float3 vNormal = vertex.normal.xyz * 2.0 - 1.0;
+ float4 vNormal = vertex.normal * 2.0 - 1.0;
float4 vTangent = vertex.tangent * 2.0 - 1.0;
- float3 vBinormal = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;
+ float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;
- result.position.x = dot4( vertex.position, rpMVPmatrixX );
- result.position.y = dot4( vertex.position, rpMVPmatrixY );
- result.position.z = dot4( vertex.position, rpMVPmatrixZ );
- result.position.w = dot4( vertex.position, rpMVPmatrixW );
+#if defined( USE_GPU_SKINNING )
+ //--------------------------------------------------------------
+ // GPU transformation of the normal / tangent / bitangent
+ //
+ // multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
+ //--------------------------------------------------------------
+ const float w0 = vertex.color2.x;
+ const float w1 = vertex.color2.y;
+ const float w2 = vertex.color2.z;
+ const float w3 = vertex.color2.w;
+
+ float4 matX, matY, matZ; // must be float4 for vec4
+ float joint = vertex.color.x * 255.1 * 3;
+ matX = matrices[int(joint+0)] * w0;
+ matY = matrices[int(joint+1)] * w0;
+ matZ = matrices[int(joint+2)] * w0;
+
+ joint = vertex.color.y * 255.1 * 3;
+ matX += matrices[int(joint+0)] * w1;
+ matY += matrices[int(joint+1)] * w1;
+ matZ += matrices[int(joint+2)] * w1;
+
+ joint = vertex.color.z * 255.1 * 3;
+ matX += matrices[int(joint+0)] * w2;
+ matY += matrices[int(joint+1)] * w2;
+ matZ += matrices[int(joint+2)] * w2;
+
+ joint = vertex.color.w * 255.1 * 3;
+ matX += matrices[int(joint+0)] * w3;
+ matY += matrices[int(joint+1)] * w3;
+ matZ += matrices[int(joint+2)] * w3;
+
+ float3 normal;
+ normal.x = dot3( matX, vNormal );
+ normal.y = dot3( matY, vNormal );
+ normal.z = dot3( matZ, vNormal );
+ normal = normalize( normal );
+
+ float3 tangent;
+ tangent.x = dot3( matX, vTangent );
+ tangent.y = dot3( matY, vTangent );
+ tangent.z = dot3( matZ, vTangent );
+ tangent = normalize( tangent );
+
+ float3 bitangent;
+ bitangent.x = dot3( matX, vBitangent );
+ bitangent.y = dot3( matY, vBitangent );
+ bitangent.z = dot3( matZ, vBitangent );
+ bitangent = normalize( bitangent );
+
+ float4 modelPosition;
+ modelPosition.x = dot4( matX, vertex.position );
+ modelPosition.y = dot4( matY, vertex.position );
+ modelPosition.z = dot4( matZ, vertex.position );
+ modelPosition.w = 1.0;
+
+#else
+ float4 modelPosition = vertex.position;
+ float3 normal = vNormal.xyz;
+ float3 tangent = vTangent.xyz;
+ float3 bitangent = vBitangent.xyz;
+#endif
+
+ result.position.x = dot4( modelPosition, rpMVPmatrixX );
+ result.position.y = dot4( modelPosition, rpMVPmatrixY );
+ result.position.z = dot4( modelPosition, rpMVPmatrixZ );
+ result.position.w = dot4( modelPosition, rpMVPmatrixW );
float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );
- //calculate vector to light in R0
- float4 toLight = rpLocalLightOrigin - vertex.position;
+ //calculate vector to light
+ float4 toLight = rpLocalLightOrigin - modelPosition;
- //result.texcoord0
- result.texcoord0.x = dot3( vTangent.xyz, toLight );
- result.texcoord0.y = dot3( vBinormal, toLight );
- result.texcoord0.z = dot3( vNormal, toLight );
+ //--------------------------------------------------------------
+
+ //result.texcoord0 is the direction to the light in tangent space
+ result.texcoord0.x = dot3( tangent, toLight );
+ result.texcoord0.y = dot3( bitangent, toLight );
+ result.texcoord0.z = dot3( normal, toLight );
result.texcoord0.w = 1.0f;
//textures 1 takes the base coordinates by the texture matrix
@@ -77,13 +148,13 @@ void main( VS_IN vertex, out VS_OUT result ) {
//# texture 2 has one texgen
result.texcoord2 = defaultTexCoord;
- result.texcoord2.x = dot4( vertex.position, rpLightFalloffS );
+ result.texcoord2.x = dot4( modelPosition, rpLightFalloffS );
//# texture 3 has three texgens
- result.texcoord3.x = dot4( vertex.position, rpLightProjectionS );
- result.texcoord3.y = dot4( vertex.position, rpLightProjectionT );
+ result.texcoord3.x = dot4( modelPosition, rpLightProjectionS );
+ result.texcoord3.y = dot4( modelPosition, rpLightProjectionT );
result.texcoord3.z = 0.0f;
- result.texcoord3.w = dot4( vertex.position, rpLightProjectionQ );
+ result.texcoord3.w = dot4( modelPosition, rpLightProjectionQ );
//# textures 4 takes the base coordinates by the texture matrix
result.texcoord4 = defaultTexCoord;
@@ -101,20 +172,27 @@ void main( VS_IN vertex, out VS_OUT result ) {
toLight = normalize( toLight );
//# calculate normalized vector to viewer in R1
- float4 toView = normalize( rpLocalViewOrigin - vertex.position );
+ float4 toView = normalize( rpLocalViewOrigin - modelPosition );
//# add together to become the half angle vector in object space (non-normalized)
float4 halfAngleVector = toLight + toView;
//# put into texture space
- result.texcoord6.x = dot3( vTangent.xyz, halfAngleVector );
- result.texcoord6.y = dot3( vBinormal, halfAngleVector );
- result.texcoord6.z = dot3( vNormal, halfAngleVector );
+ result.texcoord6.x = dot3( tangent, halfAngleVector );
+ result.texcoord6.y = dot3( bitangent, halfAngleVector );
+ result.texcoord6.z = dot3( normal, halfAngleVector );
result.texcoord6.w = 1.0f;
+#if defined( USE_GPU_SKINNING )
+ // for joint transformation of the tangent space, we use color and
+ // color2 for weighting information, so hopefully there aren't any
+ // effects that need vertex color...
+ result.color = float4( 1.0f, 1.0f, 1.0f, 1.0f );
+#else
//# generate the vertex color, which can be 1.0, color, or 1.0 - color
//# for 1.0 : env[16] = 0, env[17] = 1
//# for color : env[16] = 1, env[17] = 0
//# for 1.0-color : env[16] = -1, env[17] = 1
result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;
+#endif
}
\ No newline at end of file
diff --git a/base/renderprogs/interactionSM.pixel b/base/renderprogs/interactionSM.pixel
new file mode 100644
index 00000000..e7deeb85
--- /dev/null
+++ b/base/renderprogs/interactionSM.pixel
@@ -0,0 +1,260 @@
+/*
+===========================================================================
+
+Doom 3 BFG Edition GPL Source Code
+Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
+
+This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
+
+Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Doom 3 BFG Edition Source Code. If not, see .
+
+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.
+
+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.
+
+===========================================================================
+*/
+
+#include "renderprogs/global.inc"
+
+uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map
+uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture
+uniform sampler2D samp2 : register(s2); // texture 3 is the light projection texture
+uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map
+uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular map
+uniform sampler2DArrayShadow samp5 : register(s5); // texture 6 is the shadowmap array
+uniform sampler2D samp6 : register(s6); // texture 7 is the jitter texture
+
+
+
+struct PS_IN
+{
+ half4 position : VPOS;
+ half4 texcoord0 : TEXCOORD0_centroid;
+ half4 texcoord1 : TEXCOORD1_centroid;
+ half4 texcoord2 : TEXCOORD2_centroid;
+ half4 texcoord3 : TEXCOORD3_centroid;
+ half4 texcoord4 : TEXCOORD4_centroid;
+ half4 texcoord5 : TEXCOORD5_centroid;
+ half4 texcoord6 : TEXCOORD6_centroid;
+ half4 texcoord7 : TEXCOORD7_centroid;
+ half4 texcoord8 : TEXCOORD8_centroid;
+ half4 texcoord9 : TEXCOORD9_centroid;
+ half4 color : COLOR0;
+};
+
+struct PS_OUT
+{
+ half4 color : COLOR;
+};
+
+void main( PS_IN fragment, out PS_OUT result )
+{
+ half4 bumpMap = tex2D( samp0, fragment.texcoord1.xy );
+ half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 );
+ half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 );
+ half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy );
+ half4 specMap = tex2D( samp4, fragment.texcoord5.xy );
+
+ half3 lightVector = normalize( fragment.texcoord0.xyz );
+ half3 diffuseMap = ConvertYCoCgToRGB( YCoCG );
+
+ half3 localNormal;
+ // RB begin
+#if defined(GLES2)
+ localNormal.xy = bumpMap.rg - 0.5;
+#else
+ localNormal.xy = bumpMap.wy - 0.5;
+#endif
+ // RB end
+ localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
+ localNormal = normalize( localNormal );
+
+ // RB: http://developer.valvesoftware.com/wiki/Half_Lambert
+ float halfLdotN = dot3( localNormal, lightVector ) * 0.5 + 0.5;
+ halfLdotN *= halfLdotN;
+
+ // traditional very dark Lambert light model used in Doom 3
+ float ldotN = dot3( localNormal, lightVector );
+
+ const half specularPower = 10.0f;
+ half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );
+ // RB: added abs
+ half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );
+
+ half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;
+ half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;
+ half3 lightColor = lightProj.xyz * lightFalloff.xyz;
+
+ half rim = 1.0f - saturate( hDotN );
+ half rimPower = 16.0f;
+ half3 rimColor = diffuseColor * lightProj.xyz * lightFalloff.xyz * 1.0f * pow( rim, rimPower ) * fragment.color.rgb;// * halfLdotN;
+
+ //
+ // shadow mapping
+ //
+ int shadowIndex = 0;
+
+#if defined( LIGHT_POINT )
+ float3 toLightGlobal = normalize( fragment.texcoord8.xyz );
+
+ float axis[6];
+ axis[0] = -toLightGlobal.x;
+ axis[1] = toLightGlobal.x;
+ axis[2] = -toLightGlobal.y;
+ axis[3] = toLightGlobal.y;
+ axis[4] = -toLightGlobal.z;
+ axis[5] = toLightGlobal.z;
+
+ for( int i = 0; i < 6; i++ )
+ {
+ if( axis[i] > axis[shadowIndex] )
+ {
+ shadowIndex = i;
+ }
+ }
+
+#endif // #if defined( POINTLIGHT )
+
+#if defined( LIGHT_PARALLEL )
+
+ float viewZ = -fragment.texcoord9.z;
+
+ shadowIndex = 4;
+ for( int i = 0; i < 4; i++ )
+ {
+ if( viewZ < rpCascadeDistances[i] )
+ {
+ shadowIndex = i;
+ break;
+ }
+ }
+#endif
+
+#if 0
+ if( shadowIndex == 0 )
+ {
+ result.color = float4( 1.0, 0.0, 0.0, 1.0 );
+ }
+ else if( shadowIndex == 1 )
+ {
+ result.color = float4( 0.0, 1.0, 0.0, 1.0 );
+ }
+ else if( shadowIndex == 2 )
+ {
+ result.color = float4( 0.0, 0.0, 1.0, 1.0 );
+ }
+ else if( shadowIndex == 3 )
+ {
+ result.color = float4( 1.0, 1.0, 0.0, 1.0 );
+ }
+ else if( shadowIndex == 4 )
+ {
+ result.color = float4( 1.0, 0.0, 1.0, 1.0 );
+ }
+ else if( shadowIndex == 5 )
+ {
+ result.color = float4( 0.0, 1.0, 1.0, 1.0 );
+ }
+
+ //result.color.xyz *= lightColor;
+ return;
+#endif
+
+ float4 shadowMatrixX = rpShadowMatrices[ int ( shadowIndex * 4 + 0 ) ];
+ float4 shadowMatrixY = rpShadowMatrices[ int ( shadowIndex * 4 + 1 ) ];
+ float4 shadowMatrixZ = rpShadowMatrices[ int ( shadowIndex * 4 + 2 ) ];
+ float4 shadowMatrixW = rpShadowMatrices[ int ( shadowIndex * 4 + 3 ) ];
+
+ float4 modelPosition = float4( fragment.texcoord7.xyz, 1.0 );
+ float4 shadowTexcoord;
+ shadowTexcoord.x = dot4( modelPosition, shadowMatrixX );
+ shadowTexcoord.y = dot4( modelPosition, shadowMatrixY );
+ shadowTexcoord.z = dot4( modelPosition, shadowMatrixZ );
+ shadowTexcoord.w = dot4( modelPosition, shadowMatrixW );
+
+ //float bias = 0.001 * tan( acos( ldotN ) );
+ //bias = clamp( bias, 0, 0.001 );
+ float bias = 0.001;
+
+ shadowTexcoord.xyz /= shadowTexcoord.w;
+ shadowTexcoord.z = shadowTexcoord.z * 0.9991;
+ //shadowTexcoord.z = shadowTexcoord.z - bias;
+ shadowTexcoord.w = shadowIndex;
+
+#if 0
+ result.color.xyz = float3( shadowTexcoord.z, shadowTexcoord.z, shadowTexcoord.z );
+ result.color.w = 1.0;
+ return;
+#endif
+
+ // multiple taps
+
+#if 0
+ const float2 poissonDisk2[12] = float2[](
+ float2(-0.326,-0.406),
+ float2(-0.840,-0.074),
+ float2(-0.696, 0.457),
+ float2(-0.203, 0.621),
+ float2( 0.962,-0.195),
+ float2( 0.473,-0.480),
+ float2( 0.519, 0.767),
+ float2( 0.185,-0.893),
+ float2( 0.507, 0.064),
+ float2( 0.896, 0.412),
+ float2(-0.322,-0.933),
+ float2(-0.792,-0.598)
+ );
+ float shadow = 0.0;
+
+ float shadowTexelSize = ( 1.0 / 1024.0 ) * 0.5;
+ for( int i = 0; i < 12; i++ )
+ {
+ int index = int( rand( shadowTexcoord.xy * 1.0 ) * 12 );
+
+ float4 shadowTexcoordOffset = float4( shadowTexcoord.xy + poissonDisk2[index] * shadowTexelSize, shadowTexcoord.z, shadowTexcoord.w );
+
+ shadow += texture( samp5, shadowTexcoordOffset.xywz);
+ }
+
+ shadow *= ( 1.0 / 12.0 );
+
+#elif 1
+ float4 base = shadowTexcoord;
+
+ base.xy += rpJitterTexScale.xy * -0.5;
+
+ float shadow = 0.0;
+
+ float stepSize = 1.0 / 16;
+
+ float4 jitterTC = ( fragment.position * rpScreenCorrectionFactor ) + rpJitterTexOffset;
+ for( int i = 0; i < 16; i++ )
+ {
+ float4 jitter = base + tex2D( samp6, jitterTC.xy ) * rpJitterTexScale;
+ jitter.zw = shadowTexcoord.zw;
+
+ shadow += texture( samp5, jitter.xywz );
+ jitterTC.x += stepSize;
+ }
+
+ shadow *= ( 1.0 / 16 );
+#else
+ float shadow = texture( samp5, shadowTexcoord.xywz );
+#endif
+
+ result.color.xyz = ( diffuseColor + specularColor ) * halfLdotN * lightColor * fragment.color.rgb * shadow;// + rimColor;
+ result.color.w = 1.0;
+}
diff --git a/base/renderprogs/interaction_skinned.vertex b/base/renderprogs/interactionSM.vertex
similarity index 76%
rename from base/renderprogs/interaction_skinned.vertex
rename to base/renderprogs/interactionSM.vertex
index 53ce22aa..b443295c 100644
--- a/base/renderprogs/interaction_skinned.vertex
+++ b/base/renderprogs/interactionSM.vertex
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -26,9 +27,11 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
-#include "global.inc"
+#include "renderprogs/global.inc"
+#if defined( USE_GPU_SKINNING )
uniform matrices_ubo { float4 matrices[408]; };
+#endif
struct VS_IN {
float4 position : POSITION;
@@ -48,6 +51,9 @@ struct VS_OUT {
float4 texcoord4 : TEXCOORD4;
float4 texcoord5 : TEXCOORD5;
float4 texcoord6 : TEXCOORD6;
+ float4 texcoord7 : TEXCOORD7;
+ float4 texcoord8 : TEXCOORD8;
+ float4 texcoord9 : TEXCOORD9;
float4 color : COLOR0;
};
@@ -55,10 +61,11 @@ void main( VS_IN vertex, out VS_OUT result ) {
float4 vNormal = vertex.normal * 2.0 - 1.0;
float4 vTangent = vertex.tangent * 2.0 - 1.0;
- float3 vBinormal = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;
+ float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;
+#if defined( USE_GPU_SKINNING )
//--------------------------------------------------------------
- // GPU transformation of the normal / binormal / bitangent
+ // GPU transformation of the normal / tangent / bitangent
//
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
//--------------------------------------------------------------
@@ -100,11 +107,11 @@ void main( VS_IN vertex, out VS_OUT result ) {
tangent.z = dot3( matZ, vTangent );
tangent = normalize( tangent );
- float3 binormal;
- binormal.x = dot3( matX, vBinormal );
- binormal.y = dot3( matY, vBinormal );
- binormal.z = dot3( matZ, vBinormal );
- binormal = normalize( binormal );
+ float3 bitangent;
+ bitangent.x = dot3( matX, vBitangent );
+ bitangent.y = dot3( matY, vBitangent );
+ bitangent.z = dot3( matZ, vBitangent );
+ bitangent = normalize( bitangent );
float4 modelPosition;
modelPosition.x = dot4( matX, vertex.position );
@@ -112,6 +119,13 @@ void main( VS_IN vertex, out VS_OUT result ) {
modelPosition.z = dot4( matZ, vertex.position );
modelPosition.w = 1.0;
+#else
+ float4 modelPosition = vertex.position;
+ float3 normal = vNormal.xyz;
+ float3 tangent = vTangent.xyz;
+ float3 bitangent = vBitangent.xyz;
+#endif
+
result.position.x = dot4( modelPosition, rpMVPmatrixX );
result.position.y = dot4( modelPosition, rpMVPmatrixY );
result.position.z = dot4( modelPosition, rpMVPmatrixZ );
@@ -119,15 +133,15 @@ void main( VS_IN vertex, out VS_OUT result ) {
float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );
- //calculate vector to light in R0
- float4 toLight = rpLocalLightOrigin - modelPosition;
+ //calculate vector to light
+ float4 toLightLocal = rpLocalLightOrigin - modelPosition;
//--------------------------------------------------------------
//result.texcoord0 is the direction to the light in tangent space
- result.texcoord0.x = dot3( tangent, toLight );
- result.texcoord0.y = dot3( binormal, toLight );
- result.texcoord0.z = dot3( normal, toLight );
+ result.texcoord0.x = dot3( tangent, toLightLocal );
+ result.texcoord0.y = dot3( bitangent, toLightLocal );
+ result.texcoord0.z = dot3( normal, toLightLocal );
result.texcoord0.w = 1.0f;
//textures 1 takes the base coordinates by the texture matrix
@@ -158,28 +172,50 @@ void main( VS_IN vertex, out VS_OUT result ) {
//# texture 6's texcoords will be the halfangle in texture space
//# calculate normalized vector to light in R0
- toLight = normalize( toLight );
+ toLightLocal = normalize( toLightLocal );
//# calculate normalized vector to viewer in R1
float4 toView = normalize( rpLocalViewOrigin - modelPosition );
//# add together to become the half angle vector in object space (non-normalized)
- float4 halfAngleVector = toLight + toView;
+ float4 halfAngleVector = toLightLocal + toView;
//# put into texture space
result.texcoord6.x = dot3( tangent, halfAngleVector );
- result.texcoord6.y = dot3( binormal, halfAngleVector );
+ result.texcoord6.y = dot3( bitangent, halfAngleVector );
result.texcoord6.z = dot3( normal, halfAngleVector );
result.texcoord6.w = 1.0f;
+
+ result.texcoord7 = modelPosition;
+
+ float4 worldPosition;
+ worldPosition.x = dot4( modelPosition, rpModelMatrixX );
+ worldPosition.y = dot4( modelPosition, rpModelMatrixY );
+ worldPosition.z = dot4( modelPosition, rpModelMatrixZ );
+ worldPosition.w = dot4( modelPosition, rpModelMatrixW );
+
+ float4 toLightGlobal = rpGlobalLightOrigin - worldPosition;
+
+ result.texcoord8 = toLightGlobal;
+
+ float4 viewPosition;
+ viewPosition.x = dot4( modelPosition, rpModelViewMatrixX );
+ viewPosition.y = dot4( modelPosition, rpModelViewMatrixY );
+ viewPosition.z = dot4( modelPosition, rpModelViewMatrixZ );
+ viewPosition.w = dot4( modelPosition, rpModelViewMatrixW );
+
+ result.texcoord9 = viewPosition;
+#if defined( USE_GPU_SKINNING )
// for joint transformation of the tangent space, we use color and
// color2 for weighting information, so hopefully there aren't any
// effects that need vertex color...
result.color = float4( 1.0f, 1.0f, 1.0f, 1.0f );
-
+#else
//# generate the vertex color, which can be 1.0, color, or 1.0 - color
//# for 1.0 : env[16] = 0, env[17] = 1
//# for color : env[16] = 1, env[17] = 0
//# for 1.0-color : env[16] = -1, env[17] = 1
- // result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;
+ result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;
+#endif
}
\ No newline at end of file
diff --git a/base/renderprogs/interaction_skinned.pixel b/base/renderprogs/interaction_skinned.pixel
deleted file mode 100644
index 263c4bce..00000000
--- a/base/renderprogs/interaction_skinned.pixel
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-===========================================================================
-
-Doom 3 BFG Edition GPL Source Code
-Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
-
-This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
-
-Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Doom 3 BFG Edition Source Code. If not, see .
-
-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.
-
-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.
-
-===========================================================================
-*/
-
-#include "global.inc"
-
-uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map
-uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture
-uniform sampler2D samp2 : register(s2); // texture 3 is the light projection texture
-uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map
-uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular map
-
-struct PS_IN {
- half4 position : VPOS;
- half4 texcoord0 : TEXCOORD0_centroid;
- half4 texcoord1 : TEXCOORD1_centroid;
- half4 texcoord2 : TEXCOORD2_centroid;
- half4 texcoord3 : TEXCOORD3_centroid;
- half4 texcoord4 : TEXCOORD4_centroid;
- half4 texcoord5 : TEXCOORD5_centroid;
- half4 texcoord6 : TEXCOORD6_centroid;
- half4 color : COLOR0;
-};
-
-struct PS_OUT {
- half4 color : COLOR;
-};
-
-void main( PS_IN fragment, out PS_OUT result ) {
- half4 bumpMap = tex2D( samp0, fragment.texcoord1.xy );
- half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 );
- half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 );
- half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy );
- half4 specMap = tex2D( samp4, fragment.texcoord5.xy );
-
- half3 lightVector = normalize( fragment.texcoord0.xyz );
- half3 diffuseMap = ConvertYCoCgToRGB( YCoCG );
-
- half3 localNormal;
- localNormal.xy = bumpMap.wy - 0.5;
- localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
- localNormal = normalize( localNormal );
-
- const half specularPower = 10.0f;
- half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );
- half3 specularContribution = _half3( pow( hDotN, specularPower ) );
-
- half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;
- half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;
- half3 lightColor = dot3( lightVector, localNormal ) * lightProj.xyz * lightFalloff.xyz;
-
- result.color.xyz = ( diffuseColor + specularColor ) * lightColor * fragment.color.xyz;
- result.color.w = 1.0;
-}
diff --git a/neo/renderer/AutoRenderBink.h b/base/renderprogs/vertex_color.pixel
similarity index 83%
rename from neo/renderer/AutoRenderBink.h
rename to base/renderprogs/vertex_color.pixel
index f0c3ffb5..97cada96 100644
--- a/neo/renderer/AutoRenderBink.h
+++ b/base/renderprogs/vertex_color.pixel
@@ -2,9 +2,10 @@
===========================================================================
Doom 3 BFG Edition GPL Source Code
-Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013 Robert Beckebans
-This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
+This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,8 +26,22 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
-#ifndef __AUTO_RENDER_BINK_H__
-#define __AUTO_RENDER_BINK_H__
+#include "renderprogs/global.inc"
-#endif // __AUTO_RENDER_BINK_H__
+uniform sampler2D samp0 : register(s0);
+
+struct PS_IN
+{
+ float4 color : COLOR0;
+};
+
+struct PS_OUT
+{
+ float4 color : COLOR;
+};
+
+void main( PS_IN fragment, out PS_OUT result )
+{
+ result.color = fragment.color;
+}
\ No newline at end of file
diff --git a/neo/renderer/AutoRender.h b/base/renderprogs/vertex_color.vertex
similarity index 70%
rename from neo/renderer/AutoRender.h
rename to base/renderprogs/vertex_color.vertex
index 393126cf..de1480c0 100644
--- a/neo/renderer/AutoRender.h
+++ b/base/renderprogs/vertex_color.vertex
@@ -2,9 +2,10 @@
===========================================================================
Doom 3 BFG Edition GPL Source Code
-Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013 Robert Beckebans
-This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
+This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,34 +26,30 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
-#ifndef __AUTO_RENDER_H__
-#define __AUTO_RENDER_H__
-class idAutoRender : public idSysThread
+#include "renderprogs/global.inc"
+
+struct VS_IN
{
-public:
- idAutoRender();
- // idSysThread interface
- int Run();
-
- void StartBackgroundAutoSwaps( autoRenderIconType_t iconType );
- void EndBackgroundAutoSwaps();
-
- autoRenderIconType_t GetCurrentIcon()
- {
- return autoRenderIcon;
- }
-
-private:
- void RenderFrame();
- void RenderBackground();
- void RenderLoadingIcon( float fracX, float fracY, float size, float speed );
-
- int nextRotateTime;
- float currentRotation;
- autoRenderIconType_t autoRenderIcon;
+ float4 position : POSITION;
+ float2 texcoord : TEXCOORD0;
+ float4 normal : NORMAL;
+ float4 tangent : TANGENT;
+ float4 color : COLOR0;
};
-extern idAutoRender rAutoRender;
+struct VS_OUT
+{
+ float4 position : POSITION;
+ float4 color : COLOR0;
+};
-#endif // __AUTO_RENDER_H__
\ No newline at end of file
+void main( VS_IN vertex, out VS_OUT result )
+{
+ result.position.x = dot4( vertex.position, rpMVPmatrixX );
+ result.position.y = dot4( vertex.position, rpMVPmatrixY );
+ result.position.z = dot4( vertex.position, rpMVPmatrixZ );
+ result.position.w = dot4( vertex.position, rpMVPmatrixW );
+
+ result.color = swizzleColor( vertex.color );
+}
\ No newline at end of file
diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp
index 9ea9c7ae..b8d9e11c 100644
--- a/neo/framework/Common.cpp
+++ b/neo/framework/Common.cpp
@@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
-Copyright (C) 2012 Robert Beckebans
+Copyright (C) 2012-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -33,7 +33,6 @@ If you have questions concerning this license or the applicable additional terms
#include "Common_local.h"
#include "ConsoleHistory.h"
-#include "../renderer/AutoRenderBink.h"
#include "../sound/sound.h"
diff --git a/neo/idlib/geometry/RenderMatrix.cpp b/neo/idlib/geometry/RenderMatrix.cpp
index 653bc2f3..dd693c47 100644
--- a/neo/idlib/geometry/RenderMatrix.cpp
+++ b/neo/idlib/geometry/RenderMatrix.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -84,6 +85,15 @@ ALIGNTYPE16 const idRenderMatrix renderMatrix_windowSpaceToClipSpace(
0.0f, 0.0f, 0.0f, 1.0f
);
+// RB begin
+ALIGNTYPE16 const idRenderMatrix renderMatrix_clipSpaceToWindowSpace(
+ 0.5f, 0.0f, 0.0f, 0.5f,
+ 0.0f, 0.5f, 0.0f, 0.5f,
+ 0.0f, 0.0f, 0.5f, 0.5f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+);
+// RB end
+
/*
================================================================================================
diff --git a/neo/idlib/geometry/RenderMatrix.h b/neo/idlib/geometry/RenderMatrix.h
index 2d418b49..1d50efb9 100644
--- a/neo/idlib/geometry/RenderMatrix.h
+++ b/neo/idlib/geometry/RenderMatrix.h
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -167,6 +168,9 @@ private:
extern const idRenderMatrix renderMatrix_identity;
extern const idRenderMatrix renderMatrix_flipToOpenGL;
extern const idRenderMatrix renderMatrix_windowSpaceToClipSpace;
+// RB begin
+extern const idRenderMatrix renderMatrix_clipSpaceToWindowSpace;
+// RB end
/*
========================
diff --git a/neo/renderer/AutoRender.cpp b/neo/renderer/AutoRender.cpp
deleted file mode 100644
index f4db0640..00000000
--- a/neo/renderer/AutoRender.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
-===========================================================================
-
-Doom 3 BFG Edition GPL Source Code
-Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
-
-This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
-
-Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Doom 3 BFG Edition Source Code. If not, see .
-
-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.
-
-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.
-
-===========================================================================
-*/
-#pragma hdrstop
-#include "precompiled.h"
-#include "tr_local.h"
-
-const int AUTO_RENDER_STACK_SIZE = 256 * 1024;
-
-idAutoRender rAutoRender;
-
-/*
-============================
-idAutoRender::idAutoRender
-============================
-*/
-idAutoRender::idAutoRender()
-{
- nextRotateTime = 0.0f;
- currentRotation = 0.0f;
- autoRenderIcon = AUTORENDER_DEFAULTICON;
-}
-
-/*
-============================
-idAutoRender::Run
-============================
-*/
-int idAutoRender::Run()
-{
- while( !IsTerminating() )
- {
- RenderFrame();
- }
-
-
- return 0;
-}
-
-/*
-============================
-idAutoRender::StartBackgroundAutoSwaps
-============================
-*/
-void idAutoRender::StartBackgroundAutoSwaps( autoRenderIconType_t iconType )
-{
-
-
- if( IsRunning() )
- {
- EndBackgroundAutoSwaps();
- }
-
- autoRenderIcon = iconType;
-
- idLib::Printf( "Starting Background AutoSwaps\n" );
-
- const bool captureToImage = true;
- common->UpdateScreen( captureToImage );
-
- // unbind any shaders prior to entering the background autoswaps so we don't run
- // into any problems with cached vertex shader indices from the main thread
- renderProgManager.Unbind();
-
- // unbind all texture units so we don't run into a race condition where the device is owned
- // by the autorender thread but an image is trying to be unset from the main thread because
- // it is getting purged before our our first frame has been rendered.
- globalImages->UnbindAll();
-
- // DG: set name to "BGAutoSwaps" because Linux has a 16char (incl. \0) namelimit for threads
- StartThread( "BGAutoSwaps", CORE_0B, THREAD_NORMAL, AUTO_RENDER_STACK_SIZE );
- // DG end
-}
-
-/*
-============================
-idAutoRender::EndBackgroundAutoSwaps
-============================
-*/
-void idAutoRender::EndBackgroundAutoSwaps()
-{
- idLib::Printf( "End Background AutoSwaps\n" );
-
- StopThread();
-
-}
-
-/*
-============================
-idAutoRender::RenderFrame
-============================
-*/
-void idAutoRender::RenderFrame()
-{
- // values are 0 to 1
- float loadingIconPosX = 0.5f;
- float loadingIconPosY = 0.6f;
- float loadingIconScale = 0.025f;
- float loadingIconSpeed = 0.095f;
-
- if( autoRenderIcon == AUTORENDER_HELLICON )
- {
- loadingIconPosX = 0.85f;
- loadingIconPosY = 0.85f;
- loadingIconScale = 0.1f;
- loadingIconSpeed = 0.095f;
- }
- else if( autoRenderIcon == AUTORENDER_DIALOGICON )
- {
- loadingIconPosY = 0.73f;
- }
-
-
- GL_SetDefaultState();
-
- GL_Cull( CT_TWO_SIDED );
-
- const bool stereoRender = false;
-
- const int width = renderSystem->GetWidth();
- const int height = renderSystem->GetHeight();
- const int guardBand = height / 24;
-
- if( stereoRender )
- {
- for( int viewNum = 0 ; viewNum < 2; viewNum++ )
- {
- GL_ViewportAndScissor( 0, viewNum * ( height + guardBand ), width, height );
- RenderBackground();
- RenderLoadingIcon( loadingIconPosX, loadingIconPosY, loadingIconScale, loadingIconSpeed );
- }
- }
- else
- {
- GL_ViewportAndScissor( 0, 0, width, height );
- RenderBackground();
- RenderLoadingIcon( loadingIconPosX, loadingIconPosY, loadingIconScale, loadingIconSpeed );
- }
-
-}
-
-/*
-============================
-idAutoRender::RenderBackground
-============================
-*/
-void idAutoRender::RenderBackground()
-{
- GL_SelectTexture( 0 );
-
- globalImages->currentRenderImage->Bind();
-
- GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
-
- float mvpMatrix[16] = { 0 };
- mvpMatrix[0] = 1;
- mvpMatrix[5] = 1;
- mvpMatrix[10] = 1;
- mvpMatrix[15] = 1;
-
- // Set Parms
- float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
- float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
- renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_S, texS );
- renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_T, texT );
-
- // disable texgen
- float texGenEnabled[4] = { 0, 0, 0, 0 };
- renderProgManager.SetRenderParm( RENDERPARM_TEXGEN_0_ENABLED, texGenEnabled );
-
- // set matrix
- renderProgManager.SetRenderParms( RENDERPARM_MVPMATRIX_X, mvpMatrix, 4 );
-
- renderProgManager.BindShader_TextureVertexColor();
-
- RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
-}
-
-/*
-============================
-idAutoRender::RenderLoadingIcon
-============================
-*/
-void idAutoRender::RenderLoadingIcon( float fracX, float fracY, float size, float speed )
-{
-
- float s = 0.0f;
- float c = 1.0f;
-
- if( autoRenderIcon != AUTORENDER_HELLICON )
- {
- if( Sys_Milliseconds() >= nextRotateTime )
- {
- nextRotateTime = Sys_Milliseconds() + 100;
- currentRotation -= 90.0f;
- }
- float angle = DEG2RAD( currentRotation );
- idMath::SinCos( angle, s, c );
- }
-
- const float pixelAspect = renderSystem->GetPixelAspect();
- const float screenWidth = renderSystem->GetWidth();
- const float screenHeight = renderSystem->GetHeight();
-
- const float minSize = Min( screenWidth, screenHeight );
- if( minSize <= 0.0f )
- {
- return;
- }
-
- float scaleX = size * minSize / screenWidth;
- float scaleY = size * minSize / screenHeight;
-
- float scale[16] = { 0 };
- scale[0] = c * scaleX / pixelAspect;
- scale[1] = -s * scaleY;
- scale[4] = s * scaleX / pixelAspect;
- scale[5] = c * scaleY;
- scale[10] = 1.0f;
- scale[15] = 1.0f;
-
- scale[12] = fracX;
- scale[13] = fracY;
-
- float ortho[16] = { 0 };
- ortho[0] = 2.0f;
- ortho[5] = -2.0f;
- ortho[10] = -2.0f;
- ortho[12] = -1.0f;
- ortho[13] = 1.0f;
- ortho[14] = -1.0f;
- ortho[15] = 1.0f;
-
- float finalOrtho[16];
- R_MatrixMultiply( scale, ortho, finalOrtho );
-
- float projMatrixTranspose[16];
- R_MatrixTranspose( finalOrtho, projMatrixTranspose );
- renderProgManager.SetRenderParms( RENDERPARM_MVPMATRIX_X, projMatrixTranspose, 4 );
-
- float a = 1.0f;
- if( autoRenderIcon == AUTORENDER_HELLICON )
- {
- float alpha = DEG2RAD( Sys_Milliseconds() * speed );
- a = idMath::Sin( alpha );
- a = 0.35f + ( 0.65f * idMath::Fabs( a ) );
- }
-
- GL_SelectTexture( 0 );
-
- if( autoRenderIcon == AUTORENDER_HELLICON )
- {
- globalImages->hellLoadingIconImage->Bind();
- }
- else
- {
- globalImages->loadingIconImage->Bind();
- }
-
- GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
-
- // Set Parms
- float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
- float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
- renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_S, texS );
- renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_T, texT );
-
- if( autoRenderIcon == AUTORENDER_HELLICON )
- {
- GL_Color( 1.0f, 1.0f, 1.0f, a );
- }
-
- // disable texgen
- float texGenEnabled[4] = { 0, 0, 0, 0 };
- renderProgManager.SetRenderParm( RENDERPARM_TEXGEN_0_ENABLED, texGenEnabled );
-
- renderProgManager.BindShader_TextureVertexColor();
-
- RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
-}
diff --git a/neo/renderer/BinaryImage.cpp b/neo/renderer/BinaryImage.cpp
index e4d83ad4..1882429c 100644
--- a/neo/renderer/BinaryImage.cpp
+++ b/neo/renderer/BinaryImage.cpp
@@ -389,7 +389,7 @@ ID_TIME_T idBinaryImage::WriteGeneratedFile( ID_TIME_T sourceFileTime )
idLib::Warning( "idBinaryImage: Could not open file '%s'", binaryFileName.c_str() );
return FILE_NOT_FOUND_TIMESTAMP;
}
- idLib::Printf( "Writing %s\n", binaryFileName.c_str() );
+ idLib::Printf( "Writing %s: %ix%i\n", binaryFileName.c_str(), fileData.width, fileData.height );
fileData.headerMagic = BIMAGE_MAGIC;
fileData.sourceFileTime = sourceFileTime;
diff --git a/neo/renderer/BoundsTrack.cpp b/neo/renderer/BoundsTrack.cpp
index 8f58d3e1..2d5e6936 100644
--- a/neo/renderer/BoundsTrack.cpp
+++ b/neo/renderer/BoundsTrack.cpp
@@ -112,10 +112,12 @@ struct shortBounds_t
// the maxs are stored negated
for( int i = 0 ; i < 3 ; i++ )
{
+ // RB: replaced std::min, max
int minv = floor( set[0][i] );
- b[0][i] = std::max( -32768, minv );
+ b[0][i] = Max( -32768, minv );
int maxv = -ceil( set[1][i] );
- b[1][i] = std::min( 32767, maxv );
+ b[1][i] = Min( 32767, maxv );
+ // RB end
}
b[0][3] = b[1][3] = 0;
}
@@ -218,7 +220,9 @@ void idBoundsTrack::ClearAll()
void idBoundsTrack::SetIndex( const int index, const idBounds& bounds )
{
assert( ( unsigned )index < MAX_BOUNDS_TRACK_INDEXES );
- maxIndex = std::max( maxIndex, index + 1 );
+ // RB: replaced std::max
+ maxIndex = Max( maxIndex, index + 1 );
+ // RB end
boundsList[index].SetFromReferenceBounds( bounds );
}
diff --git a/neo/renderer/Framebuffer.cpp b/neo/renderer/Framebuffer.cpp
new file mode 100644
index 00000000..d6e69932
--- /dev/null
+++ b/neo/renderer/Framebuffer.cpp
@@ -0,0 +1,247 @@
+/*
+===========================================================================
+
+Doom 3 BFG Edition GPL Source Code
+Copyright (C) 2014 Robert Beckebans
+
+This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
+
+Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Doom 3 BFG Edition Source Code. If not, see .
+
+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.
+
+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.
+
+===========================================================================
+*/
+
+#include "precompiled.h"
+#pragma hdrstop
+
+#include "tr_local.h"
+#include "Framebuffer.h"
+
+idList Framebuffer::framebuffers;
+
+globalFramebuffers_t globalFramebuffers;
+
+static void R_ListFramebuffers_f( const idCmdArgs& args )
+{
+ if( !glConfig.framebufferObjectAvailable )
+ {
+ common->Printf( "GL_EXT_framebuffer_object is not available.\n" );
+ return;
+ }
+}
+
+Framebuffer::Framebuffer( const char* name, int w, int h )
+{
+ fboName = name;
+
+ frameBuffer = 0;
+
+ memset( colorBuffers, 0, sizeof( colorBuffers ) );
+ colorFormat = 0;
+
+ depthBuffer = 0;
+ depthFormat = 0;
+
+ stencilBuffer = 0;
+ stencilFormat = 0;
+
+ width = w;
+ height = h;
+
+ glGenFramebuffers( 1, &frameBuffer );
+
+ framebuffers.Append( this );
+}
+
+void Framebuffer::Init()
+{
+ cmdSystem->AddCommand( "listFramebuffers", R_ListFramebuffers_f, CMD_FL_RENDERER, "lists framebuffers" );
+
+ backEnd.glState.currentFramebuffer = NULL;
+
+ int width, height;
+ width = height = r_shadowMapImageSize.GetInteger();
+
+ globalFramebuffers.shadowFBO = new Framebuffer( "_shadowMap" , width, height );
+ globalFramebuffers.shadowFBO->Bind();
+ glDrawBuffers( 0, NULL );
+// globalFramebuffers.shadowFBO->AddColorBuffer( GL_RGBA8, 0 );
+// globalFramebuffers.shadowFBO->AddDepthBuffer( GL_DEPTH_COMPONENT24 );
+// globalFramebuffers.shadowFBO->Check();
+
+ BindNull();
+}
+
+void Framebuffer::Shutdown()
+{
+ // TODO
+}
+
+void Framebuffer::Bind()
+{
+#if 0
+ if( r_logFile.GetBool() )
+ {
+ RB_LogComment( "--- Framebuffer::Bind( name = '%s' ) ---\n", fboName.c_str() );
+ }
+#endif
+
+ if( backEnd.glState.currentFramebuffer != this )
+ {
+ glBindFramebuffer( GL_FRAMEBUFFER, frameBuffer );
+ backEnd.glState.currentFramebuffer = this;
+ }
+}
+
+void Framebuffer::BindNull()
+{
+ //if(backEnd.glState.framebuffer != NULL)
+ {
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glBindRenderbuffer( GL_RENDERBUFFER, 0 );
+ backEnd.glState.currentFramebuffer = NULL;
+ }
+}
+
+void Framebuffer::AddColorBuffer( int format, int index )
+{
+ if( index < 0 || index >= glConfig.maxColorAttachments )
+ {
+ common->Warning( "Framebuffer::AddColorBuffer( %s ): bad index = %i", fboName.c_str(), index );
+ return;
+ }
+
+ colorFormat = format;
+
+ bool notCreatedYet = colorBuffers[index] == 0;
+ if( notCreatedYet )
+ {
+ glGenRenderbuffers( 1, &colorBuffers[index] );
+ }
+
+ glBindRenderbuffer( GL_RENDERBUFFER, colorBuffers[index] );
+ glRenderbufferStorage( GL_RENDERBUFFER, format, width, height );
+
+ if( notCreatedYet )
+ {
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, GL_RENDERBUFFER, colorBuffers[index] );
+ }
+
+ GL_CheckErrors();
+}
+
+void Framebuffer::AddDepthBuffer( int format )
+{
+ depthFormat = format;
+
+ bool notCreatedYet = depthBuffer == 0;
+ if( notCreatedYet )
+ {
+ glGenRenderbuffers( 1, &depthBuffer );
+ }
+
+ glBindRenderbuffer( GL_RENDERBUFFER, depthBuffer );
+ glRenderbufferStorage( GL_RENDERBUFFER, format, width, height );
+
+ if( notCreatedYet )
+ {
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer );
+ }
+
+ GL_CheckErrors();
+}
+
+void Framebuffer::AttachImage2D( int target, const idImage* image, int index )
+{
+ if( ( target != GL_TEXTURE_2D ) && ( target < GL_TEXTURE_CUBE_MAP_POSITIVE_X || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ) )
+ {
+ common->Warning( "Framebuffer::AttachImage2D( %s ): invalid target", fboName.c_str() );
+ return;
+ }
+
+ if( index < 0 || index >= glConfig.maxColorAttachments )
+ {
+ common->Warning( "Framebuffer::AttachImage2D( %s ): bad index = %i", fboName.c_str(), index );
+ return;
+ }
+
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, target, image->texnum, 0 );
+}
+
+void Framebuffer::AttachImageDepth( const idImage* image )
+{
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, image->texnum, 0 );
+}
+
+void Framebuffer::AttachImageDepthLayer( const idImage* image, int layer )
+{
+ glFramebufferTextureLayer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, image->texnum, 0, layer );
+}
+
+void Framebuffer::Check()
+{
+ int prev;
+ glGetIntegerv( GL_FRAMEBUFFER_BINDING, &prev );
+
+ glBindFramebuffer( GL_FRAMEBUFFER, frameBuffer );
+
+ int status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
+ if( status == GL_FRAMEBUFFER_COMPLETE )
+ {
+ glBindFramebuffer( GL_FRAMEBUFFER, prev );
+ return;
+ }
+
+ // something went wrong
+ switch( status )
+ {
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ common->Error( "Framebuffer::Check( %s ): Framebuffer incomplete, incomplete attachment", fboName.c_str() );
+ break;
+
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ common->Error( "Framebuffer::Check( %s ): Framebuffer incomplete, missing attachment", fboName.c_str() );
+ break;
+
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ common->Error( "Framebuffer::Check( %s ): Framebuffer incomplete, missing draw buffer", fboName.c_str() );
+ break;
+
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ common->Error( "Framebuffer::Check( %s ): Framebuffer incomplete, missing read buffer", fboName.c_str() );
+ break;
+
+ case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+ common->Error( "Framebuffer::Check( %s ): Framebuffer incomplete, missing layer targets", fboName.c_str() );
+ break;
+
+ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ common->Error( "Framebuffer::Check( %s ): Framebuffer incomplete, missing multisample", fboName.c_str() );
+ break;
+
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ common->Error( "Framebuffer::Check( %s ): Unsupported framebuffer format", fboName.c_str() );
+ break;
+
+ default:
+ common->Error( "Framebuffer::Check( %s ): Unknown error 0x%X", fboName.c_str(), status );
+ break;
+ };
+
+ glBindFramebuffer( GL_FRAMEBUFFER, prev );
+}
\ No newline at end of file
diff --git a/neo/renderer/RenderTexture.h b/neo/renderer/Framebuffer.h
similarity index 55%
rename from neo/renderer/RenderTexture.h
rename to neo/renderer/Framebuffer.h
index 02541750..337c4598 100644
--- a/neo/renderer/RenderTexture.h
+++ b/neo/renderer/Framebuffer.h
@@ -2,7 +2,7 @@
===========================================================================
Doom 3 BFG Edition GPL Source Code
-Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -25,60 +25,66 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
-#ifndef __RENDERTEXTURE_H__
-#define __RENDERTEXTURE_H__
-/*
-================================================================================================
+#ifndef __FRAMEBUFFER_H__
+#define __FRAMEBUFFER_H__
- Render Texture
-
-================================================================================================
-*/
-
-#define CELL_GCM_INVALID_PITCH 64
-
-/*
-================================================
-idRenderTexture holds both the color and depth images that are made
-resident on the video hardware.
-================================================
-*/
-class idRenderTexture
+class Framebuffer
{
public:
- idRenderTexture();
- ~idRenderTexture();
+
+ Framebuffer( const char* name, int width, int height );
- ID_INLINE int GetWidth() const
+ static void Init();
+ static void Shutdown();
+
+ // deletes OpenGL object but leaves structure intact for reloading
+ void PurgeFramebuffer();
+
+ void Bind();
+ static void BindNull();
+
+ void AddColorBuffer( int format, int index );
+ void AddDepthBuffer( int format );
+
+ void AttachImage2D( int target, const idImage* image, int index );
+ void AttachImage3D( const idImage* image );
+ void AttachImageDepth( const idImage* image );
+ void AttachImageDepthLayer( const idImage* image, int layer );
+
+ // check for OpenGL errors
+ void Check();
+ uint32_t GetFramebuffer() const
{
- return ( colorImage != NULL ) ? colorImage->GetUploadWidth() : depthImage->GetUploadWidth();
+ return frameBuffer;
}
- ID_INLINE int GetHeight() const
- {
- return ( colorImage != NULL ) ? colorImage->GetUploadHeight() : depthImage->GetUploadHeight();
- }
-
- ID_INLINE idImage* GetColorImage() const
- {
- return colorImage;
- }
- ID_INLINE idImage* GetDepthImage() const
- {
- return depthImage;
- }
-
-
- void Resize( int width, int height );
-
- void MakeCurrent( int level = 0, int side = 0 );
private:
- idImage* colorImage;
- idImage* depthImage;
- int targetWidth;
- int targetHeight;
+ idStr fboName;
+ // FBO object
+ uint32_t frameBuffer;
+
+ uint32_t colorBuffers[16];
+ int colorFormat;
+
+ uint32_t depthBuffer;
+ int depthFormat;
+
+ uint32_t stencilBuffer;
+ int stencilFormat;
+
+ int width;
+ int height;
+
+ static idList framebuffers;
};
-#endif //!__RENDERTEXTURE_H__
+struct globalFramebuffers_t
+{
+ Framebuffer* shadowFBO;
+};
+extern globalFramebuffers_t globalFramebuffers;
+
+
+#endif // __FRAMEBUFFER_H__
\ No newline at end of file
diff --git a/neo/renderer/GLMatrix.cpp b/neo/renderer/GLMatrix.cpp
index 4fa6fc6a..52cdff76 100644
--- a/neo/renderer/GLMatrix.cpp
+++ b/neo/renderer/GLMatrix.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -481,3 +482,95 @@ void R_SetupProjectionMatrix( viewDef_t* viewDef )
viewDef->projectionMatrix[1 * 4 + 3] = -viewDef->projectionMatrix[1 * 4 + 3];
}
}
+
+
+// RB: standard OpenGL projection matrix
+void R_SetupProjectionMatrix2( const viewDef_t* viewDef, const float zNear, const float zFar, float projectionMatrix[16] )
+{
+ float ymax = zNear * tan( viewDef->renderView.fov_y * idMath::PI / 360.0f );
+ float ymin = -ymax;
+
+ float xmax = zNear * tan( viewDef->renderView.fov_x * idMath::PI / 360.0f );
+ float xmin = -xmax;
+
+ const float width = xmax - xmin;
+ const float height = ymax - ymin;
+
+ const int viewWidth = viewDef->viewport.x2 - viewDef->viewport.x1 + 1;
+ const int viewHeight = viewDef->viewport.y2 - viewDef->viewport.y1 + 1;
+
+ float jitterx, jittery;
+ jitterx = 0.0f;
+ jittery = 0.0f;
+ jitterx = jitterx * width / viewWidth;
+ jitterx += r_centerX.GetFloat();
+ jitterx += viewDef->renderView.stereoScreenSeparation;
+ xmin += jitterx * width;
+ xmax += jitterx * width;
+
+ jittery = jittery * height / viewHeight;
+ jittery += r_centerY.GetFloat();
+ ymin += jittery * height;
+ ymax += jittery * height;
+
+ float depth = zFar - zNear;
+
+ projectionMatrix[0 * 4 + 0] = 2.0f * zNear / width;
+ projectionMatrix[1 * 4 + 0] = 0.0f;
+ projectionMatrix[2 * 4 + 0] = ( xmax + xmin ) / width; // normally 0
+ projectionMatrix[3 * 4 + 0] = 0.0f;
+
+ projectionMatrix[0 * 4 + 1] = 0.0f;
+ projectionMatrix[1 * 4 + 1] = 2.0f * zNear / height;
+ projectionMatrix[2 * 4 + 1] = ( ymax + ymin ) / height; // normally 0
+ projectionMatrix[3 * 4 + 1] = 0.0f;
+
+ projectionMatrix[0 * 4 + 2] = 0.0f;
+ projectionMatrix[1 * 4 + 2] = 0.0f;
+ projectionMatrix[2 * 4 + 2] = -( zFar + zNear ) / depth; // -0.999f; // adjust value to prevent imprecision issues
+ projectionMatrix[3 * 4 + 2] = -2 * zFar * zNear / depth; // -2.0f * zNear;
+
+ projectionMatrix[0 * 4 + 3] = 0.0f;
+ projectionMatrix[1 * 4 + 3] = 0.0f;
+ projectionMatrix[2 * 4 + 3] = -1.0f;
+ projectionMatrix[3 * 4 + 3] = 0.0f;
+
+ if( viewDef->renderView.flipProjection )
+ {
+ projectionMatrix[1 * 4 + 1] = -viewDef->projectionMatrix[1 * 4 + 1];
+ projectionMatrix[1 * 4 + 3] = -viewDef->projectionMatrix[1 * 4 + 3];
+ }
+}
+
+
+void R_MatrixFullInverse( const float a[16], float r[16] )
+{
+ idMat4 am;
+
+ for( int i = 0 ; i < 4 ; i++ )
+ {
+ for( int j = 0 ; j < 4 ; j++ )
+ {
+ am[i][j] = a[j * 4 + i];
+ }
+ }
+
+// idVec4 test( 100, 100, 100, 1 );
+// idVec4 transformed, inverted;
+// transformed = test * am;
+
+ if( !am.InverseSelf() )
+ {
+ common->Error( "Invert failed" );
+ }
+// inverted = transformed * am;
+
+ for( int i = 0 ; i < 4 ; i++ )
+ {
+ for( int j = 0 ; j < 4 ; j++ )
+ {
+ r[j * 4 + i] = am[i][j];
+ }
+ }
+}
+// RB end
\ No newline at end of file
diff --git a/neo/renderer/GLMatrix.h b/neo/renderer/GLMatrix.h
index 57de0139..88cf8118 100644
--- a/neo/renderer/GLMatrix.h
+++ b/neo/renderer/GLMatrix.h
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -61,4 +62,9 @@ void R_LocalPlaneToGlobal( const float modelMatrix[16], const idPlane& in, idPla
void R_SetupViewMatrix( viewDef_t* viewDef );
void R_SetupProjectionMatrix( viewDef_t* viewDef );
+// RB begin
+void R_SetupProjectionMatrix2( const viewDef_t* viewDef, const float zNear, const float zFar, float out[16] );
+void R_MatrixFullInverse( const float in[16], float r[16] );
+// RB end
+
#endif /* !__GLMATRIX_H__ */
diff --git a/neo/renderer/GraphicsAPIWrapper.h b/neo/renderer/GraphicsAPIWrapper.h
index 83894d0d..ffe23740 100644
--- a/neo/renderer/GraphicsAPIWrapper.h
+++ b/neo/renderer/GraphicsAPIWrapper.h
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -166,7 +167,11 @@ ID_INLINE void GL_ViewportAndScissor( const idScreenRect& rect )
void GL_Clear( bool color, bool depth, bool stencil, byte stencilValue, float r, float g, float b, float a );
void GL_PolygonOffset( float scale, float bias );
void GL_DepthBoundsTest( const float zmin, const float zmax );
-void GL_Color( float* color );
+//void GL_Color( float* color );
+// RB begin
+void GL_Color( const idVec3& color );
+void GL_Color( const idVec4& color );
+// RB end
void GL_Color( float r, float g, float b );
void GL_Color( float r, float g, float b, float a );
void GL_SelectTexture( int unit );
diff --git a/neo/renderer/Image.h b/neo/renderer/Image.h
index 2fedc6fd..440469e7 100644
--- a/neo/renderer/Image.h
+++ b/neo/renderer/Image.h
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -55,13 +56,17 @@ typedef enum
TD_LOOKUP_TABLE_RGBA, // RGBA lookup table
TD_COVERAGE, // coverage map for fill depth pass when YCoCG is used
TD_DEPTH, // depth buffer copy for motion blur
+ // RB begin
+ TD_SHADOW_ARRAY, // 2D depth buffer array for shadow mapping
+ // RB end
} textureUsage_t;
typedef enum
{
CF_2D, // not a cube map
CF_NATIVE, // _px, _nx, _py, etc, directly sent to GL
- CF_CAMERA // _forward, _back, etc, rotated and flipped as needed before sending to GL
+ CF_CAMERA, // _forward, _back, etc, rotated and flipped as needed before sending to GL
+ CF_2D_ARRAY // not a cube map but not a single 2d texture either
} cubeFiles_t;
#include "ImageOpts.h"
@@ -71,6 +76,8 @@ typedef enum
class idImage
{
+ friend class Framebuffer;
+
public:
idImage( const char* name );
@@ -96,6 +103,10 @@ public:
void GenerateCubeImage( const byte* pic[6], int size,
textureFilter_t filter, textureUsage_t usage );
+ // RB begin
+ void GenerateShadowArray( int width, int height, textureFilter_t filter, textureRepeat_t repeat, textureUsage_t usage );
+ // RB end
+
void CopyFramebuffer( int x, int y, int width, int height );
void CopyDepthbuffer( int x, int y, int width, int height );
@@ -323,6 +334,13 @@ public:
idImage* noFalloffImage; // all 255, but zero clamped
idImage* fogImage; // increasing alpha is denser fog
idImage* fogEnterImage; // adjust fogImage alpha based on terminator plane
+ // RB begin
+ idImage* shadowImage;
+ idImage* jitterImage1; // shadow jitter
+ idImage* jitterImage4;
+ idImage* jitterImage16;
+ idImage* randomImage256;
+ // RB end
idImage* scratchImage;
idImage* scratchImage2;
idImage* accumImage;
diff --git a/neo/renderer/ImageOpts.h b/neo/renderer/ImageOpts.h
index 71bfdc7b..ed3fb270 100644
--- a/neo/renderer/ImageOpts.h
+++ b/neo/renderer/ImageOpts.h
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -33,7 +34,10 @@ enum textureType_t
{
TT_DISABLED,
TT_2D,
- TT_CUBIC
+ TT_CUBIC,
+ // RB begin
+ TT_2D_ARRAY
+ // RB end
};
/*
@@ -89,6 +93,11 @@ enum textureFormat_t
FMT_X16, // 16 bpp
FMT_Y16_X16, // 32 bpp
FMT_RGB565, // 16 bpp
+
+ // RB: don't change above for legacy .bimage compatibility
+ FMT_ETC1_RGB8_OES, // 4 bpp
+ FMT_SHADOW_ARRAY, // 32 bpp * 6
+ // RB end
};
int BitsForFormat( textureFormat_t format );
@@ -103,7 +112,11 @@ enum textureColor_t
CFM_DEFAULT, // RGBA
CFM_NORMAL_DXT5, // XY format and use the fast DXT5 compressor
CFM_YCOCG_DXT5, // convert RGBA to CoCg_Y format
- CFM_GREEN_ALPHA // Copy the alpha channel to green
+ CFM_GREEN_ALPHA, // Copy the alpha channel to green
+
+ // RB: don't change above for legacy .bimage compatibility
+ CFM_YCOCG_RGBA8,
+ // RB end
};
/*
diff --git a/neo/renderer/Image_intrinsic.cpp b/neo/renderer/Image_intrinsic.cpp
index 7fc78470..ca712f66 100644
--- a/neo/renderer/Image_intrinsic.cpp
+++ b/neo/renderer/Image_intrinsic.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -449,6 +450,99 @@ void R_QuadraticImage( idImage* image )
image->GenerateImage( ( byte* )data, QUADRATIC_WIDTH, QUADRATIC_HEIGHT, TF_DEFAULT, TR_CLAMP, TD_LOOKUP_TABLE_RGB1 );
}
+// RB begin
+static void R_CreateShadowMapImage( idImage* image )
+{
+ int size = r_shadowMapImageSize.GetInteger();
+ image->GenerateShadowArray( size, size, TF_LINEAR, TR_CLAMP_TO_ZERO_ALPHA, TD_SHADOW_ARRAY );
+}
+
+const static int JITTER_SIZE = 128;
+static void R_CreateJitterImage16( idImage* image )
+{
+ static byte data[JITTER_SIZE][JITTER_SIZE * 16][4];
+
+ for( int i = 0 ; i < JITTER_SIZE ; i++ )
+ {
+ for( int s = 0 ; s < 16 ; s++ )
+ {
+ int sOfs = 64 * ( s & 3 );
+ int tOfs = 64 * ( ( s >> 2 ) & 3 );
+
+ for( int j = 0 ; j < JITTER_SIZE ; j++ )
+ {
+ data[i][s * JITTER_SIZE + j][0] = ( rand() & 63 ) | sOfs;
+ data[i][s * JITTER_SIZE + j][1] = ( rand() & 63 ) | tOfs;
+ data[i][s * JITTER_SIZE + j][2] = rand();
+ data[i][s * JITTER_SIZE + j][3] = 0;
+ }
+ }
+ }
+
+ image->GenerateImage( ( byte* )data, JITTER_SIZE * 16, JITTER_SIZE, TF_NEAREST, TR_REPEAT, TD_LOOKUP_TABLE_RGBA );
+}
+
+static void R_CreateJitterImage4( idImage* image )
+{
+ byte data[JITTER_SIZE][JITTER_SIZE * 4][4];
+
+ for( int i = 0 ; i < JITTER_SIZE ; i++ )
+ {
+ for( int s = 0 ; s < 4 ; s++ )
+ {
+ int sOfs = 128 * ( s & 1 );
+ int tOfs = 128 * ( ( s >> 1 ) & 1 );
+
+ for( int j = 0 ; j < JITTER_SIZE ; j++ )
+ {
+ data[i][s * JITTER_SIZE + j][0] = ( rand() & 127 ) | sOfs;
+ data[i][s * JITTER_SIZE + j][1] = ( rand() & 127 ) | tOfs;
+ data[i][s * JITTER_SIZE + j][2] = rand();
+ data[i][s * JITTER_SIZE + j][3] = 0;
+ }
+ }
+ }
+
+ image->GenerateImage( ( byte* )data, JITTER_SIZE * 4, JITTER_SIZE, TF_NEAREST, TR_REPEAT, TD_LOOKUP_TABLE_RGBA );
+}
+
+static void R_CreateJitterImage1( idImage* image )
+{
+ byte data[JITTER_SIZE][JITTER_SIZE][4];
+
+ for( int i = 0 ; i < JITTER_SIZE ; i++ )
+ {
+ for( int j = 0 ; j < JITTER_SIZE ; j++ )
+ {
+ data[i][j][0] = rand();
+ data[i][j][1] = rand();
+ data[i][j][2] = rand();
+ data[i][j][3] = 0;
+ }
+ }
+
+ image->GenerateImage( ( byte* )data, JITTER_SIZE, JITTER_SIZE, TF_NEAREST, TR_REPEAT, TD_LOOKUP_TABLE_RGBA );
+}
+
+static void R_CreateRandom256Image( idImage* image )
+{
+ byte data[256][256][4];
+
+ for( int i = 0 ; i < 256 ; i++ )
+ {
+ for( int j = 0 ; j < 256 ; j++ )
+ {
+ data[i][j][0] = rand();
+ data[i][j][1] = rand();
+ data[i][j][2] = rand();
+ data[i][j][3] = rand();
+ }
+ }
+
+ image->GenerateImage( ( byte* )data, 256, 256, TF_NEAREST, TR_REPEAT, TD_LOOKUP_TABLE_RGBA );
+}
+// RB end
+
/*
================
idImageManager::CreateIntrinsicImages
@@ -467,6 +561,16 @@ void idImageManager::CreateIntrinsicImages()
noFalloffImage = ImageFromFunction( "_noFalloff", R_CreateNoFalloffImage );
ImageFromFunction( "_quadratic", R_QuadraticImage );
+ // RB begin
+ shadowImage = ImageFromFunction( va( "_shadowMap%i_0", r_shadowMapImageSize.GetInteger() ), R_CreateShadowMapImage );
+
+ jitterImage1 = globalImages->ImageFromFunction( "_jitter1", R_CreateJitterImage1 );
+ jitterImage4 = globalImages->ImageFromFunction( "_jitter4", R_CreateJitterImage4 );
+ jitterImage16 = globalImages->ImageFromFunction( "_jitter16", R_CreateJitterImage16 );
+
+ randomImage256 = globalImages->ImageFromFunction( "_random256", R_CreateRandom256Image );
+ // RB end
+
// scratchImage is used for screen wipes/doublevision etc..
scratchImage = ImageFromFunction( "_scratch", R_RGBA8Image );
scratchImage2 = ImageFromFunction( "_scratch2", R_RGBA8Image );
diff --git a/neo/renderer/Image_load.cpp b/neo/renderer/Image_load.cpp
index 2e0ed360..5e878bc9 100644
--- a/neo/renderer/Image_load.cpp
+++ b/neo/renderer/Image_load.cpp
@@ -60,6 +60,8 @@ int BitsForFormat( textureFormat_t format )
return 4;
case FMT_DXT5:
return 8;
+ case FMT_SHADOW_ARRAY:
+ return ( 32 * 6 );
case FMT_DEPTH:
return 32;
case FMT_X16:
@@ -93,6 +95,11 @@ ID_INLINE void idImage::DeriveOpts()
case TD_DEPTH:
opts.format = FMT_DEPTH;
break;
+
+ case TD_SHADOW_ARRAY:
+ opts.format = FMT_SHADOW_ARRAY;
+ break;
+
case TD_DIFFUSE:
// TD_DIFFUSE gets only set to when its a diffuse texture for an interaction
opts.gammaMips = true;
@@ -266,6 +273,47 @@ void idImage::GenerateCubeImage( const byte* pic[6], int size, textureFilter_t f
}
}
+// RB begin
+void idImage::GenerateShadowArray( int width, int height, textureFilter_t filterParm, textureRepeat_t repeatParm, textureUsage_t usageParm )
+{
+ PurgeImage();
+
+ filter = filterParm;
+ repeat = repeatParm;
+ usage = usageParm;
+ cubeFiles = CF_2D_ARRAY;
+
+ opts.textureType = TT_2D_ARRAY;
+ opts.width = width;
+ opts.height = height;
+ opts.numLevels = 0;
+ DeriveOpts();
+
+ // if we don't have a rendering context, just return after we
+ // have filled in the parms. We must have the values set, or
+ // an image match from a shader before the render starts would miss
+ // the generated texture
+ if( !R_IsInitialized() )
+ {
+ return;
+ }
+
+ //idBinaryImage im( GetName() );
+ //im.Load2DFromMemory( width, height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
+
+ AllocImage();
+
+ /*
+ for( int i = 0; i < im.NumImages(); i++ )
+ {
+ const bimageImage_t& img = im.GetImageHeader( i );
+ const byte* data = im.GetImageData( i );
+ SubImageUpload( img.level, 0, 0, img.destZ, img.width, img.height, data );
+ }
+ */
+}
+// RB end
+
/*
===============
GetGeneratedName
@@ -323,7 +371,13 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
}
else
{
- if( cubeFiles != CF_2D )
+ // RB begin
+ if( cubeFiles == CF_2D_ARRAY )
+ {
+ opts.textureType = TT_2D_ARRAY;
+ }
+ // RB end
+ else if( cubeFiles != CF_2D )
{
opts.textureType = TT_CUBIC;
repeat = TR_CLAMP;
@@ -521,11 +575,11 @@ void idImage::Bind()
// RB begin
if( glConfig.directStateAccess )
{
- glBindMultiTextureEXT( GL_TEXTURE0_ARB + texUnit, GL_TEXTURE_2D, texnum );
+ glBindMultiTextureEXT( GL_TEXTURE0 + texUnit, GL_TEXTURE_2D, texnum );
}
else
{
- glActiveTextureARB( GL_TEXTURE0_ARB + texUnit );
+ glActiveTexture( GL_TEXTURE0 + texUnit );
glBindTexture( GL_TEXTURE_2D, texnum );
}
// RB end
@@ -538,14 +592,37 @@ void idImage::Bind()
tmu->currentCubeMap = texnum;
// RB begin
+#if !defined(USE_GLES2) && !defined(USE_GLES3)
if( glConfig.directStateAccess )
{
- glBindMultiTextureEXT( GL_TEXTURE0_ARB + texUnit, GL_TEXTURE_CUBE_MAP_EXT, texnum );
+ glBindMultiTextureEXT( GL_TEXTURE0 + texUnit, GL_TEXTURE_CUBE_MAP, texnum );
}
else
+#endif
{
- glActiveTextureARB( GL_TEXTURE0_ARB + texUnit );
- glBindTexture( GL_TEXTURE_CUBE_MAP_EXT, texnum );
+ glActiveTexture( GL_TEXTURE0 + texUnit );
+ glBindTexture( GL_TEXTURE_CUBE_MAP, texnum );
+ }
+ // RB end
+ }
+ }
+ else if( opts.textureType == TT_2D_ARRAY )
+ {
+ if( tmu->current2DArray != texnum )
+ {
+ tmu->current2DArray = texnum;
+
+ // RB begin
+#if !defined(USE_GLES2) && !defined(USE_GLES3)
+ if( glConfig.directStateAccess )
+ {
+ glBindMultiTextureEXT( GL_TEXTURE0 + texUnit, GL_TEXTURE_2D_ARRAY, texnum );
+ }
+ else
+#endif
+ {
+ glActiveTexture( GL_TEXTURE0 + texUnit );
+ glBindTexture( GL_TEXTURE_2D_ARRAY, texnum );
}
// RB end
}
@@ -574,9 +651,7 @@ CopyFramebuffer
*/
void idImage::CopyFramebuffer( int x, int y, int imageWidth, int imageHeight )
{
-
-
- glBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP_EXT : GL_TEXTURE_2D, texnum );
+ glBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, texnum );
glReadBuffer( GL_BACK );
@@ -601,7 +676,7 @@ CopyDepthbuffer
*/
void idImage::CopyDepthbuffer( int x, int y, int imageWidth, int imageHeight )
{
- glBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP_EXT : GL_TEXTURE_2D, texnum );
+ glBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, texnum );
opts.width = imageWidth;
opts.height = imageHeight;
@@ -836,6 +911,6 @@ void idImage::SetSamplerState( textureFilter_t tf, textureRepeat_t tr )
}
filter = tf;
repeat = tr;
- glBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP_EXT : GL_TEXTURE_2D, texnum );
+ glBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, texnum );
SetTexParameters();
}
diff --git a/neo/renderer/Interaction.cpp b/neo/renderer/Interaction.cpp
index 7a8f70b0..eff50c9f 100644
--- a/neo/renderer/Interaction.cpp
+++ b/neo/renderer/Interaction.cpp
@@ -663,12 +663,17 @@ void idInteraction::UnlinkAndFree()
{
// clear the table pointer
idRenderWorldLocal* renderWorld = this->lightDef->world;
- int index = this->lightDef->index * renderWorld->interactionTableWidth + this->entityDef->index;
- if( renderWorld->interactionTable[index] != this && renderWorld->interactionTable[index] != INTERACTION_EMPTY )
+ // RB: added check for NULL
+ if( renderWorld->interactionTable != NULL )
{
- common->Error( "idInteraction::UnlinkAndFree: interactionTable wasn't set" );
+ int index = this->lightDef->index * renderWorld->interactionTableWidth + this->entityDef->index;
+ if( renderWorld->interactionTable[index] != this && renderWorld->interactionTable[index] != INTERACTION_EMPTY )
+ {
+ common->Error( "idInteraction::UnlinkAndFree: interactionTable wasn't set" );
+ }
+ renderWorld->interactionTable[index] = NULL;
}
- renderWorld->interactionTable[index] = NULL;
+ // RB end
Unlink();
diff --git a/neo/renderer/OpenGL/gl_GraphicsAPIWrapper.cpp b/neo/renderer/OpenGL/gl_GraphicsAPIWrapper.cpp
index 85297b75..83fed3d0 100644
--- a/neo/renderer/OpenGL/gl_GraphicsAPIWrapper.cpp
+++ b/neo/renderer/OpenGL/gl_GraphicsAPIWrapper.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -198,6 +199,7 @@ void GL_GetDepthPassRect( idScreenRect& rect )
GL_Color
====================
*/
+/*
void GL_Color( float* color )
{
if( color == NULL )
@@ -206,6 +208,19 @@ void GL_Color( float* color )
}
GL_Color( color[0], color[1], color[2], color[3] );
}
+*/
+
+// RB begin
+void GL_Color( const idVec3& color )
+{
+ GL_Color( color[0], color[1], color[2], 1.0f );
+}
+
+void GL_Color( const idVec4& color )
+{
+ GL_Color( color[0], color[1], color[2], color[3] );
+}
+// RB end
/*
====================
@@ -275,6 +290,10 @@ void GL_SetDefaultState()
memset( &backEnd.glState, 0, sizeof( backEnd.glState ) );
GL_State( 0, true );
+ // RB begin
+ Framebuffer::BindNull();
+ // RB end
+
// These are changed by GL_Cull
glCullFace( GL_FRONT_AND_BACK );
glEnable( GL_CULL_FACE );
diff --git a/neo/renderer/OpenGL/gl_Image.cpp b/neo/renderer/OpenGL/gl_Image.cpp
index d7e58366..82b62859 100644
--- a/neo/renderer/OpenGL/gl_Image.cpp
+++ b/neo/renderer/OpenGL/gl_Image.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -86,8 +87,8 @@ void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int
}
else if( opts.textureType == TT_CUBIC )
{
- target = GL_TEXTURE_CUBE_MAP_EXT;
- uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT + z;
+ target = GL_TEXTURE_CUBE_MAP;
+ uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z;
}
else
{
@@ -168,8 +169,13 @@ void idImage::SetTexParameters()
target = GL_TEXTURE_2D;
break;
case TT_CUBIC:
- target = GL_TEXTURE_CUBE_MAP_EXT;
+ target = GL_TEXTURE_CUBE_MAP;
break;
+ // RB begin
+ case TT_2D_ARRAY:
+ target = GL_TEXTURE_2D_ARRAY;
+ break;
+ // RB end
default:
idLib::FatalError( "%s: bad texture type %d", GetName(), opts.textureType );
return;
@@ -319,6 +325,15 @@ void idImage::SetTexParameters()
default:
common->FatalError( "%s: bad texture repeat %d", GetName(), repeat );
}
+
+ // RB: added shadow compare parameters for shadow map textures
+ if( opts.format == FMT_SHADOW_ARRAY )
+ {
+ //glTexParameteri( target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glTexParameteri( target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );
+ glTexParameteri( target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
+ glTexParameteri( target, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY );
+ }
}
/*
@@ -408,6 +423,13 @@ void idImage::AllocImage()
dataFormat = GL_DEPTH_COMPONENT;
dataType = GL_UNSIGNED_BYTE;
break;
+
+ case FMT_SHADOW_ARRAY:
+ internalFormat = GL_DEPTH_COMPONENT;
+ dataFormat = GL_DEPTH_COMPONENT;
+ dataType = GL_UNSIGNED_BYTE;
+ break;
+
case FMT_X16:
internalFormat = GL_INTENSITY16;
dataFormat = GL_LUMINANCE;
@@ -449,10 +471,18 @@ void idImage::AllocImage()
}
else if( opts.textureType == TT_CUBIC )
{
- target = GL_TEXTURE_CUBE_MAP_EXT;
- uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT;
+ target = GL_TEXTURE_CUBE_MAP;
+ uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
numSides = 6;
}
+ // RB begin
+ else if( opts.textureType == TT_2D_ARRAY )
+ {
+ target = GL_TEXTURE_2D_ARRAY;
+ uploadTarget = GL_TEXTURE_2D_ARRAY;
+ numSides = 6;
+ }
+ // RB end
else
{
assert( !"opts.textureType" );
@@ -462,64 +492,71 @@ void idImage::AllocImage()
glBindTexture( target, texnum );
- for( int side = 0; side < numSides; side++ )
+ if( opts.textureType == TT_2D_ARRAY )
{
- int w = opts.width;
- int h = opts.height;
- if( opts.textureType == TT_CUBIC )
- {
- h = w;
- }
- for( int level = 0; level < opts.numLevels; level++ )
- {
-
- // clear out any previous error
- GL_CheckErrors();
-
- if( IsCompressed() )
- {
- int compressedSize = ( ( ( w + 3 ) / 4 ) * ( ( h + 3 ) / 4 ) * int64( 16 ) * BitsForFormat( opts.format ) ) / 8;
-
- // Even though the OpenGL specification allows the 'data' pointer to be NULL, for some
- // drivers we actually need to upload data to get it to allocate the texture.
- // However, on 32-bit systems we may fail to allocate a large block of memory for large
- // textures. We handle this case by using HeapAlloc directly and allowing the allocation
- // to fail in which case we simply pass down NULL to glCompressedTexImage2D and hope for the best.
- // As of 2011-10-6 using NVIDIA hardware and drivers we have to allocate the memory with HeapAlloc
- // with the exact size otherwise large image allocation (for instance for physical page textures)
- // may fail on Vista 32-bit.
-
- // RB begin
-#if defined(_WIN32)
- void* data = HeapAlloc( GetProcessHeap(), 0, compressedSize );
- glCompressedTexImage2DARB( uploadTarget + side, level, internalFormat, w, h, 0, compressedSize, data );
- if( data != NULL )
- {
- HeapFree( GetProcessHeap(), 0, data );
- }
-#else
- byte* data = ( byte* )Mem_Alloc( compressedSize, TAG_TEMP );
- glCompressedTexImage2DARB( uploadTarget + side, level, internalFormat, w, h, 0, compressedSize, data );
- if( data != NULL )
- {
- Mem_Free( data );
- }
-#endif
- // RB end
- }
- else
- {
- glTexImage2D( uploadTarget + side, level, internalFormat, w, h, 0, dataFormat, dataType, NULL );
- }
-
- GL_CheckErrors();
-
- w = Max( 1, w >> 1 );
- h = Max( 1, h >> 1 );
- }
+ glTexImage3D( uploadTarget, 0, internalFormat, opts.width, opts.height, numSides, 0, dataFormat, GL_UNSIGNED_BYTE, NULL );
+ }
+ else
+ {
+ for( int side = 0; side < numSides; side++ )
+ {
+ int w = opts.width;
+ int h = opts.height;
+ if( opts.textureType == TT_CUBIC )
+ {
+ h = w;
+ }
+ for( int level = 0; level < opts.numLevels; level++ )
+ {
+
+ // clear out any previous error
+ GL_CheckErrors();
+
+ if( IsCompressed() )
+ {
+ int compressedSize = ( ( ( w + 3 ) / 4 ) * ( ( h + 3 ) / 4 ) * int64( 16 ) * BitsForFormat( opts.format ) ) / 8;
+
+ // Even though the OpenGL specification allows the 'data' pointer to be NULL, for some
+ // drivers we actually need to upload data to get it to allocate the texture.
+ // However, on 32-bit systems we may fail to allocate a large block of memory for large
+ // textures. We handle this case by using HeapAlloc directly and allowing the allocation
+ // to fail in which case we simply pass down NULL to glCompressedTexImage2D and hope for the best.
+ // As of 2011-10-6 using NVIDIA hardware and drivers we have to allocate the memory with HeapAlloc
+ // with the exact size otherwise large image allocation (for instance for physical page textures)
+ // may fail on Vista 32-bit.
+
+ // RB begin
+#if defined(_WIN32)
+ void* data = HeapAlloc( GetProcessHeap(), 0, compressedSize );
+ glCompressedTexImage2D( uploadTarget + side, level, internalFormat, w, h, 0, compressedSize, data );
+ if( data != NULL )
+ {
+ HeapFree( GetProcessHeap(), 0, data );
+ }
+#else
+ byte* data = ( byte* )Mem_Alloc( compressedSize, TAG_TEMP );
+ glCompressedTexImage2D( uploadTarget + side, level, internalFormat, w, h, 0, compressedSize, data );
+ if( data != NULL )
+ {
+ Mem_Free( data );
+ }
+#endif
+ // RB end
+ }
+ else
+ {
+ glTexImage2D( uploadTarget + side, level, internalFormat, w, h, 0, dataFormat, dataType, NULL );
+ }
+
+ GL_CheckErrors();
+
+ w = Max( 1, w >> 1 );
+ h = Max( 1, h >> 1 );
+ }
+ }
+
+ glTexParameteri( target, GL_TEXTURE_MAX_LEVEL, opts.numLevels - 1 );
}
-
- glTexParameteri( target, GL_TEXTURE_MAX_LEVEL, opts.numLevels - 1 );
// see if we messed anything up
GL_CheckErrors();
@@ -545,6 +582,7 @@ void idImage::PurgeImage()
for( int i = 0 ; i < MAX_MULTITEXTURE_UNITS ; i++ )
{
backEnd.glState.tmu[i].current2DMap = TEXTURE_NOT_LOADED;
+ backEnd.glState.tmu[i].current2DArray = TEXTURE_NOT_LOADED;
backEnd.glState.tmu[i].currentCubeMap = TEXTURE_NOT_LOADED;
}
}
diff --git a/neo/renderer/RenderLog.cpp b/neo/renderer/RenderLog.cpp
index 3ee78527..0db9c033 100644
--- a/neo/renderer/RenderLog.cpp
+++ b/neo/renderer/RenderLog.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -234,8 +235,8 @@ idRenderLog::idRenderLog()
activeLevel = 0;
indentString[0] = '\0';
indentLevel = 0;
- logFile = NULL;
-
+// logFile = NULL;
+
frameStartTime = 0;
closeBlockTime = 0;
logLevel = 0;
@@ -265,8 +266,8 @@ void idRenderLog::StartFrame()
char qpath[128];
sprintf( qpath, "renderlogPC_%04i.txt", r_logFile.GetInteger() );
- idStr finalPath = fileSystem->RelativePathToOSPath( qpath );
- sprintf( ospath, "%s", finalPath.c_str() );
+ //idStr finalPath = fileSystem->RelativePathToOSPath( qpath );
+ sprintf( ospath, "%s", qpath );
/*
for ( int i = 0; i < 9999 ; i++ ) {
char qpath[128];
@@ -281,6 +282,7 @@ void idRenderLog::StartFrame()
common->SetRefreshOnPrint( false ); // problems are caused if this print causes a refresh...
+ /*
if( logFile != NULL )
{
fileSystem->CloseFile( logFile );
@@ -301,6 +303,7 @@ void idRenderLog::StartFrame()
const char* str = asctime( newtime );
logFile->Printf( "// %s", str );
logFile->Printf( "// %s\n\n", com_version.GetString() );
+ */
frameStartTime = Sys_Microseconds();
closeBlockTime = frameStartTime;
@@ -316,15 +319,16 @@ void idRenderLog::EndFrame()
{
PC_EndFrame();
- if( logFile != NULL )
+ //if( logFile != NULL )
+ if( r_logFile.GetInteger() != 0 )
{
if( r_logFile.GetInteger() == 1 )
{
Close();
}
// log is open, so decrement r_logFile and stop if it is zero
- r_logFile.SetInteger( r_logFile.GetInteger() - 1 );
- idLib::Printf( "Frame logged.\n" );
+ //r_logFile.SetInteger( r_logFile.GetInteger() - 1 );
+ //idLib::Printf( "Frame logged.\n" );
return;
}
}
@@ -336,12 +340,13 @@ idRenderLog::Close
*/
void idRenderLog::Close()
{
- if( logFile != NULL )
+ //if( logFile != NULL )
+ if( r_logFile.GetInteger() != 0 )
{
CloseBlock();
- idLib::Printf( "Closing logfile\n" );
- fileSystem->CloseFile( logFile );
- logFile = NULL;
+ //idLib::Printf( "Closing logfile\n" );
+ //fileSystem->CloseFile( logFile );
+ //logFile = NULL;
activeLevel = 0;
}
}
@@ -374,7 +379,8 @@ void idRenderLog::OpenBlock( const char* label )
// Allow the PIX functionality even when logFile is not running.
PC_BeginNamedEvent( label );
- if( logFile != NULL )
+ //if( logFile != NULL )
+ if( r_logFile.GetInteger() != 0 )
{
LogOpenBlock( RENDER_LOG_INDENT_MAIN_BLOCK, label, NULL );
}
@@ -389,7 +395,8 @@ void idRenderLog::CloseBlock()
{
PC_EndNamedEvent();
- if( logFile != NULL )
+ //if( logFile != NULL )
+ if( r_logFile.GetInteger() != 0 )
{
LogCloseBlock( RENDER_LOG_INDENT_MAIN_BLOCK );
}
@@ -402,22 +409,41 @@ idRenderLog::Printf
*/
void idRenderLog::Printf( const char* fmt, ... )
{
+#if !defined(USE_GLES2) && !defined(USE_GLES3)
if( activeLevel <= LOG_LEVEL_BLOCKS_ONLY )
{
return;
}
- if( logFile == NULL )
+ //if( logFile == NULL )
+ if( r_logFile.GetInteger() == 0 || !glConfig.gremedyStringMarkerAvailable )
{
return;
}
- va_list marker;
- logFile->Printf( "%s", indentString );
+ va_list marker;
+ char msg[4096];
+
+ idStr out = indentString;
+
va_start( marker, fmt );
- logFile->VPrintf( fmt, marker );
+ idStr::vsnPrintf( msg, sizeof( msg ), fmt, marker );
va_end( marker );
+
+ msg[sizeof( msg ) - 1] = '\0';
+
+ out.Append( msg );
+
+ glStringMarkerGREMEDY( out.Length(), out.c_str() );
+
+ //logFile->Printf( "%s", indentString );
+ //va_start( marker, fmt );
+ //logFile->VPrintf( fmt, marker );
+ //va_end( marker );
+
+
// logFile->Flush(); this makes it take waaaay too long
+#endif
}
/*
@@ -427,18 +453,43 @@ idRenderLog::LogOpenBlock
*/
void idRenderLog::LogOpenBlock( renderLogIndentLabel_t label, const char* fmt, va_list args )
{
-
uint64 now = Sys_Microseconds();
- if( logFile != NULL )
+ //if( logFile != NULL )
+ if( r_logFile.GetInteger() != 0 )
{
- if( now - closeBlockTime >= 1000 )
+ //if( now - closeBlockTime >= 1000 )
+ //{
+ //logFile->Printf( "%s%1.1f msec gap from last closeblock\n", indentString, ( now - closeBlockTime ) * ( 1.0f / 1000.0f ) );
+ //}
+
+#if !defined(USE_GLES2) && !defined(USE_GLES3)
+ if( glConfig.gremedyStringMarkerAvailable )
{
- logFile->Printf( "%s%1.1f msec gap from last closeblock\n", indentString, ( now - closeBlockTime ) * ( 1.0f / 1000.0f ) );
+ //Printf( fmt, args );
+ //Printf( " {\n" );
+
+ //logFile->Printf( "%s", indentString );
+ //logFile->VPrintf( fmt, args );
+ //logFile->Printf( " {\n" );
+
+ va_list marker;
+ char msg[4096];
+
+ idStr out = indentString;
+
+ va_start( marker, fmt );
+ idStr::vsnPrintf( msg, sizeof( msg ), fmt, marker );
+ va_end( marker );
+
+ msg[sizeof( msg ) - 1] = '\0';
+
+ out.Append( msg );
+ out += " {";
+
+ glStringMarkerGREMEDY( out.Length(), out.c_str() );
}
- logFile->Printf( "%s", indentString );
- logFile->VPrintf( fmt, args );
- logFile->Printf( " {\n" );
+#endif
}
Indent( label );
@@ -466,9 +517,9 @@ void idRenderLog::LogCloseBlock( renderLogIndentLabel_t label )
Outdent( label );
- if( logFile != NULL )
- {
- }
+ //if( logFile != NULL )
+ //{
+ //}
}
#else // !STUB_RENDER_LOG
diff --git a/neo/renderer/RenderLog.h b/neo/renderer/RenderLog.h
index 5f493d4e..03461e07 100644
--- a/neo/renderer/RenderLog.h
+++ b/neo/renderer/RenderLog.h
@@ -111,8 +111,8 @@ public:
int indentLevel;
const char* lastLabel;
renderLogMainBlock_t lastMainBlock;
- idFile* logFile;
-
+// idFile* logFile;
+
struct logStats_t
{
uint64 startTiming;
@@ -136,7 +136,8 @@ idRenderLog::Indent
*/
ID_INLINE void idRenderLog::Indent( renderLogIndentLabel_t label )
{
- if( logFile != NULL )
+ //if( logFile != NULL )
+ if( r_logFile.GetInteger() != 0 )
{
indentLabel[indentLevel] = label;
indentLevel++;
@@ -155,7 +156,8 @@ idRenderLog::Outdent
*/
ID_INLINE void idRenderLog::Outdent( renderLogIndentLabel_t label )
{
- if( logFile != NULL && indentLevel > 0 )
+ //if( logFile != NULL && indentLevel > 0 )
+ if( r_logFile.GetInteger() != 0 && indentLevel > 0 )
{
indentLevel--;
assert( indentLabel[indentLevel] == label ); // indent and outdent out of sync ?
diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp
index ddfdfb0a..db195bd4 100644
--- a/neo/renderer/RenderProgs.cpp
+++ b/neo/renderer/RenderProgs.cpp
@@ -83,47 +83,67 @@ void idRenderProgManager::Init()
// RB: added checks for GPU skinning
struct builtinShaders_t
{
- int index;
+ int index;
const char* name;
- bool requireGPUSkinningSupport;
+ const char* nameOutSuffix;
+ uint32 shaderFeatures;
+ bool requireGPUSkinningSupport;
} builtins[] =
{
- { BUILTIN_GUI, "gui.vfp", false },
- { BUILTIN_COLOR, "color.vfp", false },
-// { BUILTIN_SIMPLESHADE, "simpleshade.vfp", false },
- { BUILTIN_TEXTURED, "texture.vfp", false },
- { BUILTIN_TEXTURE_VERTEXCOLOR, "texture_color.vfp", false },
- { BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED, "texture_color_skinned.vfp", true },
- { BUILTIN_TEXTURE_TEXGEN_VERTEXCOLOR, "texture_color_texgen.vfp", false },
- { BUILTIN_INTERACTION, "interaction.vfp", false },
- { BUILTIN_INTERACTION_SKINNED, "interaction_skinned.vfp", true },
- { BUILTIN_INTERACTION_AMBIENT, "interactionAmbient.vfp", false },
- { BUILTIN_INTERACTION_AMBIENT_SKINNED, "interactionAmbient_skinned.vfp", true },
- { BUILTIN_ENVIRONMENT, "environment.vfp", false },
- { BUILTIN_ENVIRONMENT_SKINNED, "environment_skinned.vfp", true },
- { BUILTIN_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp", false },
- { BUILTIN_BUMPY_ENVIRONMENT_SKINNED, "bumpyEnvironment_skinned.vfp", true },
+ { BUILTIN_GUI, "gui.vfp", 0, false },
+ { BUILTIN_COLOR, "color.vfp", 0, false },
+ // RB begin
+ { BUILTIN_COLOR_SKINNED, "color", "_skinned", BIT( USE_GPU_SKINNING ), true },
+ { BUILTIN_VERTEX_COLOR, "vertex_color.vfp", "", 0, false },
+ // RB end
+// { BUILTIN_SIMPLESHADE, "simpleshade.vfp", 0, false },
+ { BUILTIN_TEXTURED, "texture.vfp", 0, false },
+ { BUILTIN_TEXTURE_VERTEXCOLOR, "texture_color.vfp", 0, false },
+ { BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED, "texture_color_skinned.vfp", 0, true },
+ { BUILTIN_TEXTURE_TEXGEN_VERTEXCOLOR, "texture_color_texgen.vfp", 0, false },
+ // RB begin
+ { BUILTIN_INTERACTION, "interaction.vfp", "", 0, false },
+ { BUILTIN_INTERACTION_SKINNED, "interaction", "_skinned", BIT( USE_GPU_SKINNING ), true },
+ { BUILTIN_INTERACTION_AMBIENT, "interactionAmbient.vfp", 0, false },
+ { BUILTIN_INTERACTION_AMBIENT_SKINNED, "interactionAmbient_skinned.vfp", 0, true },
+ { BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT, "interactionSM", "_spot", 0, false },
+ { BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT_SKINNED, "interactionSM", "_spot_skinned", BIT( USE_GPU_SKINNING ), true },
+ { BUILTIN_INTERACTION_SHADOW_MAPPING_POINT, "interactionSM", "_point", BIT( LIGHT_POINT ), false },
+ { BUILTIN_INTERACTION_SHADOW_MAPPING_POINT_SKINNED, "interactionSM", "_point_skinned", BIT( USE_GPU_SKINNING ) | BIT( LIGHT_POINT ), true },
+ { BUILTIN_INTERACTION_SHADOW_MAPPING_PARALLEL, "interactionSM", "_parallel", BIT( LIGHT_PARALLEL ), false },
+ { BUILTIN_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED, "interactionSM", "_parallel_skinned", BIT( USE_GPU_SKINNING ) | BIT( LIGHT_PARALLEL ), true },
+ // RB end
+ { BUILTIN_ENVIRONMENT, "environment.vfp", 0, false },
+ { BUILTIN_ENVIRONMENT_SKINNED, "environment_skinned.vfp", 0, true },
+ { BUILTIN_BUMPY_ENVIRONMENT, "bumpyenvironment.vfp", 0, false },
+ { BUILTIN_BUMPY_ENVIRONMENT_SKINNED, "bumpyenvironment_skinned.vfp", 0, true },
- { BUILTIN_DEPTH, "depth.vfp", false },
- { BUILTIN_DEPTH_SKINNED, "depth_skinned.vfp", true },
- { BUILTIN_SHADOW_DEBUG, "shadowDebug.vfp", false },
- { BUILTIN_SHADOW_DEBUG_SKINNED, "shadowDebug_skinned.vfp", true },
+ { BUILTIN_DEPTH, "depth.vfp", 0, false },
+ { BUILTIN_DEPTH_SKINNED, "depth_skinned.vfp", 0, true },
- { BUILTIN_BLENDLIGHT, "blendlight.vfp", false },
- { BUILTIN_FOG, "fog.vfp", false },
- { BUILTIN_FOG_SKINNED, "fog_skinned.vfp", true },
- { BUILTIN_SKYBOX, "skybox.vfp", false },
- { BUILTIN_WOBBLESKY, "wobblesky.vfp", false },
- { BUILTIN_POSTPROCESS, "postprocess.vfp", false },
- { BUILTIN_STEREO_DEGHOST, "stereoDeGhost.vfp", false },
- { BUILTIN_STEREO_WARP, "stereoWarp.vfp", false },
-// { BUILTIN_ZCULL_RECONSTRUCT, "zcullReconstruct.vfp", false },
- { BUILTIN_BINK, "bink.vfp", false },
- { BUILTIN_BINK_GUI, "bink_gui.vfp", false },
- { BUILTIN_STEREO_INTERLACE, "stereoInterlace.vfp", false },
-// { BUILTIN_MOTION_BLUR, "motionBlur.vfp", false },
- { BUILTIN_SHADOW, "shadow.vfp", false },
- { BUILTIN_SHADOW_SKINNED, "shadow_skinned.vfp", true },
+ { BUILTIN_SHADOW, "shadow.vfp", 0, false },
+ { BUILTIN_SHADOW_SKINNED, "shadow_skinned.vfp", 0, true },
+
+ { BUILTIN_SHADOW_DEBUG, "shadowDebug.vfp", 0, false },
+ { BUILTIN_SHADOW_DEBUG_SKINNED, "shadowDebug_skinned.vfp", 0, true },
+
+ { BUILTIN_BLENDLIGHT, "blendlight.vfp", 0, false },
+ { BUILTIN_FOG, "fog.vfp", 0, false },
+ { BUILTIN_FOG_SKINNED, "fog_skinned.vfp", 0, true },
+ { BUILTIN_SKYBOX, "skybox.vfp", 0, false },
+ { BUILTIN_WOBBLESKY, "wobblesky.vfp", 0, false },
+ { BUILTIN_POSTPROCESS, "postprocess.vfp", 0, false },
+ { BUILTIN_STEREO_DEGHOST, "stereoDeGhost.vfp", 0, false },
+ { BUILTIN_STEREO_WARP, "stereoWarp.vfp", 0, false },
+// { BUILTIN_ZCULL_RECONSTRUCT, "zcullReconstruct.vfp", 0, false },
+ { BUILTIN_BINK, "bink.vfp", 0, false },
+ { BUILTIN_BINK_GUI, "bink_gui.vfp", 0, false },
+ { BUILTIN_STEREO_INTERLACE, "stereoInterlace.vfp", 0, false },
+ { BUILTIN_MOTION_BLUR, "motionBlur.vfp", 0, false },
+
+ // RB begin
+ { BUILTIN_DEBUG_SHADOWMAP, "debug_shadowmap.vfp", "", 0, false },
+ // RB end
};
int numBuiltins = sizeof( builtins ) / sizeof( builtins[0] );
vertexShaders.SetNum( numBuiltins );
@@ -133,7 +153,15 @@ void idRenderProgManager::Init()
for( int i = 0; i < numBuiltins; i++ )
{
vertexShaders[i].name = builtins[i].name;
+ vertexShaders[i].nameOutSuffix = builtins[i].nameOutSuffix;
+ vertexShaders[i].shaderFeatures = builtins[i].shaderFeatures;
+ vertexShaders[i].builtin = true;
+
fragmentShaders[i].name = builtins[i].name;
+ fragmentShaders[i].nameOutSuffix = builtins[i].nameOutSuffix;
+ fragmentShaders[i].shaderFeatures = builtins[i].shaderFeatures;
+ fragmentShaders[i].builtin = true;
+
builtinShaders[builtins[i].index] = i;
if( builtins[i].requireGPUSkinningSupport && !glConfig.gpuSkinningAvailable )
@@ -197,6 +225,11 @@ void idRenderProgManager::Init()
vertexShaders[builtinShaders[BUILTIN_SHADOW_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_SHADOW_DEBUG_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_FOG_SKINNED]].usesJoints = true;
+ // RB begin
+ vertexShaders[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT_SKINNED]].usesJoints = true;
+ vertexShaders[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_POINT_SKINNED]].usesJoints = true;
+ vertexShaders[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED]].usesJoints = true;
+ // RB end
}
cmdSystem->AddCommand( "reloadShaders", R_ReloadShaders, CMD_FL_RENDERER, "reloads shaders" );
@@ -220,6 +253,12 @@ void idRenderProgManager::LoadAllShaders()
for( int i = 0; i < glslPrograms.Num(); ++i )
{
+ if( glslPrograms[i].vertexShaderIndex == -1 || glslPrograms[i].fragmentShaderIndex == -1 )
+ {
+ // RB: skip reloading because we didn't load it initially
+ continue;
+ }
+
LoadGLSLProgram( i, glslPrograms[i].vertexShaderIndex, glslPrograms[i].fragmentShaderIndex );
}
}
@@ -341,7 +380,9 @@ void idRenderProgManager::LoadVertexShader( int index )
{
return; // Already loaded
}
- vertexShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_VERTEX_SHADER, vertexShaders[index].name, vertexShaders[index].uniforms );
+
+ vertexShader_t& vs = vertexShaders[index];
+ vertexShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_VERTEX_SHADER, vs.name, vs.nameOutSuffix, vs.shaderFeatures, vs.builtin, vs.uniforms );
}
/*
@@ -355,7 +396,9 @@ void idRenderProgManager::LoadFragmentShader( int index )
{
return; // Already loaded
}
- fragmentShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_FRAGMENT_SHADER, fragmentShaders[index].name, fragmentShaders[index].uniforms );
+
+ fragmentShader_t& fs = fragmentShaders[index];
+ fragmentShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_FRAGMENT_SHADER, fs.name, fs.nameOutSuffix, fs.shaderFeatures, fs.builtin, fs.uniforms );
}
/*
diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h
index 1cf0c718..ccabd238 100644
--- a/neo/renderer/RenderProgs.h
+++ b/neo/renderer/RenderProgs.h
@@ -115,6 +115,45 @@ enum renderParm_t
RENDERPARM_ENABLE_SKINNING,
RENDERPARM_ALPHA_TEST,
+ // RB begin
+ RENDERPARM_AMBIENT_COLOR,
+
+ RENDERPARM_GLOBALLIGHTORIGIN,
+ RENDERPARM_JITTERTEXSCALE,
+ RENDERPARM_JITTERTEXOFFSET,
+ RENDERPARM_CASCADEDISTANCES,
+
+ RENDERPARM_SHADOW_MATRIX_0_X, // rpShadowMatrices[6 * 4]
+ RENDERPARM_SHADOW_MATRIX_0_Y,
+ RENDERPARM_SHADOW_MATRIX_0_Z,
+ RENDERPARM_SHADOW_MATRIX_0_W,
+
+ RENDERPARM_SHADOW_MATRIX_1_X,
+ RENDERPARM_SHADOW_MATRIX_1_Y,
+ RENDERPARM_SHADOW_MATRIX_1_Z,
+ RENDERPARM_SHADOW_MATRIX_1_W,
+
+ RENDERPARM_SHADOW_MATRIX_2_X,
+ RENDERPARM_SHADOW_MATRIX_2_Y,
+ RENDERPARM_SHADOW_MATRIX_2_Z,
+ RENDERPARM_SHADOW_MATRIX_2_W,
+
+ RENDERPARM_SHADOW_MATRIX_3_X,
+ RENDERPARM_SHADOW_MATRIX_3_Y,
+ RENDERPARM_SHADOW_MATRIX_3_Z,
+ RENDERPARM_SHADOW_MATRIX_3_W,
+
+ RENDERPARM_SHADOW_MATRIX_4_X,
+ RENDERPARM_SHADOW_MATRIX_4_Y,
+ RENDERPARM_SHADOW_MATRIX_4_Z,
+ RENDERPARM_SHADOW_MATRIX_4_W,
+
+ RENDERPARM_SHADOW_MATRIX_5_X,
+ RENDERPARM_SHADOW_MATRIX_5_Y,
+ RENDERPARM_SHADOW_MATRIX_5_Z,
+ RENDERPARM_SHADOW_MATRIX_5_W,
+ // RB end
+
RENDERPARM_TOTAL,
RENDERPARM_USER = 128,
};
@@ -161,6 +200,19 @@ public:
{
BindShader_Builtin( BUILTIN_COLOR );
}
+
+ // RB begin
+ void BindShader_ColorSkinned( )
+ {
+ BindShader_Builtin( BUILTIN_COLOR_SKINNED );
+ }
+
+ void BindShader_VertexColor( )
+ {
+ BindShader_Builtin( BUILTIN_VERTEX_COLOR );
+ }
+ // RB end
+
void BindShader_Texture( )
{
BindShader_Builtin( BUILTIN_TEXTURED );
@@ -199,6 +251,39 @@ public:
{
BindShader_Builtin( BUILTIN_INTERACTION_AMBIENT_SKINNED );
}
+
+ // RB begin
+ void BindShader_Interaction_ShadowMapping_Spot()
+ {
+ BindShader_Builtin( BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT );
+ }
+
+ void BindShader_Interaction_ShadowMapping_Spot_Skinned()
+ {
+ BindShader_Builtin( BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT_SKINNED );
+ }
+
+ void BindShader_Interaction_ShadowMapping_Point()
+ {
+ BindShader_Builtin( BUILTIN_INTERACTION_SHADOW_MAPPING_POINT );
+ }
+
+ void BindShader_Interaction_ShadowMapping_Point_Skinned()
+ {
+ BindShader_Builtin( BUILTIN_INTERACTION_SHADOW_MAPPING_POINT_SKINNED );
+ }
+
+ void BindShader_Interaction_ShadowMapping_Parallel()
+ {
+ BindShader_Builtin( BUILTIN_INTERACTION_SHADOW_MAPPING_PARALLEL );
+ }
+
+ void BindShader_Interaction_ShadowMapping_Parallel_Skinned()
+ {
+ BindShader_Builtin( BUILTIN_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED );
+ }
+ // RB end
+
void BindShader_SimpleShade()
{
BindShader_Builtin( BUILTIN_SIMPLESHADE );
@@ -235,15 +320,19 @@ public:
void BindShader_Shadow()
{
- // RB begin
- BindShader( -1, builtinShaders[BUILTIN_SHADOW], -1, true );
+ // RB: no FFP fragment rendering anymore
+ //BindShader( -1, builtinShaders[BUILTIN_SHADOW], -1, true );
+
+ BindShader_Builtin( BUILTIN_SHADOW );
// RB end
}
void BindShader_ShadowSkinned()
{
- // RB begin
- BindShader( -1, builtinShaders[BUILTIN_SHADOW_SKINNED], -1, true );
+ // RB: no FFP fragment rendering anymore
+ //BindShader( -1, builtinShaders[BUILTIN_SHADOW_SKINNED], -1, true );
+
+ BindShader_Builtin( BUILTIN_SHADOW_SKINNED );
// RB end
}
@@ -322,27 +411,33 @@ public:
BindShader_Builtin( BUILTIN_MOTION_BLUR );
}
+ void BindShader_DebugShadowMap()
+ {
+ BindShader_Builtin( BUILTIN_DEBUG_SHADOWMAP );
+ }
+ // RB end
+
// the joints buffer should only be bound for vertex programs that use joints
- bool ShaderUsesJoints() const
+ bool ShaderUsesJoints() const
{
return vertexShaders[currentVertexShader].usesJoints;
}
// the rpEnableSkinning render parm should only be set for vertex programs that use it
- bool ShaderHasOptionalSkinning() const
+ bool ShaderHasOptionalSkinning() const
{
return vertexShaders[currentVertexShader].optionalSkinning;
}
// unbind the currently bound render program
- void Unbind();
+ void Unbind();
// RB begin
- bool IsShaderBound() const;
+ bool IsShaderBound() const;
// RB end
// this should only be called via the reload shader console command
- void LoadAllShaders();
- void KillAllShaders();
+ void LoadAllShaders();
+ void KillAllShaders();
static const int MAX_GLSL_USER_PARMS = 8;
const char* GetGLSLParmName( int rp ) const;
@@ -363,6 +458,10 @@ protected:
{
BUILTIN_GUI,
BUILTIN_COLOR,
+ // RB begin
+ BUILTIN_COLOR_SKINNED,
+ BUILTIN_VERTEX_COLOR,
+ // RB end
BUILTIN_SIMPLESHADE,
BUILTIN_TEXTURED,
BUILTIN_TEXTURE_VERTEXCOLOR,
@@ -372,6 +471,14 @@ protected:
BUILTIN_INTERACTION_SKINNED,
BUILTIN_INTERACTION_AMBIENT,
BUILTIN_INTERACTION_AMBIENT_SKINNED,
+ // RB begin
+ BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT,
+ BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT_SKINNED,
+ BUILTIN_INTERACTION_SHADOW_MAPPING_POINT,
+ BUILTIN_INTERACTION_SHADOW_MAPPING_POINT_SKINNED,
+ BUILTIN_INTERACTION_SHADOW_MAPPING_PARALLEL,
+ BUILTIN_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED,
+ // RB end
BUILTIN_ENVIRONMENT,
BUILTIN_ENVIRONMENT_SKINNED,
BUILTIN_BUMPY_ENVIRONMENT,
@@ -398,6 +505,8 @@ protected:
BUILTIN_STEREO_INTERLACE,
BUILTIN_MOTION_BLUR,
+ BUILTIN_DEBUG_SHADOWMAP,
+
MAX_BUILTINS
};
int builtinShaders[MAX_BUILTINS];
@@ -406,26 +515,44 @@ protected:
BindShader( -1, builtinShaders[i], builtinShaders[i], true );
}
+ enum shaderFeature_t
+ {
+ USE_GPU_SKINNING,
+ LIGHT_POINT,
+ LIGHT_PARALLEL,
+
+ MAX_SHADER_MACRO_NAMES,
+ };
+
+ static const char* GLSLMacroNames[MAX_SHADER_MACRO_NAMES];
+ const char* GetGLSLMacroName( shaderFeature_t sf ) const;
+
bool CompileGLSL( GLenum target, const char* name );
- GLuint LoadGLSLShader( GLenum target, const char* name, idList& uniforms );
+ GLuint LoadGLSLShader( GLenum target, const char* name, const char* nameOutSuffix, uint32 shaderFeatures, bool builtin, idList& uniforms );
void LoadGLSLProgram( const int programIndex, const int vertexShaderIndex, const int fragmentShaderIndex );
static const GLuint INVALID_PROGID = 0xFFFFFFFF;
struct vertexShader_t
{
- vertexShader_t() : progId( INVALID_PROGID ), usesJoints( false ), optionalSkinning( false ) {}
+ vertexShader_t() : progId( INVALID_PROGID ), usesJoints( false ), optionalSkinning( false ), shaderFeatures( 0 ), builtin( false ) {}
idStr name;
+ idStr nameOutSuffix;
GLuint progId;
bool usesJoints;
bool optionalSkinning;
+ uint32 shaderFeatures; // RB: Cg compile macros
+ bool builtin; // RB: part of the core shaders built into the executable
idList uniforms;
};
struct fragmentShader_t
{
- fragmentShader_t() : progId( INVALID_PROGID ) {}
+ fragmentShader_t() : progId( INVALID_PROGID ), shaderFeatures( 0 ), builtin( false ) {}
idStr name;
+ idStr nameOutSuffix;
GLuint progId;
+ uint32 shaderFeatures;
+ bool builtin;
idList uniforms;
};
@@ -445,14 +572,14 @@ protected:
idList uniformLocations;
};
int currentRenderProgram;
- idList glslPrograms;
+ idList glslPrograms;
idStaticList < idVec4, RENDERPARM_USER + MAX_GLSL_USER_PARMS > glslUniforms;
int currentVertexShader;
int currentFragmentShader;
- idList vertexShaders;
- idList fragmentShaders;
+ idList vertexShaders;
+ idList fragmentShaders;
};
extern idRenderProgManager renderProgManager;
diff --git a/neo/renderer/RenderProgs_GLSL.cpp b/neo/renderer/RenderProgs_GLSL.cpp
index d8957443..1f95ca2e 100644
--- a/neo/renderer/RenderProgs_GLSL.cpp
+++ b/neo/renderer/RenderProgs_GLSL.cpp
@@ -235,15 +235,18 @@ const char* prefixes[] =
"sampler1DShadow", // GLSL
"sampler2DShadow", // GLSL
+ "sampler2DArrayShadow", // GLSL
"sampler3DShadow", // GLSL
"samplerCubeShadow", // GLSL
+ "sampler2DArray", // GLSL"
+
"sampler2DMS", // GLSL
};
static const int numPrefixes = sizeof( prefixes ) / sizeof( prefixes[0] );
// For GLSL we need to have the names for the renderparms so we can look up their run time indices within the renderprograms
-static const char* GLSLParmNames[] =
+static const char* GLSLParmNames[RENDERPARM_TOTAL] =
{
"rpScreenCorrectionFactor",
"rpWindowCoord",
@@ -313,9 +316,58 @@ static const char* GLSLParmNames[] =
"rpOverbright",
"rpEnableSkinning",
- "rpAlphaTest"
+ "rpAlphaTest",
+
+ // RB begin
+ "rpAmbientColor",
+
+ "rpGlobalLightOrigin",
+ "rpJitterTexScale",
+ "rpJitterTexOffset",
+ "rpCascadeDistances",
+
+ "rpShadowMatrices",
+ "rpShadowMatrix0Y",
+ "rpShadowMatrix0Z",
+ "rpShadowMatrix0W",
+
+ "rpShadowMatrix1X",
+ "rpShadowMatrix1Y",
+ "rpShadowMatrix1Z",
+ "rpShadowMatrix1W",
+
+ "rpShadowMatrix2X",
+ "rpShadowMatrix2Y",
+ "rpShadowMatrix2Z",
+ "rpShadowMatrix2W",
+
+ "rpShadowMatrix3X",
+ "rpShadowMatrix3Y",
+ "rpShadowMatrix3Z",
+ "rpShadowMatrix3W",
+
+ "rpShadowMatrix4X",
+ "rpShadowMatrix4Y",
+ "rpShadowMatrix4Z",
+ "rpShadowMatrix4W",
+
+ "rpShadowMatrix5X",
+ "rpShadowMatrix5Y",
+ "rpShadowMatrix5Z",
+ "rpShadowMatrix5W",
+ // RB end
};
+// RB begin
+const char* idRenderProgManager::GLSLMacroNames[MAX_SHADER_MACRO_NAMES] =
+{
+ "USE_GPU_SKINNING",
+ "LIGHT_POINT",
+ "LIGHT_PARALLEL",
+};
+// RB end
+
+
// RB: added embedded Cg shader resources
static const char* FindEmbeddedSourceShader( const char* name )
{
@@ -342,6 +394,12 @@ public:
private:
int Directive_include()
{
+ if( idParser::Directive_include() )
+ {
+ // RB: try local shaders in base/renderprogs/ first
+ return true;
+ }
+
idLexer* script;
idToken token;
idStr path;
@@ -452,7 +510,7 @@ private:
StripDeadCode
========================
*/
-idStr StripDeadCode( const idStr& in, const char* name )
+idStr StripDeadCode( const idStr& in, const char* name, const idStrList& compileMacros, bool builtin )
{
if( r_skipStripDeadCode.GetBool() )
{
@@ -464,6 +522,11 @@ idStr StripDeadCode( const idStr& in, const char* name )
src.LoadMemory( in.c_str(), in.Length(), name );
src.AddDefine( "PC" );
+ for( int i = 0; i < compileMacros.Num(); i++ )
+ {
+ src.AddDefine( compileMacros[i] );
+ }
+
switch( glConfig.driverType )
{
case GLDRV_OPENGL_ES2:
@@ -472,11 +535,16 @@ idStr StripDeadCode( const idStr& in, const char* name )
break;
}
- if( glConfig.gpuSkinningAvailable )
+ if( !builtin && glConfig.gpuSkinningAvailable )
{
src.AddDefine( "USE_GPU_SKINNING" );
}
+ if( r_useUniformArrays.GetBool() )
+ {
+ src.AddDefine( "USE_UNIFORM_ARRAYS" );
+ }
+
idList< idCGBlock > blocks;
blocks.SetNum( 100 );
@@ -1056,12 +1124,13 @@ idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, i
idToken token;
while( src.ReadToken( &token ) )
{
-
// check for uniforms
- while( token == "uniform" && src.CheckTokenString( "float4" ) )
+
+ // RB: added special case for matrix arrays
+ while( token == "uniform" && ( src.CheckTokenString( "float4" ) || src.CheckTokenString( "float4x4" ) ) )
{
src.ReadToken( &token );
- uniformList.Append( token );
+ idStr uniform = token;
// strip ': register()' from uniforms
if( src.CheckTokenString( ":" ) )
@@ -1072,8 +1141,25 @@ idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, i
}
}
- src.ReadToken( & token );
+
+ if( src.PeekTokenString( "[" ) )
+ {
+ while( src.ReadToken( &token ) )
+ {
+ uniform += token;
+
+ if( token == "]" )
+ {
+ break;
+ }
+ }
+ }
+
+ uniformList.Append( uniform );
+
+ src.ReadToken( &token );
}
+ // RB end
// convert the in/out structs
if( token == "struct" )
@@ -1283,7 +1369,38 @@ idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, i
if( token == uniformList[i] )
{
program += ( token.linesCrossed > 0 ) ? newline : ( token.WhiteSpaceBeforeToken() > 0 ? " " : "" );
- program += va( "%s[%d /* %s */]", uniformArrayName, i, uniformList[i].c_str() );
+
+ // RB: for some unknown reasons has the Nvidia driver problems with regular uniforms when using glUniform4fv
+ // so we need these uniform arrays
+ // I added special check rpShadowMatrices so we can still index the uniforms from the shader
+
+ if( idStr::Cmp( uniformList[i].c_str(), "rpShadowMatrices" ) == 0 )
+ {
+ program += va( "%s[/* %s */ %d + ", uniformArrayName, uniformList[i].c_str(), i );
+
+ if( src.ExpectTokenString( "[" ) )
+ {
+ idStr uniformIndexing;
+
+ while( src.ReadToken( &token ) )
+ {
+ if( token == "]" )
+ {
+ break;
+ }
+
+ uniformIndexing += token;
+ uniformIndexing += " ";
+ }
+
+ program += uniformIndexing + "]";
+ }
+ }
+ else
+ {
+ program += va( "%s[%d /* %s */]", uniformArrayName, i, uniformList[i].c_str() );
+ }
+ // RB end
isUniform = true;
break;
}
@@ -1432,7 +1549,16 @@ idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, i
{
if( r_useUniformArrays.GetBool() )
{
- out += va( "\nuniform vec4 %s[%d];\n", uniformArrayName, uniformList.Num() );
+ int extraSize = 0;
+ for( int i = 0; i < uniformList.Num(); i++ )
+ {
+ if( idStr::Cmp( uniformList[i].c_str(), "rpShadowMatrices" ) == 0 )
+ {
+ extraSize += ( 6 * 4 );
+ }
+ }
+
+ out += va( "\nuniform vec4 %s[%d];\n", uniformArrayName, uniformList.Num() + extraSize );
}
else
{
@@ -1463,7 +1589,7 @@ idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, i
idRenderProgManager::LoadGLSLShader
================================================================================================
*/
-GLuint idRenderProgManager::LoadGLSLShader( GLenum target, const char* name, idList& uniforms )
+GLuint idRenderProgManager::LoadGLSLShader( GLenum target, const char* name, const char* nameOutSuffix, uint32 shaderFeatures, bool builtin, idList& uniforms )
{
idStr inFile;
@@ -1474,7 +1600,7 @@ GLuint idRenderProgManager::LoadGLSLShader( GLenum target, const char* name, idL
// RB: replaced backslashes
inFile.Format( "renderprogs/%s", name );
inFile.StripFileExtension();
- outFileHLSL.Format( "renderprogs/hlsl/%s", name );
+ outFileHLSL.Format( "renderprogs/hlsl/%s%s", name, nameOutSuffix );
outFileHLSL.StripFileExtension();
switch( glConfig.driverType )
@@ -1483,15 +1609,15 @@ GLuint idRenderProgManager::LoadGLSLShader( GLenum target, const char* name, idL
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
- outFileGLSL.Format( "renderprogs/glsles-1.0/%s", name );
- outFileUniforms.Format( "renderprogs/glsles-1.0/%s", name );
+ outFileGLSL.Format( "renderprogs/glsles-1_0/%s%s", name, nameOutSuffix );
+ outFileUniforms.Format( "renderprogs/glsles-1_0/%s%s", name, nameOutSuffix );
break;
}
default:
{
- outFileGLSL.Format( "renderprogs/glsl-1.50/%s", name );
- outFileUniforms.Format( "renderprogs/glsl-1.50/%s", name );
+ outFileGLSL.Format( "renderprogs/glsl-1_50/%s%s", name, nameOutSuffix );
+ outFileUniforms.Format( "renderprogs/glsl-1_50/%s%s", name, nameOutSuffix );
}
}
@@ -1547,8 +1673,19 @@ GLuint idRenderProgManager::LoadGLSLShader( GLenum target, const char* name, idL
{
return false;
}
+
+ idStrList compileMacros;
+ for( int j = 0; j < MAX_SHADER_MACRO_NAMES; j++ )
+ {
+ if( BIT( j ) & shaderFeatures )
+ {
+ const char* macroName = GetGLSLMacroName( ( shaderFeature_t ) j );
+ compileMacros.Append( idStr( macroName ) );
+ }
+ }
+
idStr hlslCode( hlslFileBuffer );
- idStr programHLSL = StripDeadCode( hlslCode, inFile );
+ idStr programHLSL = StripDeadCode( hlslCode, inFile, compileMacros, builtin );
programGLSL = ConvertCG2GLSL( programHLSL, inFile, target == GL_VERTEX_SHADER, programUniforms );
fileSystem->WriteFile( outFileHLSL, programHLSL.c_str(), programHLSL.Length(), "fs_basepath" );
@@ -1718,6 +1855,15 @@ const char* idRenderProgManager::GetGLSLParmName( int rp ) const
return GLSLParmNames[ rp ];
}
+// RB begin
+const char* idRenderProgManager::GetGLSLMacroName( shaderFeature_t sf ) const
+{
+ assert( sf < MAX_SHADER_MACRO_NAMES );
+
+ return GLSLMacroNames[ sf ];
+}
+// RB end
+
/*
================================================================================================
idRenderProgManager::SetUniformValue
@@ -1741,6 +1887,8 @@ void idRenderProgManager::CommitUniforms()
const int progID = GetGLSLCurrentProgram();
const glslProgram_t& prog = glslPrograms[progID];
+ //GL_CheckErrors();
+
if( r_useUniformArrays.GetBool() )
{
ALIGNTYPE16 idVec4 localVectors[RENDERPARM_USER + MAX_GLSL_USER_PARMS];
@@ -1750,11 +1898,26 @@ void idRenderProgManager::CommitUniforms()
const idList& vertexUniforms = vertexShaders[prog.vertexShaderIndex].uniforms;
if( prog.vertexUniformArray != -1 && vertexUniforms.Num() > 0 )
{
+ int totalUniforms = 0;
for( int i = 0; i < vertexUniforms.Num(); i++ )
{
- localVectors[i] = glslUniforms[vertexUniforms[i]];
+ // RB: HACK rpShadowMatrices[6 * 4]
+ if( vertexUniforms[i] == RENDERPARM_SHADOW_MATRIX_0_X )
+ {
+ for( int j = 0; j < ( 6 * 4 ); j++ )
+ {
+ localVectors[i + j] = glslUniforms[vertexUniforms[i] + j];
+ totalUniforms++;
+ }
+
+ }
+ else
+ {
+ localVectors[i] = glslUniforms[vertexUniforms[i]];
+ totalUniforms++;
+ }
}
- glUniform4fv( prog.vertexUniformArray, vertexUniforms.Num(), localVectors->ToFloatPtr() );
+ glUniform4fv( prog.vertexUniformArray, totalUniforms, localVectors->ToFloatPtr() );
}
}
@@ -1763,11 +1926,26 @@ void idRenderProgManager::CommitUniforms()
const idList& fragmentUniforms = fragmentShaders[prog.fragmentShaderIndex].uniforms;
if( prog.fragmentUniformArray != -1 && fragmentUniforms.Num() > 0 )
{
+ int totalUniforms = 0;
for( int i = 0; i < fragmentUniforms.Num(); i++ )
{
- localVectors[i] = glslUniforms[fragmentUniforms[i]];
+ // RB: HACK rpShadowMatrices[6 * 4]
+ if( fragmentUniforms[i] == RENDERPARM_SHADOW_MATRIX_0_X )
+ {
+ for( int j = 0; j < ( 6 * 4 ); j++ )
+ {
+ localVectors[i + j] = glslUniforms[fragmentUniforms[i] + j];
+ totalUniforms++;
+ }
+
+ }
+ else
+ {
+ localVectors[i] = glslUniforms[fragmentUniforms[i]];
+ totalUniforms++;
+ }
}
- glUniform4fv( prog.fragmentUniformArray, fragmentUniforms.Num(), localVectors->ToFloatPtr() );
+ glUniform4fv( prog.fragmentUniformArray, totalUniforms, localVectors->ToFloatPtr() );
}
}
}
@@ -1776,9 +1954,31 @@ void idRenderProgManager::CommitUniforms()
for( int i = 0; i < prog.uniformLocations.Num(); i++ )
{
const glslUniformLocation_t& uniformLocation = prog.uniformLocations[i];
- glUniform4fv( uniformLocation.uniformIndex, 1, glslUniforms[uniformLocation.parmIndex].ToFloatPtr() );
+
+ // RB: HACK rpShadowMatrices[6 * 4]
+ if( uniformLocation.parmIndex == RENDERPARM_SHADOW_MATRIX_0_X )
+ {
+ glUniform4fv( uniformLocation.uniformIndex, 6 * 4, glslUniforms[uniformLocation.parmIndex].ToFloatPtr() );
+ }
+ else
+ {
+ glUniform4fv( uniformLocation.uniformIndex, 1, glslUniforms[uniformLocation.parmIndex].ToFloatPtr() );
+
+#if 1
+ if( GL_CheckErrors() )
+ {
+ const char* parmName = GetGLSLParmName( uniformLocation.parmIndex );
+ const char* value = glslUniforms[uniformLocation.parmIndex].ToString();
+
+ idLib::Printf( "glUniform4fv( %i = %s, value = %s ) failed for %s\n", uniformLocation.parmIndex, parmName, value, prog.name.c_str() );
+ }
+#endif
+ }
+ // RB end
}
}
+
+ //GL_CheckErrors();
}
class idSort_QuickUniforms : public idSort_Quick< glslUniformLocation_t, idSort_QuickUniforms >
@@ -1927,12 +2127,36 @@ void idRenderProgManager::LoadGLSLProgram( const int programIndex, const int ver
// set the texture unit locations once for the render program. We only need to do this once since we only link the program once
glUseProgram( program );
+ int numSamplerUniforms = 0;
for( int i = 0; i < MAX_PROG_TEXTURE_PARMS; ++i )
{
GLint loc = glGetUniformLocation( program, va( "samp%d", i ) );
if( loc != -1 )
{
glUniform1i( loc, i );
+ numSamplerUniforms++;
+ }
+ }
+
+ // RB: make sure that we collected all uniforms we are interested in
+ if( !r_useUniformArrays.GetBool() )
+ {
+ int numActiveUniforms;
+ glGetProgramiv( program, GL_ACTIVE_UNIFORMS, &numActiveUniforms );
+ GL_CheckErrors();
+
+ if( ( numActiveUniforms - numSamplerUniforms ) != prog.uniformLocations.Num() )
+ {
+ int size;
+ GLenum type;
+ char uniformName[1000];
+
+ for( int i = 0; i < numActiveUniforms; i++ )
+ {
+ glGetActiveUniform( program, i, sizeof( uniformName ), NULL, &size, &type, uniformName );
+
+ idLib::Printf( "active uniform: '%s'\n", uniformName );
+ }
}
}
diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h
index 900b65af..af0e93c4 100644
--- a/neo/renderer/RenderProgs_embedded.h
+++ b/neo/renderer/RenderProgs_embedded.h
@@ -17,7 +17,7 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
"Doom 3 BFG Edition GPL Source Code\n"
"Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
- "Copyright (C) 2013 Robert Beckebans\n"
+ "Copyright (C) 2013-2014 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"
@@ -111,6 +111,20 @@ static const cgShaderDef_t cg_renderprogs[] =
"uniform float4 rpEnableSkinning : register(c51);\n"
"uniform float4 rpAlphaTest : register(c52);\n"
"\n"
+ "// RB begin\n"
+ "uniform float4 rpAmbientColor : register(c53);\n"
+ "uniform float4 rpGlobalLightOrigin : register(c54);\n"
+ "uniform float4 rpJitterTexScale : register(c55);\n"
+ "uniform float4 rpJitterTexOffset : register(c56);\n"
+ "uniform float4 rpCascadeDistances : register(c57);\n"
+ "\n"
+ "#if defined( USE_UNIFORM_ARRAYS )\n"
+ "uniform float4 rpShadowMatrices : register(c58);\n"
+ "#else\n"
+ "uniform float4 rpShadowMatrices[6*4] : register(c59);\n"
+ "#endif\n"
+ "// RB end\n"
+ "\n"
"static float dot2( float2 a, float2 b ) { return dot( a, b ); }\n"
"static float dot3( float3 a, float3 b ) { return dot( a, b ); }\n"
"static float dot3( float3 a, float4 b ) { return dot( a, b.xyz ); }\n"
@@ -194,7 +208,6 @@ static const cgShaderDef_t cg_renderprogs[] =
"static float4 swizzleColor( float4 c ) { return c; }\n"
"static float2 vposToScreenPosTexCoord( float2 vpos ) { return vpos.xy * rpWindowCoord.xy; }\n"
"\n"
- "\n"
"#define BRANCH\n"
"#define IFANY\n"
"\n"
@@ -1606,6 +1619,7 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
"Doom 3 BFG Edition GPL Source Code\n"
"Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
+ "Copyright (C) 2013-2014 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"
@@ -1631,23 +1645,73 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
"#include \"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"
"};\n"
"\n"
- "void main( VS_IN vertex, out VS_OUT result ) {\n"
+ "void main( VS_IN vertex, out VS_OUT result )\n"
+ "{\n"
+ "#if defined(USE_GPU_SKINNING)\n"
+ " //--------------------------------------------------------------\n"
+ " // GPU transformation of the position\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"
+ " float joint = vertex.color.x * 255.1 * 3;\n"
+ " matX = matrices[int(joint+0)] * w0;\n"
+ " matY = matrices[int(joint+1)] * w0;\n"
+ " matZ = matrices[int(joint+2)] * w0;\n"
+ "\n"
+ " joint = vertex.color.y * 255.1 * 3;\n"
+ " matX += matrices[int(joint+0)] * w1;\n"
+ " matY += matrices[int(joint+1)] * w1;\n"
+ " matZ += matrices[int(joint+2)] * w1;\n"
+ "\n"
+ " joint = vertex.color.z * 255.1 * 3;\n"
+ " matX += matrices[int(joint+0)] * w2;\n"
+ " matY += matrices[int(joint+1)] * w2;\n"
+ " matZ += matrices[int(joint+2)] * w2;\n"
+ "\n"
+ " joint = vertex.color.w * 255.1 * 3;\n"
+ " matX += matrices[int(joint+0)] * w3;\n"
+ " matY += matrices[int(joint+1)] * w3;\n"
+ " matZ += matrices[int(joint+2)] * w3;\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"
+ " 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"
+ "#else\n"
" result.position.x = dot4( vertex.position, rpMVPmatrixX );\n"
" result.position.y = dot4( vertex.position, rpMVPmatrixY );\n"
" result.position.z = dot4( vertex.position, rpMVPmatrixZ );\n"
" result.position.w = dot4( vertex.position, rpMVPmatrixW );\n"
+ "#endif\n"
"}\n"
},
@@ -1772,6 +1836,126 @@ static const cgShaderDef_t cg_renderprogs[] =
},
+ {
+ "renderprogs/debug_shadowmap.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) 2014 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 sampler2DArray samp0 : register(s0);\n"
+ "\n"
+ "struct PS_IN\n"
+ "{\n"
+ " float4 position : VPOS;\n"
+ " float2 texcoord0 : TEXCOORD0_centroid;\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"
+ " float3 tc;\n"
+ " tc.xy = fragment.texcoord0.xy;\n"
+ " tc.z = rpScreenCorrectionFactor.x; // layer\n"
+ "\n"
+ " result.color = texture( samp0, tc );// * rpColor;\n"
+ "}\n"
+
+ },
+
+ {
+ "renderprogs/debug_shadowmap.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"
+ " float4 position : POSITION;\n"
+ " float2 texcoord : TEXCOORD0;\n"
+ " float4 normal : NORMAL;\n"
+ " float4 tangent : TANGENT;\n"
+ " float4 color : COLOR0;\n"
+ "};\n"
+ "\n"
+ "struct VS_OUT {\n"
+ " float4 position : POSITION;\n"
+ " float2 texcoord0 : TEXCOORD0;\n"
+ "};\n"
+ "\n"
+ "void main( VS_IN vertex, out VS_OUT result ) {\n"
+ " result.position.x = dot4( vertex.position, rpMVPmatrixX );\n"
+ " result.position.y = dot4( vertex.position, rpMVPmatrixY );\n"
+ " result.position.z = dot4( vertex.position, rpMVPmatrixZ );\n"
+ " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n"
+ "\n"
+ " // compute oldschool texgen or multiply by texture matrix\n"
+ " BRANCH if ( rpTexGen0Enabled.x > 0.0 ) {\n"
+ " result.texcoord0.x = dot4( vertex.position, rpTexGen0S );\n"
+ " result.texcoord0.y = dot4( vertex.position, rpTexGen0T );\n"
+ " } else {\n"
+ " result.texcoord0.x = dot4( vertex.texcoord.xy, rpTextureMatrixS );\n"
+ " result.texcoord0.y = dot4( vertex.texcoord.xy, rpTextureMatrixT );\n"
+ " }\n"
+ "}\n"
+
+ },
+
{
"renderprogs/depth.pixel",
"/*\n"
@@ -2870,7 +3054,7 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
"Doom 3 BFG Edition GPL Source Code\n"
"Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
- "Copyright (C) 2013 Robert Beckebans\n"
+ "Copyright (C) 2013-2014 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"
@@ -2964,6 +3148,20 @@ static const cgShaderDef_t cg_renderprogs[] =
"uniform float4 rpEnableSkinning : register(c51);\n"
"uniform float4 rpAlphaTest : register(c52);\n"
"\n"
+ "// RB begin\n"
+ "uniform float4 rpAmbientColor : register(c53);\n"
+ "uniform float4 rpGlobalLightOrigin : register(c54);\n"
+ "uniform float4 rpJitterTexScale : register(c55);\n"
+ "uniform float4 rpJitterTexOffset : register(c56);\n"
+ "uniform float4 rpCascadeDistances : register(c57);\n"
+ "\n"
+ "#if defined( USE_UNIFORM_ARRAYS )\n"
+ "uniform float4 rpShadowMatrices : register(c58);\n"
+ "#else\n"
+ "uniform float4 rpShadowMatrices[6*4] : register(c59);\n"
+ "#endif\n"
+ "// RB end\n"
+ "\n"
"static float dot2( float2 a, float2 b ) { return dot( a, b ); }\n"
"static float dot3( float3 a, float3 b ) { return dot( a, b ); }\n"
"static float dot3( float3 a, float4 b ) { return dot( a, b.xyz ); }\n"
@@ -3047,7 +3245,6 @@ static const cgShaderDef_t cg_renderprogs[] =
"static float4 swizzleColor( float4 c ) { return c; }\n"
"static float2 vposToScreenPosTexCoord( float2 vpos ) { return vpos.xy * rpWindowCoord.xy; }\n"
"\n"
- "\n"
"#define BRANCH\n"
"#define IFANY\n"
"\n"
@@ -3665,6 +3862,7 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
"Doom 3 BFG Edition GPL Source Code\n"
"Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
+ "Copyright (C) 2013-2014 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"
@@ -3688,7 +3886,7 @@ static const cgShaderDef_t cg_renderprogs[] =
"===========================================================================\n"
"*/\n"
"\n"
- "#include \"global.inc\"\n"
+ "#include \"renderprogs/global.inc\"\n"
"\n"
"uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map\n"
"uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture\n"
@@ -3726,16 +3924,29 @@ static const cgShaderDef_t cg_renderprogs[] =
" localNormal.xy = bumpMap.wy - 0.5;\n"
" localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );\n"
" localNormal = normalize( localNormal );\n"
+ " \n"
+ " // RB: http://developer.valvesoftware.com/wiki/Half_Lambert\n"
+ " float halfLdotN = dot3( localNormal, lightVector ) * 0.5 + 0.5;\n"
+ " halfLdotN *= halfLdotN;\n"
+ " \n"
+ " // traditional very dark Lambert light model used in Doom 3\n"
+ " //float ldotN = clamp( dot3( localNormal, lightVector ), 0.0, 1.0 );\n"
+ " float ldotN = dot3( localNormal, lightVector );\n"
"\n"
" const half specularPower = 10.0f;\n"
" half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );\n"
- " half3 specularContribution = _half3( pow( hDotN, specularPower ) );\n"
+ " // RB: added abs\n"
+ " half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );\n"
"\n"
" half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;\n"
" half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;\n"
- " half3 lightColor = dot3( lightVector, localNormal ) * lightProj.xyz * lightFalloff.xyz;\n"
+ " half3 lightColor = lightProj.xyz * lightFalloff.xyz;\n"
+ " \n"
+ " half rim = 1.0f - saturate( hDotN );\n"
+ " half rimPower = 16.0f;\n"
+ " half3 rimColor = diffuseColor * lightProj.xyz * lightFalloff.xyz * 1.0f * pow( rim, rimPower ) * fragment.color.rgb;// * halfLdotN;\n"
"\n"
- " result.color.xyz = ( diffuseColor + specularColor ) * lightColor * fragment.color.xyz;\n"
+ " result.color.xyz = ( diffuseColor + specularColor ) * halfLdotN * lightColor * fragment.color.rgb;// + rimColor;\n"
" result.color.w = 1.0;\n"
"}\n"
"\n"
@@ -3749,6 +3960,7 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
"Doom 3 BFG Edition GPL Source Code\n"
"Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. \n"
+ "Copyright (C) 2014 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"
@@ -3772,7 +3984,11 @@ static const cgShaderDef_t cg_renderprogs[] =
"===========================================================================\n"
"*/\n"
"\n"
- "#include \"global.inc\"\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"
@@ -3780,6 +3996,7 @@ static const cgShaderDef_t cg_renderprogs[] =
" float4 normal : NORMAL;\n"
" float4 tangent : TANGENT;\n"
" float4 color : COLOR0;\n"
+ " float4 color2 : COLOR1;\n"
"};\n"
"\n"
"struct VS_OUT {\n"
@@ -3796,24 +4013,89 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
"void main( VS_IN vertex, out VS_OUT result ) {\n"
"\n"
- " float3 vNormal = vertex.normal.xyz * 2.0 - 1.0;\n"
+ " float4 vNormal = vertex.normal * 2.0 - 1.0;\n"
" float4 vTangent = vertex.tangent * 2.0 - 1.0;\n"
- " float3 vBinormal = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;\n"
+ " float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;\n"
"\n"
- " result.position.x = dot4( vertex.position, rpMVPmatrixX );\n"
- " result.position.y = dot4( vertex.position, rpMVPmatrixY );\n"
- " result.position.z = dot4( vertex.position, rpMVPmatrixZ );\n"
- " result.position.w = dot4( vertex.position, rpMVPmatrixW );\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"
+ " float joint = vertex.color.x * 255.1 * 3;\n"
+ " matX = matrices[int(joint+0)] * w0;\n"
+ " matY = matrices[int(joint+1)] * w0;\n"
+ " matZ = matrices[int(joint+2)] * w0;\n"
+ "\n"
+ " joint = vertex.color.y * 255.1 * 3;\n"
+ " matX += matrices[int(joint+0)] * w1;\n"
+ " matY += matrices[int(joint+1)] * w1;\n"
+ " matZ += matrices[int(joint+2)] * w1;\n"
+ "\n"
+ " joint = vertex.color.z * 255.1 * 3;\n"
+ " matX += matrices[int(joint+0)] * w2;\n"
+ " matY += matrices[int(joint+1)] * w2;\n"
+ " matZ += matrices[int(joint+2)] * w2;\n"
+ "\n"
+ " joint = vertex.color.w * 255.1 * 3;\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"
" float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );\n"
"\n"
- " //calculate vector to light in R0\n"
- " float4 toLight = rpLocalLightOrigin - vertex.position;\n"
+ " //calculate vector to light\n"
+ " float4 toLight = rpLocalLightOrigin - modelPosition;\n"
"\n"
- " //result.texcoord0\n"
- " result.texcoord0.x = dot3( vTangent.xyz, toLight );\n"
- " result.texcoord0.y = dot3( vBinormal, toLight );\n"
- " result.texcoord0.z = dot3( vNormal, toLight );\n"
+ " //--------------------------------------------------------------\n"
+ "\n"
+ " //result.texcoord0 is the direction to the light in tangent space\n"
+ " result.texcoord0.x = dot3( tangent, toLight );\n"
+ " result.texcoord0.y = dot3( bitangent, toLight );\n"
+ " result.texcoord0.z = dot3( normal, toLight );\n"
" result.texcoord0.w = 1.0f;\n"
"\n"
" //textures 1 takes the base coordinates by the texture matrix\n"
@@ -3823,13 +4105,13 @@ static const cgShaderDef_t cg_renderprogs[] =
"\n"
" //# texture 2 has one texgen\n"
" result.texcoord2 = defaultTexCoord;\n"
- " result.texcoord2.x = dot4( vertex.position, rpLightFalloffS );\n"
+ " result.texcoord2.x = dot4( modelPosition, rpLightFalloffS );\n"
"\n"
" //# texture 3 has three texgens\n"
- " result.texcoord3.x = dot4( vertex.position, rpLightProjectionS );\n"
- " result.texcoord3.y = dot4( vertex.position, rpLightProjectionT );\n"
+ " result.texcoord3.x = dot4( modelPosition, rpLightProjectionS );\n"
+ " result.texcoord3.y = dot4( modelPosition, rpLightProjectionT );\n"
" result.texcoord3.z = 0.0f;\n"
- " result.texcoord3.w = dot4( vertex.position, rpLightProjectionQ );\n"
+ " result.texcoord3.w = dot4( modelPosition, rpLightProjectionQ );\n"
"\n"
" //# textures 4 takes the base coordinates by the texture matrix\n"
" result.texcoord4 = defaultTexCoord;\n"
@@ -3847,22 +4129,521 @@ static const cgShaderDef_t cg_renderprogs[] =
" toLight = normalize( toLight );\n"
"\n"
" //# calculate normalized vector to viewer in R1\n"
- " float4 toView = normalize( rpLocalViewOrigin - vertex.position );\n"
+ " float4 toView = normalize( rpLocalViewOrigin - modelPosition );\n"
" \n"
" //# add together to become the half angle vector in object space (non-normalized)\n"
" float4 halfAngleVector = toLight + toView;\n"
"\n"
" //# put into texture space\n"
- " result.texcoord6.x = dot3( vTangent.xyz, halfAngleVector );\n"
- " result.texcoord6.y = dot3( vBinormal, halfAngleVector );\n"
- " result.texcoord6.z = dot3( vNormal, halfAngleVector );\n"
+ " result.texcoord6.x = dot3( tangent, halfAngleVector );\n"
+ " result.texcoord6.y = dot3( bitangent, halfAngleVector );\n"
+ " result.texcoord6.z = dot3( normal, halfAngleVector );\n"
" result.texcoord6.w = 1.0f;\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/interactionSM.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) 2013-2014 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); // texture 1 is the per-surface bump map\n"
+ "uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture\n"
+ "uniform sampler2D samp2 : register(s2); // texture 3 is the light projection texture\n"
+ "uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map\n"
+ "uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular map\n"
+ "uniform sampler2DArrayShadow samp5 : register(s5); // texture 6 is the shadowmap array\n"
+ "uniform sampler2D samp6 : register(s6); // texture 7 is the jitter texture\n"
+ "\n"
+ "\n"
+ "\n"
+ "struct PS_IN\n"
+ "{\n"
+ " half4 position : VPOS;\n"
+ " half4 texcoord0 : TEXCOORD0_centroid;\n"
+ " half4 texcoord1 : TEXCOORD1_centroid;\n"
+ " half4 texcoord2 : TEXCOORD2_centroid;\n"
+ " half4 texcoord3 : TEXCOORD3_centroid;\n"
+ " half4 texcoord4 : TEXCOORD4_centroid;\n"
+ " half4 texcoord5 : TEXCOORD5_centroid;\n"
+ " half4 texcoord6 : TEXCOORD6_centroid;\n"
+ " half4 texcoord7 : TEXCOORD7_centroid;\n"
+ " half4 texcoord8 : TEXCOORD8_centroid;\n"
+ " half4 texcoord9 : TEXCOORD9_centroid;\n"
+ " half4 color : COLOR0;\n"
+ "};\n"
+ "\n"
+ "struct PS_OUT\n"
+ "{\n"
+ " half4 color : COLOR;\n"
+ "};\n"
+ "\n"
+ "void main( PS_IN fragment, out PS_OUT result )\n"
+ "{\n"
+ " half4 bumpMap = tex2D( samp0, fragment.texcoord1.xy );\n"
+ " half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 );\n"
+ " half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 );\n"
+ " half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy );\n"
+ " half4 specMap = tex2D( samp4, fragment.texcoord5.xy );\n"
+ "\n"
+ " half3 lightVector = normalize( fragment.texcoord0.xyz );\n"
+ " half3 diffuseMap = ConvertYCoCgToRGB( YCoCG );\n"
+ "\n"
+ " half3 localNormal;\n"
+ " // RB begin\n"
+ "#if defined(GLES2)\n"
+ " localNormal.xy = bumpMap.rg - 0.5;\n"
+ "#else\n"
+ " localNormal.xy = bumpMap.wy - 0.5;\n"
+ "#endif\n"
+ " // RB end\n"
+ " localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );\n"
+ " localNormal = normalize( localNormal );\n"
+ " \n"
+ " // RB: http://developer.valvesoftware.com/wiki/Half_Lambert\n"
+ " float halfLdotN = dot3( localNormal, lightVector ) * 0.5 + 0.5;\n"
+ " halfLdotN *= halfLdotN;\n"
+ " \n"
+ " // traditional very dark Lambert light model used in Doom 3\n"
+ " float ldotN = dot3( localNormal, lightVector );\n"
+ "\n"
+ " const half specularPower = 10.0f;\n"
+ " half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );\n"
+ " // RB: added abs\n"
+ " half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );\n"
+ "\n"
+ " half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;\n"
+ " half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;\n"
+ " half3 lightColor = lightProj.xyz * lightFalloff.xyz;\n"
+ " \n"
+ " half rim = 1.0f - saturate( hDotN );\n"
+ " half rimPower = 16.0f;\n"
+ " half3 rimColor = diffuseColor * lightProj.xyz * lightFalloff.xyz * 1.0f * pow( rim, rimPower ) * fragment.color.rgb;// * halfLdotN;\n"
+ " \n"
+ " //\n"
+ " // shadow mapping\n"
+ " //\n"
+ " int shadowIndex = 0;\n"
+ " \n"
+ "#if defined( LIGHT_POINT )\n"
+ " float3 toLightGlobal = normalize( fragment.texcoord8.xyz );\n"
+ " \n"
+ " float axis[6];\n"
+ " axis[0] = -toLightGlobal.x;\n"
+ " axis[1] = toLightGlobal.x;\n"
+ " axis[2] = -toLightGlobal.y;\n"
+ " axis[3] = toLightGlobal.y;\n"
+ " axis[4] = -toLightGlobal.z;\n"
+ " axis[5] = toLightGlobal.z;\n"
+ "\n"
+ " for( int i = 0; i < 6; i++ )\n"
+ " {\n"
+ " if( axis[i] > axis[shadowIndex] )\n"
+ " {\n"
+ " shadowIndex = i;\n"
+ " }\n"
+ " }\n"
+ "\n"
+ "#endif // #if defined( POINTLIGHT )\n"
+ "\n"
+ "#if defined( LIGHT_PARALLEL )\n"
+ " \n"
+ " float viewZ = -fragment.texcoord9.z;\n"
+ " \n"
+ " shadowIndex = 4;\n"
+ " for( int i = 0; i < 4; i++ )\n"
+ " {\n"
+ " if( viewZ < rpCascadeDistances[i] )\n"
+ " {\n"
+ " shadowIndex = i;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ "#endif\n"
+ " \n"
+ "#if 0\n"
+ " if( shadowIndex == 0 )\n"
+ " {\n"
+ " result.color = float4( 1.0, 0.0, 0.0, 1.0 );\n"
+ " }\n"
+ " else if( shadowIndex == 1 )\n"
+ " {\n"
+ " result.color = float4( 0.0, 1.0, 0.0, 1.0 );\n"
+ " }\n"
+ " else if( shadowIndex == 2 )\n"
+ " {\n"
+ " result.color = float4( 0.0, 0.0, 1.0, 1.0 );\n"
+ " }\n"
+ " else if( shadowIndex == 3 )\n"
+ " {\n"
+ " result.color = float4( 1.0, 1.0, 0.0, 1.0 );\n"
+ " }\n"
+ " else if( shadowIndex == 4 )\n"
+ " {\n"
+ " result.color = float4( 1.0, 0.0, 1.0, 1.0 );\n"
+ " }\n"
+ " else if( shadowIndex == 5 )\n"
+ " {\n"
+ " result.color = float4( 0.0, 1.0, 1.0, 1.0 );\n"
+ " }\n"
+ " \n"
+ " //result.color.xyz *= lightColor;\n"
+ " return;\n"
+ "#endif\n"
+ " \n"
+ " float4 shadowMatrixX = rpShadowMatrices[ int ( shadowIndex * 4 + 0 ) ];\n"
+ " float4 shadowMatrixY = rpShadowMatrices[ int ( shadowIndex * 4 + 1 ) ];\n"
+ " float4 shadowMatrixZ = rpShadowMatrices[ int ( shadowIndex * 4 + 2 ) ];\n"
+ " float4 shadowMatrixW = rpShadowMatrices[ int ( shadowIndex * 4 + 3 ) ];\n"
+ " \n"
+ " float4 modelPosition = float4( fragment.texcoord7.xyz, 1.0 );\n"
+ " float4 shadowTexcoord;\n"
+ " shadowTexcoord.x = dot4( modelPosition, shadowMatrixX );\n"
+ " shadowTexcoord.y = dot4( modelPosition, shadowMatrixY );\n"
+ " shadowTexcoord.z = dot4( modelPosition, shadowMatrixZ );\n"
+ " shadowTexcoord.w = dot4( modelPosition, shadowMatrixW );\n"
+ " \n"
+ " //float bias = 0.001 * tan( acos( ldotN ) );\n"
+ " //bias = clamp( bias, 0, 0.001 );\n"
+ " float bias = 0.001;\n"
+ " \n"
+ " shadowTexcoord.xyz /= shadowTexcoord.w;\n"
+ " shadowTexcoord.z = shadowTexcoord.z * 0.9991;\n"
+ " //shadowTexcoord.z = shadowTexcoord.z - bias;\n"
+ " shadowTexcoord.w = shadowIndex;\n"
+ "\n"
+ "#if 0\n"
+ " result.color.xyz = float3( shadowTexcoord.z, shadowTexcoord.z, shadowTexcoord.z );\n"
+ " result.color.w = 1.0;\n"
+ " return;\n"
+ "#endif\n"
+ "\n"
+ " // multiple taps\n"
+ " \n"
+ "#if 0\n"
+ " const float2 poissonDisk2[12] = float2[](\n"
+ " float2(-0.326,-0.406),\n"
+ " float2(-0.840,-0.074),\n"
+ " float2(-0.696, 0.457),\n"
+ " float2(-0.203, 0.621),\n"
+ " float2( 0.962,-0.195),\n"
+ " float2( 0.473,-0.480),\n"
+ " float2( 0.519, 0.767),\n"
+ " float2( 0.185,-0.893),\n"
+ " float2( 0.507, 0.064),\n"
+ " float2( 0.896, 0.412),\n"
+ " float2(-0.322,-0.933),\n"
+ " float2(-0.792,-0.598)\n"
+ " );\n"
+ " float shadow = 0.0;\n"
+ " \n"
+ " float shadowTexelSize = ( 1.0 / 1024.0 ) * 0.5;\n"
+ " for( int i = 0; i < 12; i++ )\n"
+ " {\n"
+ " int index = int( rand( shadowTexcoord.xy * 1.0 ) * 12 );\n"
+ " \n"
+ " float4 shadowTexcoordOffset = float4( shadowTexcoord.xy + poissonDisk2[index] * shadowTexelSize, shadowTexcoord.z, shadowTexcoord.w );\n"
+ " \n"
+ " shadow += texture( samp5, shadowTexcoordOffset.xywz);\n"
+ " }\n"
+ "\n"
+ " shadow *= ( 1.0 / 12.0 );\n"
+ " \n"
+ "#elif 1\n"
+ " float4 base = shadowTexcoord;\n"
+ " \n"
+ " base.xy += rpJitterTexScale.xy * -0.5;\n"
+ " \n"
+ " float shadow = 0.0;\n"
+ " \n"
+ " float stepSize = 1.0 / 16;\n"
+ " \n"
+ " float4 jitterTC = ( fragment.position * rpScreenCorrectionFactor ) + rpJitterTexOffset;\n"
+ " for( int i = 0; i < 16; i++ )\n"
+ " {\n"
+ " float4 jitter = base + tex2D( samp6, jitterTC.xy ) * rpJitterTexScale;\n"
+ " jitter.zw = shadowTexcoord.zw;\n"
+ " \n"
+ " shadow += texture( samp5, jitter.xywz );\n"
+ " jitterTC.x += stepSize;\n"
+ " }\n"
+ " \n"
+ " shadow *= ( 1.0 / 16 );\n"
+ "#else \n"
+ " float shadow = texture( samp5, shadowTexcoord.xywz );\n"
+ "#endif\n"
+ "\n"
+ " result.color.xyz = ( diffuseColor + specularColor ) * halfLdotN * lightColor * fragment.color.rgb * shadow;// + rimColor;\n"
+ " result.color.w = 1.0;\n"
+ "}\n"
+ "\n"
+
+ },
+
+ {
+ "renderprogs/interactionSM.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) 2014 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"
+ " float4 texcoord0 : TEXCOORD0;\n"
+ " float4 texcoord1 : TEXCOORD1;\n"
+ " float4 texcoord2 : TEXCOORD2;\n"
+ " float4 texcoord3 : TEXCOORD3;\n"
+ " float4 texcoord4 : TEXCOORD4;\n"
+ " float4 texcoord5 : TEXCOORD5;\n"
+ " float4 texcoord6 : TEXCOORD6;\n"
+ " float4 texcoord7 : TEXCOORD7;\n"
+ " float4 texcoord8 : TEXCOORD8;\n"
+ " float4 texcoord9 : TEXCOORD9;\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"
+ " float joint = vertex.color.x * 255.1 * 3;\n"
+ " matX = matrices[int(joint+0)] * w0;\n"
+ " matY = matrices[int(joint+1)] * w0;\n"
+ " matZ = matrices[int(joint+2)] * w0;\n"
+ "\n"
+ " joint = vertex.color.y * 255.1 * 3;\n"
+ " matX += matrices[int(joint+0)] * w1;\n"
+ " matY += matrices[int(joint+1)] * w1;\n"
+ " matZ += matrices[int(joint+2)] * w1;\n"
+ "\n"
+ " joint = vertex.color.z * 255.1 * 3;\n"
+ " matX += matrices[int(joint+0)] * w2;\n"
+ " matY += matrices[int(joint+1)] * w2;\n"
+ " matZ += matrices[int(joint+2)] * w2;\n"
+ "\n"
+ " joint = vertex.color.w * 255.1 * 3;\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"
+ " float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );\n"
+ "\n"
+ " //calculate vector to light\n"
+ " float4 toLightLocal = rpLocalLightOrigin - modelPosition;\n"
+ "\n"
+ " //--------------------------------------------------------------\n"
+ "\n"
+ " //result.texcoord0 is the direction to the light in tangent space\n"
+ " result.texcoord0.x = dot3( tangent, toLightLocal );\n"
+ " result.texcoord0.y = dot3( bitangent, toLightLocal );\n"
+ " result.texcoord0.z = dot3( normal, toLightLocal );\n"
+ " result.texcoord0.w = 1.0f;\n"
+ "\n"
+ " //textures 1 takes the base coordinates by the texture matrix\n"
+ " result.texcoord1 = defaultTexCoord;\n"
+ " result.texcoord1.x = dot4( vertex.texcoord.xy, rpBumpMatrixS );\n"
+ " result.texcoord1.y = dot4( vertex.texcoord.xy, rpBumpMatrixT );\n"
+ "\n"
+ " //# texture 2 has one texgen\n"
+ " result.texcoord2 = defaultTexCoord;\n"
+ " result.texcoord2.x = dot4( modelPosition, rpLightFalloffS );\n"
+ "\n"
+ " //# texture 3 has three texgens\n"
+ " result.texcoord3.x = dot4( modelPosition, rpLightProjectionS );\n"
+ " result.texcoord3.y = dot4( modelPosition, rpLightProjectionT );\n"
+ " result.texcoord3.z = 0.0f;\n"
+ " result.texcoord3.w = dot4( modelPosition, rpLightProjectionQ );\n"
+ "\n"
+ " //# textures 4 takes the base coordinates by the texture matrix\n"
+ " result.texcoord4 = defaultTexCoord;\n"
+ " result.texcoord4.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS );\n"
+ " result.texcoord4.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT );\n"
+ "\n"
+ " //# textures 5 takes the base coordinates by the texture matrix\n"
+ " result.texcoord5 = defaultTexCoord;\n"
+ " result.texcoord5.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS );\n"
+ " result.texcoord5.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT );\n"
+ "\n"
+ " //# texture 6's texcoords will be the halfangle in texture space\n"
+ "\n"
+ " //# calculate normalized vector to light in R0\n"
+ " toLightLocal = normalize( toLightLocal );\n"
+ "\n"
+ " //# calculate normalized vector to viewer in R1\n"
+ " float4 toView = normalize( rpLocalViewOrigin - modelPosition );\n"
+ " \n"
+ " //# add together to become the half angle vector in object space (non-normalized)\n"
+ " float4 halfAngleVector = toLightLocal + toView;\n"
+ "\n"
+ " //# put into texture space\n"
+ " result.texcoord6.x = dot3( tangent, halfAngleVector );\n"
+ " result.texcoord6.y = dot3( bitangent, halfAngleVector );\n"
+ " result.texcoord6.z = dot3( normal, halfAngleVector );\n"
+ " result.texcoord6.w = 1.0f;\n"
+ " \n"
+ " result.texcoord7 = modelPosition;\n"
+ " \n"
+ " float4 worldPosition;\n"
+ " worldPosition.x = dot4( modelPosition, rpModelMatrixX );\n"
+ " worldPosition.y = dot4( modelPosition, rpModelMatrixY );\n"
+ " worldPosition.z = dot4( modelPosition, rpModelMatrixZ );\n"
+ " worldPosition.w = dot4( modelPosition, rpModelMatrixW );\n"
+ " \n"
+ " float4 toLightGlobal = rpGlobalLightOrigin - worldPosition;\n"
+ " \n"
+ " result.texcoord8 = toLightGlobal;\n"
+ " \n"
+ " float4 viewPosition;\n"
+ " viewPosition.x = dot4( modelPosition, rpModelViewMatrixX );\n"
+ " viewPosition.y = dot4( modelPosition, rpModelViewMatrixY );\n"
+ " viewPosition.z = dot4( modelPosition, rpModelViewMatrixZ );\n"
+ " viewPosition.w = dot4( modelPosition, rpModelViewMatrixW );\n"
+ " \n"
+ " result.texcoord9 = viewPosition;\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"
},
@@ -4329,280 +5110,6 @@ static const cgShaderDef_t cg_renderprogs[] =
},
- {
- "renderprogs/interaction_skinned.pixel",
- "/*\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 \"global.inc\"\n"
- "\n"
- "uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map\n"
- "uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture\n"
- "uniform sampler2D samp2 : register(s2); // texture 3 is the light projection texture\n"
- "uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map\n"
- "uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular map\n"
- "\n"
- "struct PS_IN {\n"
- " half4 position : VPOS;\n"
- " half4 texcoord0 : TEXCOORD0_centroid;\n"
- " half4 texcoord1 : TEXCOORD1_centroid;\n"
- " half4 texcoord2 : TEXCOORD2_centroid;\n"
- " half4 texcoord3 : TEXCOORD3_centroid;\n"
- " half4 texcoord4 : TEXCOORD4_centroid;\n"
- " half4 texcoord5 : TEXCOORD5_centroid;\n"
- " half4 texcoord6 : TEXCOORD6_centroid;\n"
- " half4 color : COLOR0;\n"
- "};\n"
- "\n"
- "struct PS_OUT {\n"
- " half4 color : COLOR;\n"
- "};\n"
- "\n"
- "void main( PS_IN fragment, out PS_OUT result ) {\n"
- " half4 bumpMap = tex2D( samp0, fragment.texcoord1.xy );\n"
- " half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 );\n"
- " half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 );\n"
- " half4 YCoCG = tex2D( samp3, fragment.texcoord4.xy );\n"
- " half4 specMap = tex2D( samp4, fragment.texcoord5.xy );\n"
- "\n"
- " half3 lightVector = normalize( fragment.texcoord0.xyz );\n"
- " half3 diffuseMap = ConvertYCoCgToRGB( YCoCG );\n"
- "\n"
- " half3 localNormal;\n"
- " localNormal.xy = bumpMap.wy - 0.5;\n"
- " localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );\n"
- " localNormal = normalize( localNormal );\n"
- "\n"
- " const half specularPower = 10.0f;\n"
- " half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );\n"
- " half3 specularContribution = _half3( pow( hDotN, specularPower ) );\n"
- "\n"
- " half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;\n"
- " half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;\n"
- " half3 lightColor = dot3( lightVector, localNormal ) * lightProj.xyz * lightFalloff.xyz;\n"
- "\n"
- " result.color.xyz = ( diffuseColor + specularColor ) * lightColor * fragment.color.xyz;\n"
- " result.color.w = 1.0;\n"
- "}\n"
- "\n"
-
- },
-
- {
- "renderprogs/interaction_skinned.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 \"global.inc\"\n"
- "\n"
- "uniform matrices_ubo { float4 matrices[408]; };\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"
- " float4 texcoord0 : TEXCOORD0;\n"
- " float4 texcoord1 : TEXCOORD1;\n"
- " float4 texcoord2 : TEXCOORD2;\n"
- " float4 texcoord3 : TEXCOORD3;\n"
- " float4 texcoord4 : TEXCOORD4;\n"
- " float4 texcoord5 : TEXCOORD5;\n"
- " float4 texcoord6 : TEXCOORD6;\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 vBinormal = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;\n"
- "\n"
- " //--------------------------------------------------------------\n"
- " // GPU transformation of the normal / binormal / 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"
- " float joint = vertex.color.x * 255.1 * 3;\n"
- " matX = matrices[int(joint+0)] * w0;\n"
- " matY = matrices[int(joint+1)] * w0;\n"
- " matZ = matrices[int(joint+2)] * w0;\n"
- "\n"
- " joint = vertex.color.y * 255.1 * 3;\n"
- " matX += matrices[int(joint+0)] * w1;\n"
- " matY += matrices[int(joint+1)] * w1;\n"
- " matZ += matrices[int(joint+2)] * w1;\n"
- "\n"
- " joint = vertex.color.z * 255.1 * 3;\n"
- " matX += matrices[int(joint+0)] * w2;\n"
- " matY += matrices[int(joint+1)] * w2;\n"
- " matZ += matrices[int(joint+2)] * w2;\n"
- "\n"
- " joint = vertex.color.w * 255.1 * 3;\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 binormal;\n"
- " binormal.x = dot3( matX, vBinormal );\n"
- " binormal.y = dot3( matY, vBinormal );\n"
- " binormal.z = dot3( matZ, vBinormal );\n"
- " binormal = normalize( binormal );\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"
- " 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"
- " float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );\n"
- "\n"
- " //calculate vector to light in R0\n"
- " float4 toLight = rpLocalLightOrigin - modelPosition;\n"
- "\n"
- " //--------------------------------------------------------------\n"
- "\n"
- " //result.texcoord0 is the direction to the light in tangent space\n"
- " result.texcoord0.x = dot3( tangent, toLight );\n"
- " result.texcoord0.y = dot3( binormal, toLight );\n"
- " result.texcoord0.z = dot3( normal, toLight );\n"
- " result.texcoord0.w = 1.0f;\n"
- "\n"
- " //textures 1 takes the base coordinates by the texture matrix\n"
- " result.texcoord1 = defaultTexCoord;\n"
- " result.texcoord1.x = dot4( vertex.texcoord.xy, rpBumpMatrixS );\n"
- " result.texcoord1.y = dot4( vertex.texcoord.xy, rpBumpMatrixT );\n"
- "\n"
- " //# texture 2 has one texgen\n"
- " result.texcoord2 = defaultTexCoord;\n"
- " result.texcoord2.x = dot4( modelPosition, rpLightFalloffS );\n"
- "\n"
- " //# texture 3 has three texgens\n"
- " result.texcoord3.x = dot4( modelPosition, rpLightProjectionS );\n"
- " result.texcoord3.y = dot4( modelPosition, rpLightProjectionT );\n"
- " result.texcoord3.z = 0.0f;\n"
- " result.texcoord3.w = dot4( modelPosition, rpLightProjectionQ );\n"
- "\n"
- " //# textures 4 takes the base coordinates by the texture matrix\n"
- " result.texcoord4 = defaultTexCoord;\n"
- " result.texcoord4.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS );\n"
- " result.texcoord4.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT );\n"
- "\n"
- " //# textures 5 takes the base coordinates by the texture matrix\n"
- " result.texcoord5 = defaultTexCoord;\n"
- " result.texcoord5.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS );\n"
- " result.texcoord5.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT );\n"
- "\n"
- " //# texture 6's texcoords will be the halfangle in texture space\n"
- "\n"
- " //# calculate normalized vector to light in R0\n"
- " toLight = normalize( toLight );\n"
- "\n"
- " //# calculate normalized vector to viewer in R1\n"
- " float4 toView = normalize( rpLocalViewOrigin - modelPosition );\n"
- " \n"
- " //# add together to become the half angle vector in object space (non-normalized)\n"
- " float4 halfAngleVector = toLight + toView;\n"
- "\n"
- " //# put into texture space\n"
- " result.texcoord6.x = dot3( tangent, halfAngleVector );\n"
- " result.texcoord6.y = dot3( binormal, halfAngleVector );\n"
- " result.texcoord6.z = dot3( normal, halfAngleVector );\n"
- " result.texcoord6.w = 1.0f;\n"
- "\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"
- "\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"
- "}\n"
-
- },
-
{
"renderprogs/motionBlur.pixel",
"/*\n"
@@ -6496,6 +7003,118 @@ static const cgShaderDef_t cg_renderprogs[] =
},
+ {
+ "renderprogs/vertex_color.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) 2013 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);\n"
+ "\n"
+ "struct PS_IN\n"
+ "{\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"
+ " result.color = fragment.color;\n"
+ "}\n"
+
+ },
+
+ {
+ "renderprogs/vertex_color.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) 2013 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"
+ "struct VS_IN\n"
+ "{\n"
+ " float4 position : POSITION;\n"
+ " float2 texcoord : TEXCOORD0;\n"
+ " float4 normal : NORMAL;\n"
+ " float4 tangent : TANGENT;\n"
+ " float4 color : COLOR0;\n"
+ "};\n"
+ "\n"
+ "struct VS_OUT\n"
+ "{\n"
+ " float4 position : POSITION;\n"
+ " float4 color : COLOR0;\n"
+ "};\n"
+ "\n"
+ "void main( VS_IN vertex, out VS_OUT result )\n"
+ "{\n"
+ " result.position.x = dot4( vertex.position, rpMVPmatrixX );\n"
+ " result.position.y = dot4( vertex.position, rpMVPmatrixY );\n"
+ " result.position.z = dot4( vertex.position, rpMVPmatrixZ );\n"
+ " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n"
+ " \n"
+ " result.color = swizzleColor( vertex.color );\n"
+ "}\n"
+
+ },
+
{
"renderprogs/wobblesky.pixel",
"/*\n"
diff --git a/neo/renderer/RenderSystem.h b/neo/renderer/RenderSystem.h
index 95e3df1e..a9e757d7 100644
--- a/neo/renderer/RenderSystem.h
+++ b/neo/renderer/RenderSystem.h
@@ -150,6 +150,12 @@ struct glconfig_t
bool gremedyStringMarkerAvailable;
bool vertexHalfFloatAvailable;
+ bool framebufferObjectAvailable;
+ int maxRenderbufferSize;
+ int maxColorAttachments;
+// bool framebufferPackedDepthStencilAvailable;
+ bool framebufferBlitAvailable;
+
// only true with uniform buffer support and an OpenGL driver that supports GLSL >= 1.50
bool gpuSkinningAvailable;
// RB end
diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp
index d81a7913..38181e2e 100644
--- a/neo/renderer/RenderSystem_init.cpp
+++ b/neo/renderer/RenderSystem_init.cpp
@@ -186,6 +186,9 @@ idCVar r_showTangentSpace( "r_showTangentSpace", "0", CVAR_RENDERER | CVAR_INTEG
idCVar r_showDominantTri( "r_showDominantTri", "0", CVAR_RENDERER | CVAR_BOOL, "draw lines from vertexes to center of dominant triangles" );
idCVar r_showTextureVectors( "r_showTextureVectors", "0", CVAR_RENDERER | CVAR_FLOAT, " if > 0 draw each triangles texture (tangent) vectors" );
idCVar r_showOverDraw( "r_showOverDraw", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = geometry overdraw, 2 = light interaction overdraw, 3 = geometry and light interaction overdraw", 0, 3, idCmdSystem::ArgCompletion_Integer<0, 3> );
+// RB begin
+idCVar r_showShadowMaps( "r_showShadowMaps", "0", CVAR_RENDERER | CVAR_BOOL, "" );
+// RB end
idCVar r_useEntityCallbacks( "r_useEntityCallbacks", "1", CVAR_RENDERER | CVAR_BOOL, "if 0, issue the callback immediately at update time, rather than defering" );
@@ -208,6 +211,19 @@ idCVar stereoRender_deGhost( "stereoRender_deGhost", "0.05", CVAR_FLOAT | CVAR_A
idCVar r_useVirtualScreenResolution( "r_useVirtualScreenResolution", "1", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "do 2D rendering at 640x480 and stretch to the current resolution" );
+// RB: shadow mapping parameters
+idCVar r_useShadowMapping( "r_useShadowMapping", "1", CVAR_RENDERER | CVAR_BOOL, "use shadow mapping instead of stencil shadows" );
+idCVar r_shadowMapFrustumFOV( "r_shadowMapFrustumFOV", "92", CVAR_RENDERER | CVAR_FLOAT, "oversize FOV for point light side matching" );
+idCVar r_shadowMapSingleSide( "r_shadowMapSingleSide", "-1", CVAR_RENDERER | CVAR_INTEGER, "only draw a single side (0-5) of point lights" );
+idCVar r_shadowMapImageSize( "r_shadowMapImageSize", "1024", CVAR_RENDERER | CVAR_INTEGER, "", 128, 2048 );
+idCVar r_shadowMapJitterScale( "r_shadowMapJitterScale", "0.006", CVAR_RENDERER | CVAR_FLOAT, "scale factor for jitter offset" );
+idCVar r_shadowMapBiasScale( "r_shadowMapBiasScale", "0.0001", CVAR_RENDERER | CVAR_FLOAT, "scale factor for jitter bias" );
+idCVar r_shadowMapSamples( "r_shadowMapSamples", "16", CVAR_RENDERER | CVAR_INTEGER, "0, 1, 4, or 16" );
+idCVar r_shadowMapSplits( "r_shadowMapSplits", "3", CVAR_RENDERER | CVAR_INTEGER, "number of splits for cascaded shadow mapping with parallel lights", 0, 4 );
+idCVar r_shadowMapSplitWeight( "r_shadowMapSplitWeight", "0.9", CVAR_RENDERER | CVAR_FLOAT, "" );
+// RB end
+
+
/*
========================
glBindMultiTextureEXT
@@ -263,8 +279,25 @@ static void CALLBACK DebugCallback( unsigned int source, unsigned int type,
#else
printf( "%s\n", message );
#endif
+ // RB end
+}
+
+/*
+=================
+R_CheckExtension
+=================
+*/
+bool R_CheckExtension( char* name )
+{
+ if( !strstr( glConfig.extensions_string, name ) )
+ {
+ common->Printf( "X..%s not found\n", name );
+ return false;
+ }
+
+ common->Printf( "...using %s\n", name );
+ return true;
}
-// RB end
/*
==================
@@ -295,7 +328,7 @@ static void R_CheckPortableExtensions()
}
// RB: Mesa support
- if( idStr::Icmpn( glConfig.renderer_string, "Mesa", 4 ) == 0 || idStr::Icmpn( glConfig.renderer_string, "X.org", 5 ) == 0 )
+ if( idStr::Icmpn( glConfig.renderer_string, "Mesa", 4 ) == 0 || idStr::Icmpn( glConfig.renderer_string, "X.org", 4 ) == 0 )
{
glConfig.driverType = GLDRV_OPENGL_MESA;
}
@@ -361,8 +394,8 @@ static void R_CheckPortableExtensions()
glConfig.fragmentProgramAvailable = GLEW_ARB_fragment_program != 0;
if( glConfig.fragmentProgramAvailable )
{
- glGetIntegerv( GL_MAX_TEXTURE_COORDS_ARB, ( GLint* )&glConfig.maxTextureCoords );
- glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, ( GLint* )&glConfig.maxTextureImageUnits );
+ glGetIntegerv( GL_MAX_TEXTURE_COORDS, ( GLint* )&glConfig.maxTextureCoords );
+ glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS, ( GLint* )&glConfig.maxTextureImageUnits );
}
// GLSL, core in OpenGL > 2.0
@@ -399,6 +432,42 @@ static void R_CheckPortableExtensions()
// GL_ARB_timer_query
glConfig.timerQueryAvailable = ( GLEW_ARB_timer_query != 0 || GLEW_EXT_timer_query != 0 ) && ( glConfig.vendor != VENDOR_INTEL || r_skipIntelWorkarounds.GetBool() ) && glConfig.driverType != GLDRV_OPENGL_MESA;
+ // GREMEDY_string_marker
+ glConfig.gremedyStringMarkerAvailable = GLEW_GREMEDY_string_marker != 0;
+ if( glConfig.gremedyStringMarkerAvailable )
+ {
+ common->Printf( "...using %s\n", "GL_GREMEDY_string_marker" );
+ }
+ else
+ {
+ common->Printf( "X..%s not found\n", "GL_GREMEDY_string_marker" );
+ }
+
+ // GL_EXT_framebuffer_object
+ glConfig.framebufferObjectAvailable = GLEW_EXT_framebuffer_object != 0;
+ if( glConfig.framebufferObjectAvailable )
+ {
+ glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE, &glConfig.maxRenderbufferSize );
+ glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, &glConfig.maxColorAttachments );
+
+ common->Printf( "...using %s\n", "GL_EXT_framebuffer_object" );
+ }
+ else
+ {
+ common->Printf( "X..%s not found\n", "GL_EXT_framebuffer_object" );
+ }
+
+ // GL_EXT_framebuffer_blit
+ glConfig.framebufferBlitAvailable = GLEW_EXT_framebuffer_blit != 0;
+ if( glConfig.framebufferBlitAvailable )
+ {
+ common->Printf( "...using %s\n", "GL_EXT_framebuffer_blit" );
+ }
+ else
+ {
+ common->Printf( "X..%s not found\n", "GL_EXT_framebuffer_object" );
+ }
+
// GL_ARB_debug_output
glConfig.debugOutputAvailable = GLEW_ARB_debug_output != 0;
if( glConfig.debugOutputAvailable )
@@ -2255,6 +2324,10 @@ void idRenderSystemLocal::Init()
guiModel->Clear();
tr_guiModel = guiModel; // for DeviceContext fast path
+ // RB begin
+ Framebuffer::Init();
+ // RB end
+
globalImages->Init();
idCinematic::InitCinematic( );
@@ -2318,6 +2391,10 @@ void idRenderSystemLocal::Shutdown()
globalImages->Shutdown();
+ // RB begin
+ Framebuffer::Shutdown();
+ // RB end
+
// free frame memory
R_ShutdownFrameData();
diff --git a/neo/renderer/RenderWorld_portals.cpp b/neo/renderer/RenderWorld_portals.cpp
index 849a0bf0..4b492dcd 100644
--- a/neo/renderer/RenderWorld_portals.cpp
+++ b/neo/renderer/RenderWorld_portals.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -798,7 +799,7 @@ void idRenderWorldLocal::FindViewLightsAndEntities()
portalStack_t ps;
for( int i = 0; i < 5; i++ )
{
- ps.portalPlanes[i] = tr.viewDef->frustum[i];
+ ps.portalPlanes[i] = tr.viewDef->frustums[FRUSTUM_PRIMARY][i];
}
ps.numPortalPlanes = 5;
ps.rect = tr.viewDef->scissor;
@@ -811,7 +812,7 @@ void idRenderWorldLocal::FindViewLightsAndEntities()
// note that the center of projection for flowing through portals may
// be a different point than initialViewAreaOrigin for subviews that
// may have the viewOrigin in a solid/invalid area
- FlowViewThroughPortals( tr.viewDef->renderView.vieworg, 5, tr.viewDef->frustum );
+ FlowViewThroughPortals( tr.viewDef->renderView.vieworg, 5, tr.viewDef->frustums[FRUSTUM_PRIMARY] );
}
}
@@ -1197,6 +1198,10 @@ void idRenderWorldLocal::ShowPortals()
GL_Color( 0, 1, 0 );
}
+ // RB begin
+ renderProgManager.CommitUniforms();
+ // RB end
+
glBegin( GL_LINE_LOOP );
for( j = 0; j < w->GetNumPoints(); j++ )
{
diff --git a/neo/renderer/ResolutionScale.cpp b/neo/renderer/ResolutionScale.cpp
index 7d591894..e34bbe3a 100644
--- a/neo/renderer/ResolutionScale.cpp
+++ b/neo/renderer/ResolutionScale.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -37,7 +38,9 @@ idResolutionScale resolutionScale;
static const float MINIMUM_RESOLUTION_SCALE = 0.5f;
static const float MAXIMUM_RESOLUTION_SCALE = 1.0f;
-idCVar rs_enable( "rs_enable", "1", CVAR_INTEGER, "Enable dynamic resolution scaling, 0 - off, 1 - horz only, 2 - vert only, 3 - both" );
+// RB: turned this off. It is only useful on mobile devices or consoles
+idCVar rs_enable( "rs_enable", "0", CVAR_INTEGER, "Enable dynamic resolution scaling, 0 - off, 1 - horz only, 2 - vert only, 3 - both" );
+// Rb end
idCVar rs_forceFractionX( "rs_forceFractionX", "0", CVAR_FLOAT, "Force a specific 0.0 to 1.0 horizontal resolution scale" );
idCVar rs_forceFractionY( "rs_forceFractionY", "0", CVAR_FLOAT, "Force a specific 0.0 to 1.0 vertical resolution scale" );
idCVar rs_showResolutionChanges( "rs_showResolutionChanges", "0", CVAR_INTEGER, "1 = Print whenever the resolution scale changes, 2 = always" );
diff --git a/neo/renderer/tr_backend_draw.cpp b/neo/renderer/tr_backend_draw.cpp
index 8b042e0e..09b0b895 100644
--- a/neo/renderer/tr_backend_draw.cpp
+++ b/neo/renderer/tr_backend_draw.cpp
@@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
-Copyright (C) 2013 Robert Beckebans
+Copyright (C) 2013-2014 Robert Beckebans
Copyright (C) 2014 Carl Kenner
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -32,6 +32,7 @@ If you have questions concerning this license or the applicable additional terms
#include "precompiled.h"
#include "tr_local.h"
+#include "Framebuffer.h"
idCVar r_drawEyeColor( "r_drawEyeColor", "0", CVAR_RENDERER | CVAR_BOOL, "Draw a colored box, red = left eye, blue = right eye, grey = non-stereo" );
idCVar r_motionBlur( "r_motionBlur", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE, "1 - 5, log2 of the number of motion blur samples" );
@@ -646,6 +647,24 @@ static void RB_FinishStageTexturing( const shaderStage_t* pStage, const drawSurf
}
}
+// RB: moved this up because we need to call this several times for shadow mapping
+static void RB_ResetViewportAndScissorToDefaultCamera( const viewDef_t* viewDef )
+{
+ // set the window clipping
+ GL_Viewport( viewDef->viewport.x1,
+ viewDef->viewport.y1,
+ viewDef->viewport.x2 + 1 - viewDef->viewport.x1,
+ viewDef->viewport.y2 + 1 - viewDef->viewport.y1 );
+
+ // the scissor may be smaller than the viewport for subviews
+ GL_Scissor( backEnd.viewDef->viewport.x1 + viewDef->scissor.x1,
+ backEnd.viewDef->viewport.y1 + viewDef->scissor.y1,
+ viewDef->scissor.x2 + 1 - viewDef->scissor.x1,
+ viewDef->scissor.y2 + 1 - viewDef->scissor.y1 );
+ backEnd.currentScissor = viewDef->scissor;
+}
+// RB end
+
/*
=========================================================================================
@@ -710,7 +729,7 @@ static void RB_FillDepthBufferGeneric( const drawSurf_t* const* drawSurfs, int n
}
// subviews will just down-modulate the color buffer
- float color[4];
+ idVec4 color;
if( shader->GetSort() == SS_SUBVIEW )
{
surfGLState |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_LESS;
@@ -1001,6 +1020,8 @@ const int INTERACTION_TEXUNIT_FALLOFF = 1;
const int INTERACTION_TEXUNIT_PROJECTION = 2;
const int INTERACTION_TEXUNIT_DIFFUSE = 3;
const int INTERACTION_TEXUNIT_SPECULAR = 4;
+const int INTERACTION_TEXUNIT_SHADOWMAPS = 5;
+const int INTERACTION_TEXUNIT_JITTER = 6;
/*
==================
@@ -1247,6 +1268,46 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t
bool lightDepthBoundsDisabled = false;
+ // RB begin
+ if( r_useShadowMapping.GetBool() )
+ {
+ const static int JITTER_SIZE = 128;
+
+ // screen power of two correction factor
+ float screenCorrectionParm[4];
+ screenCorrectionParm[0] = 1.0f / ( JITTER_SIZE * r_shadowMapSamples.GetInteger() ) ;
+ screenCorrectionParm[1] = 1.0f / JITTER_SIZE;
+ screenCorrectionParm[2] = 0.0f;
+ screenCorrectionParm[3] = 1.0f;
+ SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor
+
+ float jitterTexScale[4];
+ jitterTexScale[0] = r_shadowMapJitterScale.GetFloat() * 1.0f; // TODO shadow buffer size fraction shadowMapSize / maxShadowMapSize
+ jitterTexScale[1] = r_shadowMapJitterScale.GetFloat() * 1.0f;
+ jitterTexScale[2] = -r_shadowMapBiasScale.GetFloat();
+ jitterTexScale[3] = 0.0f;
+ SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
+
+ float jitterTexOffset[4];
+ jitterTexOffset[0] = ( rand() & 255 ) / 255.0;
+ jitterTexOffset[1] = ( rand() & 255 ) / 255.0;
+ jitterTexOffset[2] = 0.0f;
+ jitterTexOffset[3] = 0.0f;
+ SetFragmentParm( RENDERPARM_JITTERTEXOFFSET, jitterTexOffset ); // rpJitterTexOffset
+
+ if( vLight->parallel )
+ {
+ float cascadeDistances[4];
+ cascadeDistances[0] = backEnd.viewDef->frustumSplitDistances[0];
+ cascadeDistances[1] = backEnd.viewDef->frustumSplitDistances[1];
+ cascadeDistances[2] = backEnd.viewDef->frustumSplitDistances[2];
+ cascadeDistances[3] = backEnd.viewDef->frustumSplitDistances[3];
+ SetFragmentParm( RENDERPARM_CASCADEDISTANCES, cascadeDistances ); // rpCascadeDistances
+ }
+
+ }
+ // RB end
+
for( int lightStageNum = 0; lightStageNum < lightShader->GetNumStages(); lightStageNum++ )
{
const shaderStage_t* lightStage = lightShader->GetStage( lightStageNum );
@@ -1281,6 +1342,28 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t
GL_SelectTexture( INTERACTION_TEXUNIT_PROJECTION );
lightStage->texture.image->Bind();
+ if( r_useShadowMapping.GetBool() )
+ {
+ // texture 5 will be the shadow maps array
+ GL_SelectTexture( INTERACTION_TEXUNIT_SHADOWMAPS );
+ globalImages->shadowImage->Bind();
+
+ // texture 6 will be the jitter texture for soft shadowing
+ GL_SelectTexture( INTERACTION_TEXUNIT_JITTER );
+ if( r_shadowMapSamples.GetInteger() == 16 )
+ {
+ globalImages->jitterImage16->Bind();
+ }
+ else if( r_shadowMapSamples.GetInteger() == 4 )
+ {
+ globalImages->jitterImage4->Bind();
+ }
+ else
+ {
+ globalImages->jitterImage1->Bind();
+ }
+ }
+
// force the light textures to not use anisotropic filtering, which is wasted on them
// all of the texture sampler parms should be constant for all interactions, only
// the actual texture image bindings will change
@@ -1313,13 +1396,54 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t
}
else
{
- if( surf->jointCache )
+ if( r_useShadowMapping.GetBool() && vLight->globalShadows )
{
- renderProgManager.BindShader_InteractionSkinned();
+ // RB: we have shadow mapping enabled and shadow maps so do a shadow compare
+
+ if( vLight->parallel )
+ {
+ if( surf->jointCache )
+ {
+ renderProgManager.BindShader_Interaction_ShadowMapping_Parallel_Skinned();
+ }
+ else
+ {
+ renderProgManager.BindShader_Interaction_ShadowMapping_Parallel();
+ }
+ }
+ else if( vLight->pointLight )
+ {
+ if( surf->jointCache )
+ {
+ renderProgManager.BindShader_Interaction_ShadowMapping_Point_Skinned();
+ }
+ else
+ {
+ renderProgManager.BindShader_Interaction_ShadowMapping_Point();
+ }
+ }
+ else
+ {
+ if( surf->jointCache )
+ {
+ renderProgManager.BindShader_Interaction_ShadowMapping_Spot_Skinned();
+ }
+ else
+ {
+ renderProgManager.BindShader_Interaction_ShadowMapping_Spot();
+ }
+ }
}
else
{
- renderProgManager.BindShader_Interaction();
+ if( surf->jointCache )
+ {
+ renderProgManager.BindShader_InteractionSkinned();
+ }
+ else
+ {
+ renderProgManager.BindShader_Interaction();
+ }
}
}
@@ -1357,6 +1481,21 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t
// model-view-projection
RB_SetMVP( surf->space->mvp );
+ // RB begin
+ idRenderMatrix modelMatrix;
+ idRenderMatrix::Transpose( *( idRenderMatrix* )surf->space->modelMatrix, modelMatrix );
+
+ SetVertexParms( RENDERPARM_MODELMATRIX_X, modelMatrix[0], 4 );
+
+ // for determining the shadow mapping cascades
+ idRenderMatrix modelViewMatrix, tmp;
+ idRenderMatrix::Transpose( *( idRenderMatrix* )surf->space->modelViewMatrix, modelViewMatrix );
+ SetVertexParms( RENDERPARM_MODELVIEWMATRIX_X, modelViewMatrix[0], 4 );
+
+ idVec4 globalLightOrigin( vLight->globalLightOrigin.x, vLight->globalLightOrigin.y, vLight->globalLightOrigin.z, 1.0f );
+ SetVertexParm( RENDERPARM_GLOBALLIGHTORIGIN, globalLightOrigin.ToFloatPtr() );
+ // RB end
+
// tranform the light/view origin into model local space
idVec4 localLightOrigin( 0.0f );
idVec4 localViewOrigin( 1.0f );
@@ -1385,6 +1524,57 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t
SetVertexParm( RENDERPARM_LIGHTPROJECTION_T, lightProjection[1].ToFloatPtr() );
SetVertexParm( RENDERPARM_LIGHTPROJECTION_Q, lightProjection[2].ToFloatPtr() );
SetVertexParm( RENDERPARM_LIGHTFALLOFF_S, lightProjection[3].ToFloatPtr() );
+
+ // RB begin
+ if( r_useShadowMapping.GetBool() )
+ {
+ if( vLight->parallel )
+ {
+ for( int i = 0; i < ( r_shadowMapSplits.GetInteger() + 1 ); i++ )
+ {
+ idRenderMatrix modelToShadowMatrix;
+ idRenderMatrix::Multiply( backEnd.shadowV[i], modelMatrix, modelToShadowMatrix );
+
+ idRenderMatrix shadowClipMVP;
+ idRenderMatrix::Multiply( backEnd.shadowP[i], modelToShadowMatrix, shadowClipMVP );
+
+ idRenderMatrix shadowWindowMVP;
+ idRenderMatrix::Multiply( renderMatrix_clipSpaceToWindowSpace, shadowClipMVP, shadowWindowMVP );
+
+ SetVertexParms( ( renderParm_t )( RENDERPARM_SHADOW_MATRIX_0_X + i * 4 ), shadowWindowMVP[0], 4 );
+ }
+ }
+ else if( vLight->pointLight )
+ {
+ for( int i = 0; i < 6; i++ )
+ {
+ idRenderMatrix modelToShadowMatrix;
+ idRenderMatrix::Multiply( backEnd.shadowV[i], modelMatrix, modelToShadowMatrix );
+
+ idRenderMatrix shadowClipMVP;
+ idRenderMatrix::Multiply( backEnd.shadowP[i], modelToShadowMatrix, shadowClipMVP );
+
+ idRenderMatrix shadowWindowMVP;
+ idRenderMatrix::Multiply( renderMatrix_clipSpaceToWindowSpace, shadowClipMVP, shadowWindowMVP );
+
+ SetVertexParms( ( renderParm_t )( RENDERPARM_SHADOW_MATRIX_0_X + i * 4 ), shadowWindowMVP[0], 4 );
+ }
+ }
+ else
+ {
+ // spot light
+
+ idRenderMatrix modelToShadowMatrix;
+ idRenderMatrix::Multiply( backEnd.shadowV[0], modelMatrix, modelToShadowMatrix );
+
+ idRenderMatrix shadowClipMVP;
+ idRenderMatrix::Multiply( backEnd.shadowP[0], modelToShadowMatrix, shadowClipMVP );
+
+ SetVertexParms( ( renderParm_t )( RENDERPARM_SHADOW_MATRIX_0_X ), shadowClipMVP[0], 4 );
+
+ }
+ }
+ // RB end
}
// check for the fast path
@@ -1926,6 +2116,543 @@ static void RB_StencilSelectLight( const viewLight_t* vLight )
/*
==============================================================================================
+SHADOW MAPS RENDERING
+
+==============================================================================================
+*/
+
+/*
+same as D3DXMatrixOrthoOffCenterRH
+
+http://msdn.microsoft.com/en-us/library/bb205348(VS.85).aspx
+*/
+static void MatrixOrthogonalProjectionRH( float m[16], float left, float right, float bottom, float top, float zNear, float zFar )
+{
+ m[0] = 2 / ( right - left );
+ m[4] = 0;
+ m[8] = 0;
+ m[12] = ( left + right ) / ( left - right );
+ m[1] = 0;
+ m[5] = 2 / ( top - bottom );
+ m[9] = 0;
+ m[13] = ( top + bottom ) / ( bottom - top );
+ m[2] = 0;
+ m[6] = 0;
+ m[10] = 1 / ( zNear - zFar );
+ m[14] = zNear / ( zNear - zFar );
+ m[3] = 0;
+ m[7] = 0;
+ m[11] = 0;
+ m[15] = 1;
+}
+
+void MatrixCrop( float m[16], const idVec3 mins, const idVec3 maxs )
+{
+ float scaleX, scaleY, scaleZ;
+ float offsetX, offsetY, offsetZ;
+
+ scaleX = 2.0f / ( maxs[0] - mins[0] );
+ scaleY = 2.0f / ( maxs[1] - mins[1] );
+
+ offsetX = -0.5f * ( maxs[0] + mins[0] ) * scaleX;
+ offsetY = -0.5f * ( maxs[1] + mins[1] ) * scaleY;
+
+ scaleZ = 1.0f / ( maxs[2] - mins[2] );
+ offsetZ = -mins[2] * scaleZ;
+
+ m[ 0] = scaleX;
+ m[ 4] = 0;
+ m[ 8] = 0;
+ m[12] = offsetX;
+ m[ 1] = 0;
+ m[ 5] = scaleY;
+ m[ 9] = 0;
+ m[13] = offsetY;
+ m[ 2] = 0;
+ m[ 6] = 0;
+ m[10] = scaleZ;
+ m[14] = offsetZ;
+ m[ 3] = 0;
+ m[ 7] = 0;
+ m[11] = 0;
+ m[15] = 1;
+}
+
+void MatrixLookAtRH( float m[16], const idVec3& eye, const idVec3& dir, const idVec3& up )
+{
+ idVec3 dirN;
+ idVec3 upN;
+ idVec3 sideN;
+
+ sideN = dir.Cross( up );
+ sideN.Normalize();
+
+ upN = sideN.Cross( dir );
+ upN.Normalize();
+
+ dirN = dir;
+ dirN.Normalize();
+
+ m[ 0] = sideN[0];
+ m[ 4] = sideN[1];
+ m[ 8] = sideN[2];
+ m[12] = -( sideN * eye );
+ m[ 1] = upN[0];
+ m[ 5] = upN[1];
+ m[ 9] = upN[2];
+ m[13] = -( upN * eye );
+ m[ 2] = -dirN[0];
+ m[ 6] = -dirN[1];
+ m[10] = -dirN[2];
+ m[14] = ( dirN * eye );
+ m[ 3] = 0;
+ m[ 7] = 0;
+ m[11] = 0;
+ m[15] = 1;
+}
+
+/*
+=====================
+RB_ShadowMapPass
+=====================
+*/
+static void RB_ShadowMapPass( const drawSurf_t* drawSurfs, const viewLight_t* vLight, int side )
+{
+ if( r_skipShadows.GetBool() )
+ {
+ return;
+ }
+
+ if( drawSurfs == NULL )
+ {
+ return;
+ }
+
+ RENDERLOG_PRINTF( "---------- RB_ShadowMapPass( side = %i ) ----------\n", side );
+
+ renderProgManager.BindShader_Depth();
+
+ GL_SelectTexture( 0 );
+ globalImages->BindNull();
+
+ uint64 glState = 0;
+
+ GL_PolygonOffset( r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat() );
+
+
+ // the actual stencil func will be set in the draw code, but we need to make sure it isn't
+ // disabled here, and that the value will get reset for the interactions without looking
+ // like a no-change-required
+ GL_State( glState | GLS_POLYGON_OFFSET );
+
+ // Two Sided Stencil reduces two draw calls to one for slightly faster shadows
+ GL_Cull( CT_TWO_SIDED );
+
+ idRenderMatrix lightProjectionRenderMatrix;
+ idRenderMatrix lightViewRenderMatrix;
+
+
+ if( vLight->parallel && side >= 0 )
+ {
+ assert( side >= 0 && side < 6 );
+
+ // original light direction is from surface to light origin
+ idVec3 lightDir = -vLight->lightCenter;
+ if( lightDir.Normalize() == 0.0f )
+ {
+ lightDir[2] = -1.0f;
+ }
+
+ idMat3 rotation = lightDir.ToMat3();
+ //idAngles angles = lightDir.ToAngles();
+ //idMat3 rotation = angles.ToMat3();
+
+ const idVec3 viewDir = backEnd.viewDef->renderView.viewaxis[0];
+ const idVec3 viewPos = backEnd.viewDef->renderView.vieworg;
+
+#if 1
+ idRenderMatrix::CreateViewMatrix( backEnd.viewDef->renderView.vieworg, rotation, lightViewRenderMatrix );
+#else
+ float lightViewMatrix[16];
+ MatrixLookAtRH( lightViewMatrix, viewPos, lightDir, viewDir );
+ idRenderMatrix::Transpose( *( idRenderMatrix* )lightViewMatrix, lightViewRenderMatrix );
+#endif
+
+ idBounds lightBounds;
+ lightBounds.Clear();
+
+ ALIGNTYPE16 frustumCorners_t corners;
+ idRenderMatrix::GetFrustumCorners( corners, vLight->inverseBaseLightProject, bounds_zeroOneCube );
+
+ idVec4 point, transf;
+ for( int j = 0; j < 8; j++ )
+ {
+ point[0] = corners.x[j];
+ point[1] = corners.y[j];
+ point[2] = corners.z[j];
+ point[3] = 1;
+
+ lightViewRenderMatrix.TransformPoint( point, transf );
+ transf[0] /= transf[3];
+ transf[1] /= transf[3];
+ transf[2] /= transf[3];
+
+ lightBounds.AddPoint( transf.ToVec3() );
+ }
+
+ float lightProjectionMatrix[16];
+ MatrixOrthogonalProjectionRH( lightProjectionMatrix, lightBounds[0][0], lightBounds[1][0], lightBounds[0][1], lightBounds[1][1], -lightBounds[1][2], -lightBounds[0][2] );
+ idRenderMatrix::Transpose( *( idRenderMatrix* )lightProjectionMatrix, lightProjectionRenderMatrix );
+
+
+ // 'frustumMVP' goes from global space -> camera local space -> camera projective space
+ // invert the MVP projection so we can deform zero-to-one cubes into the frustum pyramid shape and calculate global bounds
+
+ idRenderMatrix splitFrustumInverse;
+ if( !idRenderMatrix::Inverse( backEnd.viewDef->frustumMVPs[FRUSTUM_CASCADE1 + side], splitFrustumInverse ) )
+ {
+ idLib::Warning( "splitFrustumMVP invert failed" );
+ }
+
+ // splitFrustumCorners in global space
+ ALIGNTYPE16 frustumCorners_t splitFrustumCorners;
+ idRenderMatrix::GetFrustumCorners( splitFrustumCorners, splitFrustumInverse, bounds_unitCube );
+
+#if 0
+ idBounds splitFrustumBounds;
+ splitFrustumBounds.Clear();
+ for( int j = 0; j < 8; j++ )
+ {
+ point[0] = splitFrustumCorners.x[j];
+ point[1] = splitFrustumCorners.y[j];
+ point[2] = splitFrustumCorners.z[j];
+
+ splitFrustumBounds.AddPoint( point.ToVec3() );
+ }
+
+ idVec3 center = splitFrustumBounds.GetCenter();
+ float radius = splitFrustumBounds.GetRadius( center );
+
+ //ALIGNTYPE16 frustumCorners_t splitFrustumCorners;
+ splitFrustumBounds[0] = idVec3( -radius, -radius, -radius );
+ splitFrustumBounds[1] = idVec3( radius, radius, radius );
+ splitFrustumBounds.TranslateSelf( viewPos );
+ idVec3 splitFrustumCorners2[8];
+ splitFrustumBounds.ToPoints( splitFrustumCorners2 );
+
+ for( int j = 0; j < 8; j++ )
+ {
+ splitFrustumCorners.x[j] = splitFrustumCorners2[j].x;
+ splitFrustumCorners.y[j] = splitFrustumCorners2[j].y;
+ splitFrustumCorners.z[j] = splitFrustumCorners2[j].z;
+ }
+#endif
+
+
+ idRenderMatrix lightViewProjectionRenderMatrix;
+ idRenderMatrix::Multiply( lightProjectionRenderMatrix, lightViewRenderMatrix, lightViewProjectionRenderMatrix );
+
+ // find the bounding box of the current split in the light's clip space
+ idBounds cropBounds;
+ cropBounds.Clear();
+ for( int j = 0; j < 8; j++ )
+ {
+ point[0] = splitFrustumCorners.x[j];
+ point[1] = splitFrustumCorners.y[j];
+ point[2] = splitFrustumCorners.z[j];
+ point[3] = 1;
+
+ lightViewRenderMatrix.TransformPoint( point, transf );
+ transf[0] /= transf[3];
+ transf[1] /= transf[3];
+ transf[2] /= transf[3];
+
+ cropBounds.AddPoint( transf.ToVec3() );
+ }
+
+ // don't let the frustum AABB be bigger than the light AABB
+ if( cropBounds[0][0] < lightBounds[0][0] )
+ {
+ cropBounds[0][0] = lightBounds[0][0];
+ }
+
+ if( cropBounds[0][1] < lightBounds[0][1] )
+ {
+ cropBounds[0][1] = lightBounds[0][1];
+ }
+
+ if( cropBounds[1][0] > lightBounds[1][0] )
+ {
+ cropBounds[1][0] = lightBounds[1][0];
+ }
+
+ if( cropBounds[1][1] > lightBounds[1][1] )
+ {
+ cropBounds[1][1] = lightBounds[1][1];
+ }
+
+ cropBounds[0][2] = lightBounds[0][2];
+ cropBounds[1][2] = lightBounds[1][2];
+
+ //float cropMatrix[16];
+ //MatrixCrop(cropMatrix, cropBounds[0], cropBounds[1]);
+
+ //idRenderMatrix cropRenderMatrix;
+ //idRenderMatrix::Transpose( *( idRenderMatrix* )cropMatrix, cropRenderMatrix );
+
+ //idRenderMatrix tmp = lightProjectionRenderMatrix;
+ //idRenderMatrix::Multiply( cropRenderMatrix, tmp, lightProjectionRenderMatrix );
+
+ MatrixOrthogonalProjectionRH( lightProjectionMatrix, cropBounds[0][0], cropBounds[1][0], cropBounds[0][1], cropBounds[1][1], -cropBounds[1][2], -cropBounds[0][2] );
+ idRenderMatrix::Transpose( *( idRenderMatrix* )lightProjectionMatrix, lightProjectionRenderMatrix );
+
+ backEnd.shadowV[side] = lightViewRenderMatrix;
+ backEnd.shadowP[side] = lightProjectionRenderMatrix;
+ }
+ else if( vLight->pointLight && side >= 0 )
+ {
+ assert( side >= 0 && side < 6 );
+
+ // FIXME OPTIMIZE no memset
+
+ float viewMatrix[16];
+
+ idVec3 vec;
+ idVec3 origin = vLight->globalLightOrigin;
+
+ // side of a point light
+ memset( viewMatrix, 0, sizeof( viewMatrix ) );
+ switch( side )
+ {
+ case 0:
+ viewMatrix[0] = 1;
+ viewMatrix[9] = 1;
+ viewMatrix[6] = -1;
+ break;
+ case 1:
+ viewMatrix[0] = -1;
+ viewMatrix[9] = -1;
+ viewMatrix[6] = -1;
+ break;
+ case 2:
+ viewMatrix[4] = 1;
+ viewMatrix[1] = -1;
+ viewMatrix[10] = 1;
+ break;
+ case 3:
+ viewMatrix[4] = -1;
+ viewMatrix[1] = -1;
+ viewMatrix[10] = -1;
+ break;
+ case 4:
+ viewMatrix[8] = 1;
+ viewMatrix[1] = -1;
+ viewMatrix[6] = -1;
+ break;
+ case 5:
+ viewMatrix[8] = -1;
+ viewMatrix[1] = 1;
+ viewMatrix[6] = -1;
+ break;
+ }
+
+ viewMatrix[12] = -origin[0] * viewMatrix[0] + -origin[1] * viewMatrix[4] + -origin[2] * viewMatrix[8];
+ viewMatrix[13] = -origin[0] * viewMatrix[1] + -origin[1] * viewMatrix[5] + -origin[2] * viewMatrix[9];
+ viewMatrix[14] = -origin[0] * viewMatrix[2] + -origin[1] * viewMatrix[6] + -origin[2] * viewMatrix[10];
+
+ viewMatrix[3] = 0;
+ viewMatrix[7] = 0;
+ viewMatrix[11] = 0;
+ viewMatrix[15] = 1;
+
+ // from world space to light origin, looking down the X axis
+ float unflippedLightViewMatrix[16];
+
+ // from world space to OpenGL view space, looking down the negative Z axis
+ float lightViewMatrix[16];
+
+ static float s_flipMatrix[16] =
+ {
+ // convert from our coordinate system (looking down X)
+ // to OpenGL's coordinate system (looking down -Z)
+ 0, 0, -1, 0,
+ -1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1
+ };
+
+ memcpy( unflippedLightViewMatrix, viewMatrix, sizeof( unflippedLightViewMatrix ) );
+ R_MatrixMultiply( viewMatrix, s_flipMatrix, lightViewMatrix );
+
+ idRenderMatrix::Transpose( *( idRenderMatrix* )lightViewMatrix, lightViewRenderMatrix );
+
+
+
+
+ // set up 90 degree projection matrix
+ const float zNear = 4;
+ const float fov = r_shadowMapFrustumFOV.GetFloat();
+
+ float ymax = zNear * tan( fov * idMath::PI / 360.0f );
+ float ymin = -ymax;
+
+ float xmax = zNear * tan( fov * idMath::PI / 360.0f );
+ float xmin = -xmax;
+
+ const float width = xmax - xmin;
+ const float height = ymax - ymin;
+
+ // from OpenGL view space to OpenGL NDC ( -1 : 1 in XYZ )
+ float lightProjectionMatrix[16];
+
+ lightProjectionMatrix[0 * 4 + 0] = 2.0f * zNear / width;
+ lightProjectionMatrix[1 * 4 + 0] = 0.0f;
+ lightProjectionMatrix[2 * 4 + 0] = ( xmax + xmin ) / width; // normally 0
+ lightProjectionMatrix[3 * 4 + 0] = 0.0f;
+
+ lightProjectionMatrix[0 * 4 + 1] = 0.0f;
+ lightProjectionMatrix[1 * 4 + 1] = 2.0f * zNear / height;
+ lightProjectionMatrix[2 * 4 + 1] = ( ymax + ymin ) / height; // normally 0
+ lightProjectionMatrix[3 * 4 + 1] = 0.0f;
+
+ // this is the far-plane-at-infinity formulation, and
+ // crunches the Z range slightly so w=0 vertexes do not
+ // rasterize right at the wraparound point
+ lightProjectionMatrix[0 * 4 + 2] = 0.0f;
+ lightProjectionMatrix[1 * 4 + 2] = 0.0f;
+ lightProjectionMatrix[2 * 4 + 2] = -0.999f; // adjust value to prevent imprecision issues
+ lightProjectionMatrix[3 * 4 + 2] = -2.0f * zNear;
+
+ lightProjectionMatrix[0 * 4 + 3] = 0.0f;
+ lightProjectionMatrix[1 * 4 + 3] = 0.0f;
+ lightProjectionMatrix[2 * 4 + 3] = -1.0f;
+ lightProjectionMatrix[3 * 4 + 3] = 0.0f;
+
+ idRenderMatrix::Transpose( *( idRenderMatrix* )lightProjectionMatrix, lightProjectionRenderMatrix );
+
+ backEnd.shadowV[side] = lightViewRenderMatrix;
+ backEnd.shadowP[side] = lightProjectionRenderMatrix;
+ }
+ else
+ {
+ lightViewRenderMatrix.Identity();
+ lightProjectionRenderMatrix = vLight->baseLightProject;
+
+ backEnd.shadowV[0] = lightViewRenderMatrix;
+ backEnd.shadowP[0] = lightProjectionRenderMatrix;
+ }
+
+
+
+ globalFramebuffers.shadowFBO->Bind();
+
+ if( side < 0 )
+ {
+ globalFramebuffers.shadowFBO->AttachImageDepthLayer( globalImages->shadowImage, 0 );
+ }
+ else
+ {
+ globalFramebuffers.shadowFBO->AttachImageDepthLayer( globalImages->shadowImage, side );
+ }
+
+ globalFramebuffers.shadowFBO->Check();
+
+ GL_ViewportAndScissor( 0, 0, r_shadowMapImageSize.GetInteger(), r_shadowMapImageSize.GetInteger() );
+
+ glClear( GL_DEPTH_BUFFER_BIT );
+
+ // process the chain of shadows with the current rendering state
+ backEnd.currentSpace = NULL;
+
+ for( const drawSurf_t* drawSurf = drawSurfs; drawSurf != NULL; drawSurf = drawSurf->nextOnLight )
+ {
+
+#if 1
+ // make sure the shadow occluder geometry is done
+ if( drawSurf->shadowVolumeState != SHADOWVOLUME_DONE )
+ {
+ assert( drawSurf->shadowVolumeState == SHADOWVOLUME_UNFINISHED || drawSurf->shadowVolumeState == SHADOWVOLUME_DONE );
+
+ uint64 start = Sys_Microseconds();
+ while( drawSurf->shadowVolumeState == SHADOWVOLUME_UNFINISHED )
+ {
+ Sys_Yield();
+ }
+ uint64 end = Sys_Microseconds();
+
+ backEnd.pc.shadowMicroSec += end - start;
+ }
+#endif
+
+ if( drawSurf->numIndexes == 0 )
+ {
+ continue; // a job may have created an empty shadow geometry
+ }
+
+ if( drawSurf->space != backEnd.currentSpace )
+ {
+
+ idRenderMatrix modelRenderMatrix;
+ idRenderMatrix::Transpose( *( idRenderMatrix* )drawSurf->space->modelMatrix, modelRenderMatrix );
+
+ idRenderMatrix modelToLightRenderMatrix;
+ idRenderMatrix::Multiply( lightViewRenderMatrix, modelRenderMatrix, modelToLightRenderMatrix );
+
+ idRenderMatrix clipMVP;
+ idRenderMatrix::Multiply( lightProjectionRenderMatrix, modelToLightRenderMatrix, clipMVP );
+
+ if( vLight->parallel )
+ {
+ idRenderMatrix MVP;
+ idRenderMatrix::Multiply( renderMatrix_clipSpaceToWindowSpace, clipMVP, MVP );
+
+ RB_SetMVP( clipMVP );
+ }
+ else if( side < 0 )
+ {
+ // from OpenGL view space to OpenGL NDC ( -1 : 1 in XYZ )
+ idRenderMatrix MVP;
+ idRenderMatrix::Multiply( renderMatrix_windowSpaceToClipSpace, clipMVP, MVP );
+
+ RB_SetMVP( MVP );
+ }
+ else
+ {
+ RB_SetMVP( clipMVP );
+ }
+
+ // set the local light position to allow the vertex program to project the shadow volume end cap to infinity
+ /*
+ idVec4 localLight( 0.0f );
+ R_GlobalPointToLocal( drawSurf->space->modelMatrix, vLight->globalLightOrigin, localLight.ToVec3() );
+ SetVertexParm( RENDERPARM_LOCALLIGHTORIGIN, localLight.ToFloatPtr() );
+ */
+
+ backEnd.currentSpace = drawSurf->space;
+ }
+
+ if( drawSurf->jointCache )
+ {
+ renderProgManager.BindShader_DepthSkinned();
+ }
+ else
+ {
+ renderProgManager.BindShader_Depth();
+ }
+
+ RB_DrawElementsWithCounters( drawSurf );
+ }
+
+ // cleanup the shadow specific rendering state
+
+ Framebuffer::BindNull();
+
+ GL_Cull( CT_FRONT_SIDED );
+}
+
+/*
+==============================================================================================
+
DRAW INTERACTIONS
==============================================================================================
@@ -1935,7 +2662,7 @@ DRAW INTERACTIONS
RB_DrawInteractions
==================
*/
-static void RB_DrawInteractions()
+static void RB_DrawInteractions( const viewDef_t* viewDef )
{
if( r_skipInteractions.GetBool() )
{
@@ -1948,7 +2675,7 @@ static void RB_DrawInteractions()
GL_SelectTexture( 0 );
- const bool useLightDepthBounds = r_useLightDepthBounds.GetBool();
+ const bool useLightDepthBounds = r_useLightDepthBounds.GetBool() && !r_useShadowMapping.GetBool();
//
// for each light, perform shadowing and adding
@@ -1979,70 +2706,124 @@ static void RB_DrawInteractions()
GL_DepthBoundsTest( vLight->scissorRect.zmin, vLight->scissorRect.zmax );
}
- // only need to clear the stencil buffer and perform stencil testing if there are shadows
- const bool performStencilTest = ( vLight->globalShadows != NULL || vLight->localShadows != NULL );
-
- // mirror flips the sense of the stencil select, and I don't want to risk accidentally breaking it
- // in the normal case, so simply disable the stencil select in the mirror case
- const bool useLightStencilSelect = ( r_useLightStencilSelect.GetBool() && backEnd.viewDef->isMirror == false );
-
- if( performStencilTest )
+ // RB: shadow mapping
+ if( r_useShadowMapping.GetBool() )
{
- if( useLightStencilSelect )
+ int side, sideStop;
+
+ if( vLight->parallel )
{
- // write a stencil mask for the visible light bounds to hi-stencil
- RB_StencilSelectLight( vLight );
+ side = 0;
+ sideStop = r_shadowMapSplits.GetInteger() + 1;
+ }
+ else if( vLight->pointLight )
+ {
+ if( r_shadowMapSingleSide.GetInteger() != -1 )
+ {
+ side = r_shadowMapSingleSide.GetInteger();
+ sideStop = side + 1;
+ }
+ else
+ {
+ side = 0;
+ sideStop = 6;
+ }
}
else
{
- // always clear whole S-Cull tiles
- idScreenRect rect;
- rect.x1 = ( vLight->scissorRect.x1 + 0 ) & ~15;
- rect.y1 = ( vLight->scissorRect.y1 + 0 ) & ~15;
- rect.x2 = ( vLight->scissorRect.x2 + 15 ) & ~15;
- rect.y2 = ( vLight->scissorRect.y2 + 15 ) & ~15;
-
- if( !backEnd.currentScissor.Equals( rect ) && r_useScissor.GetBool() )
- {
- GL_Scissor( backEnd.viewDef->viewport.x1 + rect.x1,
- backEnd.viewDef->viewport.y1 + rect.y1,
- rect.x2 + 1 - rect.x1,
- rect.y2 + 1 - rect.y1 );
- backEnd.currentScissor = rect;
- }
- GL_State( GLS_DEFAULT ); // make sure stencil mask passes for the clear
- GL_Clear( false, false, true, STENCIL_SHADOW_TEST_VALUE, 0.0f, 0.0f, 0.0f, 0.0f );
+ side = -1;
+ sideStop = 0;
+ }
+
+ for( ; side < sideStop ; side++ )
+ {
+ RB_ShadowMapPass( vLight->globalShadows, vLight, side );
+ }
+
+ // go back from light view to default camera view
+ RB_ResetViewportAndScissorToDefaultCamera( viewDef );
+
+ if( vLight->localInteractions != NULL )
+ {
+ renderLog.OpenBlock( "Local Light Interactions" );
+ RB_RenderInteractions( vLight->localInteractions, vLight, GLS_DEPTHFUNC_EQUAL, false, useLightDepthBounds );
+ renderLog.CloseBlock();
+ }
+
+ if( vLight->globalInteractions != NULL )
+ {
+ renderLog.OpenBlock( "Global Light Interactions" );
+ RB_RenderInteractions( vLight->globalInteractions, vLight, GLS_DEPTHFUNC_EQUAL, false, useLightDepthBounds );
+ renderLog.CloseBlock();
}
}
-
- if( vLight->globalShadows != NULL )
+ else
{
- renderLog.OpenBlock( "Global Light Shadows" );
- RB_StencilShadowPass( vLight->globalShadows, vLight );
- renderLog.CloseBlock();
+ // only need to clear the stencil buffer and perform stencil testing if there are shadows
+ const bool performStencilTest = ( vLight->globalShadows != NULL || vLight->localShadows != NULL ) && !r_useShadowMapping.GetBool();
+
+ // mirror flips the sense of the stencil select, and I don't want to risk accidentally breaking it
+ // in the normal case, so simply disable the stencil select in the mirror case
+ const bool useLightStencilSelect = ( r_useLightStencilSelect.GetBool() && backEnd.viewDef->isMirror == false );
+
+ if( performStencilTest )
+ {
+ if( useLightStencilSelect )
+ {
+ // write a stencil mask for the visible light bounds to hi-stencil
+ RB_StencilSelectLight( vLight );
+ }
+ else
+ {
+ // always clear whole S-Cull tiles
+ idScreenRect rect;
+ rect.x1 = ( vLight->scissorRect.x1 + 0 ) & ~15;
+ rect.y1 = ( vLight->scissorRect.y1 + 0 ) & ~15;
+ rect.x2 = ( vLight->scissorRect.x2 + 15 ) & ~15;
+ rect.y2 = ( vLight->scissorRect.y2 + 15 ) & ~15;
+
+ if( !backEnd.currentScissor.Equals( rect ) && r_useScissor.GetBool() )
+ {
+ GL_Scissor( backEnd.viewDef->viewport.x1 + rect.x1,
+ backEnd.viewDef->viewport.y1 + rect.y1,
+ rect.x2 + 1 - rect.x1,
+ rect.y2 + 1 - rect.y1 );
+ backEnd.currentScissor = rect;
+ }
+ GL_State( GLS_DEFAULT ); // make sure stencil mask passes for the clear
+ GL_Clear( false, false, true, STENCIL_SHADOW_TEST_VALUE, 0.0f, 0.0f, 0.0f, 0.0f );
+ }
+ }
+
+ if( vLight->globalShadows != NULL )
+ {
+ renderLog.OpenBlock( "Global Light Shadows" );
+ RB_StencilShadowPass( vLight->globalShadows, vLight );
+ renderLog.CloseBlock();
+ }
+
+ if( vLight->localInteractions != NULL )
+ {
+ renderLog.OpenBlock( "Local Light Interactions" );
+ RB_RenderInteractions( vLight->localInteractions, vLight, GLS_DEPTHFUNC_EQUAL, performStencilTest, useLightDepthBounds );
+ renderLog.CloseBlock();
+ }
+
+ if( vLight->localShadows != NULL )
+ {
+ renderLog.OpenBlock( "Local Light Shadows" );
+ RB_StencilShadowPass( vLight->localShadows, vLight );
+ renderLog.CloseBlock();
+ }
+
+ if( vLight->globalInteractions != NULL )
+ {
+ renderLog.OpenBlock( "Global Light Interactions" );
+ RB_RenderInteractions( vLight->globalInteractions, vLight, GLS_DEPTHFUNC_EQUAL, performStencilTest, useLightDepthBounds );
+ renderLog.CloseBlock();
+ }
}
-
- if( vLight->localInteractions != NULL )
- {
- renderLog.OpenBlock( "Local Light Interactions" );
- RB_RenderInteractions( vLight->localInteractions, vLight, GLS_DEPTHFUNC_EQUAL, performStencilTest, useLightDepthBounds );
- renderLog.CloseBlock();
- }
-
- if( vLight->localShadows != NULL )
- {
- renderLog.OpenBlock( "Local Light Shadows" );
- RB_StencilShadowPass( vLight->localShadows, vLight );
- renderLog.CloseBlock();
- }
-
- if( vLight->globalInteractions != NULL )
- {
- renderLog.OpenBlock( "Global Light Interactions" );
- RB_RenderInteractions( vLight->globalInteractions, vLight, GLS_DEPTHFUNC_EQUAL, performStencilTest, useLightDepthBounds );
- renderLog.CloseBlock();
- }
-
+ // RB end
if( vLight->translucentInteractions != NULL && !r_skipTranslucent.GetBool() )
{
@@ -2366,7 +3147,7 @@ static int RB_DrawShaderPasses( const drawSurf_t* const* const drawSurfs, const
//--------------------------
// set the color
- float color[4];
+ idVec4 color;
color[0] = regs[ pStage->color.registers[0] ];
color[1] = regs[ pStage->color.registers[1] ];
color[2] = regs[ pStage->color.registers[2] ];
@@ -2602,7 +3383,7 @@ static void RB_BlendLight( const drawSurf_t* drawSurfs, const drawSurf_t* drawSu
}
// get the modulate values from the light, including alpha, unlike normal lights
- float lightColor[4];
+ idVec4 lightColor;
lightColor[0] = regs[ stage->color.registers[0] ];
lightColor[1] = regs[ stage->color.registers[1] ];
lightColor[2] = regs[ stage->color.registers[2] ];
@@ -2715,7 +3496,7 @@ static void RB_FogPass( const drawSurf_t* drawSurfs, const drawSurf_t* drawSurf
// assume fog shaders have only a single stage
const shaderStage_t* stage = lightShader->GetStage( 0 );
- float lightColor[4];
+ idVec4 lightColor;
lightColor[0] = regs[ stage->color.registers[0] ];
lightColor[1] = regs[ stage->color.registers[1] ];
lightColor[2] = regs[ stage->color.registers[2] ];
@@ -2878,19 +3659,7 @@ void RB_DrawViewInternal( const viewDef_t* viewDef, const int stereoEye )
//
// clear the z buffer, set the projection matrix, etc
//-------------------------------------------------
-
- // set the window clipping
- GL_Viewport( viewDef->viewport.x1,
- viewDef->viewport.y1,
- viewDef->viewport.x2 + 1 - viewDef->viewport.x1,
- viewDef->viewport.y2 + 1 - viewDef->viewport.y1 );
-
- // the scissor may be smaller than the viewport for subviews
- GL_Scissor( backEnd.viewDef->viewport.x1 + viewDef->scissor.x1,
- backEnd.viewDef->viewport.y1 + viewDef->scissor.y1,
- viewDef->scissor.x2 + 1 - viewDef->scissor.x1,
- viewDef->scissor.y2 + 1 - viewDef->scissor.y1 );
- backEnd.currentScissor = viewDef->scissor;
+ RB_ResetViewportAndScissorToDefaultCamera( viewDef );
backEnd.glState.faceCulling = -1; // force face culling to set next time
@@ -2950,7 +3719,7 @@ void RB_DrawViewInternal( const viewDef_t* viewDef, const int stereoEye )
//-------------------------------------------------
// main light renderer
//-------------------------------------------------
- RB_DrawInteractions();
+ RB_DrawInteractions( viewDef );
//-------------------------------------------------
// now draw any non-light dependent shading passes
diff --git a/neo/renderer/tr_backend_rendertools.cpp b/neo/renderer/tr_backend_rendertools.cpp
index a1628aea..e78c2f71 100644
--- a/neo/renderer/tr_backend_rendertools.cpp
+++ b/neo/renderer/tr_backend_rendertools.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -136,7 +137,10 @@ static void RB_SimpleSurfaceSetup( const drawSurf_t* drawSurf )
// change the matrix if needed
if( drawSurf->space != backEnd.currentSpace )
{
- glLoadMatrixf( drawSurf->space->modelViewMatrix );
+ // RB begin
+ RB_SetMVP( drawSurf->space->mvp );
+ //qglLoadMatrixf( drawSurf->space->modelViewMatrix );
+ // RB end
backEnd.currentSpace = drawSurf->space;
}
@@ -160,8 +164,10 @@ static void RB_SimpleWorldSetup()
{
backEnd.currentSpace = &backEnd.viewDef->worldSpace;
-
- glLoadMatrixf( backEnd.viewDef->worldSpace.modelViewMatrix );
+ // RB begin
+ //qglLoadMatrixf( backEnd.viewDef->worldSpace.modelViewMatrix );
+ RB_SetMVP( backEnd.viewDef->worldSpace.mvp );
+ // RB end
GL_Scissor( backEnd.viewDef->viewport.x1 + backEnd.viewDef->scissor.x1,
backEnd.viewDef->viewport.y1 + backEnd.viewDef->scissor.y1,
@@ -289,16 +295,16 @@ stencil buffer. Stencil of 0 = black, 1 = red, 2 = green,
static void R_ColorByStencilBuffer()
{
int i;
- static float colors[8][3] =
+ static idVec3 colors[8] =
{
- {0, 0, 0},
- {1, 0, 0},
- {0, 1, 0},
- {0, 0, 1},
- {0, 1, 1},
- {1, 0, 1},
- {1, 1, 0},
- {1, 1, 1},
+ idVec3( 0, 0, 0 ),
+ idVec3( 1, 0, 0 ),
+ idVec3( 0, 1, 0 ),
+ idVec3( 0, 0, 1 ),
+ idVec3( 0, 1, 1 ),
+ idVec3( 1, 0, 1 ),
+ idVec3( 1, 1, 0 ),
+ idVec3( 1, 1, 1 ),
};
// clear color buffer to white (>6 passes)
@@ -683,6 +689,17 @@ static void RB_RenderDrawSurfListWithFunction( drawSurf_t** drawSurfs, int numDr
continue;
}
assert( drawSurf->space != NULL );
+
+ // RB begin
+#if 1
+ if( drawSurf->space != backEnd.currentSpace )
+ {
+ backEnd.currentSpace = drawSurf->space;
+
+ RB_SetMVP( drawSurf->space->mvp );
+ }
+#else
+
if( drawSurf->space != NULL ) // is it ever NULL? Do we need to check?
{
// Set these values ahead of time so we don't have to reconstruct the matrices on the consoles
@@ -690,28 +707,39 @@ static void RB_RenderDrawSurfListWithFunction( drawSurf_t** drawSurfs, int numDr
{
RB_SetWeaponDepthHack();
}
-
+
if( drawSurf->space->modelDepthHack != 0.0f )
{
RB_SetModelDepthHack( drawSurf->space->modelDepthHack );
}
-
+
// change the matrix if needed
if( drawSurf->space != backEnd.currentSpace )
{
RB_LoadMatrixWithBypass( drawSurf->space->modelViewMatrix );
}
-
+
if( drawSurf->space->weaponDepthHack )
{
RB_EnterWeaponDepthHack();
}
-
+
if( drawSurf->space->modelDepthHack != 0.0f )
{
RB_EnterModelDepthHack( drawSurf->space->modelDepthHack );
}
}
+#endif
+
+ if( drawSurf->jointCache )
+ {
+ renderProgManager.BindShader_ColorSkinned();
+ }
+ else
+ {
+ renderProgManager.BindShader_Color();
+ }
+ // RB end
// change the scissor if needed
if( r_useScissor.GetBool() && !backEnd.currentScissor.Equals( drawSurf->scissorRect ) )
@@ -726,10 +754,12 @@ static void RB_RenderDrawSurfListWithFunction( drawSurf_t** drawSurfs, int numDr
// render it
triFunc_( drawSurf );
- if( drawSurf->space != NULL && ( drawSurf->space->weaponDepthHack || drawSurf->space->modelDepthHack != 0.0f ) )
+ // RB begin
+ /*if( drawSurf->space != NULL && ( drawSurf->space->weaponDepthHack || drawSurf->space->modelDepthHack != 0.0f ) )
{
RB_LeaveDepthHack();
- }
+ }*/
+ // RB end
backEnd.currentSpace = drawSurf->space;
}
@@ -756,11 +786,12 @@ static void RB_ShowSilhouette()
return;
}
- //
// clear all triangle edges to black
- //
globalImages->BindNull();
- glDisable( GL_TEXTURE_2D );
+
+ // RB begin
+ renderProgManager.BindShader_Color();
+ // RB end
GL_Color( 0, 0, 0 );
@@ -772,9 +803,7 @@ static void RB_ShowSilhouette()
RB_DrawElementsWithCounters );
- //
// now blend in edges that cast silhouettes
- //
RB_SimpleWorldSetup();
GL_Color( 0.5, 0, 0 );
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
@@ -853,7 +882,7 @@ static void RB_ShowTris( drawSurf_t** drawSurfs, int numDrawSurfs )
return;
}
- float color[4] = { 1, 1, 1, 1 };
+ idVec4 color( 1, 1, 1, 1 );
GL_PolygonOffset( -1.0f, -2.0f );
@@ -878,7 +907,6 @@ static void RB_ShowTris( drawSurf_t** drawSurfs, int numDrawSurfs )
}
GL_Color( color );
- renderProgManager.BindShader_Color();
RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_DrawElementsWithCounters );
@@ -914,7 +942,6 @@ static void RB_ShowSurfaceInfo( drawSurf_t** drawSurfs, int numDrawSurfs )
}
globalImages->BindNull();
- glDisable( GL_TEXTURE_2D );
GL_Color( 1, 1, 1 );
@@ -949,6 +976,7 @@ static void RB_ShowViewEntitys( viewEntity_t* vModels )
{
return;
}
+
if( r_showViewEntitys.GetInteger() >= 2 )
{
common->Printf( "view entities: " );
@@ -978,7 +1006,7 @@ static void RB_ShowViewEntitys( viewEntity_t* vModels )
{
idBounds b;
- glLoadMatrixf( vModel->modelViewMatrix );
+ //glLoadMatrixf( vModel->modelViewMatrix );
const idRenderEntityLocal* edef = vModel->entityDef;
if( !edef )
@@ -986,8 +1014,6 @@ static void RB_ShowViewEntitys( viewEntity_t* vModels )
continue;
}
-
-
// draw the model bounds in white if directly visible,
// or, blue if it is only-for-sahdow
idVec4 color;
@@ -1062,7 +1088,7 @@ static void RB_ShowTexturePolarity( drawSurf_t** drawSurfs, int numDrawSurfs )
{
drawSurf = drawSurfs[i];
tri = drawSurf->frontEndGeo;
- if( !tri->verts )
+ if( tri == NULL || tri->verts == NULL )
{
continue;
}
@@ -1149,6 +1175,11 @@ static void RB_ShowUnsmoothedTangents( drawSurf_t** drawSurfs, int numDrawSurfs
RB_SimpleSurfaceSetup( drawSurf );
tri = drawSurf->frontEndGeo;
+ if( tri == NULL || tri->verts == NULL )
+ {
+ continue;
+ }
+
glBegin( GL_TRIANGLES );
for( j = 0; j < tri->numIndexes; j += 3 )
{
@@ -1199,10 +1230,11 @@ static void RB_ShowTangentSpace( drawSurf_t** drawSurfs, int numDrawSurfs )
RB_SimpleSurfaceSetup( drawSurf );
tri = drawSurf->frontEndGeo;
- if( !tri->verts )
+ if( tri == NULL || tri->verts == NULL )
{
continue;
}
+
glBegin( GL_TRIANGLES );
for( j = 0; j < tri->numIndexes; j++ )
{
@@ -1255,6 +1287,9 @@ static void RB_ShowVertexColor( drawSurf_t** drawSurfs, int numDrawSurfs )
}
globalImages->BindNull();
+ // RB begin
+ renderProgManager.BindShader_VertexColor();
+
GL_State( GLS_DEPTHFUNC_LESS );
for( i = 0; i < numDrawSurfs; i++ )
@@ -1264,10 +1299,13 @@ static void RB_ShowVertexColor( drawSurf_t** drawSurfs, int numDrawSurfs )
RB_SimpleSurfaceSetup( drawSurf );
tri = drawSurf->frontEndGeo;
- if( !tri->verts )
+ if( tri == NULL || tri->verts == NULL )
{
continue;
}
+
+ renderProgManager.CommitUniforms();
+
glBegin( GL_TRIANGLES );
for( j = 0; j < tri->numIndexes; j++ )
{
@@ -1280,6 +1318,8 @@ static void RB_ShowVertexColor( drawSurf_t** drawSurfs, int numDrawSurfs )
glEnd();
}
+ // RB end
+
GL_State( GLS_DEFAULT );
}
@@ -1334,33 +1374,39 @@ static void RB_ShowNormals( drawSurf_t** drawSurfs, int numDrawSurfs )
RB_SimpleSurfaceSetup( drawSurf );
tri = drawSurf->frontEndGeo;
- if( !tri->verts )
+ if( tri == NULL || tri->verts == NULL )
{
continue;
}
+ // RB begin
+ renderProgManager.BindShader_VertexColor();
+
glBegin( GL_LINES );
for( j = 0; j < tri->numVerts; j++ )
{
const idVec3 normal = tri->verts[j].GetNormal();
const idVec3 tangent = tri->verts[j].GetTangent();
const idVec3 bitangent = tri->verts[j].GetBiTangent();
- GL_Color( 0, 0, 1 );
+
+ glColor3f( 0, 0, 1 );
glVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
VectorMA( tri->verts[j].xyz, size, normal, end );
glVertex3fv( end.ToFloatPtr() );
- GL_Color( 1, 0, 0 );
+ glColor3f( 1, 0, 0 );
glVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
VectorMA( tri->verts[j].xyz, size, tangent, end );
glVertex3fv( end.ToFloatPtr() );
- GL_Color( 0, 1, 0 );
+ glColor3f( 0, 1, 0 );
glVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
VectorMA( tri->verts[j].xyz, size, bitangent, end );
glVertex3fv( end.ToFloatPtr() );
}
glEnd();
+
+ // RB end
}
if( showNumbers )
@@ -1370,7 +1416,7 @@ static void RB_ShowNormals( drawSurf_t** drawSurfs, int numDrawSurfs )
{
drawSurf = drawSurfs[i];
tri = drawSurf->frontEndGeo;
- if( !tri->verts )
+ if( tri == NULL || tri->verts == NULL )
{
continue;
}
@@ -1491,7 +1537,7 @@ static void RB_ShowTextureVectors( drawSurf_t** drawSurfs, int numDrawSurfs )
const srfTriangles_t* tri = drawSurf->frontEndGeo;
- if( tri->verts == NULL )
+ if( tri == NULL || tri->verts == NULL )
{
continue;
}
@@ -1600,7 +1646,7 @@ static void RB_ShowDominantTris( drawSurf_t** drawSurfs, int numDrawSurfs )
tri = drawSurf->frontEndGeo;
- if( !tri->verts )
+ if( tri == NULL || tri->verts == NULL )
{
continue;
}
@@ -1764,9 +1810,9 @@ static void RB_ShowLights()
GL_State( GLS_DEFAULT );
// we use the 'vLight->invProjectMVPMatrix'
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
-
+// glMatrixMode( GL_PROJECTION );
+// glLoadIdentity();
+
globalImages->BindNull();
renderProgManager.BindShader_Color();
@@ -1784,7 +1830,22 @@ static void RB_ShowLights()
if( r_showLights.GetInteger() >= 2 )
{
GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK );
- GL_Color( 0.0f, 0.0f, 1.0f, 0.25f );
+
+ // RB: show different light types
+ if( vLight->parallel )
+ {
+ GL_Color( 1.0f, 0.0f, 0.0f, 0.25f );
+ }
+ else if( vLight->pointLight )
+ {
+ GL_Color( 0.0f, 0.0f, 1.0f, 0.25f );
+ }
+ else
+ {
+ GL_Color( 0.0f, 1.0f, 0.0f, 0.25f );
+ }
+ // RB end
+
idRenderMatrix invProjectMVPMatrix;
idRenderMatrix::Multiply( backEnd.viewDef->worldSpace.mvp, vLight->inverseBaseLightProject, invProjectMVPMatrix );
RB_SetMVP( invProjectMVPMatrix );
@@ -1964,7 +2025,10 @@ static void RB_DrawText( const char* text, const idVec3& origin, float scale, co
{
renderProgManager.BindShader_Color();
-
+ // RB begin
+ GL_Color( color[0], color[1], color[2], 1 /*color[3]*/ );
+ renderProgManager.CommitUniforms();
+ // RB end
int i, j, len, num, index, charIndex, line;
float textLen = 1.0f, spacing = 1.0f;
@@ -1973,7 +2037,6 @@ static void RB_DrawText( const char* text, const idVec3& origin, float scale, co
if( text && *text )
{
glBegin( GL_LINES );
- glColor3fv( color.ToFloatPtr() );
if( text[0] == '\n' )
{
@@ -2195,6 +2258,11 @@ void RB_ShowDebugLines()
// all lines are expressed in world coordinates
RB_SimpleWorldSetup();
+ // RB begin
+ renderProgManager.BindShader_VertexColor();
+ renderProgManager.CommitUniforms();
+ // RB end
+
globalImages->BindNull();
width = r_debugLineWidth.GetInteger();
@@ -2331,9 +2399,12 @@ void RB_ShowDebugPolygons()
// all lines are expressed in world coordinates
RB_SimpleWorldSetup();
- globalImages->BindNull();
+ // RB begin
+ renderProgManager.BindShader_VertexColor();
+ renderProgManager.CommitUniforms();
+ // RB end
- glDisable( GL_TEXTURE_2D );
+ globalImages->BindNull();
if( r_debugPolygonFilled.GetBool() )
{
@@ -2721,11 +2792,12 @@ void RB_TestImage()
float projMatrixTranspose[16];
R_MatrixTranspose( finalOrtho, projMatrixTranspose );
renderProgManager.SetRenderParms( RENDERPARM_MVPMATRIX_X, projMatrixTranspose, 4 );
- glMatrixMode( GL_PROJECTION );
- glLoadMatrixf( finalOrtho );
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
+// glMatrixMode( GL_PROJECTION );
+// glLoadMatrixf( finalOrtho );
+// glMatrixMode( GL_MODELVIEW );
+// glLoadIdentity();
+
// Set Color
GL_Color( 1, 1, 1, 1 );
@@ -2752,6 +2824,102 @@ void RB_TestImage()
RB_DrawElementsWithCounters( &backEnd.testImageSurface );
}
+// RB begin
+void RB_ShowShadowMaps()
+{
+ idImage* image = NULL;
+ int max;
+ float w, h;
+
+ if( !r_showShadowMaps.GetBool() )
+ return;
+
+ image = globalImages->shadowImage;
+ if( !image )
+ {
+ return;
+ }
+
+ // Set State
+ GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
+
+ // Set Parms
+ float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
+ float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
+ renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_S, texS );
+ renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_T, texT );
+
+ float texGenEnabled[4] = { 0, 0, 0, 0 };
+ renderProgManager.SetRenderParm( RENDERPARM_TEXGEN_0_ENABLED, texGenEnabled );
+
+ for( int i = 0; i < ( r_shadowMapSplits.GetInteger() + 1 ); i++ )
+ {
+ max = image->GetUploadWidth() > image->GetUploadHeight() ? image->GetUploadWidth() : image->GetUploadHeight();
+
+ w = 0.25 * image->GetUploadWidth() / max;
+ h = 0.25 * image->GetUploadHeight() / max;
+
+ w *= ( float )renderSystem->GetHeight() / renderSystem->GetWidth();
+
+ // not really necessary but just for clarity
+ const float screenWidth = 1.0f;
+ const float screenHeight = 1.0f;
+ const float halfScreenWidth = screenWidth * 0.5f;
+ const float halfScreenHeight = screenHeight * 0.5f;
+
+ float scale[16] = { 0 };
+ scale[0] = w; // scale
+ scale[5] = h; // scale
+ scale[12] = ( halfScreenWidth * w * 2.1f * i ); // translate
+ scale[13] = halfScreenHeight + ( halfScreenHeight * h ); // translate
+ scale[10] = 1.0f;
+ scale[15] = 1.0f;
+
+ float ortho[16] = { 0 };
+ ortho[0] = 2.0f / screenWidth;
+ ortho[5] = -2.0f / screenHeight;
+ ortho[10] = -2.0f;
+ ortho[12] = -1.0f;
+ ortho[13] = 1.0f;
+ ortho[14] = -1.0f;
+ ortho[15] = 1.0f;
+
+ float finalOrtho[16];
+ R_MatrixMultiply( scale, ortho, finalOrtho );
+
+ float projMatrixTranspose[16];
+ R_MatrixTranspose( finalOrtho, projMatrixTranspose );
+ renderProgManager.SetRenderParms( RENDERPARM_MVPMATRIX_X, projMatrixTranspose, 4 );
+
+ float screenCorrectionParm[4];
+ screenCorrectionParm[0] = i;
+ screenCorrectionParm[1] = 0.0f;
+ screenCorrectionParm[2] = 0.0f;
+ screenCorrectionParm[3] = 1.0f;
+ renderProgManager.SetRenderParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor
+
+ // glMatrixMode( GL_PROJECTION );
+ // glLoadMatrixf( finalOrtho );
+ // glMatrixMode( GL_MODELVIEW );
+ // glLoadIdentity();
+
+ // Set Color
+ GL_Color( 1, 1, 1, 1 );
+
+ GL_SelectTexture( 0 );
+ image->Bind();
+ glTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_NONE );
+
+
+ renderProgManager.BindShader_DebugShadowMap();
+
+ RB_DrawElementsWithCounters( &backEnd.testImageSurface );
+ }
+
+ glTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );
+}
+// RB end
+
/*
=================
RB_DrawExpandedTriangles
@@ -2950,6 +3118,10 @@ void RB_RenderDebugTools( drawSurf_t** drawSurfs, int numDrawSurfs )
RB_ShowNormals( drawSurfs, numDrawSurfs );
RB_ShowViewEntitys( backEnd.viewDef->viewEntitys );
RB_ShowLights();
+ // RB begin
+ RB_ShowShadowMaps();
+ // RB end
+
RB_ShowTextureVectors( drawSurfs, numDrawSurfs );
RB_ShowDominantTris( drawSurfs, numDrawSurfs );
if( r_testGamma.GetInteger() > 0 ) // test here so stack check isn't so damn slow on debug builds
diff --git a/neo/renderer/tr_frontend_addlights.cpp b/neo/renderer/tr_frontend_addlights.cpp
index 0b5a21b3..cd9fa4c8 100644
--- a/neo/renderer/tr_frontend_addlights.cpp
+++ b/neo/renderer/tr_frontend_addlights.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -174,6 +175,7 @@ static void R_AddSingleLight( viewLight_t* vLight )
break;
}
}
+
if( lightStageNum == lightShader->GetNumStages() )
{
// we went through all the stages and didn't find one that adds anything
@@ -184,6 +186,7 @@ static void R_AddSingleLight( viewLight_t* vLight )
}
}
+
//--------------------------------------------
// copy data used by backend
//--------------------------------------------
@@ -207,6 +210,13 @@ static void R_AddSingleLight( viewLight_t* vLight )
// copy the matrix for deforming the 'zeroOneCubeModel' to exactly cover the light volume in world space
vLight->inverseBaseLightProject = light->inverseBaseLightProject;
+ // RB begin
+ vLight->baseLightProject = light->baseLightProject;
+ vLight->pointLight = light->parms.pointLight;
+ vLight->parallel = light->parms.parallel;
+ vLight->lightCenter = light->parms.lightCenter;
+ // RB end
+
vLight->falloffImage = light->falloffImage;
vLight->lightShader = light->lightShader;
vLight->shaderRegisters = lightRegs;
@@ -420,7 +430,7 @@ static void R_AddSingleLight( viewLight_t* vLight )
//--------------------------------------------
// add the prelight shadows for the static world geometry
//--------------------------------------------
- if( light->parms.prelightModel != NULL )
+ if( light->parms.prelightModel != NULL && !r_useShadowMapping.GetBool() )
{
srfTriangles_t* tri = light->parms.prelightModel->Surface( 0 )->geometry;
diff --git a/neo/renderer/tr_frontend_addmodels.cpp b/neo/renderer/tr_frontend_addmodels.cpp
index bee04893..6c339c49 100644
--- a/neo/renderer/tr_frontend_addmodels.cpp
+++ b/neo/renderer/tr_frontend_addmodels.cpp
@@ -685,6 +685,7 @@ void R_AddSingleModel( viewEntity_t* vEntity )
{
tri->indexCache = vertexCache.AllocIndex( tri->indexes, ALIGN( tri->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
}
+
if( !vertexCache.CacheIsCurrent( tri->ambientCache ) )
{
// we are going to use it for drawing, so make sure we have the tangents and normals
@@ -925,7 +926,7 @@ void R_AddSingleModel( viewEntity_t* vEntity )
}
// if the static shadow does not have any shadows
- if( surfInter != NULL && surfInter->numShadowIndexes == 0 )
+ if( surfInter != NULL && surfInter->numShadowIndexes == 0 && !r_useShadowMapping.GetBool() )
{
continue;
}
@@ -942,6 +943,82 @@ void R_AddSingleModel( viewEntity_t* vEntity )
continue;
}
+ // RB begin
+ if( r_useShadowMapping.GetBool() )
+ {
+ //if( addInteractions && surfaceDirectlyVisible && shader->ReceivesLighting() )
+ {
+ // static interactions can commonly find that no triangles from a surface
+ // contact the light, even when the total model does
+ if( surfInter == NULL || surfInter->lightTrisIndexCache > 0 )
+ {
+ // create a drawSurf for this interaction
+ drawSurf_t* shadowDrawSurf = ( drawSurf_t* )R_FrameAlloc( sizeof( *shadowDrawSurf ), FRAME_ALLOC_DRAW_SURFACE );
+
+ if( surfInter != NULL )
+ {
+ // optimized static interaction
+ shadowDrawSurf->numIndexes = surfInter->numLightTrisIndexes;
+ shadowDrawSurf->indexCache = surfInter->lightTrisIndexCache;
+ }
+ else
+ {
+ // make sure we have an ambient cache and all necessary normals / tangents
+ if( !vertexCache.CacheIsCurrent( tri->indexCache ) )
+ {
+ tri->indexCache = vertexCache.AllocIndex( tri->indexes, ALIGN( tri->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
+ }
+
+ // throw the entire source surface at it without any per-triangle culling
+ shadowDrawSurf->numIndexes = tri->numIndexes;
+ shadowDrawSurf->indexCache = tri->indexCache;
+ }
+
+ if( !vertexCache.CacheIsCurrent( tri->ambientCache ) )
+ {
+ // we are going to use it for drawing, so make sure we have the tangents and normals
+ if( shader->ReceivesLighting() && !tri->tangentsCalculated )
+ {
+ assert( tri->staticModelWithJoints == NULL );
+ R_DeriveTangents( tri );
+
+ // RB: this was hit by parametric particle models ..
+ //assert( false ); // this should no longer be hit
+ // RB end
+ }
+ tri->ambientCache = vertexCache.AllocVertex( tri->verts, ALIGN( tri->numVerts * sizeof( idDrawVert ), VERTEX_CACHE_ALIGN ) );
+ }
+
+ shadowDrawSurf->ambientCache = tri->ambientCache;
+ shadowDrawSurf->shadowCache = 0;
+ shadowDrawSurf->frontEndGeo = tri;
+ shadowDrawSurf->space = vEntity;
+ shadowDrawSurf->material = shader;
+ shadowDrawSurf->extraGLState = 0;
+ shadowDrawSurf->scissorRect = vLight->scissorRect; // interactionScissor;
+ shadowDrawSurf->sort = 0.0f;
+ shadowDrawSurf->renderZFail = 0;
+ //shadowDrawSurf->shaderRegisters = baseDrawSurf->shaderRegisters;
+
+ R_SetupDrawSurfJoints( shadowDrawSurf, tri, shader );
+
+ // determine which linked list to add the shadow surface to
+
+ //shadowDrawSurf->linkChain = shader->TestMaterialFlag( MF_NOSELFSHADOW ) ? &vLight->localShadows : &vLight->globalShadows;
+
+ shadowDrawSurf->linkChain = &vLight->globalShadows;
+ shadowDrawSurf->nextOnLight = vEntity->drawSurfs;
+
+ vEntity->drawSurfs = shadowDrawSurf;
+
+ }
+ }
+
+
+ continue;
+ }
+ // RB end
+
if( lightDef->parms.prelightModel && lightDef->lightHasMoved == false &&
entityDef->parms.hModel->IsStaticWorldModel() && !r_skipPrelightShadows.GetBool() )
{
diff --git a/neo/renderer/tr_frontend_main.cpp b/neo/renderer/tr_frontend_main.cpp
index 06ab5f4e..78d5cc1c 100644
--- a/neo/renderer/tr_frontend_main.cpp
+++ b/neo/renderer/tr_frontend_main.cpp
@@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
+Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -384,6 +385,69 @@ static void R_SortDrawSurfs( drawSurf_t** drawSurfs, const int numDrawSurfs )
#endif
}
+// RB begin
+static void R_SetupSplitFrustums( viewDef_t* viewDef )
+{
+ idVec3 planeOrigin;
+
+ const float zNearStart = ( viewDef->renderView.cramZNear ) ? ( r_znear.GetFloat() * 0.25f ) : r_znear.GetFloat();
+ float zFarEnd = 10000;
+
+ float zNear = zNearStart;
+ float zFar = zFarEnd;
+
+ float lambda = r_shadowMapSplitWeight.GetFloat();
+ float ratio = zFarEnd / zNearStart;
+
+ for( int i = 0; i < 6; i++ )
+ {
+ tr.viewDef->frustumSplitDistances[i] = idMath::INFINITY;
+ }
+
+ for( int i = 1; i <= ( r_shadowMapSplits.GetInteger() + 1 ) && i < MAX_FRUSTUMS; i++ )
+ {
+ float si = i / ( float )( r_shadowMapSplits.GetInteger() + 1 );
+
+ if( i > FRUSTUM_CASCADE1 )
+ {
+ zNear = zFar - ( zFar * 0.005f );
+ }
+
+ zFar = 1.005f * lambda * ( zNearStart * powf( ratio, si ) ) + ( 1 - lambda ) * ( zNearStart + ( zFarEnd - zNearStart ) * si );
+
+ if( i <= r_shadowMapSplits.GetInteger() )
+ {
+ tr.viewDef->frustumSplitDistances[i - 1] = zFar;
+ }
+
+ float projectionMatrix[16];
+ R_SetupProjectionMatrix2( tr.viewDef, zNear, zFar, projectionMatrix );
+
+ // setup render matrices for faster culling
+ idRenderMatrix projectionRenderMatrix;
+ idRenderMatrix::Transpose( *( idRenderMatrix* )projectionMatrix, projectionRenderMatrix );
+ idRenderMatrix viewRenderMatrix;
+ idRenderMatrix::Transpose( *( idRenderMatrix* )tr.viewDef->worldSpace.modelViewMatrix, viewRenderMatrix );
+ idRenderMatrix::Multiply( projectionRenderMatrix, viewRenderMatrix, tr.viewDef->frustumMVPs[i] );
+
+ // the planes of the view frustum are needed for portal visibility culling
+ idRenderMatrix::GetFrustumPlanes( tr.viewDef->frustums[i], tr.viewDef->frustumMVPs[i], false, true );
+
+ // the DOOM 3 frustum planes point outside the frustum
+ for( int j = 0; j < 6; j++ )
+ {
+ tr.viewDef->frustums[i][j] = - tr.viewDef->frustums[i][j];
+ }
+
+ // remove the Z-near to avoid portals from being near clipped
+ if( i == FRUSTUM_CASCADE1 )
+ {
+ tr.viewDef->frustums[i][4][3] -= r_znear.GetFloat();
+ }
+ }
+}
+// RB end
+
/*
================
R_RenderView
@@ -415,15 +479,19 @@ void R_RenderView( viewDef_t* parms )
idRenderMatrix::Multiply( tr.viewDef->projectionRenderMatrix, viewRenderMatrix, tr.viewDef->worldSpace.mvp );
// the planes of the view frustum are needed for portal visibility culling
- idRenderMatrix::GetFrustumPlanes( tr.viewDef->frustum, tr.viewDef->worldSpace.mvp, false, true );
+ idRenderMatrix::GetFrustumPlanes( tr.viewDef->frustums[FRUSTUM_PRIMARY], tr.viewDef->worldSpace.mvp, false, true );
// the DOOM 3 frustum planes point outside the frustum
for( int i = 0; i < 6; i++ )
{
- tr.viewDef->frustum[i] = - tr.viewDef->frustum[i];
+ tr.viewDef->frustums[FRUSTUM_PRIMARY][i] = - tr.viewDef->frustums[FRUSTUM_PRIMARY][i];
}
// remove the Z-near to avoid portals from being near clipped
- tr.viewDef->frustum[4][3] -= r_znear.GetFloat();
+ tr.viewDef->frustums[FRUSTUM_PRIMARY][4][3] -= r_znear.GetFloat();
+
+ // RB begin
+ R_SetupSplitFrustums( tr.viewDef );
+ // RB end
// identify all the visible portal areas, and create view lights and view entities
// for all the the entityDefs and lightDefs that are in the visible portal areas
diff --git a/neo/renderer/tr_frontend_subview.cpp b/neo/renderer/tr_frontend_subview.cpp
index 3ef7394d..7c968d10 100644
--- a/neo/renderer/tr_frontend_subview.cpp
+++ b/neo/renderer/tr_frontend_subview.cpp
@@ -194,7 +194,7 @@ bool R_PreciseCullSurface( const drawSurf_t* drawSurf, idBounds& ndcBounds )
for( int j = 0; j < 4; j++ )
{
- if( !w.ClipInPlace( -tr.viewDef->frustum[j], 0.1f ) )
+ if( !w.ClipInPlace( -tr.viewDef->frustums[FRUSTUM_PRIMARY][j], 0.1f ) )
{
break;
}
diff --git a/neo/renderer/tr_local.h b/neo/renderer/tr_local.h
index 932116f4..6bd01251 100644
--- a/neo/renderer/tr_local.h
+++ b/neo/renderer/tr_local.h
@@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
-Copyright (C) 2012 Robert Beckebans
+Copyright (C) 2012-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@@ -36,8 +36,8 @@ If you have questions concerning this license or the applicable additional terms
#include "ScreenRect.h"
#include "ImageOpts.h"
#include "Image.h"
-#include "RenderTexture.h"
#include "Font.h"
+#include "Framebuffer.h"
// everything that is needed by the backend needs
// to be double buffered to allow it to run in
@@ -318,6 +318,12 @@ struct viewLight_t
idVec3 globalLightOrigin; // global light origin used by backend
idPlane lightProject[4]; // light project used by backend
idPlane fogPlane; // fog plane for backend fog volume rendering
+ // RB: added for shadow mapping
+ idRenderMatrix baseLightProject; // global xyz1 to projected light strq
+ bool pointLight; // otherwise a projection light (should probably invert the sense of this, because points are way more common)
+ bool parallel; // lightCenter gives the direction to the light at infinity
+ idVec3 lightCenter; // offset the lighting direction for shading and
+ // RB end
idRenderMatrix inverseBaseLightProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the light volume in world space
const idMaterial* lightShader; // light shader used by backend
const float* shaderRegisters; // shader registers used by backend
@@ -377,6 +383,33 @@ struct viewEntity_t
const int MAX_CLIP_PLANES = 1; // we may expand this to six for some subview issues
+// RB: added multiple subfrustums for cascaded shadow mapping
+enum frustumPlanes_t
+{
+ FRUSTUM_PLANE_LEFT,
+ FRUSTUM_PLANE_RIGHT,
+ FRUSTUM_PLANE_BOTTOM,
+ FRUSTUM_PLANE_TOP,
+ FRUSTUM_PLANE_NEAR,
+ FRUSTUM_PLANE_FAR,
+ FRUSTUM_PLANES = 6,
+ FRUSTUM_CLIPALL = 1 | 2 | 4 | 8 | 16 | 32
+};
+
+enum
+{
+ FRUSTUM_PRIMARY,
+ FRUSTUM_CASCADE1,
+ FRUSTUM_CASCADE2,
+ FRUSTUM_CASCADE3,
+ FRUSTUM_CASCADE4,
+ FRUSTUM_CASCADE5,
+ MAX_FRUSTUMS,
+};
+
+typedef idPlane frustum_t[FRUSTUM_PLANES];
+// RB end
+
// viewDefs are allocated on the frame temporary stack memory
struct viewDef_t
{
@@ -432,7 +465,11 @@ struct viewDef_t
// of 2D rendering, which we can optimize in certain ways. A 2D view will
// not have any viewEntities
- idPlane frustum[6]; // positive sides face outward, [4] is the front clip plane
+ // RB begin
+ frustum_t frustums[MAX_FRUSTUMS]; // positive sides face outward, [4] is the front clip plane
+ float frustumSplitDistances[MAX_FRUSTUMS];
+ idRenderMatrix frustumMVPs[MAX_FRUSTUMS];
+ // RB end
int areaNum; // -1 = not in a valid area
@@ -623,6 +660,7 @@ struct performanceCounters_t
struct tmu_t
{
unsigned int current2DMap;
+ unsigned int current2DArray;
unsigned int currentCubeMap;
};
@@ -650,6 +688,8 @@ struct glstate_t
// RB: 64 bit fixes, changed unsigned int to uintptr_t
uintptr_t currentVertexBuffer;
uintptr_t currentIndexBuffer;
+
+ Framebuffer* currentFramebuffer;
// RB end
float polyOfsScale;
@@ -692,6 +732,11 @@ struct backEndState_t
idRenderMatrix prevMVP[2]; // world MVP from previous frame for motion blur, per-eye
+ // RB begin
+ idRenderMatrix shadowV[6]; // shadow depth view matrix
+ idRenderMatrix shadowP[6]; // shadow depth projection matrix
+ // RB end
+
// surfaces used for code-based drawing
drawSurf_t unitSquareSurface;
drawSurf_t zeroOneCubeSurface;
@@ -910,6 +955,9 @@ extern idCVar r_useEntityCallbacks; // if 0, issue the callback immediately at
extern idCVar r_lightAllBackFaces; // light all the back faces, even when they would be shadowed
extern idCVar r_useLightDepthBounds; // use depth bounds test on lights to reduce both shadow and interaction fill
extern idCVar r_useShadowDepthBounds; // use depth bounds test on individual shadows to reduce shadow fill
+// RB begin
+extern idCVar r_useShadowMapping; // use shadow mapping instead of stencil shadows
+// RB end
extern idCVar r_skipStaticInteractions; // skip interactions created at level load
extern idCVar r_skipDynamicInteractions; // skip interactions created after level load
@@ -972,6 +1020,9 @@ extern idCVar r_showPrimitives; // report vertex/index/draw counts
extern idCVar r_showPortals; // draw portal outlines in color based on passed / not passed
extern idCVar r_showSkel; // draw the skeleton when model animates
extern idCVar r_showOverDraw; // show overdraw
+// RB begin
+extern idCVar r_showShadowMaps;
+// RB end
extern idCVar r_jointNameScale; // size of joint names when r_showskel is set to 1
extern idCVar r_jointNameOffset; // offset of joint names when r_showskel is set to 1
@@ -1001,6 +1052,17 @@ extern idCVar stereoRender_deGhost; // subtract from opposite eye to reduce gh
extern idCVar r_useGPUSkinning;
+// RB begin
+extern idCVar r_shadowMapFrustumFOV;
+extern idCVar r_shadowMapSingleSide;
+extern idCVar r_shadowMapImageSize;
+extern idCVar r_shadowMapJitterScale;
+extern idCVar r_shadowMapBiasScale;
+extern idCVar r_shadowMapSamples;
+extern idCVar r_shadowMapSplits;
+extern idCVar r_shadowMapSplitWeight;
+// RB end
+
/*
====================================================================
@@ -1109,6 +1171,14 @@ void R_FreeEntityDefDecals( idRenderEntityLocal* def );
void R_FreeEntityDefOverlay( idRenderEntityLocal* def );
void R_FreeEntityDefFadedDecals( idRenderEntityLocal* def, int time );
+// RB: for dmap
+void R_DeriveLightData( idRenderLightLocal* light );
+
+// Called by the editor and dmap to operate on light volumes
+void R_RenderLightFrustum( const renderLight_t& renderLight, idPlane lightFrustum[6] );
+
+srfTriangles_t* R_PolytopeSurface( int numPlanes, const idPlane* planes, idWinding** windings );
+// RB end
void R_CreateLightRefs( idRenderLightLocal* light );
void R_FreeLightDefDerivedData( idRenderLightLocal* light );
@@ -1352,6 +1422,7 @@ TR_BACKEND_DRAW
============================================================
*/
+void RB_SetMVP( const idRenderMatrix& mvp );
void RB_DrawElementsWithCounters( const drawSurf_t* surf );
void RB_DrawViewInternal( const viewDef_t* viewDef, const int stereoEye );
void RB_DrawView( const void* data, const int stereoEye );
@@ -1387,8 +1458,8 @@ void RB_ShutdownDebugTools();
#include "ResolutionScale.h"
#include "RenderLog.h"
-#include "AutoRender.h"
-#include "AutoRenderBink.h"
+//#include "AutoRender.h"
+//#include "AutoRenderBink.h"
#include "jobs/ShadowShared.h"
#include "jobs/prelightshadowvolume/PreLightShadowVolume.h"
#include "jobs/staticshadowvolume/StaticShadowVolume.h"