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"