2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2015-12-26 15:11:47 +00:00
Copyright ( C ) 2013 - 2015 Robert Beckebans
2014-04-05 13:41:19 +00:00
Copyright ( C ) 2014 Carl Kenner
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
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 < http : //www.gnu.org/licenses/>.
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
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
2018-10-06 15:21:49 +00:00
# include "../../framework/Common_local.h"
2017-09-03 08:22:36 +00:00
# include "RenderCommon.h"
2014-05-10 12:40:01 +00:00
# include "Framebuffer.h"
2012-11-26 18:58:24 +00:00
2018-10-06 15:21:49 +00:00
2012-11-26 18:58:24 +00:00
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 " ) ;
idCVar r_forceZPassStencilShadows ( " r_forceZPassStencilShadows " , " 0 " , CVAR_RENDERER | CVAR_BOOL , " force Z-pass rendering for performance testing " ) ;
idCVar r_useStencilShadowPreload ( " r_useStencilShadowPreload " , " 1 " , CVAR_RENDERER | CVAR_BOOL , " use stencil shadow preload algorithm instead of Z-fail " ) ;
idCVar r_skipShaderPasses ( " r_skipShaderPasses " , " 0 " , CVAR_RENDERER | CVAR_BOOL , " " ) ;
idCVar r_skipInteractionFastPath ( " r_skipInteractionFastPath " , " 1 " , CVAR_RENDERER | CVAR_BOOL , " " ) ;
idCVar r_useLightStencilSelect ( " r_useLightStencilSelect " , " 0 " , CVAR_RENDERER | CVAR_BOOL , " use stencil select pass " ) ;
extern idCVar stereoRender_swapEyes ;
/*
= = = = = = = = = = = = = = = =
SetVertexParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static ID_INLINE void SetVertexParm ( renderParm_t rp , const float * value )
{
2012-11-26 18:58:24 +00:00
renderProgManager . SetUniformValue ( rp , value ) ;
}
/*
= = = = = = = = = = = = = = = =
SetVertexParms
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static ID_INLINE void SetVertexParms ( renderParm_t rp , const float * value , int num )
{
for ( int i = 0 ; i < num ; i + + )
{
renderProgManager . SetUniformValue ( ( renderParm_t ) ( rp + i ) , value + ( i * 4 ) ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
SetFragmentParm
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static ID_INLINE void SetFragmentParm ( renderParm_t rp , const float * value )
{
2012-11-26 18:58:24 +00:00
renderProgManager . SetUniformValue ( rp , value ) ;
}
2017-09-03 21:17:44 +00:00
/*
= = = = = = = = = = = = = = = = = = = =
PrintState
= = = = = = = = = = = = = = = = = = = =
*/
#if 0
void PrintState ( uint64 stateBits , uint64 * stencilBits )
{
if ( renderLog . Active ( ) = = 0 )
{
return ;
}
renderLog . OpenBlock ( " GL_State " ) ;
// culling
renderLog . Printf ( " Culling: " ) ;
switch ( stateBits & GLS_CULL_BITS )
{
case GLS_CULL_FRONTSIDED :
renderLog . Printf_NoIndent ( " FRONTSIDED -> BACK " ) ;
break ;
case GLS_CULL_BACKSIDED :
renderLog . Printf_NoIndent ( " BACKSIDED -> FRONT " ) ;
break ;
case GLS_CULL_TWOSIDED :
renderLog . Printf_NoIndent ( " TWOSIDED " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " NA " ) ;
break ;
}
renderLog . Printf_NoIndent ( " \n " ) ;
// polygon mode
renderLog . Printf ( " PolygonMode: %s \n " , ( stateBits & GLS_POLYMODE_LINE ) ? " LINE " : " FILL " ) ;
// color mask
renderLog . Printf ( " ColorMask: " ) ;
renderLog . Printf_NoIndent ( ( stateBits & GLS_REDMASK ) ? " _ " : " R " ) ;
renderLog . Printf_NoIndent ( ( stateBits & GLS_GREENMASK ) ? " _ " : " G " ) ;
renderLog . Printf_NoIndent ( ( stateBits & GLS_BLUEMASK ) ? " _ " : " B " ) ;
renderLog . Printf_NoIndent ( ( stateBits & GLS_ALPHAMASK ) ? " _ " : " A " ) ;
renderLog . Printf_NoIndent ( " \n " ) ;
// blend
renderLog . Printf ( " Blend: src= " ) ;
switch ( stateBits & GLS_SRCBLEND_BITS )
{
case GLS_SRCBLEND_ZERO :
renderLog . Printf_NoIndent ( " ZERO " ) ;
break ;
case GLS_SRCBLEND_ONE :
renderLog . Printf_NoIndent ( " ONE " ) ;
break ;
case GLS_SRCBLEND_DST_COLOR :
renderLog . Printf_NoIndent ( " DST_COLOR " ) ;
break ;
case GLS_SRCBLEND_ONE_MINUS_DST_COLOR :
renderLog . Printf_NoIndent ( " ONE_MINUS_DST_COLOR " ) ;
break ;
case GLS_SRCBLEND_SRC_ALPHA :
renderLog . Printf_NoIndent ( " SRC_ALPHA " ) ;
break ;
case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA :
renderLog . Printf_NoIndent ( " ONE_MINUS_SRC_ALPHA " ) ;
break ;
case GLS_SRCBLEND_DST_ALPHA :
renderLog . Printf_NoIndent ( " DST_ALPHA " ) ;
break ;
case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA :
renderLog . Printf_NoIndent ( " ONE_MINUS_DST_ALPHA " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " NA " ) ;
break ;
}
renderLog . Printf_NoIndent ( " , dst= " ) ;
switch ( stateBits & GLS_DSTBLEND_BITS )
{
case GLS_DSTBLEND_ZERO :
renderLog . Printf_NoIndent ( " ZERO " ) ;
break ;
case GLS_DSTBLEND_ONE :
renderLog . Printf_NoIndent ( " ONE " ) ;
break ;
case GLS_DSTBLEND_SRC_COLOR :
renderLog . Printf_NoIndent ( " SRC_COLOR " ) ;
break ;
case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR :
renderLog . Printf_NoIndent ( " ONE_MINUS_SRC_COLOR " ) ;
break ;
case GLS_DSTBLEND_SRC_ALPHA :
renderLog . Printf_NoIndent ( " SRC_ALPHA " ) ;
break ;
case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA :
renderLog . Printf_NoIndent ( " ONE_MINUS_SRC_ALPHA " ) ;
break ;
case GLS_DSTBLEND_DST_ALPHA :
renderLog . Printf_NoIndent ( " DST_ALPHA " ) ;
break ;
case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA :
renderLog . Printf_NoIndent ( " ONE_MINUS_DST_ALPHA " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " NA " ) ;
}
renderLog . Printf_NoIndent ( " \n " ) ;
// depth func
renderLog . Printf ( " DepthFunc: " ) ;
switch ( stateBits & GLS_DEPTHFUNC_BITS )
{
case GLS_DEPTHFUNC_EQUAL :
renderLog . Printf_NoIndent ( " EQUAL " ) ;
break ;
case GLS_DEPTHFUNC_ALWAYS :
renderLog . Printf_NoIndent ( " ALWAYS " ) ;
break ;
case GLS_DEPTHFUNC_LESS :
renderLog . Printf_NoIndent ( " LEQUAL " ) ;
break ;
case GLS_DEPTHFUNC_GREATER :
renderLog . Printf_NoIndent ( " GEQUAL " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " NA " ) ;
break ;
}
renderLog . Printf_NoIndent ( " \n " ) ;
// depth mask
renderLog . Printf ( " DepthWrite: %s \n " , ( stateBits & GLS_DEPTHMASK ) ? " FALSE " : " TRUE " ) ;
renderLog . Printf ( " DepthBounds: %s \n " , ( stateBits & GLS_DEPTH_TEST_MASK ) ? " TRUE " : " FALSE " ) ;
// depth bias
renderLog . Printf ( " DepthBias: %s \n " , ( stateBits & GLS_POLYGON_OFFSET ) ? " TRUE " : " FALSE " ) ;
// stencil
auto printStencil = [ & ] ( stencilFace_t face , uint64 bits , uint64 mask , uint64 ref )
{
renderLog . Printf ( " Stencil: %s, " , ( bits & ( GLS_STENCIL_FUNC_BITS | GLS_STENCIL_OP_BITS ) ) ? " ON " : " OFF " ) ;
renderLog . Printf_NoIndent ( " Face= " ) ;
switch ( face )
{
case STENCIL_FACE_FRONT :
renderLog . Printf_NoIndent ( " FRONT " ) ;
break ;
case STENCIL_FACE_BACK :
renderLog . Printf_NoIndent ( " BACK " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " BOTH " ) ;
break ;
}
renderLog . Printf_NoIndent ( " , Func= " ) ;
switch ( bits & GLS_STENCIL_FUNC_BITS )
{
case GLS_STENCIL_FUNC_NEVER :
renderLog . Printf_NoIndent ( " NEVER " ) ;
break ;
case GLS_STENCIL_FUNC_LESS :
renderLog . Printf_NoIndent ( " LESS " ) ;
break ;
case GLS_STENCIL_FUNC_EQUAL :
renderLog . Printf_NoIndent ( " EQUAL " ) ;
break ;
case GLS_STENCIL_FUNC_LEQUAL :
renderLog . Printf_NoIndent ( " LEQUAL " ) ;
break ;
case GLS_STENCIL_FUNC_GREATER :
renderLog . Printf_NoIndent ( " GREATER " ) ;
break ;
case GLS_STENCIL_FUNC_NOTEQUAL :
renderLog . Printf_NoIndent ( " NOTEQUAL " ) ;
break ;
case GLS_STENCIL_FUNC_GEQUAL :
renderLog . Printf_NoIndent ( " GEQUAL " ) ;
break ;
case GLS_STENCIL_FUNC_ALWAYS :
renderLog . Printf_NoIndent ( " ALWAYS " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " NA " ) ;
break ;
}
renderLog . Printf_NoIndent ( " , OpFail= " ) ;
switch ( bits & GLS_STENCIL_OP_FAIL_BITS )
{
case GLS_STENCIL_OP_FAIL_KEEP :
renderLog . Printf_NoIndent ( " KEEP " ) ;
break ;
case GLS_STENCIL_OP_FAIL_ZERO :
renderLog . Printf_NoIndent ( " ZERO " ) ;
break ;
case GLS_STENCIL_OP_FAIL_REPLACE :
renderLog . Printf_NoIndent ( " REPLACE " ) ;
break ;
case GLS_STENCIL_OP_FAIL_INCR :
renderLog . Printf_NoIndent ( " INCR " ) ;
break ;
case GLS_STENCIL_OP_FAIL_DECR :
renderLog . Printf_NoIndent ( " DECR " ) ;
break ;
case GLS_STENCIL_OP_FAIL_INVERT :
renderLog . Printf_NoIndent ( " INVERT " ) ;
break ;
case GLS_STENCIL_OP_FAIL_INCR_WRAP :
renderLog . Printf_NoIndent ( " INCR_WRAP " ) ;
break ;
case GLS_STENCIL_OP_FAIL_DECR_WRAP :
renderLog . Printf_NoIndent ( " DECR_WRAP " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " NA " ) ;
break ;
}
renderLog . Printf_NoIndent ( " , ZFail= " ) ;
switch ( bits & GLS_STENCIL_OP_ZFAIL_BITS )
{
case GLS_STENCIL_OP_ZFAIL_KEEP :
renderLog . Printf_NoIndent ( " KEEP " ) ;
break ;
case GLS_STENCIL_OP_ZFAIL_ZERO :
renderLog . Printf_NoIndent ( " ZERO " ) ;
break ;
case GLS_STENCIL_OP_ZFAIL_REPLACE :
renderLog . Printf_NoIndent ( " REPLACE " ) ;
break ;
case GLS_STENCIL_OP_ZFAIL_INCR :
renderLog . Printf_NoIndent ( " INCR " ) ;
break ;
case GLS_STENCIL_OP_ZFAIL_DECR :
renderLog . Printf_NoIndent ( " DECR " ) ;
break ;
case GLS_STENCIL_OP_ZFAIL_INVERT :
renderLog . Printf_NoIndent ( " INVERT " ) ;
break ;
case GLS_STENCIL_OP_ZFAIL_INCR_WRAP :
renderLog . Printf_NoIndent ( " INCR_WRAP " ) ;
break ;
case GLS_STENCIL_OP_ZFAIL_DECR_WRAP :
renderLog . Printf_NoIndent ( " DECR_WRAP " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " NA " ) ;
break ;
}
renderLog . Printf_NoIndent ( " , OpPass= " ) ;
switch ( bits & GLS_STENCIL_OP_PASS_BITS )
{
case GLS_STENCIL_OP_PASS_KEEP :
renderLog . Printf_NoIndent ( " KEEP " ) ;
break ;
case GLS_STENCIL_OP_PASS_ZERO :
renderLog . Printf_NoIndent ( " ZERO " ) ;
break ;
case GLS_STENCIL_OP_PASS_REPLACE :
renderLog . Printf_NoIndent ( " REPLACE " ) ;
break ;
case GLS_STENCIL_OP_PASS_INCR :
renderLog . Printf_NoIndent ( " INCR " ) ;
break ;
case GLS_STENCIL_OP_PASS_DECR :
renderLog . Printf_NoIndent ( " DECR " ) ;
break ;
case GLS_STENCIL_OP_PASS_INVERT :
renderLog . Printf_NoIndent ( " INVERT " ) ;
break ;
case GLS_STENCIL_OP_PASS_INCR_WRAP :
renderLog . Printf_NoIndent ( " INCR_WRAP " ) ;
break ;
case GLS_STENCIL_OP_PASS_DECR_WRAP :
renderLog . Printf_NoIndent ( " DECR_WRAP " ) ;
break ;
default :
renderLog . Printf_NoIndent ( " NA " ) ;
break ;
}
renderLog . Printf_NoIndent ( " , mask=%llu, ref=%llu \n " , mask , ref ) ;
} ;
uint32 mask = uint32 ( ( stateBits & GLS_STENCIL_FUNC_MASK_BITS ) > > GLS_STENCIL_FUNC_MASK_SHIFT ) ;
uint32 ref = uint32 ( ( stateBits & GLS_STENCIL_FUNC_REF_BITS ) > > GLS_STENCIL_FUNC_REF_SHIFT ) ;
if ( stateBits & GLS_SEPARATE_STENCIL )
{
printStencil ( STENCIL_FACE_FRONT , stencilBits [ 0 ] , mask , ref ) ;
printStencil ( STENCIL_FACE_BACK , stencilBits [ 1 ] , mask , ref ) ;
}
else
{
printStencil ( STENCIL_FACE_NUM , stateBits , mask , ref ) ;
}
renderLog . CloseBlock ( ) ;
}
# endif
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = =
RB_SetMVP
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void RB_SetMVP ( const idRenderMatrix & mvp )
{
2012-11-26 18:58:24 +00:00
SetVertexParms ( RENDERPARM_MVPMATRIX_X , mvp [ 0 ] , 4 ) ;
}
/*
= = = = = = = = = = = = = = = =
RB_SetMVPWithStereoOffset
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static void RB_SetMVPWithStereoOffset ( const idRenderMatrix & mvp , const float stereoOffset )
{
2012-11-26 18:58:24 +00:00
idRenderMatrix offset = mvp ;
offset [ 0 ] [ 3 ] + = stereoOffset ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetVertexParms ( RENDERPARM_MVPMATRIX_X , offset [ 0 ] , 4 ) ;
}
static const float zero [ 4 ] = { 0 , 0 , 0 , 0 } ;
static const float one [ 4 ] = { 1 , 1 , 1 , 1 } ;
static const float negOne [ 4 ] = { - 1 , - 1 , - 1 , - 1 } ;
/*
= = = = = = = = = = = = = = = =
RB_SetVertexColorParms
= = = = = = = = = = = = = = = =
*/
2016-07-06 22:32:44 +00:00
void RB_SetVertexColorParms ( stageVertexColor_t svc )
2012-11-28 15:47:07 +00:00
{
switch ( svc )
{
2012-11-26 18:58:24 +00:00
case SVC_IGNORE :
SetVertexParm ( RENDERPARM_VERTEXCOLOR_MODULATE , zero ) ;
SetVertexParm ( RENDERPARM_VERTEXCOLOR_ADD , one ) ;
break ;
case SVC_MODULATE :
SetVertexParm ( RENDERPARM_VERTEXCOLOR_MODULATE , one ) ;
SetVertexParm ( RENDERPARM_VERTEXCOLOR_ADD , zero ) ;
break ;
case SVC_INVERSE_MODULATE :
SetVertexParm ( RENDERPARM_VERTEXCOLOR_MODULATE , negOne ) ;
SetVertexParm ( RENDERPARM_VERTEXCOLOR_ADD , one ) ;
break ;
}
}
2017-09-03 21:17:44 +00:00
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = =
RB_GetShaderTextureMatrix
= = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static void RB_GetShaderTextureMatrix ( const float * shaderRegisters , const textureStage_t * texture , float matrix [ 16 ] )
{
matrix [ 0 * 4 + 0 ] = shaderRegisters [ texture - > matrix [ 0 ] [ 0 ] ] ;
matrix [ 1 * 4 + 0 ] = shaderRegisters [ texture - > matrix [ 0 ] [ 1 ] ] ;
matrix [ 2 * 4 + 0 ] = 0.0f ;
matrix [ 3 * 4 + 0 ] = shaderRegisters [ texture - > matrix [ 0 ] [ 2 ] ] ;
matrix [ 0 * 4 + 1 ] = shaderRegisters [ texture - > matrix [ 1 ] [ 0 ] ] ;
matrix [ 1 * 4 + 1 ] = shaderRegisters [ texture - > matrix [ 1 ] [ 1 ] ] ;
matrix [ 2 * 4 + 1 ] = 0.0f ;
matrix [ 3 * 4 + 1 ] = shaderRegisters [ texture - > matrix [ 1 ] [ 2 ] ] ;
2012-11-26 18:58:24 +00:00
// we attempt to keep scrolls from generating incredibly large texture values, but
// center rotations and center scales can still generate offsets that need to be > 1
2012-11-28 15:47:07 +00:00
if ( matrix [ 3 * 4 + 0 ] < - 40.0f | | matrix [ 12 ] > 40.0f )
{
matrix [ 3 * 4 + 0 ] - = ( int ) matrix [ 3 * 4 + 0 ] ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( matrix [ 13 ] < - 40.0f | | matrix [ 13 ] > 40.0f )
{
matrix [ 13 ] - = ( int ) matrix [ 13 ] ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
matrix [ 0 * 4 + 2 ] = 0.0f ;
matrix [ 1 * 4 + 2 ] = 0.0f ;
matrix [ 2 * 4 + 2 ] = 1.0f ;
matrix [ 3 * 4 + 2 ] = 0.0f ;
matrix [ 0 * 4 + 3 ] = 0.0f ;
matrix [ 1 * 4 + 3 ] = 0.0f ;
matrix [ 2 * 4 + 3 ] = 0.0f ;
matrix [ 3 * 4 + 3 ] = 1.0f ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = =
RB_LoadShaderTextureMatrix
= = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static void RB_LoadShaderTextureMatrix ( const float * shaderRegisters , const textureStage_t * texture )
{
2012-11-26 18:58:24 +00:00
float texS [ 4 ] = { 1.0f , 0.0f , 0.0f , 0.0f } ;
float texT [ 4 ] = { 0.0f , 1.0f , 0.0f , 0.0f } ;
2012-11-28 15:47:07 +00:00
if ( texture - > hasMatrix )
{
2012-11-26 18:58:24 +00:00
float matrix [ 16 ] ;
RB_GetShaderTextureMatrix ( shaderRegisters , texture , matrix ) ;
2012-11-28 15:47:07 +00:00
texS [ 0 ] = matrix [ 0 * 4 + 0 ] ;
texS [ 1 ] = matrix [ 1 * 4 + 0 ] ;
texS [ 2 ] = matrix [ 2 * 4 + 0 ] ;
texS [ 3 ] = matrix [ 3 * 4 + 0 ] ;
texT [ 0 ] = matrix [ 0 * 4 + 1 ] ;
texT [ 1 ] = matrix [ 1 * 4 + 1 ] ;
texT [ 2 ] = matrix [ 2 * 4 + 1 ] ;
texT [ 3 ] = matrix [ 3 * 4 + 1 ] ;
RENDERLOG_PRINTF ( " Setting Texture Matrix \n " ) ;
2012-11-26 18:58:24 +00:00
renderLog . Indent ( ) ;
RENDERLOG_PRINTF ( " Texture Matrix S : %4.3f, %4.3f, %4.3f, %4.3f \n " , texS [ 0 ] , texS [ 1 ] , texS [ 2 ] , texS [ 3 ] ) ;
RENDERLOG_PRINTF ( " Texture Matrix T : %4.3f, %4.3f, %4.3f, %4.3f \n " , texT [ 0 ] , texT [ 1 ] , texT [ 2 ] , texT [ 3 ] ) ;
renderLog . Outdent ( ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
SetVertexParm ( RENDERPARM_TEXTUREMATRIX_S , texS ) ;
SetVertexParm ( RENDERPARM_TEXTUREMATRIX_T , texT ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
RB_BakeTextureMatrixIntoTexgen
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static void RB_BakeTextureMatrixIntoTexgen ( idPlane lightProject [ 3 ] , const float * textureMatrix )
{
2012-11-26 18:58:24 +00:00
float genMatrix [ 16 ] ;
float final [ 16 ] ;
2012-11-28 15:47:07 +00:00
genMatrix [ 0 * 4 + 0 ] = lightProject [ 0 ] [ 0 ] ;
genMatrix [ 1 * 4 + 0 ] = lightProject [ 0 ] [ 1 ] ;
genMatrix [ 2 * 4 + 0 ] = lightProject [ 0 ] [ 2 ] ;
genMatrix [ 3 * 4 + 0 ] = lightProject [ 0 ] [ 3 ] ;
genMatrix [ 0 * 4 + 1 ] = lightProject [ 1 ] [ 0 ] ;
genMatrix [ 1 * 4 + 1 ] = lightProject [ 1 ] [ 1 ] ;
genMatrix [ 2 * 4 + 1 ] = lightProject [ 1 ] [ 2 ] ;
genMatrix [ 3 * 4 + 1 ] = lightProject [ 1 ] [ 3 ] ;
genMatrix [ 0 * 4 + 2 ] = 0.0f ;
genMatrix [ 1 * 4 + 2 ] = 0.0f ;
genMatrix [ 2 * 4 + 2 ] = 0.0f ;
genMatrix [ 3 * 4 + 2 ] = 0.0f ;
genMatrix [ 0 * 4 + 3 ] = lightProject [ 2 ] [ 0 ] ;
genMatrix [ 1 * 4 + 3 ] = lightProject [ 2 ] [ 1 ] ;
genMatrix [ 2 * 4 + 3 ] = lightProject [ 2 ] [ 2 ] ;
genMatrix [ 3 * 4 + 3 ] = lightProject [ 2 ] [ 3 ] ;
2012-11-26 18:58:24 +00:00
R_MatrixMultiply ( genMatrix , textureMatrix , final ) ;
2012-11-28 15:47:07 +00:00
lightProject [ 0 ] [ 0 ] = final [ 0 * 4 + 0 ] ;
lightProject [ 0 ] [ 1 ] = final [ 1 * 4 + 0 ] ;
lightProject [ 0 ] [ 2 ] = final [ 2 * 4 + 0 ] ;
lightProject [ 0 ] [ 3 ] = final [ 3 * 4 + 0 ] ;
lightProject [ 1 ] [ 0 ] = final [ 0 * 4 + 1 ] ;
lightProject [ 1 ] [ 1 ] = final [ 1 * 4 + 1 ] ;
lightProject [ 1 ] [ 2 ] = final [ 2 * 4 + 1 ] ;
lightProject [ 1 ] [ 3 ] = final [ 3 * 4 + 1 ] ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : BindVariableStageImage
2012-11-26 18:58:24 +00:00
Handles generating a cinematic frame if needed
= = = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : BindVariableStageImage ( const textureStage_t * texture , const float * shaderRegisters )
2012-11-28 15:47:07 +00:00
{
if ( texture - > cinematic )
{
2012-11-26 18:58:24 +00:00
cinData_t cin ;
2012-11-28 15:47:07 +00:00
if ( r_skipDynamicTextures . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
globalImages - > defaultImage - > Bind ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// offset time by shaderParm[7] (FIXME: make the time offset a parameter of the shader?)
// We make no attempt to optimize for multiple identical cinematics being in view, or
// for cinematics going at a lower framerate than the renderer.
2017-09-03 21:17:44 +00:00
cin = texture - > cinematic - > ImageForTime ( viewDef - > renderView . time [ 0 ] + idMath : : Ftoi ( 1000.0f * viewDef - > renderView . shaderParms [ 11 ] ) ) ;
2012-11-28 15:47:07 +00:00
if ( cin . imageY ! = NULL )
{
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
cin . imageY - > Bind ( ) ;
2018-10-13 17:46:31 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 1 ) ;
cin . imageCr - > Bind ( ) ;
2018-10-13 17:46:31 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 2 ) ;
cin . imageCb - > Bind ( ) ;
2018-10-13 17:46:31 +00:00
2018-04-29 20:04:47 +00:00
// DG: imageY is only used for bink videos (with libbinkdec), so the bink shader must be used
2018-10-13 17:46:31 +00:00
if ( viewDef - > is2Dgui )
{
renderProgManager . BindShader_BinkGUI ( ) ;
}
else
{
renderProgManager . BindShader_Bink ( ) ;
}
2014-04-05 13:41:19 +00:00
}
else if ( cin . image ! = NULL )
{
2016-01-18 21:21:32 +00:00
// Carl: A single RGB image works better with the FFMPEG BINK codec.
2014-04-05 13:41:19 +00:00
GL_SelectTexture ( 0 ) ;
cin . image - > Bind ( ) ;
2016-01-18 21:21:32 +00:00
/*
if ( backEnd . viewDef - > is2Dgui )
{
renderProgManager . BindShader_TextureVertexColor_sRGB ( ) ;
}
else
{
renderProgManager . BindShader_TextureVertexColor ( ) ;
}
*/
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
globalImages - > blackImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
// because the shaders may have already been set - we need to make sure we are not using a bink shader which would
2012-11-26 18:58:24 +00:00
// display incorrectly. We may want to get rid of RB_BindVariableStageImage and inline the code so that the
// SWF GUI case is handled better, too
renderProgManager . BindShader_TextureVertexColor ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// FIXME: see why image is invalid
2012-11-28 15:47:07 +00:00
if ( texture - > image ! = NULL )
{
2012-11-26 18:58:24 +00:00
texture - > image - > Bind ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : PrepareStageTexturing
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : PrepareStageTexturing ( const shaderStage_t * pStage , const drawSurf_t * surf )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
float useTexGenParm [ 4 ] = { 0.0f , 0.0f , 0.0f , 0.0f } ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the texture matrix if needed
RB_LoadShaderTextureMatrix ( surf - > shaderRegisters , & pStage - > texture ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texgens
2012-11-28 15:47:07 +00:00
if ( pStage - > texture . texgen = = TG_REFLECT_CUBE )
{
2012-11-26 18:58:24 +00:00
// see if there is also a bump map specified
2012-11-28 15:47:07 +00:00
const shaderStage_t * bumpStage = surf - > material - > GetBumpStage ( ) ;
if ( bumpStage ! = NULL )
{
2012-11-26 18:58:24 +00:00
// per-pixel reflection mapping with bump mapping
GL_SelectTexture ( 1 ) ;
bumpStage - > texture . image - > Bind ( ) ;
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RENDERLOG_PRINTF ( " TexGen: TG_REFLECT_CUBE: Bumpy Environment \n " ) ;
2012-11-28 15:47:07 +00:00
if ( surf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_BumpyEnvironmentSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_BumpyEnvironment ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
RENDERLOG_PRINTF ( " TexGen: TG_REFLECT_CUBE: Environment \n " ) ;
2012-11-28 15:47:07 +00:00
if ( surf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_EnvironmentSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Environment ( ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else if ( pStage - > texture . texgen = = TG_SKYBOX_CUBE )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_SkyBox ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( pStage - > texture . texgen = = TG_WOBBLESKY_CUBE )
{
const int * parms = surf - > material - > GetTexGenRegisters ( ) ;
2012-11-26 18:58:24 +00:00
float wobbleDegrees = surf - > shaderRegisters [ parms [ 0 ] ] * ( idMath : : PI / 180.0f ) ;
float wobbleSpeed = surf - > shaderRegisters [ parms [ 1 ] ] * ( 2.0f * idMath : : PI / 60.0f ) ;
float rotateSpeed = surf - > shaderRegisters [ parms [ 2 ] ] * ( 2.0f * idMath : : PI / 60.0f ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 axis [ 3 ] ;
{
// very ad-hoc "wobble" transform
float s , c ;
2017-09-03 21:17:44 +00:00
idMath : : SinCos ( wobbleSpeed * viewDef - > renderView . time [ 0 ] * 0.001f , s , c ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float ws , wc ;
idMath : : SinCos ( wobbleDegrees , ws , wc ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
axis [ 2 ] [ 0 ] = ws * c ;
axis [ 2 ] [ 1 ] = ws * s ;
axis [ 2 ] [ 2 ] = wc ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
axis [ 1 ] [ 0 ] = - s * s * ws ;
axis [ 1 ] [ 2 ] = - s * ws * ws ;
axis [ 1 ] [ 1 ] = idMath : : Sqrt ( idMath : : Fabs ( 1.0f - ( axis [ 1 ] [ 0 ] * axis [ 1 ] [ 0 ] + axis [ 1 ] [ 2 ] * axis [ 1 ] [ 2 ] ) ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make the second vector exactly perpendicular to the first
axis [ 1 ] - = ( axis [ 2 ] * axis [ 1 ] ) * axis [ 2 ] ;
axis [ 1 ] . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// construct the third with a cross
axis [ 0 ] . Cross ( axis [ 1 ] , axis [ 2 ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add the rotate
float rs , rc ;
2017-09-03 21:17:44 +00:00
idMath : : SinCos ( rotateSpeed * viewDef - > renderView . time [ 0 ] * 0.001f , rs , rc ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float transform [ 12 ] ;
2012-11-28 15:47:07 +00:00
transform [ 0 * 4 + 0 ] = axis [ 0 ] [ 0 ] * rc + axis [ 1 ] [ 0 ] * rs ;
transform [ 0 * 4 + 1 ] = axis [ 0 ] [ 1 ] * rc + axis [ 1 ] [ 1 ] * rs ;
transform [ 0 * 4 + 2 ] = axis [ 0 ] [ 2 ] * rc + axis [ 1 ] [ 2 ] * rs ;
transform [ 0 * 4 + 3 ] = 0.0f ;
transform [ 1 * 4 + 0 ] = axis [ 1 ] [ 0 ] * rc - axis [ 0 ] [ 0 ] * rs ;
transform [ 1 * 4 + 1 ] = axis [ 1 ] [ 1 ] * rc - axis [ 0 ] [ 1 ] * rs ;
transform [ 1 * 4 + 2 ] = axis [ 1 ] [ 2 ] * rc - axis [ 0 ] [ 2 ] * rs ;
transform [ 1 * 4 + 3 ] = 0.0f ;
transform [ 2 * 4 + 0 ] = axis [ 2 ] [ 0 ] ;
transform [ 2 * 4 + 1 ] = axis [ 2 ] [ 1 ] ;
transform [ 2 * 4 + 2 ] = axis [ 2 ] [ 2 ] ;
transform [ 2 * 4 + 3 ] = 0.0f ;
2012-11-26 18:58:24 +00:00
SetVertexParms ( RENDERPARM_WOBBLESKY_X , transform , 3 ) ;
renderProgManager . BindShader_WobbleSky ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( ( pStage - > texture . texgen = = TG_SCREEN ) | | ( pStage - > texture . texgen = = TG_SCREEN2 ) )
{
2012-11-26 18:58:24 +00:00
useTexGenParm [ 0 ] = 1.0f ;
useTexGenParm [ 1 ] = 1.0f ;
useTexGenParm [ 2 ] = 1.0f ;
useTexGenParm [ 3 ] = 1.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float mat [ 16 ] ;
2017-09-03 21:17:44 +00:00
R_MatrixMultiply ( surf - > space - > modelViewMatrix , viewDef - > projectionMatrix , mat ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RENDERLOG_PRINTF ( " TexGen : %s \n " , ( pStage - > texture . texgen = = TG_SCREEN ) ? " TG_SCREEN " : " TG_SCREEN2 " ) ;
renderLog . Indent ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float plane [ 4 ] ;
2012-11-28 15:47:07 +00:00
plane [ 0 ] = mat [ 0 * 4 + 0 ] ;
plane [ 1 ] = mat [ 1 * 4 + 0 ] ;
plane [ 2 ] = mat [ 2 * 4 + 0 ] ;
plane [ 3 ] = mat [ 3 * 4 + 0 ] ;
2012-11-26 18:58:24 +00:00
SetVertexParm ( RENDERPARM_TEXGEN_0_S , plane ) ;
RENDERLOG_PRINTF ( " TEXGEN_S = %4.3f, %4.3f, %4.3f, %4.3f \n " , plane [ 0 ] , plane [ 1 ] , plane [ 2 ] , plane [ 3 ] ) ;
2012-11-28 15:47:07 +00:00
plane [ 0 ] = mat [ 0 * 4 + 1 ] ;
plane [ 1 ] = mat [ 1 * 4 + 1 ] ;
plane [ 2 ] = mat [ 2 * 4 + 1 ] ;
plane [ 3 ] = mat [ 3 * 4 + 1 ] ;
2012-11-26 18:58:24 +00:00
SetVertexParm ( RENDERPARM_TEXGEN_0_T , plane ) ;
RENDERLOG_PRINTF ( " TEXGEN_T = %4.3f, %4.3f, %4.3f, %4.3f \n " , plane [ 0 ] , plane [ 1 ] , plane [ 2 ] , plane [ 3 ] ) ;
2012-11-28 15:47:07 +00:00
plane [ 0 ] = mat [ 0 * 4 + 3 ] ;
plane [ 1 ] = mat [ 1 * 4 + 3 ] ;
plane [ 2 ] = mat [ 2 * 4 + 3 ] ;
plane [ 3 ] = mat [ 3 * 4 + 3 ] ;
SetVertexParm ( RENDERPARM_TEXGEN_0_Q , plane ) ;
2012-11-26 18:58:24 +00:00
RENDERLOG_PRINTF ( " TEXGEN_Q = %4.3f, %4.3f, %4.3f, %4.3f \n " , plane [ 0 ] , plane [ 1 ] , plane [ 2 ] , plane [ 3 ] ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . Outdent ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( pStage - > texture . texgen = = TG_DIFFUSE_CUBE )
{
2012-11-26 18:58:24 +00:00
// As far as I can tell, this is never used
idLib : : Warning ( " Using Diffuse Cube! Please contact Brian! " ) ;
2012-11-28 15:47:07 +00:00
}
else if ( pStage - > texture . texgen = = TG_GLASSWARP )
{
2012-11-26 18:58:24 +00:00
// As far as I can tell, this is never used
idLib : : Warning ( " Using GlassWarp! Please contact Brian! " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetVertexParm ( RENDERPARM_TEXGEN_0_ENABLED , useTexGenParm ) ;
}
/*
= = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : FinishStageTexturing
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : FinishStageTexturing ( const shaderStage_t * pStage , const drawSurf_t * surf )
2012-11-28 15:47:07 +00:00
{
if ( pStage - > texture . cinematic )
{
2012-11-26 18:58:24 +00:00
// unbind the extra bink textures
GL_SelectTexture ( 0 ) ;
}
2012-11-28 15:47:07 +00:00
if ( pStage - > texture . texgen = = TG_REFLECT_CUBE )
{
2012-11-26 18:58:24 +00:00
// see if there is also a bump map specified
2012-11-28 15:47:07 +00:00
const shaderStage_t * bumpStage = surf - > material - > GetBumpStage ( ) ;
if ( bumpStage ! = NULL )
{
2012-11-26 18:58:24 +00:00
// per-pixel reflection mapping with bump mapping
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// per-pixel reflection mapping without bump mapping
}
renderProgManager . Unbind ( ) ;
}
}
2014-05-10 12:40:01 +00:00
// RB: moved this up because we need to call this several times for shadow mapping
2017-09-03 21:17:44 +00:00
void idRenderBackend : : ResetViewportAndScissorToDefaultCamera ( const viewDef_t * _viewDef )
2014-05-10 12:40:01 +00:00
{
// set the window clipping
2017-09-03 21:17:44 +00:00
GL_Viewport ( _viewDef - > viewport . x1 ,
_viewDef - > viewport . y1 ,
_viewDef - > viewport . x2 + 1 - _viewDef - > viewport . x1 ,
_viewDef - > viewport . y2 + 1 - _viewDef - > viewport . y1 ) ;
2014-05-10 12:40:01 +00:00
// the scissor may be smaller than the viewport for subviews
2017-09-03 21:17:44 +00:00
GL_Scissor ( viewDef - > viewport . x1 + _viewDef - > scissor . x1 ,
viewDef - > viewport . y1 + _viewDef - > scissor . y1 ,
_viewDef - > scissor . x2 + 1 - _viewDef - > scissor . x1 ,
_viewDef - > scissor . y2 + 1 - _viewDef - > scissor . y1 ) ;
currentScissor = viewDef - > scissor ;
2014-05-10 12:40:01 +00:00
}
// RB end
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
DEPTH BUFFER RENDERING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : FillDepthBufferGeneric
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : FillDepthBufferGeneric ( const drawSurf_t * const * drawSurfs , int numDrawSurfs )
2012-11-28 15:47:07 +00:00
{
for ( int i = 0 ; i < numDrawSurfs ; i + + )
{
const drawSurf_t * drawSurf = drawSurfs [ i ] ;
const idMaterial * shader = drawSurf - > material ;
2012-11-26 18:58:24 +00:00
// translucent surfaces don't put anything in the depth buffer and don't
// test against it, which makes them fail the mirror clip plane operation
2012-11-28 15:47:07 +00:00
if ( shader - > Coverage ( ) = = MC_TRANSLUCENT )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the expressions for conditionals / color / texcoords
2012-11-28 15:47:07 +00:00
const float * regs = drawSurf - > shaderRegisters ;
2012-11-26 18:58:24 +00:00
// if all stages of a material have been conditioned off, don't do anything
int stage = 0 ;
2012-11-28 15:47:07 +00:00
for ( ; stage < shader - > GetNumStages ( ) ; stage + + )
{
const shaderStage_t * pStage = shader - > GetStage ( stage ) ;
2012-11-26 18:58:24 +00:00
// check the stage enable condition
2012-11-28 15:47:07 +00:00
if ( regs [ pStage - > conditionRegister ] ! = 0 )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( stage = = shader - > GetNumStages ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// change the matrix if needed
2017-09-03 21:17:44 +00:00
if ( drawSurf - > space ! = currentSpace )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
RB_SetMVP ( drawSurf - > space - > mvp ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
currentSpace = drawSurf - > space ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint64 surfGLState = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set polygon offset if necessary
2012-11-28 15:47:07 +00:00
if ( shader - > TestMaterialFlag ( MF_POLYGONOFFSET ) )
{
2012-11-26 18:58:24 +00:00
surfGLState | = GLS_POLYGON_OFFSET ;
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * shader - > GetPolygonOffset ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// subviews will just down-modulate the color buffer
2014-05-10 12:40:01 +00:00
idVec4 color ;
2012-11-28 15:47:07 +00:00
if ( shader - > GetSort ( ) = = SS_SUBVIEW )
{
2012-11-26 18:58:24 +00:00
surfGLState | = GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_LESS ;
color [ 0 ] = 1.0f ;
color [ 1 ] = 1.0f ;
color [ 2 ] = 1.0f ;
color [ 3 ] = 1.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// others just draw black
color [ 0 ] = 0.0f ;
color [ 1 ] = 0.0f ;
color [ 2 ] = 0.0f ;
color [ 3 ] = 1.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( shader - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool drawSolid = false ;
2012-11-28 15:47:07 +00:00
if ( shader - > Coverage ( ) = = MC_OPAQUE )
{
2012-11-26 18:58:24 +00:00
drawSolid = true ;
2012-11-28 15:47:07 +00:00
}
else if ( shader - > Coverage ( ) = = MC_PERFORATED )
{
2012-11-26 18:58:24 +00:00
// we may have multiple alpha tested stages
// if the only alpha tested stages are condition register omitted,
// draw a normal opaque surface
bool didDraw = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// perforated surfaces may have multiple alpha tested stages
2012-11-28 15:47:07 +00:00
for ( stage = 0 ; stage < shader - > GetNumStages ( ) ; stage + + )
{
const shaderStage_t * pStage = shader - > GetStage ( stage ) ;
if ( ! pStage - > hasAlphaTest )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check the stage enable condition
2012-11-28 15:47:07 +00:00
if ( regs [ pStage - > conditionRegister ] = = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we at least tried to draw an alpha tested stage,
// we won't draw the opaque surface
didDraw = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the alpha modulate
color [ 3 ] = regs [ pStage - > color . registers [ 3 ] ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip the entire stage if alpha would be black
2012-11-28 15:47:07 +00:00
if ( color [ 3 ] < = 0.0f )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint64 stageGLState = surfGLState ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set privatePolygonOffset if necessary
2012-11-28 15:47:07 +00:00
if ( pStage - > privatePolygonOffset )
{
2012-11-26 18:58:24 +00:00
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * pStage - > privatePolygonOffset ) ;
stageGLState | = GLS_POLYGON_OFFSET ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_Color ( color ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# ifdef USE_CORE_PROFILE
GL_State ( stageGLState ) ;
idVec4 alphaTestValue ( regs [ pStage - > alphaTestRegister ] ) ;
SetFragmentParm ( RENDERPARM_ALPHA_TEST , alphaTestValue . ToFloatPtr ( ) ) ;
# else
GL_State ( stageGLState | GLS_ALPHATEST_FUNC_GREATER | GLS_ALPHATEST_MAKE_REF ( idMath : : Ftob ( 255.0f * regs [ pStage - > alphaTestRegister ] ) ) ) ;
# endif
2012-11-28 15:47:07 +00:00
if ( drawSurf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_TextureVertexColorSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_TextureVertexColor ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RB_SetVertexColorParms ( SVC_IGNORE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// bind the texture
GL_SelectTexture ( 0 ) ;
pStage - > texture . image - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set texture matrix and texGens
2017-09-03 21:17:44 +00:00
PrepareStageTexturing ( pStage , drawSurf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// must render with less-equal for Z-Cull to work properly
assert ( ( GL_GetCurrentState ( ) & GLS_DEPTHFUNC_BITS ) = = GLS_DEPTHFUNC_LESS ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw it
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( drawSurf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clean up
2017-09-03 21:17:44 +00:00
FinishStageTexturing ( pStage , drawSurf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// unset privatePolygonOffset if necessary
2012-11-28 15:47:07 +00:00
if ( pStage - > privatePolygonOffset )
{
2012-11-26 18:58:24 +00:00
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * shader - > GetPolygonOffset ( ) ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! didDraw )
{
2012-11-26 18:58:24 +00:00
drawSolid = true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw the entire surface solid
2012-11-28 15:47:07 +00:00
if ( drawSolid )
{
if ( shader - > GetSort ( ) = = SS_SUBVIEW )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Color ( ) ;
GL_Color ( color ) ;
GL_State ( surfGLState ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( drawSurf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_DepthSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Depth ( ) ;
}
GL_State ( surfGLState | GLS_ALPHAMASK ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// must render with less-equal for Z-Cull to work properly
assert ( ( GL_GetCurrentState ( ) & GLS_DEPTHFUNC_BITS ) = = GLS_DEPTHFUNC_LESS ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw it
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( drawSurf ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# ifdef USE_CORE_PROFILE
SetFragmentParm ( RENDERPARM_ALPHA_TEST , vec4_zero . ToFloatPtr ( ) ) ;
# endif
}
/*
= = = = = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : FillDepthBufferFast
2012-11-26 18:58:24 +00:00
Optimized fast path code .
If there are subview surfaces , they must be guarded in the depth buffer to allow
the mirror / subview to show through underneath the current view rendering .
Surfaces with perforated shaders need the full shader setup done , but should be
drawn after the opaque surfaces .
The bulk of the surfaces should be simple opaque geometry that can be drawn very rapidly .
If there are no subview surfaces , we could clear to black and use fast - Z rendering
on the 360.
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : FillDepthBufferFast ( drawSurf_t * * drawSurfs , int numDrawSurfs )
2012-11-28 15:47:07 +00:00
{
if ( numDrawSurfs = = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we are just doing 2D rendering, no need to fill the depth buffer
2017-09-03 21:17:44 +00:00
if ( viewDef - > viewEntitys = = NULL )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . OpenMainBlock ( MRB_FILL_DEPTH_BUFFER ) ;
renderLog . OpenBlock ( " RB_FillDepthBufferFast " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// force MVP change on first surface
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw all the subview surfaces, which will already be at the start of the sorted list,
// with the general purpose path
GL_State ( GLS_DEFAULT ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int surfNum ;
2012-11-28 15:47:07 +00:00
for ( surfNum = 0 ; surfNum < numDrawSurfs ; surfNum + + )
{
if ( drawSurfs [ surfNum ] - > material - > GetSort ( ) ! = SS_SUBVIEW )
{
2012-11-26 18:58:24 +00:00
break ;
}
2017-09-03 21:17:44 +00:00
FillDepthBufferGeneric ( & drawSurfs [ surfNum ] , 1 ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
const drawSurf_t * * perforatedSurfaces = ( const drawSurf_t * * ) _alloca ( numDrawSurfs * sizeof ( drawSurf_t * ) ) ;
2012-11-26 18:58:24 +00:00
int numPerforatedSurfaces = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw all the opaque surfaces and build up a list of perforated surfaces that
// we will defer drawing until all opaque surfaces are done
GL_State ( GLS_DEFAULT ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// continue checking past the subview surfaces
2012-11-28 15:47:07 +00:00
for ( ; surfNum < numDrawSurfs ; surfNum + + )
{
const drawSurf_t * surf = drawSurfs [ surfNum ] ;
const idMaterial * shader = surf - > material ;
2012-11-26 18:58:24 +00:00
// translucent surfaces don't put anything in the depth buffer
2012-11-28 15:47:07 +00:00
if ( shader - > Coverage ( ) = = MC_TRANSLUCENT )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( shader - > Coverage ( ) = = MC_PERFORATED )
{
2012-11-26 18:58:24 +00:00
// save for later drawing
perforatedSurfaces [ numPerforatedSurfaces ] = surf ;
numPerforatedSurfaces + + ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set polygon offset?
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set mvp matrix
2017-09-03 21:17:44 +00:00
if ( surf - > space ! = currentSpace )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
RB_SetMVP ( surf - > space - > mvp ) ;
2017-09-03 21:17:44 +00:00
currentSpace = surf - > space ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( shader - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( surf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_DepthSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Depth ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// must render with less-equal for Z-Cull to work properly
assert ( ( GL_GetCurrentState ( ) & GLS_DEPTHFUNC_BITS ) = = GLS_DEPTHFUNC_LESS ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw it solid
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( surf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw all perforated surfaces with the general code path
2012-11-28 15:47:07 +00:00
if ( numPerforatedSurfaces > 0 )
{
2017-09-03 21:17:44 +00:00
FillDepthBufferGeneric ( perforatedSurfaces , numPerforatedSurfaces ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
renderLog . CloseMainBlock ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
GENERAL INTERACTION RENDERING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
const int INTERACTION_TEXUNIT_BUMP = 0 ;
const int INTERACTION_TEXUNIT_FALLOFF = 1 ;
const int INTERACTION_TEXUNIT_PROJECTION = 2 ;
const int INTERACTION_TEXUNIT_DIFFUSE = 3 ;
const int INTERACTION_TEXUNIT_SPECULAR = 4 ;
2014-05-10 12:40:01 +00:00
const int INTERACTION_TEXUNIT_SHADOWMAPS = 5 ;
const int INTERACTION_TEXUNIT_JITTER = 6 ;
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : SetupInteractionStage
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : SetupInteractionStage ( const shaderStage_t * surfaceStage , const float * surfaceRegs , const float lightColor [ 4 ] ,
idVec4 matrix [ 2 ] , float color [ 4 ] )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( surfaceStage - > texture . hasMatrix )
{
2012-11-26 18:58:24 +00:00
matrix [ 0 ] [ 0 ] = surfaceRegs [ surfaceStage - > texture . matrix [ 0 ] [ 0 ] ] ;
matrix [ 0 ] [ 1 ] = surfaceRegs [ surfaceStage - > texture . matrix [ 0 ] [ 1 ] ] ;
matrix [ 0 ] [ 2 ] = 0.0f ;
matrix [ 0 ] [ 3 ] = surfaceRegs [ surfaceStage - > texture . matrix [ 0 ] [ 2 ] ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
matrix [ 1 ] [ 0 ] = surfaceRegs [ surfaceStage - > texture . matrix [ 1 ] [ 0 ] ] ;
matrix [ 1 ] [ 1 ] = surfaceRegs [ surfaceStage - > texture . matrix [ 1 ] [ 1 ] ] ;
matrix [ 1 ] [ 2 ] = 0.0f ;
matrix [ 1 ] [ 3 ] = surfaceRegs [ surfaceStage - > texture . matrix [ 1 ] [ 2 ] ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we attempt to keep scrolls from generating incredibly large texture values, but
// center rotations and center scales can still generate offsets that need to be > 1
2012-11-28 15:47:07 +00:00
if ( matrix [ 0 ] [ 3 ] < - 40.0f | | matrix [ 0 ] [ 3 ] > 40.0f )
{
2012-11-26 18:58:24 +00:00
matrix [ 0 ] [ 3 ] - = idMath : : Ftoi ( matrix [ 0 ] [ 3 ] ) ;
}
2012-11-28 15:47:07 +00:00
if ( matrix [ 1 ] [ 3 ] < - 40.0f | | matrix [ 1 ] [ 3 ] > 40.0f )
{
2012-11-26 18:58:24 +00:00
matrix [ 1 ] [ 3 ] - = idMath : : Ftoi ( matrix [ 1 ] [ 3 ] ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
matrix [ 0 ] [ 0 ] = 1.0f ;
matrix [ 0 ] [ 1 ] = 0.0f ;
matrix [ 0 ] [ 2 ] = 0.0f ;
matrix [ 0 ] [ 3 ] = 0.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
matrix [ 1 ] [ 0 ] = 0.0f ;
matrix [ 1 ] [ 1 ] = 1.0f ;
matrix [ 1 ] [ 2 ] = 0.0f ;
matrix [ 1 ] [ 3 ] = 0.0f ;
}
2012-11-28 15:47:07 +00:00
if ( color ! = NULL )
{
for ( int i = 0 ; i < 4 ; i + + )
{
2012-11-26 18:58:24 +00:00
// clamp here, so cards with a greater range don't look different.
// we could perform overbrighting like we do for lights, but
// it doesn't currently look worth it.
color [ i ] = idMath : : ClampFloat ( 0.0f , 1.0f , surfaceRegs [ surfaceStage - > color . registers [ i ] ] ) * lightColor [ i ] ;
}
}
}
/*
= = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : DrawSingleInteraction
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : DrawSingleInteraction ( drawInteraction_t * din )
2012-11-28 15:47:07 +00:00
{
if ( din - > bumpImage = = NULL )
{
2012-11-26 18:58:24 +00:00
// stage wasn't actually an interaction
return ;
}
2012-11-28 15:47:07 +00:00
if ( din - > diffuseImage = = NULL | | r_skipDiffuse . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
// this isn't a YCoCg black, but it doesn't matter, because
// the diffuseColor will also be 0
din - > diffuseImage = globalImages - > blackImage ;
}
2012-11-28 15:47:07 +00:00
if ( din - > specularImage = = NULL | | r_skipSpecular . GetBool ( ) | | din - > ambientLight )
{
2012-11-26 18:58:24 +00:00
din - > specularImage = globalImages - > blackImage ;
}
2012-11-28 15:47:07 +00:00
if ( r_skipBump . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
din - > bumpImage = globalImages - > flatNormalMap ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we wouldn't draw anything, don't call the Draw function
const bool diffuseIsBlack = ( din - > diffuseImage = = globalImages - > blackImage )
2012-11-28 15:47:07 +00:00
| | ( ( din - > diffuseColor [ 0 ] < = 0 ) & & ( din - > diffuseColor [ 1 ] < = 0 ) & & ( din - > diffuseColor [ 2 ] < = 0 ) ) ;
2012-11-26 18:58:24 +00:00
const bool specularIsBlack = ( din - > specularImage = = globalImages - > blackImage )
2012-11-28 15:47:07 +00:00
| | ( ( din - > specularColor [ 0 ] < = 0 ) & & ( din - > specularColor [ 1 ] < = 0 ) & & ( din - > specularColor [ 2 ] < = 0 ) ) ;
if ( diffuseIsBlack & & specularIsBlack )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// bump matrix
SetVertexParm ( RENDERPARM_BUMPMATRIX_S , din - > bumpMatrix [ 0 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_BUMPMATRIX_T , din - > bumpMatrix [ 1 ] . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// diffuse matrix
SetVertexParm ( RENDERPARM_DIFFUSEMATRIX_S , din - > diffuseMatrix [ 0 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_DIFFUSEMATRIX_T , din - > diffuseMatrix [ 1 ] . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// specular matrix
SetVertexParm ( RENDERPARM_SPECULARMATRIX_S , din - > specularMatrix [ 0 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_SPECULARMATRIX_T , din - > specularMatrix [ 1 ] . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RB_SetVertexColorParms ( din - > vertexColor ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetFragmentParm ( RENDERPARM_DIFFUSEMODIFIER , din - > diffuseColor . ToFloatPtr ( ) ) ;
SetFragmentParm ( RENDERPARM_SPECULARMODIFIER , din - > specularColor . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 0 will be the per-surface bump map
2012-11-28 15:47:07 +00:00
GL_SelectTexture ( INTERACTION_TEXUNIT_BUMP ) ;
2012-11-26 18:58:24 +00:00
din - > bumpImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 3 is the per-surface diffuse map
GL_SelectTexture ( INTERACTION_TEXUNIT_DIFFUSE ) ;
din - > diffuseImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 4 is the per-surface specular map
GL_SelectTexture ( INTERACTION_TEXUNIT_SPECULAR ) ;
din - > specularImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( din - > surf ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = =
RB_SetupForFastPathInteractions
These are common for all fast path surfaces
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static void RB_SetupForFastPathInteractions ( const idVec4 & diffuseColor , const idVec4 & specularColor )
{
2012-11-26 18:58:24 +00:00
const idVec4 sMatrix ( 1 , 0 , 0 , 0 ) ;
const idVec4 tMatrix ( 0 , 1 , 0 , 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// bump matrix
SetVertexParm ( RENDERPARM_BUMPMATRIX_S , sMatrix . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_BUMPMATRIX_T , tMatrix . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// diffuse matrix
SetVertexParm ( RENDERPARM_DIFFUSEMATRIX_S , sMatrix . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_DIFFUSEMATRIX_T , tMatrix . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// specular matrix
SetVertexParm ( RENDERPARM_SPECULARMATRIX_S , sMatrix . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_SPECULARMATRIX_T , tMatrix . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RB_SetVertexColorParms ( SVC_IGNORE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetFragmentParm ( RENDERPARM_DIFFUSEMODIFIER , diffuseColor . ToFloatPtr ( ) ) ;
SetFragmentParm ( RENDERPARM_SPECULARMODIFIER , specularColor . ToFloatPtr ( ) ) ;
}
/*
= = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : RenderInteractions
2012-11-26 18:58:24 +00:00
With added sorting and trivial path work .
= = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : RenderInteractions ( const drawSurf_t * surfList , const viewLight_t * vLight , int depthFunc , bool performStencilTest , bool useLightDepthBounds )
2012-11-28 15:47:07 +00:00
{
if ( surfList = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// change the scissor if needed, it will be constant across all the surfaces lit by the light
2017-09-03 21:17:44 +00:00
if ( ! currentScissor . Equals ( vLight - > scissorRect ) & & r_useScissor . GetBool ( ) )
2012-11-28 15:47:07 +00:00
{
2017-09-03 21:17:44 +00:00
GL_Scissor ( viewDef - > viewport . x1 + vLight - > scissorRect . x1 ,
viewDef - > viewport . y1 + vLight - > scissorRect . y1 ,
2012-11-26 18:58:24 +00:00
vLight - > scissorRect . x2 + 1 - vLight - > scissorRect . x1 ,
vLight - > scissorRect . y2 + 1 - vLight - > scissorRect . y1 ) ;
2017-09-03 21:17:44 +00:00
currentScissor = vLight - > scissorRect ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// perform setup here that will be constant for all interactions
2012-11-28 15:47:07 +00:00
if ( performStencilTest )
{
2012-11-26 18:58:24 +00:00
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | depthFunc | GLS_STENCIL_FUNC_EQUAL | GLS_STENCIL_MAKE_REF ( STENCIL_SHADOW_TEST_VALUE ) | GLS_STENCIL_MAKE_MASK ( STENCIL_SHADOW_MASK_VALUE ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | depthFunc | GLS_STENCIL_FUNC_ALWAYS ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// some rare lights have multiple animating stages, loop over them outside the surface list
2012-11-28 15:47:07 +00:00
const idMaterial * lightShader = vLight - > lightShader ;
const float * lightRegs = vLight - > shaderRegisters ;
2012-11-26 18:58:24 +00:00
drawInteraction_t inter = { } ;
inter . ambientLight = lightShader - > IsAmbientLight ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//---------------------------------
// Split out the complex surfaces from the fast-path surfaces
// so we can do the fast path ones all in a row.
// The surfaces should already be sorted by space because they
// are added single-threaded, and there is only a negligable amount
// of benefit to trying to sort by materials.
//---------------------------------
static const int MAX_INTERACTIONS_PER_LIGHT = 1024 ;
2014-04-20 14:29:58 +00:00
static const int MAX_COMPLEX_INTERACTIONS_PER_LIGHT = 256 ;
2012-11-28 15:47:07 +00:00
idStaticList < const drawSurf_t * , MAX_INTERACTIONS_PER_LIGHT > allSurfaces ;
idStaticList < const drawSurf_t * , MAX_COMPLEX_INTERACTIONS_PER_LIGHT > complexSurfaces ;
for ( const drawSurf_t * walk = surfList ; walk ! = NULL ; walk = walk - > nextOnLight )
{
2012-11-26 18:58:24 +00:00
// make sure the triangle culling is done
2012-11-28 15:47:07 +00:00
if ( walk - > shadowVolumeState ! = SHADOWVOLUME_DONE )
{
2012-11-26 18:58:24 +00:00
assert ( walk - > shadowVolumeState = = SHADOWVOLUME_UNFINISHED | | walk - > shadowVolumeState = = SHADOWVOLUME_DONE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint64 start = Sys_Microseconds ( ) ;
2012-11-28 15:47:07 +00:00
while ( walk - > shadowVolumeState = = SHADOWVOLUME_UNFINISHED )
{
2012-11-26 18:58:24 +00:00
Sys_Yield ( ) ;
}
uint64 end = Sys_Microseconds ( ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
pc . shadowMicroSec + = end - start ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
const idMaterial * surfaceShader = walk - > material ;
if ( surfaceShader - > GetFastPathBumpImage ( ) )
{
2012-11-26 18:58:24 +00:00
allSurfaces . Append ( walk ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
complexSurfaces . Append ( walk ) ;
}
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < complexSurfaces . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
allSurfaces . Append ( complexSurfaces [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool lightDepthBoundsDisabled = false ;
2012-11-28 15:47:07 +00:00
2014-05-10 12:40:01 +00:00
// RB begin
if ( r_useShadowMapping . GetBool ( ) )
{
const static int JITTER_SIZE = 128 ;
2014-05-15 22:14:42 +00:00
// default high quality
float jitterSampleScale = 1.0f ;
2014-05-16 19:50:49 +00:00
float shadowMapSamples = r_shadowMapSamples . GetInteger ( ) ;
2014-05-15 22:14:42 +00:00
2014-05-10 12:40:01 +00:00
// screen power of two correction factor
float screenCorrectionParm [ 4 ] ;
2014-05-15 22:14:42 +00:00
screenCorrectionParm [ 0 ] = 1.0f / ( JITTER_SIZE * shadowMapSamples ) ;
2014-05-10 12:40:01 +00:00
screenCorrectionParm [ 1 ] = 1.0f / JITTER_SIZE ;
2014-05-14 16:49:56 +00:00
screenCorrectionParm [ 2 ] = 1.0f / shadowMapResolutions [ vLight - > shadowLOD ] ;
2015-03-19 00:27:44 +00:00
screenCorrectionParm [ 3 ] = vLight - > parallel ? r_shadowMapSunDepthBiasScale . GetFloat ( ) : r_shadowMapRegularDepthBiasScale . GetFloat ( ) ;
2014-05-10 12:40:01 +00:00
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
float jitterTexScale [ 4 ] ;
2014-05-15 22:14:42 +00:00
jitterTexScale [ 0 ] = r_shadowMapJitterScale . GetFloat ( ) * jitterSampleScale ; // TODO shadow buffer size fraction shadowMapSize / maxShadowMapSize
jitterTexScale [ 1 ] = r_shadowMapJitterScale . GetFloat ( ) * jitterSampleScale ;
2014-05-10 12:40:01 +00:00
jitterTexScale [ 2 ] = - r_shadowMapBiasScale . GetFloat ( ) ;
jitterTexScale [ 3 ] = 0.0f ;
SetFragmentParm ( RENDERPARM_JITTERTEXSCALE , jitterTexScale ) ; // rpJitterTexScale
float jitterTexOffset [ 4 ] ;
2014-05-16 19:33:39 +00:00
if ( r_shadowMapRandomizeJitter . GetBool ( ) )
{
jitterTexOffset [ 0 ] = ( rand ( ) & 255 ) / 255.0 ;
jitterTexOffset [ 1 ] = ( rand ( ) & 255 ) / 255.0 ;
}
else
{
jitterTexOffset [ 0 ] = 0 ;
jitterTexOffset [ 1 ] = 0 ;
}
2014-05-10 12:40:01 +00:00
jitterTexOffset [ 2 ] = 0.0f ;
jitterTexOffset [ 3 ] = 0.0f ;
SetFragmentParm ( RENDERPARM_JITTERTEXOFFSET , jitterTexOffset ) ; // rpJitterTexOffset
if ( vLight - > parallel )
{
float cascadeDistances [ 4 ] ;
2017-09-03 21:17:44 +00:00
cascadeDistances [ 0 ] = viewDef - > frustumSplitDistances [ 0 ] ;
cascadeDistances [ 1 ] = viewDef - > frustumSplitDistances [ 1 ] ;
cascadeDistances [ 2 ] = viewDef - > frustumSplitDistances [ 2 ] ;
cascadeDistances [ 3 ] = viewDef - > frustumSplitDistances [ 3 ] ;
2014-05-10 12:40:01 +00:00
SetFragmentParm ( RENDERPARM_CASCADEDISTANCES , cascadeDistances ) ; // rpCascadeDistances
}
}
// RB end
2016-01-13 23:59:41 +00:00
float lightScale = r_useHDR . GetBool ( ) ? 3.0f : r_lightScale . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
for ( int lightStageNum = 0 ; lightStageNum < lightShader - > GetNumStages ( ) ; lightStageNum + + )
{
const shaderStage_t * lightStage = lightShader - > GetStage ( lightStageNum ) ;
2012-11-26 18:58:24 +00:00
// ignore stages that fail the condition
2012-11-28 15:47:07 +00:00
if ( ! lightRegs [ lightStage - > conditionRegister ] )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const idVec4 lightColor (
lightScale * lightRegs [ lightStage - > color . registers [ 0 ] ] ,
lightScale * lightRegs [ lightStage - > color . registers [ 1 ] ] ,
lightScale * lightRegs [ lightStage - > color . registers [ 2 ] ] ,
lightRegs [ lightStage - > color . registers [ 3 ] ] ) ;
// apply the world-global overbright and the 2x factor for specular
const idVec4 diffuseColor = lightColor ;
const idVec4 specularColor = lightColor * 2.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float lightTextureMatrix [ 16 ] ;
2012-11-28 15:47:07 +00:00
if ( lightStage - > texture . hasMatrix )
{
2012-11-26 18:58:24 +00:00
RB_GetShaderTextureMatrix ( lightRegs , & lightStage - > texture , lightTextureMatrix ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 1 will be the light falloff texture
GL_SelectTexture ( INTERACTION_TEXUNIT_FALLOFF ) ;
vLight - > falloffImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 2 will be the light projection texture
GL_SelectTexture ( INTERACTION_TEXUNIT_PROJECTION ) ;
lightStage - > texture . image - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2014-05-10 12:40:01 +00:00
if ( r_useShadowMapping . GetBool ( ) )
{
// texture 5 will be the shadow maps array
GL_SelectTexture ( INTERACTION_TEXUNIT_SHADOWMAPS ) ;
2014-05-11 20:30:01 +00:00
globalImages - > shadowImage [ vLight - > shadowLOD ] - > Bind ( ) ;
2014-05-10 12:40:01 +00:00
// texture 6 will be the jitter texture for soft shadowing
GL_SelectTexture ( INTERACTION_TEXUNIT_JITTER ) ;
2014-05-16 19:50:49 +00:00
if ( r_shadowMapSamples . GetInteger ( ) = = 16 )
{
globalImages - > jitterImage16 - > Bind ( ) ;
}
else if ( r_shadowMapSamples . GetInteger ( ) = = 4 )
2014-05-10 12:40:01 +00:00
{
2014-05-18 13:17:15 +00:00
globalImages - > jitterImage4 - > Bind ( ) ;
2014-05-10 12:40:01 +00:00
}
else
{
2014-05-16 19:50:49 +00:00
globalImages - > jitterImage1 - > Bind ( ) ;
2014-05-10 12:40:01 +00:00
}
}
2012-11-26 18:58:24 +00:00
// 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
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//----------------------------------
// For all surfaces on this light list, generate an interaction for this light stage
//----------------------------------
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// setup renderparms assuming we will be drawing trivial surfaces first
RB_SetupForFastPathInteractions ( diffuseColor , specularColor ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// even if the space does not change between light stages, each light stage may need a different lightTextureMatrix baked in
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2012-11-28 15:47:07 +00:00
for ( int sortedSurfNum = 0 ; sortedSurfNum < allSurfaces . Num ( ) ; sortedSurfNum + + )
{
const drawSurf_t * const surf = allSurfaces [ sortedSurfNum ] ;
2012-11-26 18:58:24 +00:00
// select the render prog
2012-11-28 15:47:07 +00:00
if ( lightShader - > IsAmbientLight ( ) )
{
if ( surf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_InteractionAmbientSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_InteractionAmbient ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2014-05-10 12:40:01 +00:00
if ( r_useShadowMapping . GetBool ( ) & & vLight - > globalShadows )
2012-11-28 15:47:07 +00:00
{
2014-05-10 12:40:01 +00:00
// 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 ( ) ;
}
}
2012-11-28 15:47:07 +00:00
}
else
{
2014-05-10 12:40:01 +00:00
if ( surf - > jointCache )
{
renderProgManager . BindShader_InteractionSkinned ( ) ;
}
else
{
renderProgManager . BindShader_Interaction ( ) ;
}
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
const idMaterial * surfaceShader = surf - > material ;
const float * surfaceRegs = surf - > shaderRegisters ;
2012-11-26 18:58:24 +00:00
inter . surf = surf ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// change the MVP matrix, view/light origin and light projection vectors if needed
2017-09-03 21:17:44 +00:00
if ( surf - > space ! = currentSpace )
2012-11-28 15:47:07 +00:00
{
2017-09-03 21:17:44 +00:00
currentSpace = surf - > space ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// turn off the light depth bounds test if this model is rendered with a depth hack
2012-11-28 15:47:07 +00:00
if ( useLightDepthBounds )
{
if ( ! surf - > space - > weaponDepthHack & & surf - > space - > modelDepthHack = = 0.0f )
{
if ( lightDepthBoundsDisabled )
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( vLight - > scissorRect . zmin , vLight - > scissorRect . zmax ) ;
lightDepthBoundsDisabled = false ;
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( ! lightDepthBoundsDisabled )
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( 0.0f , 0.0f ) ;
lightDepthBoundsDisabled = true ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// model-view-projection
RB_SetMVP ( surf - > space - > mvp ) ;
2012-11-28 15:47:07 +00:00
2014-05-10 12:40:01 +00:00
// 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
2012-11-26 18:58:24 +00:00
// tranform the light/view origin into model local space
idVec4 localLightOrigin ( 0.0f ) ;
idVec4 localViewOrigin ( 1.0f ) ;
R_GlobalPointToLocal ( surf - > space - > modelMatrix , vLight - > globalLightOrigin , localLightOrigin . ToVec3 ( ) ) ;
2017-09-03 21:17:44 +00:00
R_GlobalPointToLocal ( surf - > space - > modelMatrix , viewDef - > renderView . vieworg , localViewOrigin . ToVec3 ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the local light/view origin
SetVertexParm ( RENDERPARM_LOCALLIGHTORIGIN , localLightOrigin . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_LOCALVIEWORIGIN , localViewOrigin . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// transform the light project into model local space
idPlane lightProjection [ 4 ] ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 4 ; i + + )
{
2012-11-26 18:58:24 +00:00
R_GlobalPlaneToLocal ( surf - > space - > modelMatrix , vLight - > lightProject [ i ] , lightProjection [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// optionally multiply the local light projection by the light texture matrix
2012-11-28 15:47:07 +00:00
if ( lightStage - > texture . hasMatrix )
{
2012-11-26 18:58:24 +00:00
RB_BakeTextureMatrixIntoTexgen ( lightProjection , lightTextureMatrix ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the light projection
SetVertexParm ( RENDERPARM_LIGHTPROJECTION_S , lightProjection [ 0 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_LIGHTPROJECTION_T , lightProjection [ 1 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_LIGHTPROJECTION_Q , lightProjection [ 2 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_LIGHTFALLOFF_S , lightProjection [ 3 ] . ToFloatPtr ( ) ) ;
2014-05-10 12:40:01 +00:00
// RB begin
if ( r_useShadowMapping . GetBool ( ) )
{
if ( vLight - > parallel )
{
for ( int i = 0 ; i < ( r_shadowMapSplits . GetInteger ( ) + 1 ) ; i + + )
{
idRenderMatrix modelToShadowMatrix ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( shadowV [ i ] , modelMatrix , modelToShadowMatrix ) ;
2014-05-10 12:40:01 +00:00
idRenderMatrix shadowClipMVP ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( shadowP [ i ] , modelToShadowMatrix , shadowClipMVP ) ;
2014-05-10 12:40:01 +00:00
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 ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( shadowV [ i ] , modelMatrix , modelToShadowMatrix ) ;
2014-05-10 12:40:01 +00:00
idRenderMatrix shadowClipMVP ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( shadowP [ i ] , modelToShadowMatrix , shadowClipMVP ) ;
2014-05-10 12:40:01 +00:00
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 ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( shadowV [ 0 ] , modelMatrix , modelToShadowMatrix ) ;
2014-05-10 12:40:01 +00:00
idRenderMatrix shadowClipMVP ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( shadowP [ 0 ] , modelToShadowMatrix , shadowClipMVP ) ;
2014-05-10 12:40:01 +00:00
SetVertexParms ( ( renderParm_t ) ( RENDERPARM_SHADOW_MATRIX_0_X ) , shadowClipMVP [ 0 ] , 4 ) ;
}
}
// RB end
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check for the fast path
2012-11-28 15:47:07 +00:00
if ( surfaceShader - > GetFastPathBumpImage ( ) & & ! r_skipInteractionFastPath . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( surf - > material - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 0 will be the per-surface bump map
GL_SelectTexture ( INTERACTION_TEXUNIT_BUMP ) ;
surfaceShader - > GetFastPathBumpImage ( ) - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 3 is the per-surface diffuse map
GL_SelectTexture ( INTERACTION_TEXUNIT_DIFFUSE ) ;
surfaceShader - > GetFastPathDiffuseImage ( ) - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 4 is the per-surface specular map
GL_SelectTexture ( INTERACTION_TEXUNIT_SPECULAR ) ;
surfaceShader - > GetFastPathSpecularImage ( ) - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( surf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
continue ;
}
renderLog . OpenBlock ( surf - > material - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
inter . bumpImage = NULL ;
inter . specularImage = NULL ;
inter . diffuseImage = NULL ;
inter . diffuseColor [ 0 ] = inter . diffuseColor [ 1 ] = inter . diffuseColor [ 2 ] = inter . diffuseColor [ 3 ] = 0 ;
inter . specularColor [ 0 ] = inter . specularColor [ 1 ] = inter . specularColor [ 2 ] = inter . specularColor [ 3 ] = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// go through the individual surface stages
//
// This is somewhat arcane because of the old support for video cards that had to render
// interactions in multiple passes.
//
// We also have the very rare case of some materials that have conditional interactions
// for the "hell writing" that can be shined on them.
2012-11-28 15:47:07 +00:00
for ( int surfaceStageNum = 0 ; surfaceStageNum < surfaceShader - > GetNumStages ( ) ; surfaceStageNum + + )
{
const shaderStage_t * surfaceStage = surfaceShader - > GetStage ( surfaceStageNum ) ;
switch ( surfaceStage - > lighting )
{
case SL_COVERAGE :
{
2012-11-26 18:58:24 +00:00
// ignore any coverage stages since they should only be used for the depth fill pass
// for diffuse stages that use alpha test.
break ;
}
2012-11-28 15:47:07 +00:00
case SL_AMBIENT :
{
2012-11-26 18:58:24 +00:00
// ignore ambient stages while drawing interactions
break ;
}
2012-11-28 15:47:07 +00:00
case SL_BUMP :
{
2012-11-26 18:58:24 +00:00
// ignore stage that fails the condition
2012-11-28 15:47:07 +00:00
if ( ! surfaceRegs [ surfaceStage - > conditionRegister ] )
{
2012-11-26 18:58:24 +00:00
break ;
}
// draw any previous interaction
2012-11-28 15:47:07 +00:00
if ( inter . bumpImage ! = NULL )
{
2017-09-03 21:17:44 +00:00
DrawSingleInteraction ( & inter ) ;
2012-11-26 18:58:24 +00:00
}
inter . bumpImage = surfaceStage - > texture . image ;
inter . diffuseImage = NULL ;
inter . specularImage = NULL ;
2017-09-10 11:32:44 +00:00
SetupInteractionStage ( surfaceStage , surfaceRegs , NULL , inter . bumpMatrix , NULL ) ;
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
case SL_DIFFUSE :
{
2012-11-26 18:58:24 +00:00
// ignore stage that fails the condition
2012-11-28 15:47:07 +00:00
if ( ! surfaceRegs [ surfaceStage - > conditionRegister ] )
{
2012-11-26 18:58:24 +00:00
break ;
}
// draw any previous interaction
2012-11-28 15:47:07 +00:00
if ( inter . diffuseImage ! = NULL )
{
2017-09-03 21:17:44 +00:00
DrawSingleInteraction ( & inter ) ;
2012-11-26 18:58:24 +00:00
}
inter . diffuseImage = surfaceStage - > texture . image ;
inter . vertexColor = surfaceStage - > vertexColor ;
2017-09-10 11:32:44 +00:00
SetupInteractionStage ( surfaceStage , surfaceRegs , diffuseColor . ToFloatPtr ( ) ,
inter . diffuseMatrix , inter . diffuseColor . ToFloatPtr ( ) ) ;
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
case SL_SPECULAR :
{
2012-11-26 18:58:24 +00:00
// ignore stage that fails the condition
2012-11-28 15:47:07 +00:00
if ( ! surfaceRegs [ surfaceStage - > conditionRegister ] )
{
2012-11-26 18:58:24 +00:00
break ;
}
// draw any previous interaction
2012-11-28 15:47:07 +00:00
if ( inter . specularImage ! = NULL )
{
2017-09-03 21:17:44 +00:00
DrawSingleInteraction ( & inter ) ;
2012-11-26 18:58:24 +00:00
}
inter . specularImage = surfaceStage - > texture . image ;
inter . vertexColor = surfaceStage - > vertexColor ;
2017-09-10 11:32:44 +00:00
SetupInteractionStage ( surfaceStage , surfaceRegs , specularColor . ToFloatPtr ( ) ,
inter . specularMatrix , inter . specularColor . ToFloatPtr ( ) ) ;
2012-11-26 18:58:24 +00:00
break ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw the final interaction
2017-09-03 21:17:44 +00:00
DrawSingleInteraction ( & inter ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( useLightDepthBounds & & lightDepthBoundsDisabled )
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( vLight - > scissorRect . zmin , vLight - > scissorRect . zmax ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderProgManager . Unbind ( ) ;
}
2015-12-24 15:43:02 +00:00
// RB begin
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
AMBIENT PASS RENDERING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : AmbientPass
2015-12-24 15:43:02 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : AmbientPass ( const drawSurf_t * const * drawSurfs , int numDrawSurfs , bool fillGbuffer )
2015-12-24 15:43:02 +00:00
{
2016-01-09 19:17:09 +00:00
if ( fillGbuffer )
2016-01-09 15:23:49 +00:00
{
2016-01-13 23:59:41 +00:00
if ( ! r_useSSGI . GetBool ( ) & & ! r_useSSAO . GetBool ( ) )
2016-01-09 19:17:09 +00:00
{
return ;
}
2016-01-09 15:23:49 +00:00
}
2016-01-09 19:17:09 +00:00
else
2015-12-24 15:43:02 +00:00
{
2016-01-09 19:17:09 +00:00
if ( r_forceAmbient . GetFloat ( ) < = 0 | | r_skipAmbient . GetBool ( ) )
{
return ;
}
2015-12-24 15:43:02 +00:00
}
if ( numDrawSurfs = = 0 )
{
return ;
}
// if we are just doing 2D rendering, no need to fill the depth buffer
2017-09-03 21:17:44 +00:00
if ( viewDef - > viewEntitys = = NULL )
2015-12-24 15:43:02 +00:00
{
return ;
}
2015-12-31 17:11:34 +00:00
const bool hdrIsActive = ( r_useHDR . GetBool ( ) & & globalFramebuffers . hdrFBO ! = NULL & & globalFramebuffers . hdrFBO - > IsBound ( ) ) ;
2016-01-18 22:21:53 +00:00
/*
if ( fillGbuffer )
{
globalFramebuffers . geometryBufferFBO - > Bind ( ) ;
glClearColor ( 0 , 0 , 0 , 0 ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
}
*/
2015-12-31 17:11:34 +00:00
2016-01-09 12:38:49 +00:00
renderLog . OpenMainBlock ( MRB_AMBIENT_PASS ) ;
renderLog . OpenBlock ( " RB_AmbientPass " ) ;
2015-12-24 15:43:02 +00:00
// RB: not needed
// GL_StartDepthPass( backEnd.viewDef->scissor );
// force MVP change on first surface
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2015-12-24 15:43:02 +00:00
// draw all the subview surfaces, which will already be at the start of the sorted list,
// with the general purpose path
//GL_State( GLS_DEFAULT );
2016-01-18 22:21:53 +00:00
//if( fillGbuffer )
{
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL ) ;
}
//else
//{
// GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
//}
2015-12-24 15:43:02 +00:00
2015-12-31 17:11:34 +00:00
GL_Color ( colorWhite ) ;
2015-12-24 15:43:02 +00:00
const float lightScale = 1.0f ; //r_lightScale.GetFloat();
const idVec4 lightColor = colorWhite * lightScale ;
// apply the world-global overbright and the 2x factor for specular
const idVec4 diffuseColor = lightColor ;
const idVec4 specularColor = lightColor * 2.0f ;
2016-01-13 23:59:41 +00:00
idVec4 ambientColor ;
float ambientBoost = 1.0f ;
2016-01-17 11:49:04 +00:00
ambientBoost + = r_useSSAO . GetBool ( ) ? 0.2f : 0.0f ;
2016-01-13 23:59:41 +00:00
ambientBoost * = r_useHDR . GetBool ( ) ? 1.1f : 1.0f ;
ambientColor . x = r_forceAmbient . GetFloat ( ) * ambientBoost ;
ambientColor . y = r_forceAmbient . GetFloat ( ) * ambientBoost ;
ambientColor . z = r_forceAmbient . GetFloat ( ) * ambientBoost ;
ambientColor . w = 1 ;
renderProgManager . SetRenderParm ( RENDERPARM_AMBIENT_COLOR , ambientColor . ToFloatPtr ( ) ) ;
2015-12-24 15:43:02 +00:00
// setup renderparms assuming we will be drawing trivial surfaces first
RB_SetupForFastPathInteractions ( diffuseColor , specularColor ) ;
for ( int i = 0 ; i < numDrawSurfs ; i + + )
{
const drawSurf_t * drawSurf = drawSurfs [ i ] ;
const idMaterial * surfaceMaterial = drawSurf - > material ;
// translucent surfaces don't put anything in the depth buffer and don't
// test against it, which makes them fail the mirror clip plane operation
if ( surfaceMaterial - > Coverage ( ) = = MC_TRANSLUCENT )
{
continue ;
}
// get the expressions for conditionals / color / texcoords
const float * surfaceRegs = drawSurf - > shaderRegisters ;
// if all stages of a material have been conditioned off, don't do anything
int stage = 0 ;
for ( ; stage < surfaceMaterial - > GetNumStages ( ) ; stage + + )
{
const shaderStage_t * pStage = surfaceMaterial - > GetStage ( stage ) ;
// check the stage enable condition
if ( surfaceRegs [ pStage - > conditionRegister ] ! = 0 )
{
break ;
}
}
if ( stage = = surfaceMaterial - > GetNumStages ( ) )
{
continue ;
}
2016-01-19 23:55:30 +00:00
//bool isWorldModel = ( drawSurf->space->entityDef->parms.origin == vec3_origin );
2015-12-24 15:43:02 +00:00
//if( isWorldModel )
//{
// renderProgManager.BindShader_VertexLighting();
//}
//else
{
2016-01-09 12:38:49 +00:00
# if 1
2016-01-18 22:21:53 +00:00
if ( fillGbuffer )
2015-12-24 15:43:02 +00:00
{
2015-12-31 17:11:34 +00:00
// fill geometry buffer with normal/roughness information
if ( drawSurf - > jointCache )
{
renderProgManager . BindShader_SmallGeometryBufferSkinned ( ) ;
}
else
{
renderProgManager . BindShader_SmallGeometryBuffer ( ) ;
}
2015-12-24 15:43:02 +00:00
}
else
2016-01-08 18:30:21 +00:00
# endif
2015-12-24 15:43:02 +00:00
{
2015-12-31 17:11:34 +00:00
// draw Quake 4 style ambient
if ( drawSurf - > jointCache )
{
renderProgManager . BindShader_AmbientLightingSkinned ( ) ;
}
else
{
renderProgManager . BindShader_AmbientLighting ( ) ;
}
2015-12-24 15:43:02 +00:00
}
}
// change the matrix if needed
2017-09-03 21:17:44 +00:00
if ( drawSurf - > space ! = currentSpace )
2015-12-24 15:43:02 +00:00
{
2017-09-03 21:17:44 +00:00
currentSpace = drawSurf - > space ;
2015-12-24 15:43:02 +00:00
RB_SetMVP ( drawSurf - > space - > mvp ) ;
// tranform the view origin into model local space
idVec4 localViewOrigin ( 1.0f ) ;
2017-09-03 21:17:44 +00:00
R_GlobalPointToLocal ( drawSurf - > space - > modelMatrix , viewDef - > renderView . vieworg , localViewOrigin . ToVec3 ( ) ) ;
2015-12-24 15:43:02 +00:00
SetVertexParm ( RENDERPARM_LOCALVIEWORIGIN , localViewOrigin . ToFloatPtr ( ) ) ;
2016-01-19 23:55:30 +00:00
//if( !isWorldModel )
//{
// // tranform the light direction into model local space
// idVec3 globalLightDirection( 0.0f, 0.0f, -1.0f ); // HACK
// idVec4 localLightDirection( 0.0f );
// R_GlobalVectorToLocal( drawSurf->space->modelMatrix, globalLightDirection, localLightDirection.ToVec3() );
//
// SetVertexParm( RENDERPARM_LOCALLIGHTORIGIN, localLightDirection.ToFloatPtr() );
//}
2015-12-31 17:11:34 +00:00
2016-01-02 18:28:49 +00:00
// RB: if we want to store the normals in world space so we need the model -> world matrix
2015-12-31 17:11:34 +00:00
idRenderMatrix modelMatrix ;
idRenderMatrix : : Transpose ( * ( idRenderMatrix * ) drawSurf - > space - > modelMatrix , modelMatrix ) ;
SetVertexParms ( RENDERPARM_MODELMATRIX_X , modelMatrix [ 0 ] , 4 ) ;
2016-01-02 18:28:49 +00:00
// RB: if we want to store the normals in camera space so we need the model -> camera matrix
float modelViewMatrixTranspose [ 16 ] ;
R_MatrixTranspose ( drawSurf - > space - > modelViewMatrix , modelViewMatrixTranspose ) ;
SetVertexParms ( RENDERPARM_MODELVIEWMATRIX_X , modelViewMatrixTranspose , 4 ) ;
2015-12-24 15:43:02 +00:00
}
#if 0
if ( ! isWorldModel )
{
idVec4 directedColor ;
directedColor . x = drawSurf - > space - > gridDirectedLight . x ;
directedColor . y = drawSurf - > space - > gridDirectedLight . y ;
directedColor . z = drawSurf - > space - > gridDirectedLight . z ;
directedColor . w = 1 ;
idVec4 ambientColor ;
ambientColor . x = drawSurf - > space - > gridAmbientLight . x ;
ambientColor . y = drawSurf - > space - > gridAmbientLight . y ;
ambientColor . z = drawSurf - > space - > gridAmbientLight . z ;
ambientColor . w = 1 ;
renderProgManager . SetRenderParm ( RENDERPARM_COLOR , directedColor . ToFloatPtr ( ) ) ;
renderProgManager . SetRenderParm ( RENDERPARM_AMBIENT_COLOR , ambientColor . ToFloatPtr ( ) ) ;
}
# endif
/*
uint64 surfGLState = 0 ;
// set polygon offset if necessary
if ( surfaceMaterial - > TestMaterialFlag ( MF_POLYGONOFFSET ) )
{
surfGLState | = GLS_POLYGON_OFFSET ;
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * surfaceMaterial - > GetPolygonOffset ( ) ) ;
}
// subviews will just down-modulate the color buffer
idVec4 color ;
if ( surfaceMaterial - > GetSort ( ) = = SS_SUBVIEW )
{
surfGLState | = GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_LESS ;
color [ 0 ] = 1.0f ;
color [ 1 ] = 1.0f ;
color [ 2 ] = 1.0f ;
color [ 3 ] = 1.0f ;
}
else
{
// others just draw black
#if 0
color [ 0 ] = 0.0f ;
color [ 1 ] = 0.0f ;
color [ 2 ] = 0.0f ;
color [ 3 ] = 1.0f ;
# else
color = colorWhite ;
# endif
}
*/
// check for the fast path
if ( surfaceMaterial - > GetFastPathBumpImage ( ) & & ! r_skipInteractionFastPath . GetBool ( ) )
{
renderLog . OpenBlock ( surfaceMaterial - > GetName ( ) ) ;
// texture 0 will be the per-surface bump map
GL_SelectTexture ( INTERACTION_TEXUNIT_BUMP ) ;
surfaceMaterial - > GetFastPathBumpImage ( ) - > Bind ( ) ;
// texture 3 is the per-surface diffuse map
GL_SelectTexture ( INTERACTION_TEXUNIT_DIFFUSE ) ;
surfaceMaterial - > GetFastPathDiffuseImage ( ) - > Bind ( ) ;
// texture 4 is the per-surface specular map
GL_SelectTexture ( INTERACTION_TEXUNIT_SPECULAR ) ;
surfaceMaterial - > GetFastPathSpecularImage ( ) - > Bind ( ) ;
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( drawSurf ) ;
2015-12-24 15:43:02 +00:00
renderLog . CloseBlock ( ) ;
continue ;
}
renderLog . OpenBlock ( surfaceMaterial - > GetName ( ) ) ;
//bool drawSolid = false;
// we may have multiple alpha tested stages
// if the only alpha tested stages are condition register omitted,
// draw a normal opaque surface
bool didDraw = false ;
drawInteraction_t inter = { } ;
inter . surf = drawSurf ;
inter . bumpImage = NULL ;
inter . specularImage = NULL ;
inter . diffuseImage = NULL ;
inter . diffuseColor [ 0 ] = inter . diffuseColor [ 1 ] = inter . diffuseColor [ 2 ] = inter . diffuseColor [ 3 ] = 1 ;
inter . specularColor [ 0 ] = inter . specularColor [ 1 ] = inter . specularColor [ 2 ] = inter . specularColor [ 3 ] = 0 ;
// perforated surfaces may have multiple alpha tested stages
for ( stage = 0 ; stage < surfaceMaterial - > GetNumStages ( ) ; stage + + )
{
const shaderStage_t * surfaceStage = surfaceMaterial - > GetStage ( stage ) ;
switch ( surfaceStage - > lighting )
{
case SL_COVERAGE :
{
// ignore any coverage stages since they should only be used for the depth fill pass
// for diffuse stages that use alpha test.
break ;
}
case SL_AMBIENT :
{
// ignore ambient stages while drawing interactions
break ;
}
case SL_BUMP :
{
// ignore stage that fails the condition
if ( ! surfaceRegs [ surfaceStage - > conditionRegister ] )
{
break ;
}
// draw any previous interaction
if ( inter . bumpImage ! = NULL )
{
2017-09-03 21:17:44 +00:00
DrawSingleInteraction ( & inter ) ;
2015-12-24 15:43:02 +00:00
}
inter . bumpImage = surfaceStage - > texture . image ;
inter . diffuseImage = NULL ;
inter . specularImage = NULL ;
2017-09-10 11:32:44 +00:00
SetupInteractionStage ( surfaceStage , surfaceRegs , NULL ,
inter . bumpMatrix , NULL ) ;
2015-12-24 15:43:02 +00:00
break ;
}
case SL_DIFFUSE :
{
// ignore stage that fails the condition
if ( ! surfaceRegs [ surfaceStage - > conditionRegister ] )
{
break ;
}
// draw any previous interaction
if ( inter . diffuseImage ! = NULL )
{
2017-09-03 21:17:44 +00:00
DrawSingleInteraction ( & inter ) ;
2015-12-24 15:43:02 +00:00
}
inter . diffuseImage = surfaceStage - > texture . image ;
inter . vertexColor = surfaceStage - > vertexColor ;
2017-09-10 11:32:44 +00:00
SetupInteractionStage ( surfaceStage , surfaceRegs , diffuseColor . ToFloatPtr ( ) ,
inter . diffuseMatrix , inter . diffuseColor . ToFloatPtr ( ) ) ;
2015-12-24 15:43:02 +00:00
break ;
}
case SL_SPECULAR :
{
// ignore stage that fails the condition
if ( ! surfaceRegs [ surfaceStage - > conditionRegister ] )
{
break ;
}
// draw any previous interaction
if ( inter . specularImage ! = NULL )
{
2017-09-03 21:17:44 +00:00
DrawSingleInteraction ( & inter ) ;
2015-12-24 15:43:02 +00:00
}
inter . specularImage = surfaceStage - > texture . image ;
inter . vertexColor = surfaceStage - > vertexColor ;
2017-09-10 11:32:44 +00:00
SetupInteractionStage ( surfaceStage , surfaceRegs , specularColor . ToFloatPtr ( ) ,
inter . specularMatrix , inter . specularColor . ToFloatPtr ( ) ) ;
2015-12-24 15:43:02 +00:00
break ;
}
}
}
// draw the final interaction
2017-09-03 21:17:44 +00:00
DrawSingleInteraction ( & inter ) ;
2015-12-24 15:43:02 +00:00
renderLog . CloseBlock ( ) ;
}
# ifdef USE_CORE_PROFILE
SetFragmentParm ( RENDERPARM_ALPHA_TEST , vec4_zero . ToFloatPtr ( ) ) ;
# endif
renderLog . CloseBlock ( ) ;
renderLog . CloseMainBlock ( ) ;
2015-12-31 17:11:34 +00:00
2017-09-10 13:27:31 +00:00
GL_SelectTexture ( 0 ) ;
2016-01-18 22:21:53 +00:00
if ( fillGbuffer )
2015-12-31 17:11:34 +00:00
{
// FIXME: this copies RGBA16F into _currentNormals if HDR is enabled
2017-09-09 12:57:48 +00:00
const idScreenRect & viewport = viewDef - > viewport ;
2015-12-31 17:11:34 +00:00
globalImages - > currentNormalsImage - > CopyFramebuffer ( viewport . x1 , viewport . y1 , viewport . GetWidth ( ) , viewport . GetHeight ( ) ) ;
2016-01-18 22:21:53 +00:00
//GL_Clear( true, false, false, STENCIL_SHADOW_TEST_VALUE, 0.0f, 0.0f, 0.0f, 1.0f, false );
2015-12-31 17:11:34 +00:00
2016-01-18 22:21:53 +00:00
/*
if ( hdrIsActive )
{
globalFramebuffers . hdrFBO - > Bind ( ) ;
}
else
{
Framebuffer : : Unbind ( ) ;
}
*/
}
renderProgManager . Unbind ( ) ;
2015-12-24 15:43:02 +00:00
}
// RB end
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
STENCIL SHADOW RENDERING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : StencilShadowPass
2012-11-26 18:58:24 +00:00
The stencil buffer should have been set to 128 on any surfaces that might receive shadows .
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : StencilShadowPass ( const drawSurf_t * drawSurfs , const viewLight_t * vLight )
2012-11-28 15:47:07 +00:00
{
if ( r_skipShadows . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( drawSurfs = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RENDERLOG_PRINTF ( " ---------- RB_StencilShadowPass ---------- \n " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Shadow ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint64 glState = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// for visualizing the shadows
2012-11-28 15:47:07 +00:00
if ( r_showShadows . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
// set the debug shadow color
SetFragmentParm ( RENDERPARM_COLOR , colorMagenta . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( r_showShadows . GetInteger ( ) = = 2 )
{
2012-11-26 18:58:24 +00:00
// draw filled in
glState = GLS_DEPTHMASK | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_LESS ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// draw as lines, filling the depth buffer
glState = GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// don't write to the color or depth buffer, just the stencil buffer
glState = GLS_DEPTHMASK | GLS_COLORMASK | GLS_ALPHAMASK | GLS_DEPTHFUNC_LESS ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_PolygonOffset ( r_shadowPolygonFactor . GetFloat ( ) , - r_shadowPolygonOffset . GetFloat ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// 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
2012-11-28 15:47:07 +00:00
GL_State ( glState | GLS_STENCIL_OP_FAIL_KEEP | GLS_STENCIL_OP_ZFAIL_KEEP | GLS_STENCIL_OP_PASS_INCR |
GLS_STENCIL_MAKE_REF ( STENCIL_SHADOW_TEST_VALUE ) | GLS_STENCIL_MAKE_MASK ( STENCIL_SHADOW_MASK_VALUE ) | GLS_POLYGON_OFFSET ) ;
2012-11-26 18:58:24 +00:00
// Two Sided Stencil reduces two draw calls to one for slightly faster shadows
GL_Cull ( CT_TWO_SIDED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// process the chain of shadows with the current rendering state
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2012-11-28 15:47:07 +00:00
for ( const drawSurf_t * drawSurf = drawSurfs ; drawSurf ! = NULL ; drawSurf = drawSurf - > nextOnLight )
{
if ( drawSurf - > scissorRect . IsEmpty ( ) )
{
2012-11-26 18:58:24 +00:00
continue ; // !@# FIXME: find out why this is sometimes being hit!
2012-11-28 15:47:07 +00:00
// temporarily jump over the scissor and draw so the gl error callback doesn't get hit
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure the shadow volume is done
2012-11-28 15:47:07 +00:00
if ( drawSurf - > shadowVolumeState ! = SHADOWVOLUME_DONE )
{
2012-11-26 18:58:24 +00:00
assert ( drawSurf - > shadowVolumeState = = SHADOWVOLUME_UNFINISHED | | drawSurf - > shadowVolumeState = = SHADOWVOLUME_DONE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint64 start = Sys_Microseconds ( ) ;
2012-11-28 15:47:07 +00:00
while ( drawSurf - > shadowVolumeState = = SHADOWVOLUME_UNFINISHED )
{
2012-11-26 18:58:24 +00:00
Sys_Yield ( ) ;
}
uint64 end = Sys_Microseconds ( ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
pc . shadowMicroSec + = end - start ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( drawSurf - > numIndexes = = 0 )
{
2012-11-26 18:58:24 +00:00
continue ; // a job may have created an empty shadow volume
}
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
if ( ! currentScissor . Equals ( drawSurf - > scissorRect ) & & r_useScissor . GetBool ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// change the scissor
2017-09-03 21:17:44 +00:00
GL_Scissor ( viewDef - > viewport . x1 + drawSurf - > scissorRect . x1 ,
viewDef - > viewport . y1 + drawSurf - > scissorRect . y1 ,
2012-11-26 18:58:24 +00:00
drawSurf - > scissorRect . x2 + 1 - drawSurf - > scissorRect . x1 ,
drawSurf - > scissorRect . y2 + 1 - drawSurf - > scissorRect . y1 ) ;
2017-09-03 21:17:44 +00:00
currentScissor = drawSurf - > scissorRect ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
if ( drawSurf - > space ! = currentSpace )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// change the matrix
RB_SetMVP ( drawSurf - > space - > mvp ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// 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 ( ) ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
currentSpace = drawSurf - > space ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( r_showShadows . GetInteger ( ) = = 0 )
{
if ( drawSurf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_ShadowSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Shadow ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( drawSurf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_ShadowDebugSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_ShadowDebug ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set depth bounds per shadow
2012-11-28 15:47:07 +00:00
if ( r_useShadowDepthBounds . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( drawSurf - > scissorRect . zmin , drawSurf - > scissorRect . zmax ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Determine whether or not the shadow volume needs to be rendered with Z-pass or
// Z-fail. It is worthwhile to spend significant resources to reduce the number of
// cases where shadow volumes need to be rendered with Z-fail because Z-fail
// rendering can be significantly slower even on today's hardware. For instance,
// on NVIDIA hardware Z-fail rendering causes the Z-Cull to be used in reverse:
// Z-near becomes Z-far (trivial accept becomes trivial reject). Using the Z-Cull
// in reverse is far less efficient because the Z-Cull only stores Z-near per 16x16
// pixels while the Z-far is stored per 4x2 pixels. (The Z-near coallesce buffer
// which has 4x4 granularity is only used when updating the depth which is not the
// case for shadow volumes.) Note that it is also important to NOT use a Z-Cull
// reconstruct because that would clear the Z-near of the Z-Cull which results in
// no trivial rejection for Z-fail stencil shadow rendering.
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const bool renderZPass = ( drawSurf - > renderZFail = = 0 ) | | r_forceZPassStencilShadows . GetBool ( ) ;
2012-11-28 15:47:07 +00:00
2018-10-03 19:14:28 +00:00
# if !defined(USE_VULKAN)
2012-11-28 15:47:07 +00:00
if ( renderZPass )
{
2012-11-26 18:58:24 +00:00
// Z-pass
2012-12-17 16:30:59 +00:00
glStencilOpSeparate ( GL_FRONT , GL_KEEP , GL_KEEP , GL_INCR ) ;
glStencilOpSeparate ( GL_BACK , GL_KEEP , GL_KEEP , GL_DECR ) ;
2012-11-28 15:47:07 +00:00
}
else if ( r_useStencilShadowPreload . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
// preload + Z-pass
2012-12-17 16:30:59 +00:00
glStencilOpSeparate ( GL_FRONT , GL_KEEP , GL_DECR , GL_DECR ) ;
glStencilOpSeparate ( GL_BACK , GL_KEEP , GL_INCR , GL_INCR ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// Z-fail
}
2014-08-20 09:09:02 +00:00
# endif
2012-11-28 15:47:07 +00:00
2018-10-03 19:14:28 +00:00
DrawStencilShadowPass ( drawSurf , renderZPass ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// cleanup the shadow specific rendering state
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_Cull ( CT_FRONT_SIDED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reset depth bounds
2012-11-28 15:47:07 +00:00
if ( r_useShadowDepthBounds . GetBool ( ) )
{
if ( r_useLightDepthBounds . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( vLight - > scissorRect . zmin , vLight - > scissorRect . zmax ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( 0.0f , 0.0f ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : StencilSelectLight
2012-11-26 18:58:24 +00:00
Deform the zeroOneCubeModel to exactly cover the light volume . Render the deformed cube model to the stencil buffer in
2012-11-28 15:47:07 +00:00
such a way that only fragments that are directly visible and contained within the volume will be written creating a
2012-11-26 18:58:24 +00:00
mask to be used by the following stencil shadow and draw interaction passes .
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : StencilSelectLight ( const viewLight_t * vLight )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( " Stencil Select " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// enable the light scissor
2017-09-03 21:17:44 +00:00
if ( ! currentScissor . Equals ( vLight - > scissorRect ) & & r_useScissor . GetBool ( ) )
2012-11-28 15:47:07 +00:00
{
2017-09-03 21:17:44 +00:00
GL_Scissor ( viewDef - > viewport . x1 + vLight - > scissorRect . x1 ,
viewDef - > viewport . y1 + vLight - > scissorRect . y1 ,
2012-11-26 18:58:24 +00:00
vLight - > scissorRect . x2 + 1 - vLight - > scissorRect . x1 ,
vLight - > scissorRect . y2 + 1 - vLight - > scissorRect . y1 ) ;
2017-09-03 21:17:44 +00:00
currentScissor = vLight - > scissorRect ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear stencil buffer to 0 (not drawable)
uint64 glStateMinusStencil = GL_GetCurrentStateMinusStencil ( ) ;
GL_State ( glStateMinusStencil | GLS_STENCIL_FUNC_ALWAYS | GLS_STENCIL_MAKE_REF ( STENCIL_SHADOW_TEST_VALUE ) | GLS_STENCIL_MAKE_MASK ( STENCIL_SHADOW_MASK_VALUE ) ) ; // make sure stencil mask passes for the clear
2015-12-20 11:28:46 +00:00
GL_Clear ( false , false , true , 0 , 0.0f , 0.0f , 0.0f , 0.0f , false ) ; // clear to 0 for stencil select
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the depthbounds
GL_DepthBoundsTest ( vLight - > scissorRect . zmin , vLight - > scissorRect . zmax ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_State ( GLS_COLORMASK | GLS_ALPHAMASK | GLS_DEPTHMASK | GLS_DEPTHFUNC_LESS | GLS_STENCIL_FUNC_ALWAYS | GLS_STENCIL_MAKE_REF ( STENCIL_SHADOW_TEST_VALUE ) | GLS_STENCIL_MAKE_MASK ( STENCIL_SHADOW_MASK_VALUE ) ) ;
GL_Cull ( CT_TWO_SIDED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Depth ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the matrix for deforming the 'zeroOneCubeModel' into the frustum to exactly cover the light volume
idRenderMatrix invProjectMVPMatrix ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( viewDef - > worldSpace . mvp , vLight - > inverseBaseLightProject , invProjectMVPMatrix ) ;
2012-11-26 18:58:24 +00:00
RB_SetMVP ( invProjectMVPMatrix ) ;
2012-11-28 15:47:07 +00:00
2018-10-03 19:14:28 +00:00
# if !defined(USE_VULKAN)
2012-11-26 18:58:24 +00:00
// two-sided stencil test
2012-12-17 16:30:59 +00:00
glStencilOpSeparate ( GL_FRONT , GL_KEEP , GL_REPLACE , GL_ZERO ) ;
glStencilOpSeparate ( GL_BACK , GL_KEEP , GL_ZERO , GL_REPLACE ) ;
2018-10-03 19:14:28 +00:00
# endif
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & zeroOneCubeSurface ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reset stencil state
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_Cull ( CT_FRONT_SIDED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderProgManager . Unbind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// unset the depthbounds
GL_DepthBoundsTest ( 0.0f , 0.0f ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2014-05-10 12:40:01 +00:00
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 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : ShadowMapPass
2014-05-10 12:40:01 +00:00
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : ShadowMapPass ( const drawSurf_t * drawSurfs , const viewLight_t * vLight , int side )
2014-05-10 12:40:01 +00:00
{
if ( r_skipShadows . GetBool ( ) )
{
return ;
}
if ( drawSurfs = = NULL )
{
return ;
}
RENDERLOG_PRINTF ( " ---------- RB_ShadowMapPass( side = %i ) ---------- \n " , side ) ;
renderProgManager . BindShader_Depth ( ) ;
GL_SelectTexture ( 0 ) ;
uint64 glState = 0 ;
// 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
2014-05-11 20:30:01 +00:00
GL_State ( glState | GLS_POLYGON_OFFSET ) ;
2014-05-10 12:40:01 +00:00
2014-05-11 20:30:01 +00:00
switch ( r_shadowMapOccluderFacing . GetInteger ( ) )
{
case 0 :
GL_Cull ( CT_FRONT_SIDED ) ;
GL_PolygonOffset ( r_shadowMapPolygonFactor . GetFloat ( ) , r_shadowMapPolygonOffset . GetFloat ( ) ) ;
break ;
case 1 :
GL_Cull ( CT_BACK_SIDED ) ;
GL_PolygonOffset ( - r_shadowMapPolygonFactor . GetFloat ( ) , - r_shadowMapPolygonOffset . GetFloat ( ) ) ;
break ;
default :
GL_Cull ( CT_TWO_SIDED ) ;
GL_PolygonOffset ( r_shadowMapPolygonFactor . GetFloat ( ) , r_shadowMapPolygonOffset . GetFloat ( ) ) ;
break ;
}
2014-05-10 12:40:01 +00:00
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();
2017-09-03 21:17:44 +00:00
const idVec3 viewDir = viewDef - > renderView . viewaxis [ 0 ] ;
const idVec3 viewPos = viewDef - > renderView . vieworg ;
2014-05-10 12:40:01 +00:00
# if 1
2017-09-03 21:17:44 +00:00
idRenderMatrix : : CreateViewMatrix ( viewDef - > renderView . vieworg , rotation , lightViewRenderMatrix ) ;
2014-05-10 12:40:01 +00:00
# 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 ;
2017-09-03 21:17:44 +00:00
if ( ! idRenderMatrix : : Inverse ( viewDef - > frustumMVPs [ FRUSTUM_CASCADE1 + side ] , splitFrustumInverse ) )
2014-05-10 12:40:01 +00:00
{
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 ) ;
2017-09-03 21:17:44 +00:00
shadowV [ side ] = lightViewRenderMatrix ;
shadowP [ side ] = lightProjectionRenderMatrix ;
2014-05-10 12:40:01 +00:00
}
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 ) ;
2017-09-03 21:17:44 +00:00
shadowV [ side ] = lightViewRenderMatrix ;
shadowP [ side ] = lightProjectionRenderMatrix ;
2014-05-10 12:40:01 +00:00
}
else
{
lightViewRenderMatrix . Identity ( ) ;
lightProjectionRenderMatrix = vLight - > baseLightProject ;
2017-09-03 21:17:44 +00:00
shadowV [ 0 ] = lightViewRenderMatrix ;
shadowP [ 0 ] = lightProjectionRenderMatrix ;
2014-05-10 12:40:01 +00:00
}
2018-10-03 21:40:35 +00:00
// FIXME
# if !defined(USE_VULKAN)
2014-05-11 20:30:01 +00:00
globalFramebuffers . shadowFBO [ vLight - > shadowLOD ] - > Bind ( ) ;
2014-05-10 12:40:01 +00:00
if ( side < 0 )
{
2014-05-11 20:30:01 +00:00
globalFramebuffers . shadowFBO [ vLight - > shadowLOD ] - > AttachImageDepthLayer ( globalImages - > shadowImage [ vLight - > shadowLOD ] , 0 ) ;
2014-05-10 12:40:01 +00:00
}
else
{
2014-05-11 20:30:01 +00:00
globalFramebuffers . shadowFBO [ vLight - > shadowLOD ] - > AttachImageDepthLayer ( globalImages - > shadowImage [ vLight - > shadowLOD ] , side ) ;
2014-05-10 12:40:01 +00:00
}
2014-05-11 20:30:01 +00:00
globalFramebuffers . shadowFBO [ vLight - > shadowLOD ] - > Check ( ) ;
2014-05-10 12:40:01 +00:00
2014-05-11 20:30:01 +00:00
GL_ViewportAndScissor ( 0 , 0 , shadowMapResolutions [ vLight - > shadowLOD ] , shadowMapResolutions [ vLight - > shadowLOD ] ) ;
2014-05-10 12:40:01 +00:00
2018-10-03 21:40:35 +00:00
2014-05-10 12:40:01 +00:00
glClear ( GL_DEPTH_BUFFER_BIT ) ;
2018-10-03 19:14:28 +00:00
# endif
2014-05-10 12:40:01 +00:00
// process the chain of shadows with the current rendering state
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2014-05-10 12:40:01 +00:00
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 ( ) ;
2017-09-03 21:17:44 +00:00
pc . shadowMicroSec + = end - start ;
2014-05-10 12:40:01 +00:00
}
# endif
if ( drawSurf - > numIndexes = = 0 )
{
continue ; // a job may have created an empty shadow geometry
}
2017-09-03 21:17:44 +00:00
if ( drawSurf - > space ! = currentSpace )
2014-05-10 12:40:01 +00:00
{
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 ( ) ) ;
*/
2017-09-03 21:17:44 +00:00
currentSpace = drawSurf - > space ;
2014-05-10 12:40:01 +00:00
}
2014-05-11 12:36:51 +00:00
bool didDraw = false ;
const idMaterial * shader = drawSurf - > material ;
// get the expressions for conditionals / color / texcoords
const float * regs = drawSurf - > shaderRegisters ;
idVec4 color ( 0 , 0 , 0 , 1 ) ;
uint64 surfGLState = 0 ;
// set polygon offset if necessary
2014-05-15 10:14:37 +00:00
if ( shader & & shader - > TestMaterialFlag ( MF_POLYGONOFFSET ) )
2014-05-10 12:40:01 +00:00
{
2014-05-11 12:36:51 +00:00
surfGLState | = GLS_POLYGON_OFFSET ;
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * shader - > GetPolygonOffset ( ) ) ;
2014-05-10 12:40:01 +00:00
}
2014-05-11 12:36:51 +00:00
# if 1
2014-05-15 10:14:37 +00:00
if ( shader & & shader - > Coverage ( ) = = MC_PERFORATED )
2014-05-10 12:40:01 +00:00
{
2014-05-11 12:36:51 +00:00
// perforated surfaces may have multiple alpha tested stages
for ( int stage = 0 ; stage < shader - > GetNumStages ( ) ; stage + + )
{
const shaderStage_t * pStage = shader - > GetStage ( stage ) ;
if ( ! pStage - > hasAlphaTest )
{
continue ;
}
// check the stage enable condition
if ( regs [ pStage - > conditionRegister ] = = 0 )
{
continue ;
}
// if we at least tried to draw an alpha tested stage,
// we won't draw the opaque surface
didDraw = true ;
// set the alpha modulate
color [ 3 ] = regs [ pStage - > color . registers [ 3 ] ] ;
// skip the entire stage if alpha would be black
if ( color [ 3 ] < = 0.0f )
{
continue ;
}
uint64 stageGLState = surfGLState ;
// set privatePolygonOffset if necessary
if ( pStage - > privatePolygonOffset )
{
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * pStage - > privatePolygonOffset ) ;
stageGLState | = GLS_POLYGON_OFFSET ;
}
GL_Color ( color ) ;
# ifdef USE_CORE_PROFILE
GL_State ( stageGLState ) ;
idVec4 alphaTestValue ( regs [ pStage - > alphaTestRegister ] ) ;
SetFragmentParm ( RENDERPARM_ALPHA_TEST , alphaTestValue . ToFloatPtr ( ) ) ;
# else
GL_State ( stageGLState | GLS_ALPHATEST_FUNC_GREATER | GLS_ALPHATEST_MAKE_REF ( idMath : : Ftob ( 255.0f * regs [ pStage - > alphaTestRegister ] ) ) ) ;
# endif
if ( drawSurf - > jointCache )
{
renderProgManager . BindShader_TextureVertexColorSkinned ( ) ;
}
else
{
renderProgManager . BindShader_TextureVertexColor ( ) ;
}
RB_SetVertexColorParms ( SVC_IGNORE ) ;
// bind the texture
GL_SelectTexture ( 0 ) ;
pStage - > texture . image - > Bind ( ) ;
// set texture matrix and texGens
2017-09-03 21:17:44 +00:00
PrepareStageTexturing ( pStage , drawSurf ) ;
2014-05-11 12:36:51 +00:00
// must render with less-equal for Z-Cull to work properly
assert ( ( GL_GetCurrentState ( ) & GLS_DEPTHFUNC_BITS ) = = GLS_DEPTHFUNC_LESS ) ;
// draw it
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( drawSurf ) ;
2014-05-11 12:36:51 +00:00
// clean up
2017-09-03 21:17:44 +00:00
FinishStageTexturing ( pStage , drawSurf ) ;
2014-05-11 12:36:51 +00:00
// unset privatePolygonOffset if necessary
if ( pStage - > privatePolygonOffset )
{
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * shader - > GetPolygonOffset ( ) ) ;
}
}
2014-05-10 12:40:01 +00:00
}
2014-05-11 12:36:51 +00:00
# endif
2014-05-10 12:40:01 +00:00
2014-05-11 12:36:51 +00:00
if ( ! didDraw )
{
if ( drawSurf - > jointCache )
{
renderProgManager . BindShader_DepthSkinned ( ) ;
}
else
{
renderProgManager . BindShader_Depth ( ) ;
}
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( drawSurf ) ;
2014-05-11 12:36:51 +00:00
}
2014-05-10 12:40:01 +00:00
}
// cleanup the shadow specific rendering state
2015-12-20 11:28:46 +00:00
if ( r_useHDR . GetBool ( ) ) //&& !backEnd.viewDef->is2Dgui )
{
globalFramebuffers . hdrFBO - > Bind ( ) ;
}
else
{
Framebuffer : : Unbind ( ) ;
}
2014-05-11 12:36:51 +00:00
renderProgManager . Unbind ( ) ;
2014-05-10 12:40:01 +00:00
2014-05-11 12:36:51 +00:00
GL_State ( GLS_DEFAULT ) ;
2014-05-10 12:40:01 +00:00
GL_Cull ( CT_FRONT_SIDED ) ;
2014-05-11 12:36:51 +00:00
# ifdef USE_CORE_PROFILE
SetFragmentParm ( RENDERPARM_ALPHA_TEST , vec4_zero . ToFloatPtr ( ) ) ;
# endif
2014-05-10 12:40:01 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2012-11-26 18:58:24 +00:00
DRAW INTERACTIONS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : DrawInteractions
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : DrawInteractions ( const viewDef_t * _viewDef )
2012-11-28 15:47:07 +00:00
{
if ( r_skipInteractions . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . OpenMainBlock ( MRB_DRAW_INTERACTIONS ) ;
renderLog . OpenBlock ( " RB_DrawInteractions " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2014-05-10 12:40:01 +00:00
const bool useLightDepthBounds = r_useLightDepthBounds . GetBool ( ) & & ! r_useShadowMapping . GetBool ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// for each light, perform shadowing and adding
//
2017-09-03 21:17:44 +00:00
for ( const viewLight_t * vLight = viewDef - > viewLights ; vLight ! = NULL ; vLight = vLight - > next )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// do fogging later
2012-11-28 15:47:07 +00:00
if ( vLight - > lightShader - > IsFogLight ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( vLight - > lightShader - > IsBlendLight ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( vLight - > localInteractions = = NULL & & vLight - > globalInteractions = = NULL & & vLight - > translucentInteractions = = NULL )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
const idMaterial * lightShader = vLight - > lightShader ;
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( lightShader - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the depth bounds for the whole light
2012-11-28 15:47:07 +00:00
if ( useLightDepthBounds )
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( vLight - > scissorRect . zmin , vLight - > scissorRect . zmax ) ;
}
2012-11-28 15:47:07 +00:00
2014-05-10 12:40:01 +00:00
// RB: shadow mapping
if ( r_useShadowMapping . GetBool ( ) )
2012-11-28 15:47:07 +00:00
{
2014-05-10 12:40:01 +00:00
int side , sideStop ;
if ( vLight - > parallel )
2012-11-28 15:47:07 +00:00
{
2014-05-10 12:40:01 +00:00
side = 0 ;
sideStop = r_shadowMapSplits . GetInteger ( ) + 1 ;
2012-11-28 15:47:07 +00:00
}
2014-05-10 12:40:01 +00:00
else if ( vLight - > pointLight )
2012-11-28 15:47:07 +00:00
{
2014-05-10 12:40:01 +00:00
if ( r_shadowMapSingleSide . GetInteger ( ) ! = - 1 )
2012-11-28 15:47:07 +00:00
{
2014-05-10 12:40:01 +00:00
side = r_shadowMapSingleSide . GetInteger ( ) ;
sideStop = side + 1 ;
}
else
{
side = 0 ;
sideStop = 6 ;
2012-11-26 18:58:24 +00:00
}
2014-05-10 12:40:01 +00:00
}
else
{
side = - 1 ;
sideStop = 0 ;
}
for ( ; side < sideStop ; side + + )
{
2017-09-03 21:17:44 +00:00
ShadowMapPass ( vLight - > globalShadows , vLight , side ) ;
2014-05-10 12:40:01 +00:00
}
// go back from light view to default camera view
2017-09-03 21:17:44 +00:00
ResetViewportAndScissorToDefaultCamera ( _viewDef ) ;
2014-05-10 12:40:01 +00:00
if ( vLight - > localInteractions ! = NULL )
{
renderLog . OpenBlock ( " Local Light Interactions " ) ;
2017-09-03 21:17:44 +00:00
RenderInteractions ( vLight - > localInteractions , vLight , GLS_DEPTHFUNC_EQUAL , false , useLightDepthBounds ) ;
2014-05-10 12:40:01 +00:00
renderLog . CloseBlock ( ) ;
}
if ( vLight - > globalInteractions ! = NULL )
{
renderLog . OpenBlock ( " Global Light Interactions " ) ;
2017-09-03 21:17:44 +00:00
RenderInteractions ( vLight - > globalInteractions , vLight , GLS_DEPTHFUNC_EQUAL , false , useLightDepthBounds ) ;
2014-05-10 12:40:01 +00:00
renderLog . CloseBlock ( ) ;
2012-11-26 18:58:24 +00:00
}
}
2014-05-10 12:40:01 +00:00
else
2012-11-28 15:47:07 +00:00
{
2014-05-10 12:40:01 +00:00
// 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
2017-09-03 21:17:44 +00:00
const bool useLightStencilSelect = ( r_useLightStencilSelect . GetBool ( ) & & viewDef - > isMirror = = false ) ;
2014-05-10 12:40:01 +00:00
if ( performStencilTest )
{
if ( useLightStencilSelect )
{
// write a stencil mask for the visible light bounds to hi-stencil
2017-09-03 21:17:44 +00:00
StencilSelectLight ( vLight ) ;
2014-05-10 12:40:01 +00:00
}
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 ;
2017-09-03 21:17:44 +00:00
if ( ! currentScissor . Equals ( rect ) & & r_useScissor . GetBool ( ) )
2014-05-10 12:40:01 +00:00
{
2017-09-09 12:57:48 +00:00
GL_Scissor ( viewDef - > viewport . x1 + rect . x1 ,
viewDef - > viewport . y1 + rect . y1 ,
2014-05-10 12:40:01 +00:00
rect . x2 + 1 - rect . x1 ,
rect . y2 + 1 - rect . y1 ) ;
2017-09-09 12:57:48 +00:00
currentScissor = rect ;
2014-05-10 12:40:01 +00:00
}
GL_State ( GLS_DEFAULT ) ; // make sure stencil mask passes for the clear
2015-12-20 11:28:46 +00:00
GL_Clear ( false , false , true , STENCIL_SHADOW_TEST_VALUE , 0.0f , 0.0f , 0.0f , 0.0f , false ) ;
2014-05-10 12:40:01 +00:00
}
}
if ( vLight - > globalShadows ! = NULL )
{
renderLog . OpenBlock ( " Global Light Shadows " ) ;
2017-09-03 21:17:44 +00:00
StencilShadowPass ( vLight - > globalShadows , vLight ) ;
2014-05-10 12:40:01 +00:00
renderLog . CloseBlock ( ) ;
}
if ( vLight - > localInteractions ! = NULL )
{
renderLog . OpenBlock ( " Local Light Interactions " ) ;
2017-09-03 21:17:44 +00:00
RenderInteractions ( vLight - > localInteractions , vLight , GLS_DEPTHFUNC_EQUAL , performStencilTest , useLightDepthBounds ) ;
2014-05-10 12:40:01 +00:00
renderLog . CloseBlock ( ) ;
}
if ( vLight - > localShadows ! = NULL )
{
renderLog . OpenBlock ( " Local Light Shadows " ) ;
2017-09-03 21:17:44 +00:00
StencilShadowPass ( vLight - > localShadows , vLight ) ;
2014-05-10 12:40:01 +00:00
renderLog . CloseBlock ( ) ;
}
if ( vLight - > globalInteractions ! = NULL )
{
renderLog . OpenBlock ( " Global Light Interactions " ) ;
2017-09-03 21:17:44 +00:00
RenderInteractions ( vLight - > globalInteractions , vLight , GLS_DEPTHFUNC_EQUAL , performStencilTest , useLightDepthBounds ) ;
2014-05-10 12:40:01 +00:00
renderLog . CloseBlock ( ) ;
}
2012-11-26 18:58:24 +00:00
}
2014-05-10 12:40:01 +00:00
// RB end
2012-11-28 15:47:07 +00:00
if ( vLight - > translucentInteractions ! = NULL & & ! r_skipTranslucent . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( " Translucent Interactions " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Disable the depth bounds test because translucent surfaces don't work with
// the depth bounds tests since they did not write depth during the depth pass.
2012-11-28 15:47:07 +00:00
if ( useLightDepthBounds )
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( 0.0f , 0.0f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// The depth buffer wasn't filled in for translucent surfaces, so they
// can never be constrained to perforated surfaces with the depthfunc equal.
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Translucent surfaces do not receive shadows. This is a case where a
// shadow buffer solution would work but stencil shadows do not because
// stencil shadows only affect surfaces that contribute to the view depth
// buffer and translucent surfaces do not contribute to the view depth buffer.
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
RenderInteractions ( vLight - > translucentInteractions , vLight , GLS_DEPTHFUNC_LESS , false , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// disable stencil shadow test
GL_State ( GLS_DEFAULT ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// unbind texture units
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reset depth bounds
2012-11-28 15:47:07 +00:00
if ( useLightDepthBounds )
{
2012-11-26 18:58:24 +00:00
GL_DepthBoundsTest ( 0.0f , 0.0f ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
renderLog . CloseMainBlock ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
NON - INTERACTION SHADER PASSES
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : DrawShaderPasses
2012-11-26 18:58:24 +00:00
Draw non - light dependent passes
If we are rendering Guis , the drawSurf_t : : sort value is a depth offset that can
be multiplied by guiEye for polarity and screenSeparation for scale .
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
int idRenderBackend : : DrawShaderPasses ( const drawSurf_t * const * const drawSurfs , const int numDrawSurfs ,
const float guiStereoScreenOffset , const int stereoEye )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// only obey skipAmbient if we are rendering a view
2017-09-09 12:57:48 +00:00
if ( viewDef - > viewEntitys & & r_skipAmbient . GetBool ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return numDrawSurfs ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( " RB_DrawShaderPasses " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2017-09-09 12:57:48 +00:00
currentSpace = ( const viewEntity_t * ) 1 ; // using NULL makes /analyze think surf->space needs to be checked...
2012-11-26 18:58:24 +00:00
float currentGuiStereoOffset = 0.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int i = 0 ;
2012-11-28 15:47:07 +00:00
for ( ; i < numDrawSurfs ; i + + )
{
const drawSurf_t * surf = drawSurfs [ i ] ;
const idMaterial * shader = surf - > material ;
if ( ! shader - > HasAmbient ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( shader - > IsPortalSky ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// some deforms may disable themselves by setting numIndexes = 0
2012-11-28 15:47:07 +00:00
if ( surf - > numIndexes = = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( shader - > SuppressInSubview ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2017-09-09 12:57:48 +00:00
if ( viewDef - > isXraySubview & & surf - > space - > entityDef )
2012-11-28 15:47:07 +00:00
{
if ( surf - > space - > entityDef - > parms . xrayIndex ! = 2 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we need to draw the post process shaders after we have drawn the fog lights
2017-09-09 12:57:48 +00:00
if ( shader - > GetSort ( ) > = SS_POST_PROCESS & & ! currentRenderCopied )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
// if we are rendering a 3D view and the surface's eye index doesn't match
2012-11-26 18:58:24 +00:00
// the current view's eye index then we skip the surface
// if the stereoEye value of a surface is 0 then we need to draw it for both eyes.
const int shaderStereoEye = shader - > GetStereoEye ( ) ;
const bool isEyeValid = stereoRender_swapEyes . GetBool ( ) ? ( shaderStereoEye = = stereoEye ) : ( shaderStereoEye ! = stereoEye ) ;
2012-11-28 15:47:07 +00:00
if ( ( stereoEye ! = 0 ) & & ( shaderStereoEye ! = 0 ) & & ( isEyeValid ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( shader - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
// determine the stereoDepth offset
2012-11-26 18:58:24 +00:00
// guiStereoScreenOffset will always be zero for 3D views, so the !=
// check will never force an update due to the current sort value.
const float thisGuiStereoOffset = guiStereoScreenOffset * surf - > sort ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// change the matrix and other space related vars if needed
2017-09-09 12:57:48 +00:00
if ( surf - > space ! = currentSpace | | thisGuiStereoOffset ! = currentGuiStereoOffset )
2012-11-28 15:47:07 +00:00
{
2017-09-09 12:57:48 +00:00
currentSpace = surf - > space ;
2012-11-26 18:58:24 +00:00
currentGuiStereoOffset = thisGuiStereoOffset ;
2012-11-28 15:47:07 +00:00
2017-09-09 12:57:48 +00:00
const viewEntity_t * space = currentSpace ;
2012-11-28 15:47:07 +00:00
if ( guiStereoScreenOffset ! = 0.0f )
{
2012-11-26 18:58:24 +00:00
RB_SetMVPWithStereoOffset ( space - > mvp , currentGuiStereoOffset ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
RB_SetMVP ( space - > mvp ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set eye position in local space
idVec4 localViewOrigin ( 1.0f ) ;
2017-09-09 12:57:48 +00:00
R_GlobalPointToLocal ( space - > modelMatrix , viewDef - > renderView . vieworg , localViewOrigin . ToVec3 ( ) ) ;
2012-11-26 18:58:24 +00:00
SetVertexParm ( RENDERPARM_LOCALVIEWORIGIN , localViewOrigin . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set model Matrix
float modelMatrixTranspose [ 16 ] ;
R_MatrixTranspose ( space - > modelMatrix , modelMatrixTranspose ) ;
SetVertexParms ( RENDERPARM_MODELMATRIX_X , modelMatrixTranspose , 4 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set ModelView Matrix
float modelViewMatrixTranspose [ 16 ] ;
R_MatrixTranspose ( space - > modelViewMatrix , modelViewMatrixTranspose ) ;
SetVertexParms ( RENDERPARM_MODELVIEWMATRIX_X , modelViewMatrixTranspose , 4 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// change the scissor if needed
2017-09-09 12:57:48 +00:00
if ( ! currentScissor . Equals ( surf - > scissorRect ) & & r_useScissor . GetBool ( ) )
2012-11-28 15:47:07 +00:00
{
2017-09-09 12:57:48 +00:00
GL_Scissor ( viewDef - > viewport . x1 + surf - > scissorRect . x1 ,
viewDef - > viewport . y1 + surf - > scissorRect . y1 ,
2012-11-26 18:58:24 +00:00
surf - > scissorRect . x2 + 1 - surf - > scissorRect . x1 ,
surf - > scissorRect . y2 + 1 - surf - > scissorRect . y1 ) ;
2017-09-09 12:57:48 +00:00
currentScissor = surf - > scissorRect ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the expressions for conditionals / color / texcoords
2012-11-28 15:47:07 +00:00
const float * regs = surf - > shaderRegisters ;
2012-11-26 18:58:24 +00:00
// set face culling appropriately
2012-11-28 15:47:07 +00:00
if ( surf - > space - > isGuiSurface )
{
2012-11-26 18:58:24 +00:00
GL_Cull ( CT_TWO_SIDED ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
GL_Cull ( shader - > GetCullType ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint64 surfGLState = surf - > extraGLState ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set polygon offset if necessary
2012-11-28 15:47:07 +00:00
if ( shader - > TestMaterialFlag ( MF_POLYGONOFFSET ) )
{
2012-11-26 18:58:24 +00:00
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * shader - > GetPolygonOffset ( ) ) ;
surfGLState = GLS_POLYGON_OFFSET ;
}
2012-11-28 15:47:07 +00:00
for ( int stage = 0 ; stage < shader - > GetNumStages ( ) ; stage + + )
{
const shaderStage_t * pStage = shader - > GetStage ( stage ) ;
2012-11-26 18:58:24 +00:00
// check the enable condition
2012-11-28 15:47:07 +00:00
if ( regs [ pStage - > conditionRegister ] = = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip the stages involved in lighting
2012-11-28 15:47:07 +00:00
if ( pStage - > lighting ! = SL_AMBIENT )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint64 stageGLState = surfGLState ;
2012-11-28 15:47:07 +00:00
if ( ( surfGLState & GLS_OVERRIDE ) = = 0 )
{
2012-11-26 18:58:24 +00:00
stageGLState | = pStage - > drawStateBits ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip if the stage is ( GL_ZERO, GL_ONE ), which is used for some alpha masks
2012-11-28 15:47:07 +00:00
if ( ( stageGLState & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) = = ( GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2014-04-20 14:29:58 +00:00
2012-11-26 18:58:24 +00:00
// see if we are a new-style stage
2012-11-28 15:47:07 +00:00
newShaderStage_t * newStage = pStage - > newStage ;
if ( newStage ! = NULL )
{
2012-11-26 18:58:24 +00:00
//--------------------------
//
// new style stages
//
//--------------------------
2012-11-28 15:47:07 +00:00
if ( r_skipNewAmbient . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
renderLog . OpenBlock ( " New Shader Stage " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_State ( stageGLState ) ;
2012-11-28 15:47:07 +00:00
2018-10-13 16:34:29 +00:00
renderProgManager . BindProgram ( newStage - > glslProgram ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < newStage - > numVertexParms ; j + + )
{
2012-11-26 18:58:24 +00:00
float parm [ 4 ] ;
parm [ 0 ] = regs [ newStage - > vertexParms [ j ] [ 0 ] ] ;
parm [ 1 ] = regs [ newStage - > vertexParms [ j ] [ 1 ] ] ;
parm [ 2 ] = regs [ newStage - > vertexParms [ j ] [ 2 ] ] ;
parm [ 3 ] = regs [ newStage - > vertexParms [ j ] [ 3 ] ] ;
2018-10-13 11:50:44 +00:00
SetVertexParm ( ( renderParm_t ) ( RENDERPARM_USER0 + j ) , parm ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set rpEnableSkinning if the shader has optional support for skinning
2012-11-28 15:47:07 +00:00
if ( surf - > jointCache & & renderProgManager . ShaderHasOptionalSkinning ( ) )
{
2012-11-26 18:58:24 +00:00
const idVec4 skinningParm ( 1.0f ) ;
SetVertexParm ( RENDERPARM_ENABLE_SKINNING , skinningParm . ToFloatPtr ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// bind texture units
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < newStage - > numFragmentProgramImages ; j + + )
{
idImage * image = newStage - > fragmentProgramImages [ j ] ;
if ( image ! = NULL )
{
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( j ) ;
image - > Bind ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw it
2017-09-09 12:57:48 +00:00
DrawElementsWithCounters ( surf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear rpEnableSkinning if it was set
2012-11-28 15:47:07 +00:00
if ( surf - > jointCache & & renderProgManager . ShaderHasOptionalSkinning ( ) )
{
2012-11-26 18:58:24 +00:00
const idVec4 skinningParm ( 0.0f ) ;
SetVertexParm ( RENDERPARM_ENABLE_SKINNING , skinningParm . ToFloatPtr ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
renderProgManager . Unbind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//--------------------------
//
// old style stages
//
//--------------------------
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the color
2014-05-10 12:40:01 +00:00
idVec4 color ;
2012-11-26 18:58:24 +00:00
color [ 0 ] = regs [ pStage - > color . registers [ 0 ] ] ;
color [ 1 ] = regs [ pStage - > color . registers [ 1 ] ] ;
color [ 2 ] = regs [ pStage - > color . registers [ 2 ] ] ;
color [ 3 ] = regs [ pStage - > color . registers [ 3 ] ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip the entire stage if an add would be black
2012-11-28 15:47:07 +00:00
if ( ( stageGLState & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) = = ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE )
& & color [ 0 ] < = 0 & & color [ 1 ] < = 0 & & color [ 2 ] < = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip the entire stage if a blend would be completely transparent
2012-11-28 15:47:07 +00:00
if ( ( stageGLState & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) = = ( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA )
& & color [ 3 ] < = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stageVertexColor_t svc = pStage - > vertexColor ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( " Old Shader Stage " ) ;
GL_Color ( color ) ;
2012-11-28 15:47:07 +00:00
if ( surf - > space - > isGuiSurface )
{
2012-11-26 18:58:24 +00:00
// Force gui surfaces to always be SVC_MODULATE
svc = SVC_MODULATE ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// use special shaders for bink cinematics
2012-11-28 15:47:07 +00:00
if ( pStage - > texture . cinematic )
{
if ( ( stageGLState & GLS_OVERRIDE ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
// This is a hack... Only SWF Guis set GLS_OVERRIDE
// Old style guis do not, and we don't want them to use the new GUI renederProg
2016-01-18 21:21:32 +00:00
renderProgManager . BindShader_TextureVertexColor_sRGB ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2016-01-18 21:21:32 +00:00
renderProgManager . BindShader_TextureVertexColor ( ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
}
else
{
if ( ( stageGLState & GLS_OVERRIDE ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
// This is a hack... Only SWF Guis set GLS_OVERRIDE
// Old style guis do not, and we don't want them to use the new GUI renderProg
renderProgManager . BindShader_GUI ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( surf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_TextureVertexColorSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2017-09-09 12:57:48 +00:00
if ( viewDef - > is2Dgui )
2016-02-02 22:12:53 +00:00
{
// RB: 2D fullscreen drawing like warp or damage blend effects
renderProgManager . BindShader_TextureVertexColor_sRGB ( ) ;
}
else
{
renderProgManager . BindShader_TextureVertexColor ( ) ;
}
2012-11-26 18:58:24 +00:00
}
}
}
2012-11-28 15:47:07 +00:00
}
else if ( ( pStage - > texture . texgen = = TG_SCREEN ) | | ( pStage - > texture . texgen = = TG_SCREEN2 ) )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_TextureTexGenVertexColor ( ) ;
2012-11-28 15:47:07 +00:00
}
else if ( pStage - > texture . cinematic )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Bink ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( surf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_TextureVertexColorSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_TextureVertexColor ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RB_SetVertexColorParms ( svc ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// bind the texture
2017-09-09 12:57:48 +00:00
BindVariableStageImage ( & pStage - > texture , regs ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set privatePolygonOffset if necessary
2012-11-28 15:47:07 +00:00
if ( pStage - > privatePolygonOffset )
{
2012-11-26 18:58:24 +00:00
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * pStage - > privatePolygonOffset ) ;
stageGLState | = GLS_POLYGON_OFFSET ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the state
GL_State ( stageGLState ) ;
2012-11-28 15:47:07 +00:00
2017-09-09 12:57:48 +00:00
PrepareStageTexturing ( pStage , surf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw it
2017-09-09 12:57:48 +00:00
DrawElementsWithCounters ( surf ) ;
2012-11-28 15:47:07 +00:00
2017-09-09 12:57:48 +00:00
FinishStageTexturing ( pStage , surf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// unset privatePolygonOffset if necessary
2012-11-28 15:47:07 +00:00
if ( pStage - > privatePolygonOffset )
{
2012-11-26 18:58:24 +00:00
GL_PolygonOffset ( r_offsetFactor . GetFloat ( ) , r_offsetUnits . GetFloat ( ) * shader - > GetPolygonOffset ( ) ) ;
}
renderLog . CloseBlock ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_Cull ( CT_FRONT_SIDED ) ;
GL_Color ( 1.0f , 1.0f , 1.0f ) ;
2012-11-28 15:47:07 +00:00
2016-01-11 18:00:20 +00:00
// disable stencil shadow test
GL_State ( GLS_DEFAULT ) ;
GL_SelectTexture ( 0 ) ;
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
return i ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BLEND LIGHT PROJECTION
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : T_BlendLight
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : T_BlendLight ( const drawSurf_t * drawSurfs , const viewLight_t * vLight )
2012-11-28 15:47:07 +00:00
{
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2012-11-28 15:47:07 +00:00
for ( const drawSurf_t * drawSurf = drawSurfs ; drawSurf ! = NULL ; drawSurf = drawSurf - > nextOnLight )
{
if ( drawSurf - > scissorRect . IsEmpty ( ) )
{
2012-11-26 18:58:24 +00:00
continue ; // !@# FIXME: find out why this is sometimes being hit!
2012-11-28 15:47:07 +00:00
// temporarily jump over the scissor and draw so the gl error callback doesn't get hit
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
if ( ! currentScissor . Equals ( drawSurf - > scissorRect ) & & r_useScissor . GetBool ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// change the scissor
2017-09-03 21:17:44 +00:00
GL_Scissor ( viewDef - > viewport . x1 + drawSurf - > scissorRect . x1 ,
viewDef - > viewport . y1 + drawSurf - > scissorRect . y1 ,
2012-11-26 18:58:24 +00:00
drawSurf - > scissorRect . x2 + 1 - drawSurf - > scissorRect . x1 ,
drawSurf - > scissorRect . y2 + 1 - drawSurf - > scissorRect . y1 ) ;
2017-09-03 21:17:44 +00:00
currentScissor = drawSurf - > scissorRect ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
if ( drawSurf - > space ! = currentSpace )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// change the matrix
RB_SetMVP ( drawSurf - > space - > mvp ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// change the light projection matrix
idPlane lightProjectInCurrentSpace [ 4 ] ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 4 ; i + + )
{
2012-11-26 18:58:24 +00:00
R_GlobalPlaneToLocal ( drawSurf - > space - > modelMatrix , vLight - > lightProject [ i ] , lightProjectInCurrentSpace [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetVertexParm ( RENDERPARM_TEXGEN_0_S , lightProjectInCurrentSpace [ 0 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_TEXGEN_0_T , lightProjectInCurrentSpace [ 1 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_TEXGEN_0_Q , lightProjectInCurrentSpace [ 2 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_TEXGEN_1_S , lightProjectInCurrentSpace [ 3 ] . ToFloatPtr ( ) ) ; // falloff
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
currentSpace = drawSurf - > space ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( drawSurf ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : BlendLight
2012-11-26 18:58:24 +00:00
Dual texture together the falloff and projection texture with a blend
mode to the framebuffer , instead of interacting with the surface texture
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : BlendLight ( const drawSurf_t * drawSurfs , const drawSurf_t * drawSurfs2 , const viewLight_t * vLight )
2012-11-28 15:47:07 +00:00
{
if ( drawSurfs = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( r_skipBlendLights . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
renderLog . OpenBlock ( vLight - > lightShader - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
const idMaterial * lightShader = vLight - > lightShader ;
const float * regs = vLight - > shaderRegisters ;
2012-11-26 18:58:24 +00:00
// texture 1 will get the falloff texture
GL_SelectTexture ( 1 ) ;
vLight - > falloffImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 0 will get the projected texture
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_BlendLight ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < lightShader - > GetNumStages ( ) ; i + + )
{
const shaderStage_t * stage = lightShader - > GetStage ( i ) ;
if ( ! regs [ stage - > conditionRegister ] )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_State ( GLS_DEPTHMASK | stage - > drawStateBits | GLS_DEPTHFUNC_EQUAL ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
stage - > texture . image - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
if ( stage - > texture . hasMatrix )
{
2012-11-26 18:58:24 +00:00
RB_LoadShaderTextureMatrix ( regs , & stage - > texture ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the modulate values from the light, including alpha, unlike normal lights
2014-05-10 12:40:01 +00:00
idVec4 lightColor ;
2012-11-26 18:58:24 +00:00
lightColor [ 0 ] = regs [ stage - > color . registers [ 0 ] ] ;
lightColor [ 1 ] = regs [ stage - > color . registers [ 1 ] ] ;
lightColor [ 2 ] = regs [ stage - > color . registers [ 2 ] ] ;
lightColor [ 3 ] = regs [ stage - > color . registers [ 3 ] ] ;
GL_Color ( lightColor ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
T_BlendLight ( drawSurfs , vLight ) ;
T_BlendLight ( drawSurfs2 , vLight ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderProgManager . Unbind ( ) ;
renderLog . CloseBlock ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
FOG LIGHTS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : T_BasicFog
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : T_BasicFog ( const drawSurf_t * drawSurfs , const idPlane fogPlanes [ 4 ] , const idRenderMatrix * inverseBaseLightProject )
2012-11-28 15:47:07 +00:00
{
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2012-11-28 15:47:07 +00:00
for ( const drawSurf_t * drawSurf = drawSurfs ; drawSurf ! = NULL ; drawSurf = drawSurf - > nextOnLight )
{
if ( drawSurf - > scissorRect . IsEmpty ( ) )
{
2012-11-26 18:58:24 +00:00
continue ; // !@# FIXME: find out why this is sometimes being hit!
2012-11-28 15:47:07 +00:00
// temporarily jump over the scissor and draw so the gl error callback doesn't get hit
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
if ( ! currentScissor . Equals ( drawSurf - > scissorRect ) & & r_useScissor . GetBool ( ) )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// change the scissor
2017-09-03 21:17:44 +00:00
GL_Scissor ( viewDef - > viewport . x1 + drawSurf - > scissorRect . x1 ,
viewDef - > viewport . y1 + drawSurf - > scissorRect . y1 ,
2012-11-26 18:58:24 +00:00
drawSurf - > scissorRect . x2 + 1 - drawSurf - > scissorRect . x1 ,
drawSurf - > scissorRect . y2 + 1 - drawSurf - > scissorRect . y1 ) ;
2017-09-03 21:17:44 +00:00
currentScissor = drawSurf - > scissorRect ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
if ( drawSurf - > space ! = currentSpace )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
idPlane localFogPlanes [ 4 ] ;
2012-11-28 15:47:07 +00:00
if ( inverseBaseLightProject = = NULL )
{
2012-11-26 18:58:24 +00:00
RB_SetMVP ( drawSurf - > space - > mvp ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 4 ; i + + )
{
2012-11-26 18:58:24 +00:00
R_GlobalPlaneToLocal ( drawSurf - > space - > modelMatrix , fogPlanes [ i ] , localFogPlanes [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idRenderMatrix invProjectMVPMatrix ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( viewDef - > worldSpace . mvp , * inverseBaseLightProject , invProjectMVPMatrix ) ;
2012-11-26 18:58:24 +00:00
RB_SetMVP ( invProjectMVPMatrix ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 4 ; i + + )
{
2012-11-26 18:58:24 +00:00
inverseBaseLightProject - > InverseTransformPlane ( fogPlanes [ i ] , localFogPlanes [ i ] , false ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetVertexParm ( RENDERPARM_TEXGEN_0_S , localFogPlanes [ 0 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_TEXGEN_0_T , localFogPlanes [ 1 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_TEXGEN_1_T , localFogPlanes [ 2 ] . ToFloatPtr ( ) ) ;
SetVertexParm ( RENDERPARM_TEXGEN_1_S , localFogPlanes [ 3 ] . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
currentSpace = ( inverseBaseLightProject = = NULL ) ? drawSurf - > space : NULL ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( drawSurf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_FogSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_Fog ( ) ;
}
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( drawSurf ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : FogPass
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : FogPass ( const drawSurf_t * drawSurfs , const drawSurf_t * drawSurfs2 , const viewLight_t * vLight )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( vLight - > lightShader - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find the current color and density of the fog
2012-11-28 15:47:07 +00:00
const idMaterial * lightShader = vLight - > lightShader ;
const float * regs = vLight - > shaderRegisters ;
2012-11-26 18:58:24 +00:00
// assume fog shaders have only a single stage
2012-11-28 15:47:07 +00:00
const shaderStage_t * stage = lightShader - > GetStage ( 0 ) ;
2014-05-10 12:40:01 +00:00
idVec4 lightColor ;
2012-11-26 18:58:24 +00:00
lightColor [ 0 ] = regs [ stage - > color . registers [ 0 ] ] ;
lightColor [ 1 ] = regs [ stage - > color . registers [ 1 ] ] ;
lightColor [ 2 ] = regs [ stage - > color . registers [ 2 ] ] ;
lightColor [ 3 ] = regs [ stage - > color . registers [ 3 ] ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_Color ( lightColor ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// calculate the falloff planes
float a ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if they left the default value on, set a fog distance of 500
2012-11-28 15:47:07 +00:00
if ( lightColor [ 3 ] < = 1.0f )
{
2012-11-26 18:58:24 +00:00
a = - 0.5f / DEFAULT_FOG_DISTANCE ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// otherwise, distance = alpha color
a = - 0.5f / lightColor [ 3 ] ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 0 is the falloff image
GL_SelectTexture ( 0 ) ;
globalImages - > fogImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// texture 1 is the entering plane fade correction
GL_SelectTexture ( 1 ) ;
globalImages - > fogEnterImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// S is based on the view origin
2017-09-03 21:17:44 +00:00
const float s = vLight - > fogPlane . Distance ( viewDef - > renderView . vieworg ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const float FOG_SCALE = 0.001f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPlane fogPlanes [ 4 ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// S-0
2017-09-03 21:17:44 +00:00
fogPlanes [ 0 ] [ 0 ] = a * viewDef - > worldSpace . modelViewMatrix [ 0 * 4 + 2 ] ;
fogPlanes [ 0 ] [ 1 ] = a * viewDef - > worldSpace . modelViewMatrix [ 1 * 4 + 2 ] ;
fogPlanes [ 0 ] [ 2 ] = a * viewDef - > worldSpace . modelViewMatrix [ 2 * 4 + 2 ] ;
fogPlanes [ 0 ] [ 3 ] = a * viewDef - > worldSpace . modelViewMatrix [ 3 * 4 + 2 ] + 0.5f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// T-0
fogPlanes [ 1 ] [ 0 ] = 0.0f ; //a * backEnd.viewDef->worldSpace.modelViewMatrix[0*4+0];
fogPlanes [ 1 ] [ 1 ] = 0.0f ; //a * backEnd.viewDef->worldSpace.modelViewMatrix[1*4+0];
fogPlanes [ 1 ] [ 2 ] = 0.0f ; //a * backEnd.viewDef->worldSpace.modelViewMatrix[2*4+0];
fogPlanes [ 1 ] [ 3 ] = 0.5f ; //a * backEnd.viewDef->worldSpace.modelViewMatrix[3*4+0] + 0.5f;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// T-1 will get a texgen for the fade plane, which is always the "top" plane on unrotated lights
fogPlanes [ 2 ] [ 0 ] = FOG_SCALE * vLight - > fogPlane [ 0 ] ;
fogPlanes [ 2 ] [ 1 ] = FOG_SCALE * vLight - > fogPlane [ 1 ] ;
fogPlanes [ 2 ] [ 2 ] = FOG_SCALE * vLight - > fogPlane [ 2 ] ;
fogPlanes [ 2 ] [ 3 ] = FOG_SCALE * vLight - > fogPlane [ 3 ] + FOG_ENTER ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// S-1
fogPlanes [ 3 ] [ 0 ] = 0.0f ;
fogPlanes [ 3 ] [ 1 ] = 0.0f ;
fogPlanes [ 3 ] [ 2 ] = 0.0f ;
fogPlanes [ 3 ] [ 3 ] = FOG_SCALE * s + FOG_ENTER ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw it
GL_State ( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ) ;
2017-09-09 12:57:48 +00:00
T_BasicFog ( drawSurfs , fogPlanes , NULL ) ;
T_BasicFog ( drawSurfs2 , fogPlanes , NULL ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the light frustum bounding planes aren't in the depth buffer, so use depthfunc_less instead
// of depthfunc_equal
GL_State ( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_LESS ) ;
GL_Cull ( CT_BACK_SIDED ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
zeroOneCubeSurface . space = & viewDef - > worldSpace ;
zeroOneCubeSurface . scissorRect = viewDef - > scissor ;
T_BasicFog ( & zeroOneCubeSurface , fogPlanes , & vLight - > inverseBaseLightProject ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_Cull ( CT_FRONT_SIDED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderProgManager . Unbind ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : FogAllLights
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : FogAllLights ( )
2012-11-28 15:47:07 +00:00
{
if ( r_skipFogLights . GetBool ( ) | | r_showOverDraw . GetInteger ( ) ! = 0
2017-09-03 21:17:44 +00:00
| | viewDef - > isXraySubview /* don't fog in xray mode*/ )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
renderLog . OpenMainBlock ( MRB_FOG_ALL_LIGHTS ) ;
renderLog . OpenBlock ( " RB_FogAllLights " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// force fog plane to recalculate
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
for ( viewLight_t * vLight = viewDef - > viewLights ; vLight ! = NULL ; vLight = vLight - > next )
2012-11-28 15:47:07 +00:00
{
if ( vLight - > lightShader - > IsFogLight ( ) )
{
2017-09-03 21:17:44 +00:00
FogPass ( vLight - > globalInteractions , vLight - > localInteractions , vLight ) ;
2012-11-28 15:47:07 +00:00
}
else if ( vLight - > lightShader - > IsBlendLight ( ) )
{
2017-09-03 21:17:44 +00:00
BlendLight ( vLight - > globalInteractions , vLight - > localInteractions , vLight ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
renderLog . CloseMainBlock ( ) ;
}
2015-12-20 11:28:46 +00:00
// RB begin
2017-09-03 21:17:44 +00:00
void idRenderBackend : : CalculateAutomaticExposure ( )
2015-12-20 11:28:46 +00:00
{
int i ;
static float image [ 64 * 64 * 4 ] ;
float curTime ;
float deltaTime ;
float luminance ;
float avgLuminance ;
float maxLuminance ;
double sum ;
2015-12-23 12:53:21 +00:00
const idVec3 LUMINANCE_SRGB ( 0.2125f , 0.7154f , 0.0721f ) ; // be careful wether this should be linear RGB or sRGB
2015-12-20 11:28:46 +00:00
idVec4 color ;
float newAdaptation ;
float newMaximum ;
2016-01-13 23:59:41 +00:00
if ( ! r_hdrAutoExposure . GetBool ( ) )
2015-12-20 11:28:46 +00:00
{
2016-01-13 23:59:41 +00:00
// no dynamic exposure
2015-12-20 11:28:46 +00:00
2017-09-03 21:17:44 +00:00
hdrKey = r_hdrKey . GetFloat ( ) ;
hdrAverageLuminance = r_hdrMinLuminance . GetFloat ( ) ;
hdrMaxLuminance = 1 ;
2016-01-13 23:59:41 +00:00
}
else
{
curTime = Sys_Milliseconds ( ) / 1000.0f ;
2015-12-20 11:28:46 +00:00
2016-01-13 23:59:41 +00:00
// calculate the average scene luminance
globalFramebuffers . hdr64FBO - > Bind ( ) ;
2018-10-03 21:40:35 +00:00
// FIXME
# if !defined(USE_VULKAN)
2016-01-13 23:59:41 +00:00
// read back the contents
glReadPixels ( 0 , 0 , 64 , 64 , GL_RGBA , GL_FLOAT , image ) ;
2018-10-03 21:40:35 +00:00
# endif
2016-01-13 23:59:41 +00:00
sum = 0.0f ;
maxLuminance = 0.0f ;
for ( i = 0 ; i < ( 64 * 64 ) ; i + = 4 )
2015-12-20 11:28:46 +00:00
{
2016-01-13 23:59:41 +00:00
color [ 0 ] = image [ i * 4 + 0 ] ;
color [ 1 ] = image [ i * 4 + 1 ] ;
color [ 2 ] = image [ i * 4 + 2 ] ;
color [ 3 ] = image [ i * 4 + 3 ] ;
luminance = ( color . x * LUMINANCE_SRGB . x + color . y * LUMINANCE_SRGB . y + color . z * LUMINANCE_SRGB . z ) + 0.0001f ;
if ( luminance > maxLuminance )
{
maxLuminance = luminance ;
}
float logLuminance = log ( luminance + 1 ) ;
//if( logLuminance > 0 )
{
sum + = luminance ;
}
2015-12-20 11:28:46 +00:00
}
2015-12-21 10:39:19 +00:00
#if 0
2016-01-13 23:59:41 +00:00
sum / = ( 64.0f * 64.0f ) ;
avgLuminance = exp ( sum ) ;
2015-12-21 10:39:19 +00:00
# else
2016-01-13 23:59:41 +00:00
avgLuminance = sum / ( 64.0f * 64.0f ) ;
2015-12-21 10:39:19 +00:00
# endif
2015-12-20 11:28:46 +00:00
2016-01-13 23:59:41 +00:00
// the user's adapted luminance level is simulated by closing the gap between
// adapted luminance and current luminance by 2% every frame, based on a
// 30 fps rate. This is not an accurate model of human adaptation, which can
// take longer than half an hour.
2017-09-03 21:17:44 +00:00
if ( hdrTime > curTime )
2016-01-13 23:59:41 +00:00
{
2017-09-03 21:17:44 +00:00
hdrTime = curTime ;
2016-01-13 23:59:41 +00:00
}
2017-09-03 21:17:44 +00:00
deltaTime = curTime - hdrTime ;
2016-01-13 23:59:41 +00:00
//if(r_hdrMaxLuminance->value)
{
2017-09-09 12:57:48 +00:00
hdrAverageLuminance = idMath : : ClampFloat ( r_hdrMinLuminance . GetFloat ( ) , r_hdrMaxLuminance . GetFloat ( ) , hdrAverageLuminance ) ;
2016-01-13 23:59:41 +00:00
avgLuminance = idMath : : ClampFloat ( r_hdrMinLuminance . GetFloat ( ) , r_hdrMaxLuminance . GetFloat ( ) , avgLuminance ) ;
2017-09-09 12:57:48 +00:00
hdrMaxLuminance = idMath : : ClampFloat ( r_hdrMinLuminance . GetFloat ( ) , r_hdrMaxLuminance . GetFloat ( ) , hdrMaxLuminance ) ;
2016-01-13 23:59:41 +00:00
maxLuminance = idMath : : ClampFloat ( r_hdrMinLuminance . GetFloat ( ) , r_hdrMaxLuminance . GetFloat ( ) , maxLuminance ) ;
}
2017-09-03 21:17:44 +00:00
newAdaptation = hdrAverageLuminance + ( avgLuminance - hdrAverageLuminance ) * ( 1.0f - powf ( 0.98f , 30.0f * deltaTime ) ) ;
newMaximum = hdrMaxLuminance + ( maxLuminance - hdrMaxLuminance ) * ( 1.0f - powf ( 0.98f , 30.0f * deltaTime ) ) ;
2016-01-13 23:59:41 +00:00
if ( ! IsNAN ( newAdaptation ) & & ! IsNAN ( newMaximum ) )
{
2015-12-20 11:28:46 +00:00
# if 1
2017-09-03 21:17:44 +00:00
hdrAverageLuminance = newAdaptation ;
hdrMaxLuminance = newMaximum ;
2015-12-20 11:28:46 +00:00
# else
2017-09-03 21:17:44 +00:00
hdrAverageLuminance = avgLuminance ;
hdrMaxLuminance = maxLuminance ;
2015-12-20 11:28:46 +00:00
# endif
2016-01-13 23:59:41 +00:00
}
2017-09-03 21:17:44 +00:00
hdrTime = curTime ;
2016-01-13 23:59:41 +00:00
// calculate HDR image key
#if 0
// RB: this never worked :/
if ( r_hdrAutoExposure . GetBool ( ) )
{
// calculation from: Perceptual Effects in Real-time Tone Mapping - Krawczyk et al.
2017-09-03 21:17:44 +00:00
hdrKey = 1.03 - ( 2.0 / ( 2.0 + ( hdrAverageLuminance + 1.0f ) ) ) ;
2016-01-13 23:59:41 +00:00
}
else
# endif
{
2017-09-03 21:17:44 +00:00
hdrKey = r_hdrKey . GetFloat ( ) ;
2016-01-13 23:59:41 +00:00
}
2015-12-20 11:28:46 +00:00
}
if ( r_hdrDebug . GetBool ( ) )
{
2017-09-03 21:17:44 +00:00
idLib : : Printf ( " HDR luminance avg = %f, max = %f, key = %f \n " , hdrAverageLuminance , hdrMaxLuminance , hdrKey ) ;
2015-12-20 11:28:46 +00:00
}
2016-01-09 21:24:57 +00:00
//GL_CheckErrors();
2015-12-20 11:28:46 +00:00
}
2017-09-03 21:17:44 +00:00
void idRenderBackend : : Tonemap ( const viewDef_t * _viewDef )
2015-12-20 11:28:46 +00:00
{
2017-09-03 21:17:44 +00:00
RENDERLOG_PRINTF ( " ---------- RB_Tonemap( avg = %f, max = %f, key = %f, is2Dgui = %i ) ---------- \n " , hdrAverageLuminance , hdrMaxLuminance , hdrKey , ( int ) viewDef - > is2Dgui ) ;
2015-12-20 11:28:46 +00:00
//postProcessCommand_t* cmd = ( postProcessCommand_t* )data;
//const idScreenRect& viewport = cmd->viewDef->viewport;
//globalImages->currentRenderImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
Framebuffer : : Unbind ( ) ;
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
GL_Cull ( CT_TWO_SIDED ) ;
int screenWidth = renderSystem - > GetWidth ( ) ;
int screenHeight = renderSystem - > GetHeight ( ) ;
// set the window clipping
GL_Viewport ( 0 , 0 , screenWidth , screenHeight ) ;
GL_Scissor ( 0 , 0 , screenWidth , screenHeight ) ;
GL_SelectTexture ( 0 ) ;
2015-12-28 22:44:22 +00:00
# if defined(USE_HDR_MSAA)
2016-10-24 23:06:21 +00:00
if ( glConfig . multisamples > 0 )
2015-12-20 11:28:46 +00:00
{
globalImages - > currentRenderHDRImageNoMSAA - > Bind ( ) ;
}
else
2015-12-28 22:44:22 +00:00
# endif
2015-12-20 11:28:46 +00:00
{
globalImages - > currentRenderHDRImage - > Bind ( ) ;
}
2015-12-21 10:39:19 +00:00
GL_SelectTexture ( 1 ) ;
globalImages - > heatmap7Image - > Bind ( ) ;
if ( r_hdrDebug . GetBool ( ) )
{
renderProgManager . BindShader_HDRDebug ( ) ;
}
else
{
renderProgManager . BindShader_Tonemap ( ) ;
}
2015-12-20 11:28:46 +00:00
float screenCorrectionParm [ 4 ] ;
2017-09-03 21:17:44 +00:00
if ( _viewDef - > is2Dgui )
2015-12-20 11:28:46 +00:00
{
2016-01-17 11:49:04 +00:00
screenCorrectionParm [ 0 ] = 2.0f ;
2015-12-20 11:28:46 +00:00
screenCorrectionParm [ 1 ] = 1.0f ;
screenCorrectionParm [ 2 ] = 1.0f ;
}
else
{
2016-01-17 11:49:04 +00:00
if ( r_hdrAutoExposure . GetBool ( ) )
{
float exposureOffset = Lerp ( - 0.01f , 0.02f , idMath : : ClampFloat ( 0.0 , 1.0 , r_exposure . GetFloat ( ) ) ) ;
2017-09-03 21:17:44 +00:00
screenCorrectionParm [ 0 ] = hdrKey + exposureOffset ;
screenCorrectionParm [ 1 ] = hdrAverageLuminance ;
screenCorrectionParm [ 2 ] = hdrMaxLuminance ;
2016-01-17 11:49:04 +00:00
screenCorrectionParm [ 3 ] = exposureOffset ;
//screenCorrectionParm[3] = Lerp( -1, 5, idMath::ClampFloat( 0.0, 1.0, r_exposure.GetFloat() ) );
}
else
{
//float exposureOffset = ( idMath::ClampFloat( 0.0, 1.0, r_exposure.GetFloat() ) * 2.0f - 1.0f ) * 0.01f;
float exposureOffset = Lerp ( - 0.01f , 0.01f , idMath : : ClampFloat ( 0.0 , 1.0 , r_exposure . GetFloat ( ) ) ) ;
screenCorrectionParm [ 0 ] = 0.015f + exposureOffset ;
screenCorrectionParm [ 1 ] = 0.005f ;
screenCorrectionParm [ 2 ] = 1 ;
// RB: this gives a nice exposure curve in Scilab when using
// log2( max( 3 + 0..10, 0.001 ) ) as input for exp2
//float exposureOffset = r_exposure.GetFloat() * 10.0f;
//screenCorrectionParm[3] = exposureOffset;
}
2015-12-20 11:28:46 +00:00
}
2016-01-13 23:59:41 +00:00
2015-12-20 11:28:46 +00:00
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
// Draw
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2015-12-20 11:28:46 +00:00
GL_SelectTexture ( 0 ) ;
renderProgManager . Unbind ( ) ;
GL_State ( GLS_DEFAULT ) ;
GL_Cull ( CT_FRONT_SIDED ) ;
}
2017-09-03 21:17:44 +00:00
void idRenderBackend : : Bloom ( const viewDef_t * _viewDef )
2015-12-20 11:28:46 +00:00
{
2017-09-03 21:17:44 +00:00
if ( _viewDef - > is2Dgui | | ! r_useHDR . GetBool ( ) )
2015-12-20 11:28:46 +00:00
{
return ;
}
2017-09-03 21:17:44 +00:00
RENDERLOG_PRINTF ( " ---------- RB_Bloom( avg = %f, max = %f, key = %f ) ---------- \n " , hdrAverageLuminance , hdrMaxLuminance , hdrKey ) ;
2015-12-20 11:28:46 +00:00
// BRIGHTPASS
2016-01-09 21:24:57 +00:00
//GL_CheckErrors();
2015-12-20 11:28:46 +00:00
//Framebuffer::Unbind();
//globalFramebuffers.hdrQuarterFBO->Bind();
2018-10-03 21:40:35 +00:00
// FIXME
# if !defined(USE_VULKAN)
2015-12-20 11:28:46 +00:00
glClearColor ( 0 , 0 , 0 , 1 ) ;
// glClear( GL_COLOR_BUFFER_BIT );
2018-10-03 21:40:35 +00:00
# endif
2015-12-20 11:28:46 +00:00
GL_State ( /*GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO |*/ GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
GL_Cull ( CT_TWO_SIDED ) ;
int screenWidth = renderSystem - > GetWidth ( ) ;
int screenHeight = renderSystem - > GetHeight ( ) ;
// set the window clipping
GL_Viewport ( 0 , 0 , screenWidth / 4 , screenHeight / 4 ) ;
GL_Scissor ( 0 , 0 , screenWidth / 4 , screenHeight / 4 ) ;
globalFramebuffers . bloomRenderFBO [ 0 ] - > Bind ( ) ;
GL_SelectTexture ( 0 ) ;
if ( r_useHDR . GetBool ( ) )
{
globalImages - > currentRenderHDRImage - > Bind ( ) ;
renderProgManager . BindShader_Brightpass ( ) ;
}
else
{
2017-09-03 21:17:44 +00:00
int x = viewDef - > viewport . x1 ;
int y = viewDef - > viewport . y1 ;
int w = viewDef - > viewport . x2 - viewDef - > viewport . x1 + 1 ;
int h = viewDef - > viewport . y2 - viewDef - > viewport . y1 + 1 ;
2015-12-20 11:28:46 +00:00
RENDERLOG_PRINTF ( " Resolve to %i x %i buffer \n " , w , h ) ;
// resolve the screen
globalImages - > currentRenderImage - > CopyFramebuffer ( x , y , w , h ) ;
renderProgManager . BindShader_Brightpass ( ) ;
}
float screenCorrectionParm [ 4 ] ;
2017-09-03 21:17:44 +00:00
screenCorrectionParm [ 0 ] = hdrKey ;
screenCorrectionParm [ 1 ] = hdrAverageLuminance ;
screenCorrectionParm [ 2 ] = hdrMaxLuminance ;
2015-12-20 11:28:46 +00:00
screenCorrectionParm [ 3 ] = 1.0f ;
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
float overbright [ 4 ] ;
if ( r_useHDR . GetBool ( ) )
{
2016-01-13 23:59:41 +00:00
if ( r_hdrAutoExposure . GetBool ( ) )
{
overbright [ 0 ] = r_hdrContrastDynamicThreshold . GetFloat ( ) ;
}
else
{
overbright [ 0 ] = r_hdrContrastStaticThreshold . GetFloat ( ) ;
}
2015-12-20 11:28:46 +00:00
overbright [ 1 ] = r_hdrContrastOffset . GetFloat ( ) ;
overbright [ 2 ] = 0 ;
overbright [ 3 ] = 0 ;
}
else
{
overbright [ 0 ] = r_ldrContrastThreshold . GetFloat ( ) ;
overbright [ 1 ] = r_ldrContrastOffset . GetFloat ( ) ;
overbright [ 2 ] = 0 ;
overbright [ 3 ] = 0 ;
}
SetFragmentParm ( RENDERPARM_OVERBRIGHT , overbright ) ; // rpOverbright
// Draw
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2015-12-20 11:28:46 +00:00
// BLOOM PING PONG rendering
renderProgManager . BindShader_HDRGlareChromatic ( ) ;
int j ;
for ( j = 0 ; j < r_hdrGlarePasses . GetInteger ( ) ; j + + )
{
globalFramebuffers . bloomRenderFBO [ ( j + 1 ) % 2 ] - > Bind ( ) ;
2018-10-03 21:40:35 +00:00
// FIXME
# if !defined(USE_VULKAN)
2015-12-20 11:28:46 +00:00
glClear ( GL_COLOR_BUFFER_BIT ) ;
2018-10-03 21:40:35 +00:00
# endif
2015-12-20 11:28:46 +00:00
2016-01-06 21:37:16 +00:00
globalImages - > bloomRenderImage [ j % 2 ] - > Bind ( ) ;
2015-12-20 11:28:46 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2015-12-20 11:28:46 +00:00
}
// add filtered glare back to main context
Framebuffer : : Unbind ( ) ;
2017-09-03 21:17:44 +00:00
ResetViewportAndScissorToDefaultCamera ( _viewDef ) ;
2015-12-20 11:28:46 +00:00
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
renderProgManager . BindShader_Screen ( ) ;
2016-01-06 21:37:16 +00:00
globalImages - > bloomRenderImage [ ( j + 1 ) % 2 ] - > Bind ( ) ;
2015-12-20 11:28:46 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2015-12-20 11:28:46 +00:00
renderProgManager . Unbind ( ) ;
GL_State ( GLS_DEFAULT ) ;
GL_Cull ( CT_FRONT_SIDED ) ;
}
2016-01-02 18:28:49 +00:00
2017-09-03 21:17:44 +00:00
void idRenderBackend : : DrawScreenSpaceAmbientOcclusion ( const viewDef_t * _viewDef )
2016-01-02 18:28:49 +00:00
{
2018-10-03 21:40:35 +00:00
# if !defined(USE_VULKAN)
2017-09-03 21:17:44 +00:00
if ( ! _viewDef - > viewEntitys | | _viewDef - > is2Dgui )
2016-01-02 18:28:49 +00:00
{
// 3D views only
return ;
}
2016-01-13 23:59:41 +00:00
if ( r_useSSAO . GetInteger ( ) < = 0 )
2016-01-02 18:28:49 +00:00
{
return ;
}
// FIXME very expensive to enable this in subviews
2017-09-03 21:17:44 +00:00
if ( _viewDef - > isSubview )
2016-01-02 18:28:49 +00:00
{
return ;
}
2016-01-06 21:37:16 +00:00
RENDERLOG_PRINTF ( " ---------- RB_SSAO() ---------- \n " ) ;
2016-01-09 21:24:57 +00:00
#if 0
2016-01-02 18:28:49 +00:00
GL_CheckErrors ( ) ;
// clear the alpha buffer and draw only the hands + weapon into it so
// we can avoid blurring them
glClearColor ( 0 , 0 , 0 , 1 ) ;
GL_State ( GLS_COLORMASK | GLS_DEPTHMASK ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
GL_Color ( 0 , 0 , 0 , 0 ) ;
2016-01-09 21:24:57 +00:00
2016-01-02 18:28:49 +00:00
GL_SelectTexture ( 0 ) ;
globalImages - > blackImage - > Bind ( ) ;
backEnd . currentSpace = NULL ;
drawSurf_t * * drawSurfs = ( drawSurf_t * * ) & backEnd . viewDef - > drawSurfs [ 0 ] ;
for ( int surfNum = 0 ; surfNum < backEnd . viewDef - > numDrawSurfs ; surfNum + + )
{
const drawSurf_t * surf = drawSurfs [ surfNum ] ;
if ( ! surf - > space - > weaponDepthHack & & ! surf - > space - > skipMotionBlur & & ! surf - > material - > HasSubview ( ) )
{
// Apply motion blur to this object
continue ;
}
const idMaterial * shader = surf - > material ;
if ( shader - > Coverage ( ) = = MC_TRANSLUCENT )
{
// muzzle flash, etc
continue ;
}
// set mvp matrix
if ( surf - > space ! = backEnd . currentSpace )
{
RB_SetMVP ( surf - > space - > mvp ) ;
backEnd . currentSpace = surf - > space ;
}
// this could just be a color, but we don't have a skinned color-only prog
if ( surf - > jointCache )
{
renderProgManager . BindShader_TextureVertexColorSkinned ( ) ;
}
else
{
renderProgManager . BindShader_TextureVertexColor ( ) ;
}
// draw it solid
RB_DrawElementsWithCounters ( surf ) ;
}
GL_State ( GLS_DEPTHFUNC_ALWAYS ) ;
// copy off the color buffer and the depth buffer for the motion blur prog
// we use the viewport dimensions for copying the buffers in case resolution scaling is enabled.
const idScreenRect & viewport = backEnd . viewDef - > viewport ;
globalImages - > currentRenderImage - > CopyFramebuffer ( viewport . x1 , viewport . y1 , viewport . GetWidth ( ) , viewport . GetHeight ( ) ) ;
// in stereo rendering, each eye needs to get a separate previous frame mvp
int mvpIndex = ( backEnd . viewDef - > renderView . viewEyeBuffer = = 1 ) ? 1 : 0 ;
// derive the matrix to go from current pixels to previous frame pixels
idRenderMatrix inverseMVP ;
idRenderMatrix : : Inverse ( backEnd . viewDef - > worldSpace . mvp , inverseMVP ) ;
idRenderMatrix motionMatrix ;
idRenderMatrix : : Multiply ( backEnd . prevMVP [ mvpIndex ] , inverseMVP , motionMatrix ) ;
backEnd . prevMVP [ mvpIndex ] = backEnd . viewDef - > worldSpace . mvp ;
RB_SetMVP ( motionMatrix ) ;
# endif
2017-09-03 21:17:44 +00:00
currentSpace = & viewDef - > worldSpace ;
RB_SetMVP ( viewDef - > worldSpace . mvp ) ;
2016-01-02 18:28:49 +00:00
2016-01-09 12:38:49 +00:00
const bool hdrIsActive = ( r_useHDR . GetBool ( ) & & globalFramebuffers . hdrFBO ! = NULL & & globalFramebuffers . hdrFBO - > IsBound ( ) ) ;
2016-01-02 18:28:49 +00:00
int screenWidth = renderSystem - > GetWidth ( ) ;
int screenHeight = renderSystem - > GetHeight ( ) ;
2016-01-09 12:38:49 +00:00
// build hierarchical depth buffer
if ( r_useHierarchicalDepthBuffer . GetBool ( ) )
{
renderProgManager . BindShader_AmbientOcclusionMinify ( ) ;
glClearColor ( 0 , 0 , 0 , 1 ) ;
GL_SelectTexture ( 0 ) ;
2016-01-09 15:23:49 +00:00
//globalImages->currentDepthImage->Bind();
2016-01-09 12:38:49 +00:00
for ( int i = 0 ; i < MAX_HIERARCHICAL_ZBUFFERS ; i + + )
{
int width = globalFramebuffers . csDepthFBO [ i ] - > GetWidth ( ) ;
int height = globalFramebuffers . csDepthFBO [ i ] - > GetHeight ( ) ;
GL_Viewport ( 0 , 0 , width , height ) ;
GL_Scissor ( 0 , 0 , width , height ) ;
globalFramebuffers . csDepthFBO [ i ] - > Bind ( ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
2016-01-09 15:23:49 +00:00
if ( i = = 0 )
{
renderProgManager . BindShader_AmbientOcclusionReconstructCSZ ( ) ;
globalImages - > currentDepthImage - > Bind ( ) ;
}
else
{
renderProgManager . BindShader_AmbientOcclusionMinify ( ) ;
GL_SelectTexture ( 0 ) ;
globalImages - > hierarchicalZbufferImage - > Bind ( ) ;
}
float jitterTexScale [ 4 ] ;
jitterTexScale [ 0 ] = i - 1 ;
jitterTexScale [ 1 ] = 0 ;
jitterTexScale [ 2 ] = 0 ;
jitterTexScale [ 3 ] = 0 ;
SetFragmentParm ( RENDERPARM_JITTERTEXSCALE , jitterTexScale ) ; // rpJitterTexScale
2016-01-09 12:38:49 +00:00
# if 1
float screenCorrectionParm [ 4 ] ;
screenCorrectionParm [ 0 ] = 1.0f / width ;
screenCorrectionParm [ 1 ] = 1.0f / height ;
screenCorrectionParm [ 2 ] = width ;
screenCorrectionParm [ 3 ] = height ;
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
# endif
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2016-01-09 12:38:49 +00:00
}
}
2016-01-02 18:28:49 +00:00
// set the window clipping
GL_Viewport ( 0 , 0 , screenWidth , screenHeight ) ;
GL_Scissor ( 0 , 0 , screenWidth , screenHeight ) ;
2016-01-06 21:37:16 +00:00
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
GL_Cull ( CT_TWO_SIDED ) ;
2016-01-08 18:30:21 +00:00
if ( r_ssaoFiltering . GetBool ( ) )
{
globalFramebuffers . ambientOcclusionFBO [ 0 ] - > Bind ( ) ;
2016-01-09 19:17:09 +00:00
glClearColor ( 0 , 0 , 0 , 0 ) ;
2016-01-08 18:30:21 +00:00
glClear ( GL_COLOR_BUFFER_BIT ) ;
renderProgManager . BindShader_AmbientOcclusion ( ) ;
}
else
{
2016-01-13 23:59:41 +00:00
if ( r_ssaoDebug . GetInteger ( ) < = 0 )
2016-01-08 18:30:21 +00:00
{
2016-01-10 22:47:16 +00:00
GL_State ( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_ALPHAMASK | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
2016-01-08 18:30:21 +00:00
}
2016-01-09 12:38:49 +00:00
if ( hdrIsActive )
{
globalFramebuffers . hdrFBO - > Bind ( ) ;
}
else
{
Framebuffer : : Unbind ( ) ;
}
2016-01-08 18:30:21 +00:00
renderProgManager . BindShader_AmbientOcclusionAndOutput ( ) ;
}
2016-01-02 18:28:49 +00:00
float screenCorrectionParm [ 4 ] ;
2016-10-24 01:55:16 +00:00
screenCorrectionParm [ 0 ] = 1.0f / screenWidth ;
screenCorrectionParm [ 1 ] = 1.0f / screenHeight ;
screenCorrectionParm [ 2 ] = screenWidth ;
screenCorrectionParm [ 3 ] = screenHeight ;
2016-01-02 18:28:49 +00:00
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
2016-01-08 18:30:21 +00:00
#if 0
2016-01-02 18:28:49 +00:00
// RB: set unprojection matrices so we can convert zbuffer values back to camera and world spaces
2016-01-02 22:59:44 +00:00
idRenderMatrix modelViewMatrix ;
idRenderMatrix : : Transpose ( * ( idRenderMatrix * ) backEnd . viewDef - > worldSpace . modelViewMatrix , modelViewMatrix ) ;
idRenderMatrix cameraToWorldMatrix ;
if ( ! idRenderMatrix : : Inverse ( modelViewMatrix , cameraToWorldMatrix ) )
{
idLib : : Warning ( " cameraToWorldMatrix invert failed " ) ;
}
SetVertexParms ( RENDERPARM_MODELMATRIX_X , cameraToWorldMatrix [ 0 ] , 4 ) ;
2016-01-11 18:00:20 +00:00
//SetVertexParms( RENDERPARM_MODELMATRIX_X, viewDef->unprojectionToWorldRenderMatrix[0], 4 );
2016-01-08 18:30:21 +00:00
# endif
2016-01-11 18:00:20 +00:00
SetVertexParms ( RENDERPARM_MODELMATRIX_X , viewDef - > unprojectionToCameraRenderMatrix [ 0 ] , 4 ) ;
2016-01-02 18:28:49 +00:00
2016-01-08 18:30:21 +00:00
2016-01-02 22:59:44 +00:00
float jitterTexOffset [ 4 ] ;
if ( r_shadowMapRandomizeJitter . GetBool ( ) )
{
jitterTexOffset [ 0 ] = ( rand ( ) & 255 ) / 255.0 ;
jitterTexOffset [ 1 ] = ( rand ( ) & 255 ) / 255.0 ;
}
else
{
jitterTexOffset [ 0 ] = 0 ;
jitterTexOffset [ 1 ] = 0 ;
}
2016-01-11 18:00:20 +00:00
jitterTexOffset [ 2 ] = viewDef - > renderView . time [ 0 ] * 0.001f ;
2016-01-02 22:59:44 +00:00
jitterTexOffset [ 3 ] = 0.0f ;
SetFragmentParm ( RENDERPARM_JITTERTEXOFFSET , jitterTexOffset ) ; // rpJitterTexOffset
2016-01-02 18:28:49 +00:00
GL_SelectTexture ( 0 ) ;
globalImages - > currentNormalsImage - > Bind ( ) ;
GL_SelectTexture ( 1 ) ;
2016-01-09 12:38:49 +00:00
if ( r_useHierarchicalDepthBuffer . GetBool ( ) )
{
globalImages - > hierarchicalZbufferImage - > Bind ( ) ;
}
else
{
globalImages - > currentDepthImage - > Bind ( ) ;
}
2016-01-02 18:28:49 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2016-01-02 22:59:44 +00:00
2016-01-08 18:30:21 +00:00
if ( r_ssaoFiltering . GetBool ( ) )
{
float jitterTexScale [ 4 ] ;
// AO blur X
2016-01-02 22:59:44 +00:00
# if 1
2016-01-08 18:30:21 +00:00
globalFramebuffers . ambientOcclusionFBO [ 1 ] - > Bind ( ) ;
renderProgManager . BindShader_AmbientOcclusionBlur ( ) ;
// set axis parameter
jitterTexScale [ 0 ] = 1 ;
jitterTexScale [ 1 ] = 0 ;
jitterTexScale [ 2 ] = 0 ;
jitterTexScale [ 3 ] = 0 ;
SetFragmentParm ( RENDERPARM_JITTERTEXSCALE , jitterTexScale ) ; // rpJitterTexScale
2016-01-11 18:00:20 +00:00
GL_SelectTexture ( 2 ) ;
2016-01-08 18:30:21 +00:00
globalImages - > ambientOcclusionImage [ 0 ] - > Bind ( ) ;
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2016-01-06 21:37:16 +00:00
# endif
2016-01-08 18:30:21 +00:00
// AO blur Y
if ( hdrIsActive )
{
globalFramebuffers . hdrFBO - > Bind ( ) ;
}
else
{
Framebuffer : : Unbind ( ) ;
}
2016-01-13 23:59:41 +00:00
if ( r_ssaoDebug . GetInteger ( ) < = 0 )
2016-01-08 18:30:21 +00:00
{
GL_State ( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
}
renderProgManager . BindShader_AmbientOcclusionBlurAndOutput ( ) ;
// set axis parameter
jitterTexScale [ 0 ] = 0 ;
jitterTexScale [ 1 ] = 1 ;
jitterTexScale [ 2 ] = 0 ;
jitterTexScale [ 3 ] = 0 ;
SetFragmentParm ( RENDERPARM_JITTERTEXSCALE , jitterTexScale ) ; // rpJitterTexScale
2016-01-11 18:00:20 +00:00
GL_SelectTexture ( 2 ) ;
2016-01-08 18:30:21 +00:00
globalImages - > ambientOcclusionImage [ 1 ] - > Bind ( ) ;
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2016-01-06 21:37:16 +00:00
}
2016-01-09 19:17:09 +00:00
renderProgManager . Unbind ( ) ;
GL_State ( GLS_DEFAULT ) ;
GL_Cull ( CT_FRONT_SIDED ) ;
2016-01-02 22:59:44 +00:00
2016-01-09 21:24:57 +00:00
//GL_CheckErrors();
2018-10-03 21:40:35 +00:00
# endif
2016-01-09 21:24:57 +00:00
}
2017-09-03 21:17:44 +00:00
void idRenderBackend : : DrawScreenSpaceGlobalIllumination ( const viewDef_t * _viewDef )
2016-01-09 21:24:57 +00:00
{
2018-10-03 21:40:35 +00:00
# if !defined(USE_VULKAN)
2017-09-03 21:17:44 +00:00
if ( ! _viewDef - > viewEntitys | | _viewDef - > is2Dgui )
2016-01-09 21:24:57 +00:00
{
// 3D views only
return ;
}
if ( r_useSSGI . GetInteger ( ) < = 0 )
{
return ;
}
// FIXME very expensive to enable this in subviews
2017-09-03 21:17:44 +00:00
if ( _viewDef - > isSubview )
2016-01-09 21:24:57 +00:00
{
return ;
}
RENDERLOG_PRINTF ( " ---------- RB_SSGI() ---------- \n " ) ;
2017-09-03 21:17:44 +00:00
currentSpace = & viewDef - > worldSpace ;
RB_SetMVP ( viewDef - > worldSpace . mvp ) ;
2016-01-09 21:24:57 +00:00
const bool hdrIsActive = ( r_useHDR . GetBool ( ) & & globalFramebuffers . hdrFBO ! = NULL & & globalFramebuffers . hdrFBO - > IsBound ( ) ) ;
int screenWidth = renderSystem - > GetWidth ( ) ;
int screenHeight = renderSystem - > GetHeight ( ) ;
2016-01-10 16:20:38 +00:00
// set the window clipping
GL_Viewport ( 0 , 0 , screenWidth , screenHeight ) ;
GL_Scissor ( 0 , 0 , screenWidth , screenHeight ) ;
if ( ! hdrIsActive )
{
const idScreenRect & viewport = viewDef - > viewport ;
globalImages - > currentRenderImage - > CopyFramebuffer ( viewport . x1 , viewport . y1 , viewport . GetWidth ( ) , viewport . GetHeight ( ) ) ;
}
2016-01-09 21:24:57 +00:00
// build hierarchical depth buffer
if ( r_useHierarchicalDepthBuffer . GetBool ( ) )
{
renderProgManager . BindShader_AmbientOcclusionMinify ( ) ;
glClearColor ( 0 , 0 , 0 , 1 ) ;
GL_SelectTexture ( 0 ) ;
//globalImages->currentDepthImage->Bind();
for ( int i = 0 ; i < MAX_HIERARCHICAL_ZBUFFERS ; i + + )
{
int width = globalFramebuffers . csDepthFBO [ i ] - > GetWidth ( ) ;
int height = globalFramebuffers . csDepthFBO [ i ] - > GetHeight ( ) ;
GL_Viewport ( 0 , 0 , width , height ) ;
GL_Scissor ( 0 , 0 , width , height ) ;
globalFramebuffers . csDepthFBO [ i ] - > Bind ( ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
if ( i = = 0 )
{
renderProgManager . BindShader_AmbientOcclusionReconstructCSZ ( ) ;
globalImages - > currentDepthImage - > Bind ( ) ;
}
else
{
renderProgManager . BindShader_AmbientOcclusionMinify ( ) ;
GL_SelectTexture ( 0 ) ;
globalImages - > hierarchicalZbufferImage - > Bind ( ) ;
}
float jitterTexScale [ 4 ] ;
jitterTexScale [ 0 ] = i - 1 ;
jitterTexScale [ 1 ] = 0 ;
jitterTexScale [ 2 ] = 0 ;
jitterTexScale [ 3 ] = 0 ;
SetFragmentParm ( RENDERPARM_JITTERTEXSCALE , jitterTexScale ) ; // rpJitterTexScale
# if 1
float screenCorrectionParm [ 4 ] ;
screenCorrectionParm [ 0 ] = 1.0f / width ;
screenCorrectionParm [ 1 ] = 1.0f / height ;
screenCorrectionParm [ 2 ] = width ;
screenCorrectionParm [ 3 ] = height ;
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
# endif
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2016-01-09 21:24:57 +00:00
}
}
// set the window clipping
GL_Viewport ( 0 , 0 , screenWidth , screenHeight ) ;
GL_Scissor ( 0 , 0 , screenWidth , screenHeight ) ;
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
GL_Cull ( CT_TWO_SIDED ) ;
2016-01-10 16:20:38 +00:00
if ( r_ssgiFiltering . GetBool ( ) )
2016-01-09 21:24:57 +00:00
{
globalFramebuffers . ambientOcclusionFBO [ 0 ] - > Bind ( ) ;
2016-01-10 16:20:38 +00:00
// FIXME remove and mix with color from previous frame
2016-01-09 21:24:57 +00:00
glClearColor ( 0 , 0 , 0 , 0 ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
2016-01-10 16:20:38 +00:00
renderProgManager . BindShader_DeepGBufferRadiosity ( ) ;
2016-01-09 21:24:57 +00:00
}
else
{
2016-01-10 22:47:16 +00:00
if ( r_ssgiDebug . GetInteger ( ) > 0 )
2016-01-10 16:20:38 +00:00
{
2016-01-10 22:47:16 +00:00
// replace current
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
2016-01-10 16:20:38 +00:00
}
else
{
2016-01-10 22:47:16 +00:00
// add result to main color
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
2016-01-10 16:20:38 +00:00
}
2016-01-09 21:24:57 +00:00
if ( hdrIsActive )
{
globalFramebuffers . hdrFBO - > Bind ( ) ;
}
else
{
Framebuffer : : Unbind ( ) ;
}
renderProgManager . BindShader_DeepGBufferRadiosity ( ) ;
}
float screenCorrectionParm [ 4 ] ;
2016-10-24 01:55:16 +00:00
screenCorrectionParm [ 0 ] = 1.0f / screenWidth ;
screenCorrectionParm [ 1 ] = 1.0f / screenHeight ;
screenCorrectionParm [ 2 ] = screenWidth ;
screenCorrectionParm [ 3 ] = screenHeight ;
2016-01-09 21:24:57 +00:00
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
#if 0
// RB: set unprojection matrices so we can convert zbuffer values back to camera and world spaces
idRenderMatrix modelViewMatrix ;
idRenderMatrix : : Transpose ( * ( idRenderMatrix * ) backEnd . viewDef - > worldSpace . modelViewMatrix , modelViewMatrix ) ;
idRenderMatrix cameraToWorldMatrix ;
if ( ! idRenderMatrix : : Inverse ( modelViewMatrix , cameraToWorldMatrix ) )
{
idLib : : Warning ( " cameraToWorldMatrix invert failed " ) ;
}
SetVertexParms ( RENDERPARM_MODELMATRIX_X , cameraToWorldMatrix [ 0 ] , 4 ) ;
2016-01-11 18:00:20 +00:00
//SetVertexParms( RENDERPARM_MODELMATRIX_X, viewDef->unprojectionToWorldRenderMatrix[0], 4 );
2016-01-09 21:24:57 +00:00
# endif
2016-01-11 18:00:20 +00:00
SetVertexParms ( RENDERPARM_MODELMATRIX_X , viewDef - > unprojectionToCameraRenderMatrix [ 0 ] , 4 ) ;
2016-01-09 21:24:57 +00:00
float jitterTexOffset [ 4 ] ;
if ( r_shadowMapRandomizeJitter . GetBool ( ) )
{
jitterTexOffset [ 0 ] = ( rand ( ) & 255 ) / 255.0 ;
jitterTexOffset [ 1 ] = ( rand ( ) & 255 ) / 255.0 ;
}
else
{
jitterTexOffset [ 0 ] = 0 ;
jitterTexOffset [ 1 ] = 0 ;
}
2016-01-11 18:00:20 +00:00
jitterTexOffset [ 2 ] = viewDef - > renderView . time [ 0 ] * 0.001f ;
2016-01-09 21:24:57 +00:00
jitterTexOffset [ 3 ] = 0.0f ;
SetFragmentParm ( RENDERPARM_JITTERTEXOFFSET , jitterTexOffset ) ; // rpJitterTexOffset
GL_SelectTexture ( 0 ) ;
globalImages - > currentNormalsImage - > Bind ( ) ;
GL_SelectTexture ( 1 ) ;
if ( r_useHierarchicalDepthBuffer . GetBool ( ) )
{
globalImages - > hierarchicalZbufferImage - > Bind ( ) ;
}
else
{
globalImages - > currentDepthImage - > Bind ( ) ;
}
GL_SelectTexture ( 2 ) ;
2016-01-10 22:47:16 +00:00
if ( hdrIsActive )
{
globalImages - > currentRenderHDRImage - > Bind ( ) ;
}
else
{
globalImages - > currentRenderImage - > Bind ( ) ;
}
2016-01-09 21:24:57 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2016-01-09 21:24:57 +00:00
2016-01-10 16:20:38 +00:00
if ( r_ssgiFiltering . GetBool ( ) )
2016-01-09 21:24:57 +00:00
{
float jitterTexScale [ 4 ] ;
// AO blur X
# if 1
globalFramebuffers . ambientOcclusionFBO [ 1 ] - > Bind ( ) ;
2016-01-10 16:20:38 +00:00
renderProgManager . BindShader_DeepGBufferRadiosityBlur ( ) ;
2016-01-09 21:24:57 +00:00
// set axis parameter
jitterTexScale [ 0 ] = 1 ;
jitterTexScale [ 1 ] = 0 ;
jitterTexScale [ 2 ] = 0 ;
jitterTexScale [ 3 ] = 0 ;
SetFragmentParm ( RENDERPARM_JITTERTEXSCALE , jitterTexScale ) ; // rpJitterTexScale
2016-01-11 18:00:20 +00:00
GL_SelectTexture ( 2 ) ;
2016-01-09 21:24:57 +00:00
globalImages - > ambientOcclusionImage [ 0 ] - > Bind ( ) ;
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2016-01-09 21:24:57 +00:00
# endif
// AO blur Y
if ( hdrIsActive )
{
globalFramebuffers . hdrFBO - > Bind ( ) ;
}
else
{
Framebuffer : : Unbind ( ) ;
}
2016-01-10 22:47:16 +00:00
if ( r_ssgiDebug . GetInteger ( ) > 0 )
2016-01-10 16:20:38 +00:00
{
2016-01-10 22:47:16 +00:00
// replace current
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
2016-01-10 16:20:38 +00:00
}
else
2016-01-09 21:24:57 +00:00
{
2016-01-10 22:47:16 +00:00
// add result to main color
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
2016-01-09 21:24:57 +00:00
}
2016-01-10 16:20:38 +00:00
renderProgManager . BindShader_DeepGBufferRadiosityBlurAndOutput ( ) ;
2016-01-09 21:24:57 +00:00
// set axis parameter
jitterTexScale [ 0 ] = 0 ;
jitterTexScale [ 1 ] = 1 ;
jitterTexScale [ 2 ] = 0 ;
jitterTexScale [ 3 ] = 0 ;
SetFragmentParm ( RENDERPARM_JITTERTEXSCALE , jitterTexScale ) ; // rpJitterTexScale
2016-01-11 18:00:20 +00:00
GL_SelectTexture ( 2 ) ;
2016-01-09 21:24:57 +00:00
globalImages - > ambientOcclusionImage [ 1 ] - > Bind ( ) ;
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2016-01-09 21:24:57 +00:00
}
renderProgManager . Unbind ( ) ;
GL_State ( GLS_DEFAULT ) ;
GL_Cull ( CT_FRONT_SIDED ) ;
//GL_CheckErrors();
2018-10-03 21:40:35 +00:00
# endif
2016-01-02 18:28:49 +00:00
}
2015-12-20 11:28:46 +00:00
// RB end
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BACKEND COMMANDS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2018-10-06 15:21:49 +00:00
/*
= = = = = = = = = = = = = = = = = = = =
RB_ExecuteBackEndCommands
This function will be called syncronously if running without
smp extensions , or asyncronously by another thread .
= = = = = = = = = = = = = = = = = = = =
*/
void idRenderBackend : : ExecuteBackEndCommands ( const emptyCommand_t * cmds )
{
// r_debugRenderToTexture
int c_draw3d = 0 ;
int c_draw2d = 0 ;
int c_setBuffers = 0 ;
int c_copyRenders = 0 ;
resolutionScale . SetCurrentGPUFrameTime ( commonLocal . GetRendererGPUMicroseconds ( ) ) ;
renderLog . StartFrame ( ) ;
GL_StartFrame ( ) ;
if ( cmds - > commandId = = RC_NOP & & ! cmds - > next )
{
return ;
}
if ( renderSystem - > GetStereo3DMode ( ) ! = STEREO3D_OFF )
{
StereoRenderExecuteBackEndCommands ( cmds ) ;
renderLog . EndFrame ( ) ;
return ;
}
uint64 backEndStartTime = Sys_Microseconds ( ) ;
// needed for editor rendering
GL_SetDefaultState ( ) ;
for ( ; cmds ! = NULL ; cmds = ( const emptyCommand_t * ) cmds - > next )
{
switch ( cmds - > commandId )
{
case RC_NOP :
break ;
case RC_DRAW_VIEW_3D :
case RC_DRAW_VIEW_GUI :
DrawView ( cmds , 0 ) ;
if ( ( ( const drawSurfsCommand_t * ) cmds ) - > viewDef - > viewEntitys )
{
c_draw3d + + ;
}
else
{
c_draw2d + + ;
}
break ;
case RC_SET_BUFFER :
//RB_SetBuffer( cmds );
c_setBuffers + + ;
break ;
case RC_COPY_RENDER :
CopyRender ( cmds ) ;
c_copyRenders + + ;
break ;
case RC_POST_PROCESS :
PostProcess ( cmds ) ;
break ;
default :
common - > Error ( " RB_ExecuteBackEndCommands: bad commandId " ) ;
break ;
}
}
DrawFlickerBox ( ) ;
GL_EndFrame ( ) ;
// stop rendering on this thread
uint64 backEndFinishTime = Sys_Microseconds ( ) ;
pc . totalMicroSec = backEndFinishTime - backEndStartTime ;
if ( r_debugRenderToTexture . GetInteger ( ) = = 1 )
{
common - > Printf ( " 3d: %i, 2d: %i, SetBuf: %i, CpyRenders: %i, CpyFrameBuf: %i \n " , c_draw3d , c_draw2d , c_setBuffers , c_copyRenders , pc . c_copyFrameBuffer ) ;
pc . c_copyFrameBuffer = 0 ;
}
renderLog . EndFrame ( ) ;
}
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : DrawViewInternal
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : DrawViewInternal ( const viewDef_t * _viewDef , const int stereoEye )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
renderLog . OpenBlock ( " RB_DrawViewInternal " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//-------------------------------------------------
// guis can wind up referencing purged images that need to be loaded.
// this used to be in the gui emit code, but now that it can be running
// in a separate thread, it must not try to load images, so do it here.
//-------------------------------------------------
2017-09-03 21:17:44 +00:00
drawSurf_t * * drawSurfs = ( drawSurf_t * * ) & _viewDef - > drawSurfs [ 0 ] ;
const int numDrawSurfs = _viewDef - > numDrawSurfs ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numDrawSurfs ; i + + )
{
2017-09-03 21:17:44 +00:00
const drawSurf_t * ds = _viewDef - > drawSurfs [ i ] ;
2012-11-28 15:47:07 +00:00
if ( ds - > material ! = NULL )
{
const_cast < idMaterial * > ( ds - > material ) - > EnsureNotPurged ( ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//-------------------------------------------------
// RB_BeginDrawingView
//
// Any mirrored or portaled views have already been drawn, so prepare
// to actually render the visible surfaces for this view
//
// clear the z buffer, set the projection matrix, etc
//-------------------------------------------------
2017-09-03 21:17:44 +00:00
ResetViewportAndScissorToDefaultCamera ( _viewDef ) ;
2012-11-28 15:47:07 +00:00
2018-10-03 21:40:35 +00:00
# if !defined(USE_VULKAN)
2017-09-03 21:17:44 +00:00
faceCulling = - 1 ; // force face culling to set next time
2018-10-03 21:40:35 +00:00
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// ensures that depth writes are enabled for the depth clear
GL_State ( GLS_DEFAULT ) ;
2012-11-28 15:47:07 +00:00
2016-01-09 21:24:57 +00:00
//GL_CheckErrors();
2012-11-28 15:47:07 +00:00
2016-02-02 22:12:53 +00:00
// RB begin
2017-09-03 21:17:44 +00:00
bool useHDR = r_useHDR . GetBool ( ) & & ! _viewDef - > is2Dgui ;
2016-02-02 22:12:53 +00:00
2012-11-26 18:58:24 +00:00
// Clear the depth buffer and clear the stencil to 128 for stencil shadows as well as gui masking
2016-02-02 22:12:53 +00:00
GL_Clear ( false , true , true , STENCIL_SHADOW_TEST_VALUE , 0.0f , 0.0f , 0.0f , 0.0f , useHDR ) ;
2015-12-20 11:28:46 +00:00
2016-02-02 22:12:53 +00:00
if ( useHDR )
2015-12-20 11:28:46 +00:00
{
globalFramebuffers . hdrFBO - > Bind ( ) ;
}
else
{
Framebuffer : : Unbind ( ) ;
}
// RB end
2016-01-09 21:24:57 +00:00
//GL_CheckErrors();
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// normal face culling
GL_Cull ( CT_FRONT_SIDED ) ;
2012-11-28 15:47:07 +00:00
2018-10-03 19:14:28 +00:00
# if defined(USE_CORE_PROFILE) && !defined(USE_VULKAN)
2012-11-26 18:58:24 +00:00
// bind one global Vertex Array Object (VAO)
2012-12-17 16:30:59 +00:00
glBindVertexArray ( glConfig . global_vao ) ;
2012-11-26 18:58:24 +00:00
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//------------------------------------
// sets variables that can be used by all programs
//------------------------------------
{
//
// set eye position in global space
//
float parm [ 4 ] ;
2017-09-03 21:17:44 +00:00
parm [ 0 ] = viewDef - > renderView . vieworg [ 0 ] ;
parm [ 1 ] = viewDef - > renderView . vieworg [ 1 ] ;
parm [ 2 ] = viewDef - > renderView . vieworg [ 2 ] ;
2012-11-26 18:58:24 +00:00
parm [ 3 ] = 1.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetVertexParm ( RENDERPARM_GLOBALEYEPOS , parm ) ; // rpGlobalEyePos
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// sets overbright to make world brighter
// This value is baked into the specularScale and diffuseScale values so
// the interaction programs don't need to perform the extra multiply,
// but any other renderprogs that want to obey the brightness value
// can reference this.
float overbright = r_lightScale . GetFloat ( ) * 0.5f ;
parm [ 0 ] = overbright ;
parm [ 1 ] = overbright ;
parm [ 2 ] = overbright ;
parm [ 3 ] = overbright ;
SetFragmentParm ( RENDERPARM_OVERBRIGHT , parm ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Set Projection Matrix
float projMatrixTranspose [ 16 ] ;
2017-09-03 21:17:44 +00:00
R_MatrixTranspose ( viewDef - > projectionMatrix , projMatrixTranspose ) ;
2012-11-26 18:58:24 +00:00
SetVertexParms ( RENDERPARM_PROJMATRIX_X , projMatrixTranspose , 4 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//-------------------------------------------------
// fill the depth buffer and clear color buffer to black except on subviews
//-------------------------------------------------
2017-09-03 21:17:44 +00:00
FillDepthBufferFast ( drawSurfs , numDrawSurfs ) ;
2012-11-28 15:47:07 +00:00
2016-01-09 15:23:49 +00:00
//-------------------------------------------------
// FIXME, OPTIMIZE: merge this with FillDepthBufferFast like in a light prepass deferred renderer
//
// fill the geometric buffer with normals and roughness
//-------------------------------------------------
2017-09-03 21:17:44 +00:00
AmbientPass ( drawSurfs , numDrawSurfs , true ) ;
2016-01-09 15:23:49 +00:00
2015-12-24 15:43:02 +00:00
//-------------------------------------------------
// fill the depth buffer and the color buffer with precomputed Q3A style lighting
//-------------------------------------------------
2017-09-03 21:17:44 +00:00
AmbientPass ( drawSurfs , numDrawSurfs , false ) ;
2015-12-24 15:43:02 +00:00
2012-11-26 18:58:24 +00:00
//-------------------------------------------------
// main light renderer
//-------------------------------------------------
2017-09-03 21:17:44 +00:00
DrawInteractions ( _viewDef ) ;
2012-11-28 15:47:07 +00:00
2016-01-02 18:28:49 +00:00
//-------------------------------------------------
// capture the depth for the motion blur before rendering any post process surfaces that may contribute to the depth
//-------------------------------------------------
2016-01-13 23:59:41 +00:00
if ( ( r_motionBlur . GetInteger ( ) > 0 | | r_useSSAO . GetBool ( ) | | r_useSSGI . GetBool ( ) ) & & ! r_useHDR . GetBool ( ) )
2016-01-02 18:28:49 +00:00
{
2017-09-03 21:17:44 +00:00
const idScreenRect & viewport = viewDef - > viewport ;
2016-01-02 18:28:49 +00:00
globalImages - > currentDepthImage - > CopyDepthbuffer ( viewport . x1 , viewport . y1 , viewport . GetWidth ( ) , viewport . GetHeight ( ) ) ;
}
2016-01-09 21:24:57 +00:00
//-------------------------------------------------
2016-01-13 23:59:41 +00:00
// darken the scene using the screen space ambient occlusion
2016-01-09 21:24:57 +00:00
//-------------------------------------------------
2017-09-03 21:17:44 +00:00
DrawScreenSpaceAmbientOcclusion ( _viewDef ) ;
//RB_SSGI( _viewDef );
2016-01-02 18:28:49 +00:00
2012-11-26 18:58:24 +00:00
//-------------------------------------------------
// now draw any non-light dependent shading passes
//-------------------------------------------------
int processed = 0 ;
2012-11-28 15:47:07 +00:00
if ( ! r_skipShaderPasses . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
renderLog . OpenMainBlock ( MRB_DRAW_SHADER_PASSES ) ;
float guiScreenOffset ;
2017-09-03 21:17:44 +00:00
if ( _viewDef - > viewEntitys ! = NULL )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// guiScreenOffset will be 0 in non-gui views
guiScreenOffset = 0.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2017-09-03 21:17:44 +00:00
guiScreenOffset = stereoEye * _viewDef - > renderView . stereoScreenSeparation ;
2012-11-26 18:58:24 +00:00
}
2017-09-03 21:17:44 +00:00
processed = DrawShaderPasses ( drawSurfs , numDrawSurfs , guiScreenOffset , stereoEye ) ;
2012-11-26 18:58:24 +00:00
renderLog . CloseMainBlock ( ) ;
}
2012-11-28 15:47:07 +00:00
2016-01-09 21:24:57 +00:00
//-------------------------------------------------
// use direct light and emissive light contributions to add indirect screen space light
//-------------------------------------------------
2016-01-13 19:33:16 +00:00
//RB_SSGI( viewDef );
2016-01-09 21:24:57 +00:00
2012-11-26 18:58:24 +00:00
//-------------------------------------------------
// fog and blend lights, drawn after emissive surfaces
// so they are properly dimmed down
//-------------------------------------------------
2017-09-03 21:17:44 +00:00
FogAllLights ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//-------------------------------------------------
// now draw any screen warping post-process effects using _currentRender
//-------------------------------------------------
2012-11-28 15:47:07 +00:00
if ( processed < numDrawSurfs & & ! r_skipPostProcess . GetBool ( ) )
{
2017-09-03 21:17:44 +00:00
int x = viewDef - > viewport . x1 ;
int y = viewDef - > viewport . y1 ;
int w = viewDef - > viewport . x2 - viewDef - > viewport . x1 + 1 ;
int h = viewDef - > viewport . y2 - viewDef - > viewport . y1 + 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RENDERLOG_PRINTF ( " Resolve to %i x %i buffer \n " , w , h ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// resolve the screen
globalImages - > currentRenderImage - > CopyFramebuffer ( x , y , w , h ) ;
2017-09-03 21:17:44 +00:00
currentRenderCopied = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// RENDERPARM_SCREENCORRECTIONFACTOR amd RENDERPARM_WINDOWCOORD overlap
// diffuseScale and specularScale
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// screen power of two correction factor (no longer relevant now)
float screenCorrectionParm [ 4 ] ;
screenCorrectionParm [ 0 ] = 1.0f ;
screenCorrectionParm [ 1 ] = 1.0f ;
screenCorrectionParm [ 2 ] = 0.0f ;
screenCorrectionParm [ 3 ] = 1.0f ;
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// window coord to 0.0 to 1.0 conversion
float windowCoordParm [ 4 ] ;
windowCoordParm [ 0 ] = 1.0f / w ;
windowCoordParm [ 1 ] = 1.0f / h ;
windowCoordParm [ 2 ] = 0.0f ;
windowCoordParm [ 3 ] = 1.0f ;
SetFragmentParm ( RENDERPARM_WINDOWCOORD , windowCoordParm ) ; // rpWindowCoord
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// render the remaining surfaces
renderLog . OpenMainBlock ( MRB_DRAW_SHADER_PASSES_POST ) ;
2017-09-03 21:17:44 +00:00
DrawShaderPasses ( drawSurfs + processed , numDrawSurfs - processed , 0.0f /* definitely not a gui */ , stereoEye ) ;
2012-11-26 18:58:24 +00:00
renderLog . CloseMainBlock ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//-------------------------------------------------
// render debug tools
//-------------------------------------------------
2017-09-10 11:32:44 +00:00
DBG_RenderDebugTools ( drawSurfs , numDrawSurfs ) ;
2012-11-28 15:47:07 +00:00
2018-10-03 21:40:35 +00:00
# if !defined(USE_VULKAN)
2015-12-20 11:28:46 +00:00
// RB: convert back from HDR to LDR range
2016-02-02 22:12:53 +00:00
if ( useHDR )
2015-12-20 11:28:46 +00:00
{
/*
int x = backEnd . viewDef - > viewport . x1 ;
int y = backEnd . viewDef - > viewport . y1 ;
int w = backEnd . viewDef - > viewport . x2 - backEnd . viewDef - > viewport . x1 + 1 ;
int h = backEnd . viewDef - > viewport . y2 - backEnd . viewDef - > viewport . y1 + 1 ;
GL_Viewport ( viewDef - > viewport . x1 ,
viewDef - > viewport . y1 ,
viewDef - > viewport . x2 + 1 - viewDef - > viewport . x1 ,
viewDef - > viewport . y2 + 1 - viewDef - > viewport . y1 ) ;
*/
/*
glBindFramebuffer ( GL_READ_FRAMEBUFFER , globalFramebuffers . hdrFBO - > GetFramebuffer ( ) ) ;
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , globalFramebuffers . hdrQuarterFBO - > GetFramebuffer ( ) ) ;
2016-10-24 01:55:16 +00:00
glBlitFramebuffer ( 0 , 0 , renderSystem - > GetWidth ( ) , renderSystem - > GetHeight ( ) ,
0 , 0 , renderSystem - > GetWidth ( ) * 0.25f , renderSystem - > GetHeight ( ) * 0.25f ,
2015-12-20 11:28:46 +00:00
GL_COLOR_BUFFER_BIT ,
GL_LINEAR ) ;
*/
2015-12-28 22:44:22 +00:00
# if defined(USE_HDR_MSAA)
2016-10-24 23:06:21 +00:00
if ( glConfig . multisamples > 0 )
2015-12-20 11:28:46 +00:00
{
glBindFramebuffer ( GL_READ_FRAMEBUFFER , globalFramebuffers . hdrFBO - > GetFramebuffer ( ) ) ;
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , globalFramebuffers . hdrNonMSAAFBO - > GetFramebuffer ( ) ) ;
2016-10-24 01:55:16 +00:00
glBlitFramebuffer ( 0 , 0 , renderSystem - > GetWidth ( ) , renderSystem - > GetHeight ( ) ,
0 , 0 , renderSystem - > GetWidth ( ) , renderSystem - > GetHeight ( ) ,
2015-12-20 11:28:46 +00:00
GL_COLOR_BUFFER_BIT ,
GL_LINEAR ) ;
// TODO resolve to 1x1
glBindFramebuffer ( GL_READ_FRAMEBUFFER_EXT , globalFramebuffers . hdrNonMSAAFBO - > GetFramebuffer ( ) ) ;
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER_EXT , globalFramebuffers . hdr64FBO - > GetFramebuffer ( ) ) ;
2016-10-24 01:55:16 +00:00
glBlitFramebuffer ( 0 , 0 , renderSystem - > GetWidth ( ) , renderSystem - > GetHeight ( ) ,
2015-12-20 11:28:46 +00:00
0 , 0 , 64 , 64 ,
GL_COLOR_BUFFER_BIT ,
GL_LINEAR ) ;
}
else
2015-12-28 22:44:22 +00:00
# endif
2015-12-20 11:28:46 +00:00
{
glBindFramebuffer ( GL_READ_FRAMEBUFFER_EXT , globalFramebuffers . hdrFBO - > GetFramebuffer ( ) ) ;
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER_EXT , globalFramebuffers . hdr64FBO - > GetFramebuffer ( ) ) ;
2016-10-24 01:55:16 +00:00
glBlitFramebuffer ( 0 , 0 , renderSystem - > GetWidth ( ) , renderSystem - > GetHeight ( ) ,
2015-12-20 11:28:46 +00:00
0 , 0 , 64 , 64 ,
GL_COLOR_BUFFER_BIT ,
GL_LINEAR ) ;
}
2017-09-03 21:17:44 +00:00
CalculateAutomaticExposure ( ) ;
2015-12-20 11:28:46 +00:00
2017-09-03 21:17:44 +00:00
Tonemap ( _viewDef ) ;
2015-12-20 11:28:46 +00:00
}
2017-09-03 21:17:44 +00:00
Bloom ( _viewDef ) ;
2018-10-03 21:40:35 +00:00
# endif
2015-12-20 11:28:46 +00:00
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
RB_MotionBlur
Experimental feature
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : MotionBlur ( )
2012-11-28 15:47:07 +00:00
{
2017-09-03 21:17:44 +00:00
if ( ! viewDef - > viewEntitys )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// 3D views only
return ;
}
2012-11-28 15:47:07 +00:00
if ( r_motionBlur . GetInteger ( ) < = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2017-09-03 21:17:44 +00:00
if ( viewDef - > isSubview )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_CheckErrors ( ) ;
2012-11-28 15:47:07 +00:00
2018-10-03 21:40:35 +00:00
2012-11-26 18:58:24 +00:00
// clear the alpha buffer and draw only the hands + weapon into it so
// we can avoid blurring them
GL_State ( GLS_COLORMASK | GLS_DEPTHMASK ) ;
2018-10-03 21:40:35 +00:00
// FIXME
# if !defined(USE_VULKAN)
glClearColor ( 0 , 0 , 0 , 1 ) ;
2012-12-17 16:30:59 +00:00
glClear ( GL_COLOR_BUFFER_BIT ) ;
2018-10-03 21:40:35 +00:00
# endif
2012-11-26 18:58:24 +00:00
GL_Color ( 0 , 0 , 0 , 0 ) ;
GL_SelectTexture ( 0 ) ;
globalImages - > blackImage - > Bind ( ) ;
2017-09-03 21:17:44 +00:00
currentSpace = NULL ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
drawSurf_t * * drawSurfs = ( drawSurf_t * * ) & viewDef - > drawSurfs [ 0 ] ;
for ( int surfNum = 0 ; surfNum < viewDef - > numDrawSurfs ; surfNum + + )
2012-11-28 15:47:07 +00:00
{
const drawSurf_t * surf = drawSurfs [ surfNum ] ;
if ( ! surf - > space - > weaponDepthHack & & ! surf - > space - > skipMotionBlur & & ! surf - > material - > HasSubview ( ) )
{
2012-11-26 18:58:24 +00:00
// Apply motion blur to this object
continue ;
}
2012-11-28 15:47:07 +00:00
const idMaterial * shader = surf - > material ;
if ( shader - > Coverage ( ) = = MC_TRANSLUCENT )
{
2012-11-26 18:58:24 +00:00
// muzzle flash, etc
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set mvp matrix
2017-09-03 21:17:44 +00:00
if ( surf - > space ! = currentSpace )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
RB_SetMVP ( surf - > space - > mvp ) ;
2017-09-03 21:17:44 +00:00
currentSpace = surf - > space ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// this could just be a color, but we don't have a skinned color-only prog
2012-11-28 15:47:07 +00:00
if ( surf - > jointCache )
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_TextureVertexColorSkinned ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_TextureVertexColor ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// draw it solid
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( surf ) ;
2012-11-26 18:58:24 +00:00
}
2017-09-03 21:17:44 +00:00
2012-11-26 18:58:24 +00:00
GL_State ( GLS_DEPTHFUNC_ALWAYS ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// copy off the color buffer and the depth buffer for the motion blur prog
// we use the viewport dimensions for copying the buffers in case resolution scaling is enabled.
2017-09-03 21:17:44 +00:00
const idScreenRect & viewport = viewDef - > viewport ;
2012-11-26 18:58:24 +00:00
globalImages - > currentRenderImage - > CopyFramebuffer ( viewport . x1 , viewport . y1 , viewport . GetWidth ( ) , viewport . GetHeight ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// in stereo rendering, each eye needs to get a separate previous frame mvp
2017-09-03 21:17:44 +00:00
int mvpIndex = ( viewDef - > renderView . viewEyeBuffer = = 1 ) ? 1 : 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// derive the matrix to go from current pixels to previous frame pixels
idRenderMatrix inverseMVP ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Inverse ( viewDef - > worldSpace . mvp , inverseMVP ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idRenderMatrix motionMatrix ;
2017-09-03 21:17:44 +00:00
idRenderMatrix : : Multiply ( prevMVP [ mvpIndex ] , inverseMVP , motionMatrix ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
prevMVP [ mvpIndex ] = viewDef - > worldSpace . mvp ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RB_SetMVP ( motionMatrix ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_State ( GLS_DEPTHFUNC_ALWAYS ) ;
GL_Cull ( CT_TWO_SIDED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderProgManager . BindShader_MotionBlur ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// let the fragment program know how many samples we are going to use
2012-11-28 15:47:07 +00:00
idVec4 samples ( ( float ) ( 1 < < r_motionBlur . GetInteger ( ) ) ) ;
2012-11-26 18:58:24 +00:00
SetFragmentParm ( RENDERPARM_OVERBRIGHT , samples . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
GL_SelectTexture ( 0 ) ;
globalImages - > currentRenderImage - > Bind ( ) ;
GL_SelectTexture ( 1 ) ;
globalImages - > currentDepthImage - > Bind ( ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2012-11-26 18:58:24 +00:00
GL_CheckErrors ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : DrawView
2012-11-26 18:58:24 +00:00
StereoEye will always be 0 in mono modes , or - 1 / 1 in stereo modes .
If the view is a GUI view that is repeated for both eyes , the viewDef . stereoEye value
is 0 , so the stereoEye parameter is not always the same as that .
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : DrawView ( const void * data , const int stereoEye )
2012-11-28 15:47:07 +00:00
{
const drawSurfsCommand_t * cmd = ( const drawSurfsCommand_t * ) data ;
2017-09-03 21:17:44 +00:00
viewDef = cmd - > viewDef ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we will need to do a new copyTexSubImage of the screen
// when a SS_POST_PROCESS material is used
2017-09-03 21:17:44 +00:00
currentRenderCopied = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if there aren't any drawsurfs, do nothing
2017-09-03 21:17:44 +00:00
if ( ! viewDef - > numDrawSurfs )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip render bypasses everything that has models, assuming
// them to be 3D views, but leaves 2D rendering visible
2017-09-03 21:17:44 +00:00
if ( r_skipRender . GetBool ( ) & & viewDef - > viewEntitys )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// skip render context sets the wgl context to NULL,
// which should factor out the API cost, under the assumption
// that all gl calls just return if the context isn't valid
2012-12-11 22:17:23 +00:00
// RB: not really needed
//if( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys )
//{
// GLimp_DeactivateContext();
//}
// RB end
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
pc . c_surfaces + = viewDef - > numDrawSurfs ;
2012-11-28 15:47:07 +00:00
2017-09-09 12:57:48 +00:00
DBG_ShowOverdraw ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// render the scene
2017-09-03 21:17:44 +00:00
DrawViewInternal ( cmd - > viewDef , stereoEye ) ;
2012-11-28 15:47:07 +00:00
2017-09-03 21:17:44 +00:00
MotionBlur ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// restore the context for 2D drawing if we were stubbing it out
2012-12-11 22:17:23 +00:00
// RB: not really needed
//if( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys )
//{
// GLimp_ActivateContext();
// GL_SetDefaultState();
//}
// RB end
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// optionally draw a box colored based on the eye number
2012-11-28 15:47:07 +00:00
if ( r_drawEyeColor . GetBool ( ) )
{
2017-09-03 21:17:44 +00:00
const idScreenRect & r = viewDef - > viewport ;
2012-11-26 18:58:24 +00:00
GL_Scissor ( ( r . x1 + r . x2 ) / 2 , ( r . y1 + r . y2 ) / 2 , 32 , 32 ) ;
2012-11-28 15:47:07 +00:00
switch ( stereoEye )
{
2012-11-26 18:58:24 +00:00
case - 1 :
GL_Clear ( true , false , false , 0 , 1.0f , 0.0f , 0.0f , 1.0f ) ;
break ;
case 1 :
GL_Clear ( true , false , false , 0 , 0.0f , 1.0f , 0.0f , 1.0f ) ;
break ;
default :
GL_Clear ( true , false , false , 0 , 0.5f , 0.5f , 0.5f , 1.0f ) ;
break ;
}
}
}
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : CopyRender
2012-11-26 18:58:24 +00:00
Copy part of the current framebuffer to an image
= = = = = = = = = = = = = = = = = =
*/
2017-09-03 21:17:44 +00:00
void idRenderBackend : : CopyRender ( const void * data )
2012-11-28 15:47:07 +00:00
{
const copyRenderCommand_t * cmd = ( const copyRenderCommand_t * ) data ;
if ( r_skipCopyTexture . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RENDERLOG_PRINTF ( " ***************** RB_CopyRender ***************** \n " ) ;
2012-11-28 15:47:07 +00:00
if ( cmd - > image )
{
2012-11-26 18:58:24 +00:00
cmd - > image - > CopyFramebuffer ( cmd - > x , cmd - > y , cmd - > imageWidth , cmd - > imageHeight ) ;
}
2012-11-28 15:47:07 +00:00
if ( cmd - > clearColorAfterCopy )
{
2012-11-26 18:58:24 +00:00
GL_Clear ( true , false , false , STENCIL_SHADOW_TEST_VALUE , 0 , 0 , 0 , 0 ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
2017-09-03 21:17:44 +00:00
idRenderBackend : : PostProcess
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = =
*/
extern idCVar rs_enable ;
2017-09-03 21:17:44 +00:00
void idRenderBackend : : PostProcess ( const void * data )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
// only do the post process step if resolution scaling is enabled. Prevents the unnecessary copying of the framebuffer and
// corresponding full screen quad pass.
2015-12-30 11:07:24 +00:00
if ( rs_enable . GetInteger ( ) = = 0 & & ! r_useFilmicPostProcessEffects . GetBool ( ) & & r_antiAliasing . GetInteger ( ) = = 0 )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2016-01-13 23:59:41 +00:00
if ( ( r_ssaoDebug . GetInteger ( ) > 0 ) | | ( r_ssgiDebug . GetInteger ( ) > 0 ) )
2016-01-11 18:00:20 +00:00
{
return ;
}
2015-12-23 12:53:21 +00:00
RENDERLOG_PRINTF ( " ---------- RB_PostProcess() ---------- \n " ) ;
2018-10-03 21:40:35 +00:00
// FIXME
# if !defined(USE_VULKAN)
2012-11-26 18:58:24 +00:00
// resolve the scaled rendering to a temporary texture
2012-11-28 15:47:07 +00:00
postProcessCommand_t * cmd = ( postProcessCommand_t * ) data ;
const idScreenRect & viewport = cmd - > viewDef - > viewport ;
2012-11-26 18:58:24 +00:00
GL_State ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS ) ;
GL_Cull ( CT_TWO_SIDED ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int screenWidth = renderSystem - > GetWidth ( ) ;
int screenHeight = renderSystem - > GetHeight ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the window clipping
GL_Viewport ( 0 , 0 , screenWidth , screenHeight ) ;
GL_Scissor ( 0 , 0 , screenWidth , screenHeight ) ;
2012-11-28 15:47:07 +00:00
2015-12-26 15:11:47 +00:00
// SMAA
2015-12-30 11:07:24 +00:00
int aaMode = r_antiAliasing . GetInteger ( ) ;
if ( aaMode = = ANTI_ALIASING_SMAA_1X )
2015-12-26 15:11:47 +00:00
{
/*
* The shader has three passes , chained together as follows :
*
* | input | - - - - - - - - - - - - - - - - - - <EFBFBD>
* v |
* [ SMAA * EdgeDetection ] |
* v |
* | edgesTex | |
* v |
* [ SMAABlendingWeightCalculation ] |
* v |
* | blendTex | |
* v |
* [ SMAANeighborhoodBlending ] < - - - - - - <EFBFBD>
* v
* | output |
*/
2016-10-24 01:55:16 +00:00
globalImages - > smaaInputImage - > CopyFramebuffer ( 0 , 0 , screenWidth , screenHeight ) ;
2015-12-30 11:07:24 +00:00
2015-12-27 16:45:41 +00:00
// set SMAA_RT_METRICS = rpScreenCorrectionFactor
float screenCorrectionParm [ 4 ] ;
2016-10-24 01:55:16 +00:00
screenCorrectionParm [ 0 ] = 1.0f / screenWidth ;
screenCorrectionParm [ 1 ] = 1.0f / screenHeight ;
screenCorrectionParm [ 2 ] = screenWidth ;
screenCorrectionParm [ 3 ] = screenHeight ;
2015-12-27 16:45:41 +00:00
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
2015-12-28 12:34:39 +00:00
globalFramebuffers . smaaEdgesFBO - > Bind ( ) ;
glClearColor ( 0 , 0 , 0 , 0 ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
2015-12-30 11:07:24 +00:00
GL_SelectTexture ( 0 ) ;
globalImages - > smaaInputImage - > Bind ( ) ;
2015-12-28 10:42:11 +00:00
renderProgManager . BindShader_SMAA_EdgeDetection ( ) ;
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2015-12-28 10:42:11 +00:00
2015-12-28 20:36:25 +00:00
# if 1
2015-12-28 12:34:39 +00:00
//globalImages->smaaEdgesImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
2015-12-28 22:22:58 +00:00
globalFramebuffers . smaaBlendFBO - > Bind ( ) ;
//Framebuffer::Unbind();
2015-12-28 12:34:39 +00:00
glClear ( GL_COLOR_BUFFER_BIT ) ;
2015-12-28 10:42:11 +00:00
2015-12-28 20:36:25 +00:00
GL_SelectTexture ( 0 ) ;
globalImages - > smaaEdgesImage - > Bind ( ) ;
2015-12-28 10:42:11 +00:00
GL_SelectTexture ( 1 ) ;
globalImages - > smaaAreaImage - > Bind ( ) ;
GL_SelectTexture ( 2 ) ;
globalImages - > smaaSearchImage - > Bind ( ) ;
renderProgManager . BindShader_SMAA_BlendingWeightCalculation ( ) ;
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2015-12-28 10:42:11 +00:00
2015-12-28 12:34:39 +00:00
Framebuffer : : Unbind ( ) ;
2015-12-28 20:36:25 +00:00
# endif
2015-12-28 10:42:11 +00:00
2015-12-28 22:22:58 +00:00
# if 1
2015-12-28 12:34:39 +00:00
//GL_SelectTexture( 0 );
//globalImages->smaaBlendImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
GL_SelectTexture ( 0 ) ;
2015-12-28 20:36:25 +00:00
globalImages - > smaaInputImage - > Bind ( ) ;
2015-12-28 10:42:11 +00:00
2015-12-28 12:34:39 +00:00
GL_SelectTexture ( 1 ) ;
globalImages - > smaaBlendImage - > Bind ( ) ;
renderProgManager . BindShader_SMAA_NeighborhoodBlending ( ) ;
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2015-12-28 20:36:25 +00:00
# endif
2015-12-26 15:11:47 +00:00
}
2015-12-28 22:33:39 +00:00
# if 1
2015-12-30 11:07:24 +00:00
if ( r_useFilmicPostProcessEffects . GetBool ( ) )
2015-12-23 12:53:21 +00:00
{
2015-12-30 11:07:24 +00:00
globalImages - > currentRenderImage - > CopyFramebuffer ( viewport . x1 , viewport . y1 , viewport . GetWidth ( ) , viewport . GetHeight ( ) ) ;
GL_SelectTexture ( 0 ) ;
globalImages - > currentRenderImage - > Bind ( ) ;
GL_SelectTexture ( 1 ) ;
globalImages - > grainImage1 - > Bind ( ) ;
renderProgManager . BindShader_PostProcess ( ) ;
const static int GRAIN_SIZE = 128 ;
// screen power of two correction factor
float screenCorrectionParm [ 4 ] ;
screenCorrectionParm [ 0 ] = 1.0f / GRAIN_SIZE ;
screenCorrectionParm [ 1 ] = 1.0f / GRAIN_SIZE ;
screenCorrectionParm [ 2 ] = 1.0f ;
screenCorrectionParm [ 3 ] = 1.0f ;
SetFragmentParm ( RENDERPARM_SCREENCORRECTIONFACTOR , screenCorrectionParm ) ; // rpScreenCorrectionFactor
float jitterTexOffset [ 4 ] ;
if ( r_shadowMapRandomizeJitter . GetBool ( ) )
{
jitterTexOffset [ 0 ] = ( rand ( ) & 255 ) / 255.0 ;
jitterTexOffset [ 1 ] = ( rand ( ) & 255 ) / 255.0 ;
}
else
{
jitterTexOffset [ 0 ] = 0 ;
jitterTexOffset [ 1 ] = 0 ;
}
jitterTexOffset [ 2 ] = 0.0f ;
jitterTexOffset [ 3 ] = 0.0f ;
SetFragmentParm ( RENDERPARM_JITTERTEXOFFSET , jitterTexOffset ) ; // rpJitterTexOffset
// Draw
2017-09-03 21:17:44 +00:00
DrawElementsWithCounters ( & unitSquareSurface ) ;
2015-12-23 12:53:21 +00:00
}
2015-12-27 16:45:41 +00:00
# endif
2015-12-28 10:42:11 +00:00
GL_SelectTexture ( 0 ) ;
renderProgManager . Unbind ( ) ;
2018-10-03 21:40:35 +00:00
# endif
2012-11-26 18:58:24 +00:00
renderLog . CloseBlock ( ) ;
}