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.
|
2014-04-05 13:41:19 +00:00
|
|
|
|
Copyright (C) 2014 Carl Kenner
|
2019-10-31 20:05:00 +00:00
|
|
|
|
Copyright (C) 2016-2017 Dustin Land
|
2020-04-28 23:19:53 +00:00
|
|
|
|
Copyright (C) 2013-2020 Robert Beckebans
|
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
|
|
|
|
|
2019-10-15 05:43:24 +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
|
|
|
|
|
2019-10-28 19:06:10 +00:00
|
|
|
|
#include "imgui/ImGui_Hooks.h"
|
|
|
|
|
|
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" );
|
2019-11-19 20:02:47 +00:00
|
|
|
|
idCVar r_useStencilShadowPreload( "r_useStencilShadowPreload", "0", CVAR_RENDERER | CVAR_BOOL, "use stencil shadow preload algorithm instead of Z-fail" );
|
2012-11-26 18:58:24 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
renderLog.OpenBlock( "GL_State" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
// 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" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
// polygon mode
|
|
|
|
|
renderLog.Printf( "PolygonMode: %s\n", ( stateBits & GLS_POLYMODE_LINE ) ? "LINE" : "FILL" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
// 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" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
// 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" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
// 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" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
// depth mask
|
|
|
|
|
renderLog.Printf( "DepthWrite: %s\n", ( stateBits & GLS_DEPTHMASK ) ? "FALSE" : "TRUE" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
renderLog.Printf( "DepthBounds: %s\n", ( stateBits & GLS_DEPTH_TEST_MASK ) ? "TRUE" : "FALSE" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
// depth bias
|
|
|
|
|
renderLog.Printf( "DepthBias: %s\n", ( stateBits & GLS_POLYGON_OFFSET ) ? "TRUE" : "FALSE" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
// 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 );
|
|
|
|
|
};
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +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
|
|
|
|
|
======================
|
|
|
|
|
*/
|
2018-09-30 19:39:20 +00:00
|
|
|
|
void RB_GetShaderTextureMatrix( const float* shaderRegisters, const textureStage_t* texture, float matrix[16] )
|
2012-11-28 15:47:07 +00:00
|
|
|
|
{
|
|
|
|
|
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] ];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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] ];
|
2019-11-11 19:27:44 +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[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
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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
|
|
|
|
|
======================
|
|
|
|
|
*/
|
2018-09-30 19:39:20 +00:00
|
|
|
|
void RB_LoadShaderTextureMatrix( const float* shaderRegisters, const textureStage_t* texture )
|
2012-11-28 15:47:07 +00:00
|
|
|
|
{
|
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 };
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
texT[0] = matrix[0 * 4 + 1];
|
|
|
|
|
texT[1] = matrix[1 * 4 + 1];
|
|
|
|
|
texT[2] = matrix[2 * 4 + 1];
|
|
|
|
|
texT[3] = matrix[3 * 4 + 1];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
SetVertexParm( RENDERPARM_TEXTUREMATRIX_S, texS );
|
|
|
|
|
SetVertexParm( RENDERPARM_TEXTUREMATRIX_T, texT );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
=====================
|
|
|
|
|
RB_BakeTextureMatrixIntoTexgen
|
|
|
|
|
=====================
|
|
|
|
|
*/
|
2018-09-30 19:39:20 +00:00
|
|
|
|
void RB_BakeTextureMatrixIntoTexgen( idPlane lightProject[3], const float* textureMatrix )
|
2012-11-28 15:47:07 +00:00
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
float genMatrix[16];
|
|
|
|
|
float final[16];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
genMatrix[0 * 4 + 2] = 0.0f;
|
|
|
|
|
genMatrix[1 * 4 + 2] = 0.0f;
|
|
|
|
|
genMatrix[2 * 4 + 2] = 0.0f;
|
|
|
|
|
genMatrix[3 * 4 + 2] = 0.0f;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
R_MatrixMultiply( genMatrix, textureMatrix, final );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( r_skipDynamicTextures.GetBool() )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
globalImages->defaultImage->Bind();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 1 );
|
|
|
|
|
cin.imageCr->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 2 );
|
|
|
|
|
cin.imageCb->Bind();
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 };
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// set the texture matrix if needed
|
|
|
|
|
RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture );
|
2019-11-11 19:27:44 +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 )
|
|
|
|
|
{
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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();
|
2020-05-17 11:29:18 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 )
|
|
|
|
|
{
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
const int* parms = surf->material->GetTexGenRegisters();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
float ws, wc;
|
|
|
|
|
idMath::SinCos( wobbleDegrees, ws, wc );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
axis[2][0] = ws * c;
|
|
|
|
|
axis[2][1] = ws * s;
|
|
|
|
|
axis[2][2] = wc;
|
2019-11-11 19:27:44 +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] ) ) );
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// construct the third with a cross
|
|
|
|
|
axis[0].Cross( axis[1], axis[2] );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
SetVertexParms( RENDERPARM_WOBBLESKY_X, transform, 3 );
|
|
|
|
|
renderProgManager.BindShader_WobbleSky();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
}
|
|
|
|
|
else if( ( pStage->texture.texgen == TG_SCREEN ) || ( pStage->texture.texgen == TG_SCREEN2 ) )
|
|
|
|
|
{
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
useTexGenParm[0] = 1.0f;
|
|
|
|
|
useTexGenParm[1] = 1.0f;
|
|
|
|
|
useTexGenParm[2] = 1.0f;
|
|
|
|
|
useTexGenParm[3] = 1.0f;
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +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] );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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] );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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] );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.Outdent();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
}
|
|
|
|
|
else if( pStage->texture.texgen == TG_DIFFUSE_CUBE )
|
|
|
|
|
{
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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!" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
}
|
|
|
|
|
else if( pStage->texture.texgen == TG_GLASSWARP )
|
|
|
|
|
{
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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!" );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentSpace = drawSurf->space;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
uint64 surfGLState = 0;
|
2019-11-11 19:27:44 +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() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( shader->GetName(), colorMdGrey );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( !pStage->hasAlphaTest )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// set the alpha modulate
|
|
|
|
|
color[3] = regs[ pStage->color.registers[3] ];
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
uint64 stageGLState = surfGLState;
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_Color( color );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_State( stageGLState );
|
|
|
|
|
idVec4 alphaTestValue( regs[ pStage->alphaTestRegister ] );
|
|
|
|
|
SetFragmentParm( RENDERPARM_ALPHA_TEST, alphaTestValue.ToFloatPtr() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
RB_SetVertexColorParms( SVC_IGNORE );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// bind the texture
|
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
pStage->texture.image->Bind();
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// draw it
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( drawSurf );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// clean up
|
2017-09-03 21:17:44 +00:00
|
|
|
|
FinishStageTexturing( pStage, drawSurf );
|
2019-11-11 19:27:44 +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() );
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( !didDraw )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
drawSolid = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
=====================
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.OpenMainBlock( MRB_FILL_DEPTH_BUFFER );
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Render_FillDepthBufferFast", colorBlue );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
FillDepthBufferGeneric( &drawSurfs[surfNum], 1 );
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// set polygon offset?
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( shader->GetName(), colorMdGrey );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// draw it solid
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( surf );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
renderLog.CloseMainBlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
=========================================================================================
|
|
|
|
|
|
|
|
|
|
GENERAL INTERACTION RENDERING
|
|
|
|
|
|
|
|
|
|
=========================================================================================
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
const int INTERACTION_TEXUNIT_BUMP = 0;
|
2018-11-03 11:01:03 +00:00
|
|
|
|
const int INTERACTION_TEXUNIT_SPECULARMIX = 1;
|
|
|
|
|
const int INTERACTION_TEXUNIT_BASECOLOR = 2;
|
2020-04-25 16:30:40 +00:00
|
|
|
|
const int INTERACTION_TEXUNIT_FALLOFF = 3; // RB: also _brdfLut
|
|
|
|
|
const int INTERACTION_TEXUNIT_PROJECTION = 4; // RB: also SSAO render target
|
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
|
|
|
|
|
2019-10-31 20:17:31 +00:00
|
|
|
|
#if defined( USE_VULKAN )
|
2020-04-25 16:30:40 +00:00
|
|
|
|
const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 5;
|
|
|
|
|
const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 6;
|
2019-10-31 20:17:31 +00:00
|
|
|
|
#else
|
2019-11-11 19:27:44 +00:00
|
|
|
|
const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 7;
|
|
|
|
|
const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 8;
|
2019-10-31 20:17:31 +00:00
|
|
|
|
#endif
|
2016-07-07 01:17:33 +00:00
|
|
|
|
|
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]];
|
2019-11-11 19:27:44 +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]];
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
=================
|
|
|
|
|
*/
|
2020-04-16 16:08:50 +00:00
|
|
|
|
void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFastPath, bool useIBL, bool setInteractionShader )
|
2012-11-28 15:47:07 +00:00
|
|
|
|
{
|
2020-04-16 16:08:50 +00:00
|
|
|
|
if( !useFastPath )
|
2012-11-28 15:47:07 +00:00
|
|
|
|
{
|
2020-04-16 16:08:50 +00:00
|
|
|
|
if( din->bumpImage == NULL )
|
|
|
|
|
{
|
|
|
|
|
// stage wasn't actually an interaction
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
if( din->diffuseImage == NULL || r_skipDiffuse.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
// this isn't a YCoCg black, but it doesn't matter, because
|
|
|
|
|
// the diffuseColor will also be 0
|
|
|
|
|
din->diffuseImage = globalImages->blackImage;
|
|
|
|
|
}
|
|
|
|
|
if( din->specularImage == NULL || r_skipSpecular.GetBool() || ( din->vLight && din->vLight->lightShader->IsAmbientLight() ) )
|
|
|
|
|
{
|
|
|
|
|
din->specularImage = globalImages->blackImage;
|
|
|
|
|
}
|
|
|
|
|
if( r_skipBump.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
din->bumpImage = globalImages->flatNormalMap;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
// if we wouldn't draw anything, don't call the Draw function
|
|
|
|
|
const bool diffuseIsBlack = ( din->diffuseImage == globalImages->blackImage )
|
|
|
|
|
|| ( ( din->diffuseColor[0] <= 0 ) && ( din->diffuseColor[1] <= 0 ) && ( din->diffuseColor[2] <= 0 ) );
|
|
|
|
|
const bool specularIsBlack = ( din->specularImage == globalImages->blackImage )
|
|
|
|
|
|| ( ( din->specularColor[0] <= 0 ) && ( din->specularColor[1] <= 0 ) && ( din->specularColor[2] <= 0 ) );
|
|
|
|
|
if( diffuseIsBlack && specularIsBlack )
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// bump matrix
|
|
|
|
|
SetVertexParm( RENDERPARM_BUMPMATRIX_S, din->bumpMatrix[0].ToFloatPtr() );
|
|
|
|
|
SetVertexParm( RENDERPARM_BUMPMATRIX_T, din->bumpMatrix[1].ToFloatPtr() );
|
|
|
|
|
|
|
|
|
|
// diffuse matrix
|
|
|
|
|
SetVertexParm( RENDERPARM_DIFFUSEMATRIX_S, din->diffuseMatrix[0].ToFloatPtr() );
|
|
|
|
|
SetVertexParm( RENDERPARM_DIFFUSEMATRIX_T, din->diffuseMatrix[1].ToFloatPtr() );
|
|
|
|
|
|
|
|
|
|
// specular matrix
|
|
|
|
|
SetVertexParm( RENDERPARM_SPECULARMATRIX_S, din->specularMatrix[0].ToFloatPtr() );
|
|
|
|
|
SetVertexParm( RENDERPARM_SPECULARMATRIX_T, din->specularMatrix[1].ToFloatPtr() );
|
|
|
|
|
|
|
|
|
|
RB_SetVertexColorParms( din->vertexColor );
|
|
|
|
|
|
|
|
|
|
SetFragmentParm( RENDERPARM_DIFFUSEMODIFIER, din->diffuseColor.ToFloatPtr() );
|
|
|
|
|
SetFragmentParm( RENDERPARM_SPECULARMODIFIER, din->specularColor.ToFloatPtr() );
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
const textureUsage_t specUsage = din->specularImage->GetUsage();
|
|
|
|
|
|
|
|
|
|
// RB begin
|
2016-07-10 21:46:24 +00:00
|
|
|
|
if( useIBL )
|
|
|
|
|
{
|
|
|
|
|
if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD )
|
|
|
|
|
{
|
|
|
|
|
// PBR path with roughness, metal and AO
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_ImageBasedLightingSkinned_PBR();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_ImageBasedLighting_PBR();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_ImageBasedLightingSkinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_ImageBasedLighting();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-20 18:51:09 +00:00
|
|
|
|
GL_SelectTexture( INTERACTION_TEXUNIT_FALLOFF );
|
|
|
|
|
globalImages->brdfLutImage->Bind();
|
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
GL_SelectTexture( INTERACTION_TEXUNIT_PROJECTION );
|
|
|
|
|
if( !r_useSSAO.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
globalImages->whiteImage->Bind();
|
|
|
|
|
//globalImages->brdfLutImage->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
globalImages->ambientOcclusionImage[0]->Bind();
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 );
|
|
|
|
|
globalImages->defaultUACIrradianceCube->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 );
|
|
|
|
|
globalImages->defaultUACRadianceCube->Bind();
|
|
|
|
|
}
|
|
|
|
|
else if( setInteractionShader )
|
|
|
|
|
{
|
|
|
|
|
if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD )
|
|
|
|
|
{
|
|
|
|
|
// PBR path with roughness, metal and AO
|
|
|
|
|
// select the render prog
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
if( din->vLight->lightShader->IsAmbientLight() )
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_InteractionAmbientSkinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_InteractionAmbient();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( r_useShadowMapping.GetBool() && din->vLight->globalShadows )
|
|
|
|
|
{
|
|
|
|
|
// RB: we have shadow mapping enabled and shadow maps so do a shadow compare
|
|
|
|
|
|
|
|
|
|
if( din->vLight->parallel )
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_Interaction_ShadowMapping_Parallel_Skinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_Interaction_ShadowMapping_Parallel();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( din->vLight->pointLight )
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_Interaction_ShadowMapping_Point_Skinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_Interaction_ShadowMapping_Point();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_Interaction_ShadowMapping_Spot_Skinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_Interaction_ShadowMapping_Spot();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_InteractionSkinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_PBR_Interaction();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// only oldschool D3 gloss maps provided
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
if( din->vLight->lightShader->IsAmbientLight() )
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_InteractionAmbientSkinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_InteractionAmbient();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( r_useShadowMapping.GetBool() && din->vLight->globalShadows )
|
|
|
|
|
{
|
|
|
|
|
// RB: we have shadow mapping enabled and shadow maps so do a shadow compare
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
if( din->vLight->parallel )
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Interaction_ShadowMapping_Parallel_Skinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Interaction_ShadowMapping_Parallel();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( din->vLight->pointLight )
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Interaction_ShadowMapping_Point_Skinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Interaction_ShadowMapping_Point();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Interaction_ShadowMapping_Spot_Skinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Interaction_ShadowMapping_Spot();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( din->surf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_InteractionSkinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Interaction();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// RB end
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-03 11:01:03 +00:00
|
|
|
|
// texture 1 is the per-surface specular map
|
|
|
|
|
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULARMIX );
|
2012-11-26 18:58:24 +00:00
|
|
|
|
din->specularImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-03 11:01:03 +00:00
|
|
|
|
// texture 2 is the per-surface diffuse map
|
|
|
|
|
GL_SelectTexture( INTERACTION_TEXUNIT_BASECOLOR );
|
|
|
|
|
din->diffuseImage->Bind();
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// bump matrix
|
|
|
|
|
SetVertexParm( RENDERPARM_BUMPMATRIX_S, sMatrix.ToFloatPtr() );
|
|
|
|
|
SetVertexParm( RENDERPARM_BUMPMATRIX_T, tMatrix.ToFloatPtr() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// diffuse matrix
|
|
|
|
|
SetVertexParm( RENDERPARM_DIFFUSEMATRIX_S, sMatrix.ToFloatPtr() );
|
|
|
|
|
SetVertexParm( RENDERPARM_DIFFUSEMATRIX_T, tMatrix.ToFloatPtr() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// specular matrix
|
|
|
|
|
SetVertexParm( RENDERPARM_SPECULARMATRIX_S, sMatrix.ToFloatPtr() );
|
|
|
|
|
SetVertexParm( RENDERPARM_SPECULARMATRIX_T, tMatrix.ToFloatPtr() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
RB_SetVertexColorParms( SVC_IGNORE );
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentScissor = vLight->scissorRect;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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 )
|
|
|
|
|
{
|
2019-11-08 19:09:57 +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 ) );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-11-08 19:09:57 +00:00
|
|
|
|
GL_State(
|
|
|
|
|
GLS_SRCBLEND_ONE |
|
|
|
|
|
GLS_DSTBLEND_ONE |
|
|
|
|
|
GLS_DEPTHMASK |
|
|
|
|
|
depthFunc |
|
|
|
|
|
GLS_STENCIL_FUNC_ALWAYS );
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
drawInteraction_t inter = {};
|
2020-04-16 16:08:50 +00:00
|
|
|
|
inter.vLight = vLight;
|
2019-11-11 19:27:44 +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 )
|
|
|
|
|
{
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-04 23:21:29 +00:00
|
|
|
|
pc.cpuShadowMicroSec += end - start;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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] );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
bool lightDepthBoundsDisabled = false;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// RB begin
|
|
|
|
|
if( r_useShadowMapping.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
const static int JITTER_SIZE = 128;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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();
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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();
|
2020-05-11 21:49:04 +00:00
|
|
|
|
jitterTexScale[3] = shadowMapSamples;
|
2014-05-10 12:40:01 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
float jitterTexOffset[4];
|
2020-05-10 20:10:32 +00:00
|
|
|
|
jitterTexOffset[0] = 1.0f / globalImages->blueNoiseImage256->GetUploadWidth();
|
|
|
|
|
jitterTexOffset[1] = 1.0f / globalImages->blueNoiseImage256->GetUploadWidth();
|
|
|
|
|
|
2014-05-16 19:33:39 +00:00
|
|
|
|
if( r_shadowMapRandomizeJitter.GetBool() )
|
|
|
|
|
{
|
2020-04-28 23:19:53 +00:00
|
|
|
|
jitterTexOffset[2] = Sys_Milliseconds() / 1000.0f;
|
|
|
|
|
jitterTexOffset[3] = tr.frameCount % 64;
|
2014-05-16 19:33:39 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-04-28 23:19:53 +00:00
|
|
|
|
jitterTexOffset[2] = 0.0f;
|
|
|
|
|
jitterTexOffset[3] = 0.0f;
|
2014-05-16 19:33:39 +00:00
|
|
|
|
}
|
2014-05-10 12:40:01 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_JITTERTEXOFFSET, jitterTexOffset ); // rpJitterTexOffset
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
}
|
|
|
|
|
// RB end
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-01 21:30:16 +00:00
|
|
|
|
//const float lightScale = r_useHDR.GetBool() ? r_lightScale.GetFloat() * 0.666f : r_lightScale.GetFloat();
|
|
|
|
|
const float lightScale = r_lightScale.GetFloat();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
for( int lightStageNum = 0; lightStageNum < lightShader->GetNumStages(); lightStageNum++ )
|
|
|
|
|
{
|
|
|
|
|
const shaderStage_t* lightStage = lightShader->GetStage( lightStageNum );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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] ] );
|
2020-04-20 18:51:09 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// apply the world-global overbright and the 2x factor for specular
|
|
|
|
|
const idVec4 diffuseColor = lightColor;
|
|
|
|
|
const idVec4 specularColor = lightColor * 2.0f;
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// texture 6 will be the jitter texture for soft shadowing
|
|
|
|
|
GL_SelectTexture( INTERACTION_TEXUNIT_JITTER );
|
2020-04-28 23:19:53 +00:00
|
|
|
|
globalImages->blueNoiseImage256->Bind();
|
|
|
|
|
/*
|
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
|
|
|
|
}
|
2020-04-28 23:19:53 +00:00
|
|
|
|
*/
|
2014-05-10 12:40:01 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
//----------------------------------
|
|
|
|
|
// For all surfaces on this light list, generate an interaction for this light stage
|
|
|
|
|
//----------------------------------
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// setup renderparms assuming we will be drawing trivial surfaces first
|
|
|
|
|
RB_SetupForFastPathInteractions( diffuseColor, specularColor );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
for( int sortedSurfNum = 0; sortedSurfNum < allSurfaces.Num(); sortedSurfNum++ )
|
|
|
|
|
{
|
|
|
|
|
const drawSurf_t* const surf = allSurfaces[ sortedSurfNum ];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
const idMaterial* surfaceShader = surf->material;
|
|
|
|
|
const float* surfaceRegs = surf->shaderRegisters;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
inter.surf = surf;
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// model-view-projection
|
|
|
|
|
RB_SetMVP( surf->space->mvp );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// RB begin
|
|
|
|
|
idRenderMatrix modelMatrix;
|
|
|
|
|
idRenderMatrix::Transpose( *( idRenderMatrix* )surf->space->modelMatrix, modelMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
SetVertexParms( RENDERPARM_MODELMATRIX_X, modelMatrix[0], 4 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// for determining the shadow mapping cascades
|
|
|
|
|
idRenderMatrix modelViewMatrix, tmp;
|
|
|
|
|
idRenderMatrix::Transpose( *( idRenderMatrix* )surf->space->modelViewMatrix, modelViewMatrix );
|
|
|
|
|
SetVertexParms( RENDERPARM_MODELVIEWMATRIX_X, modelViewMatrix[0], 4 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idVec4 globalLightOrigin( vLight->globalLightOrigin.x, vLight->globalLightOrigin.y, vLight->globalLightOrigin.z, 1.0f );
|
|
|
|
|
SetVertexParm( RENDERPARM_GLOBALLIGHTORIGIN, globalLightOrigin.ToFloatPtr() );
|
|
|
|
|
// RB end
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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() );
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +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] );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix shadowClipMVP;
|
2017-09-03 21:17:44 +00:00
|
|
|
|
idRenderMatrix::Multiply( shadowP[i], modelToShadowMatrix, shadowClipMVP );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix shadowWindowMVP;
|
|
|
|
|
idRenderMatrix::Multiply( renderMatrix_clipSpaceToWindowSpace, shadowClipMVP, shadowWindowMVP );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix shadowClipMVP;
|
2017-09-03 21:17:44 +00:00
|
|
|
|
idRenderMatrix::Multiply( shadowP[i], modelToShadowMatrix, shadowClipMVP );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix shadowWindowMVP;
|
|
|
|
|
idRenderMatrix::Multiply( renderMatrix_clipSpaceToWindowSpace, shadowClipMVP, shadowWindowMVP );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
SetVertexParms( ( renderParm_t )( RENDERPARM_SHADOW_MATRIX_0_X + i * 4 ), shadowWindowMVP[0], 4 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// spot light
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix modelToShadowMatrix;
|
2017-09-03 21:17:44 +00:00
|
|
|
|
idRenderMatrix::Multiply( shadowV[0], modelMatrix, modelToShadowMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix shadowClipMVP;
|
2017-09-03 21:17:44 +00:00
|
|
|
|
idRenderMatrix::Multiply( shadowP[0], modelToShadowMatrix, shadowClipMVP );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
SetVertexParms( ( renderParm_t )( RENDERPARM_SHADOW_MATRIX_0_X ), shadowClipMVP[0], 4 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// RB end
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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() )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( surf->material->GetName(), colorMdGrey );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
inter.bumpImage = surfaceShader->GetFastPathBumpImage();
|
|
|
|
|
inter.specularImage = surfaceShader->GetFastPathSpecularImage();
|
|
|
|
|
inter.diffuseImage = surfaceShader->GetFastPathDiffuseImage();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, true, false, true );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( surf->material->GetName(), colorMdGrey );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, false, false, true );
|
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 )
|
|
|
|
|
{
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, false, false, true );
|
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 )
|
|
|
|
|
{
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, false, false, true );
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// draw the final interaction
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, false, false, true );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
|
|
|
{
|
2020-05-10 10:58:14 +00:00
|
|
|
|
const bool hdrIsActive = ( r_useHDR.GetBool() && globalFramebuffers.hdrFBO != NULL && globalFramebuffers.hdrFBO->IsBound() );
|
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
if( numDrawSurfs == 0 )
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +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 )
|
2015-12-24 15:43:02 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-15 14:25:36 +00:00
|
|
|
|
/*
|
2020-05-14 15:55:53 +00:00
|
|
|
|
if( !fillGbuffer )
|
|
|
|
|
{
|
|
|
|
|
// clear gbuffer
|
|
|
|
|
GL_Clear( true, false, false, 0, 0.0f, 0.0f, 0.0f, 1.0f, false );
|
|
|
|
|
}
|
2020-05-15 14:25:36 +00:00
|
|
|
|
*/
|
2020-05-14 15:55:53 +00:00
|
|
|
|
|
2020-05-10 10:58:14 +00:00
|
|
|
|
if( !fillGbuffer && r_useSSAO.GetBool() && r_ssaoDebug.GetBool() )
|
2019-11-22 17:25:33 +00:00
|
|
|
|
{
|
2020-05-10 10:58:14 +00:00
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
|
|
|
|
|
|
|
|
|
|
// We just want to do a quad pass - so make sure we disable any texgen and
|
|
|
|
|
// set the texture matrix to the identity so we don't get anomalies from
|
|
|
|
|
// any stale uniform data being present from a previous draw call
|
|
|
|
|
const float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
|
|
|
|
|
const float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
|
|
|
|
|
renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_S, texS );
|
|
|
|
|
renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_T, texT );
|
|
|
|
|
|
|
|
|
|
// disable any texgen
|
|
|
|
|
const float texGenEnabled[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
|
|
|
renderProgManager.SetRenderParm( RENDERPARM_TEXGEN_0_ENABLED, texGenEnabled );
|
|
|
|
|
|
|
|
|
|
currentSpace = NULL;
|
|
|
|
|
RB_SetMVP( renderMatrix_identity );
|
|
|
|
|
|
|
|
|
|
renderProgManager.BindShader_Texture();
|
|
|
|
|
GL_Color( 1, 1, 1, 1 );
|
|
|
|
|
|
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->ambientOcclusionImage[0]->Bind();
|
|
|
|
|
|
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
|
|
|
|
|
|
|
|
|
renderProgManager.Unbind();
|
|
|
|
|
GL_State( GLS_DEFAULT );
|
|
|
|
|
|
|
|
|
|
SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
|
|
|
|
|
|
|
|
|
|
return;
|
2019-11-22 17:25:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-15 14:25:36 +00:00
|
|
|
|
renderLog.OpenMainBlock( MRB_AMBIENT_PASS );
|
|
|
|
|
renderLog.OpenBlock( "Render_AmbientPass", colorBlue );
|
2020-05-10 10:58:14 +00:00
|
|
|
|
|
2016-01-18 22:21:53 +00:00
|
|
|
|
if( fillGbuffer )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.geometryBufferFBO->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-15 14:25:36 +00:00
|
|
|
|
GL_Clear( true, false, false, 0, 0.0f, 0.0f, 0.0f, 1.0f, false );
|
2016-01-18 22:21:53 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// RB: not needed
|
|
|
|
|
// GL_StartDepthPass( backEnd.viewDef->scissor );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// force MVP change on first surface
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentSpace = NULL;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2020-05-14 15:55:53 +00:00
|
|
|
|
GL_State( GLS_DEFAULT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-15 14:25:36 +00:00
|
|
|
|
#define BLEND_NORMALS 1
|
|
|
|
|
|
2020-05-14 15:55:53 +00:00
|
|
|
|
// RB: even use additive blending to blend the normals
|
2020-05-15 14:25:36 +00:00
|
|
|
|
//GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-31 17:11:34 +00:00
|
|
|
|
GL_Color( colorWhite );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-01 21:30:16 +00:00
|
|
|
|
//const float lightScale = r_useHDR.GetBool() ? r_lightScale.GetFloat() * 0.666f : r_lightScale.GetFloat();
|
|
|
|
|
const float lightScale = r_lightScale.GetFloat();
|
2015-12-24 15:43:02 +00:00
|
|
|
|
const idVec4 lightColor = colorWhite * lightScale;
|
2020-04-20 18:51:09 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// apply the world-global overbright and the 2x factor for specular
|
|
|
|
|
const idVec4 diffuseColor = lightColor;
|
|
|
|
|
const idVec4 specularColor = lightColor * 2.0f;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-13 23:59:41 +00:00
|
|
|
|
idVec4 ambientColor;
|
|
|
|
|
float ambientBoost = 1.0f;
|
2019-11-22 17:25:33 +00:00
|
|
|
|
|
2020-04-26 08:41:09 +00:00
|
|
|
|
if( !r_usePBR.GetBool() )
|
2019-11-22 17:25:33 +00:00
|
|
|
|
{
|
|
|
|
|
ambientBoost += r_useSSAO.GetBool() ? 0.2f : 0.0f;
|
|
|
|
|
ambientBoost *= r_useHDR.GetBool() ? 1.1f : 1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-26 08:41:09 +00:00
|
|
|
|
bool useIBL = r_usePBR.GetBool() && !fillGbuffer;
|
2019-11-22 17:25:33 +00:00
|
|
|
|
|
2016-01-13 23:59:41 +00:00
|
|
|
|
ambientColor.x = r_forceAmbient.GetFloat() * ambientBoost;
|
|
|
|
|
ambientColor.y = r_forceAmbient.GetFloat() * ambientBoost;
|
|
|
|
|
ambientColor.z = r_forceAmbient.GetFloat() * ambientBoost;
|
|
|
|
|
ambientColor.w = 1;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-13 23:59:41 +00:00
|
|
|
|
renderProgManager.SetRenderParm( RENDERPARM_AMBIENT_COLOR, ambientColor.ToFloatPtr() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// setup renderparms assuming we will be drawing trivial surfaces first
|
|
|
|
|
RB_SetupForFastPathInteractions( diffuseColor, specularColor );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
for( int i = 0; i < numDrawSurfs; i++ )
|
|
|
|
|
{
|
|
|
|
|
const drawSurf_t* drawSurf = drawSurfs[i];
|
|
|
|
|
const idMaterial* surfaceMaterial = drawSurf->material;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +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
|
|
|
|
|
if( surfaceMaterial->Coverage() == MC_TRANSLUCENT )
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// get the expressions for conditionals / color / texcoords
|
|
|
|
|
const float* surfaceRegs = drawSurf->shaderRegisters;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// 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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-19 23:55:30 +00:00
|
|
|
|
//bool isWorldModel = ( drawSurf->space->entityDef->parms.origin == vec3_origin );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
//if( isWorldModel )
|
|
|
|
|
//{
|
|
|
|
|
// renderProgManager.BindShader_VertexLighting();
|
|
|
|
|
//}
|
|
|
|
|
//else
|
|
|
|
|
{
|
2016-01-18 22:21:53 +00:00
|
|
|
|
if( fillGbuffer )
|
2015-12-24 15:43:02 +00:00
|
|
|
|
{
|
2020-04-25 16:30:40 +00:00
|
|
|
|
// TODO support PBR textures and store roughness in the alpha channel
|
|
|
|
|
|
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
|
|
|
|
|
{
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
// TODO support PBR textures
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
// draw Quake 4 style ambient
|
|
|
|
|
if( drawSurf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_AmbientLightingSkinned();
|
2015-12-31 17:11:34 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-04-25 16:30:40 +00:00
|
|
|
|
renderProgManager.BindShader_AmbientLighting();
|
2015-12-31 17:11:34 +00:00
|
|
|
|
}
|
2015-12-24 15:43:02 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
RB_SetMVP( drawSurf->space->mvp );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// 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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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() );
|
|
|
|
|
//}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-31 17:11:34 +00:00
|
|
|
|
SetVertexParms( RENDERPARM_MODELMATRIX_X, modelMatrix[0], 4 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
idVec4 ambientColor;
|
|
|
|
|
ambientColor.x = drawSurf->space->gridAmbientLight.x;
|
|
|
|
|
ambientColor.y = drawSurf->space->gridAmbientLight.y;
|
|
|
|
|
ambientColor.z = drawSurf->space->gridAmbientLight.z;
|
|
|
|
|
ambientColor.w = 1;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
renderProgManager.SetRenderParm( RENDERPARM_COLOR, directedColor.ToFloatPtr() );
|
|
|
|
|
renderProgManager.SetRenderParm( RENDERPARM_AMBIENT_COLOR, ambientColor.ToFloatPtr() );
|
|
|
|
|
}
|
2015-12-24 17:01:23 +00:00
|
|
|
|
float ambientBoost = r_useHDR.GetBool() ? 1.5 : 1.0;
|
2015-12-24 15:43:02 +00:00
|
|
|
|
#endif
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
/*
|
|
|
|
|
uint64 surfGLState = 0;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// set polygon offset if necessary
|
|
|
|
|
if( surfaceMaterial->TestMaterialFlag( MF_POLYGONOFFSET ) )
|
|
|
|
|
{
|
|
|
|
|
surfGLState |= GLS_POLYGON_OFFSET;
|
|
|
|
|
GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * surfaceMaterial->GetPolygonOffset() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
*/
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
drawInteraction_t inter = {};
|
|
|
|
|
inter.surf = drawSurf;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// check for the fast path
|
|
|
|
|
if( surfaceMaterial->GetFastPathBumpImage() && !r_skipInteractionFastPath.GetBool() )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( surfaceMaterial->GetName(), colorMdGrey );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
inter.bumpImage = surfaceMaterial->GetFastPathBumpImage();
|
|
|
|
|
inter.specularImage = surfaceMaterial->GetFastPathSpecularImage();
|
|
|
|
|
inter.diffuseImage = surfaceMaterial->GetFastPathDiffuseImage();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, true, useIBL, false );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( surfaceMaterial->GetName(), colorMdGrey );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
//bool drawSolid = false;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
inter.bumpImage = NULL;
|
|
|
|
|
inter.specularImage = NULL;
|
|
|
|
|
inter.diffuseImage = NULL;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// perforated surfaces may have multiple alpha tested stages
|
|
|
|
|
for( stage = 0; stage < surfaceMaterial->GetNumStages(); stage++ )
|
|
|
|
|
{
|
|
|
|
|
const shaderStage_t* surfaceStage = surfaceMaterial->GetStage( stage );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
case SL_AMBIENT:
|
|
|
|
|
{
|
|
|
|
|
// ignore ambient stages while drawing interactions
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
case SL_BUMP:
|
|
|
|
|
{
|
|
|
|
|
// ignore stage that fails the condition
|
|
|
|
|
if( !surfaceRegs[ surfaceStage->conditionRegister ] )
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// draw any previous interaction
|
|
|
|
|
if( inter.bumpImage != NULL )
|
|
|
|
|
{
|
2020-05-15 14:25:36 +00:00
|
|
|
|
#if BLEND_NORMALS
|
|
|
|
|
if( inter.vertexColor == SVC_IGNORE )
|
|
|
|
|
{
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// RB: this is a bit hacky: use additive blending to blend the normals
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, false, useIBL, false );
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
case SL_DIFFUSE:
|
|
|
|
|
{
|
|
|
|
|
// ignore stage that fails the condition
|
|
|
|
|
if( !surfaceRegs[ surfaceStage->conditionRegister ] )
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// draw any previous interaction
|
|
|
|
|
if( inter.diffuseImage != NULL )
|
|
|
|
|
{
|
2020-05-15 14:25:36 +00:00
|
|
|
|
#if BLEND_NORMALS
|
|
|
|
|
if( inter.vertexColor == SVC_IGNORE )
|
|
|
|
|
{
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// RB: this is a bit hacky: use additive blending to blend the normals
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, false, useIBL, false );
|
2015-12-24 15:43:02 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
case SL_SPECULAR:
|
|
|
|
|
{
|
|
|
|
|
// ignore stage that fails the condition
|
|
|
|
|
if( !surfaceRegs[ surfaceStage->conditionRegister ] )
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// draw any previous interaction
|
|
|
|
|
if( inter.specularImage != NULL )
|
|
|
|
|
{
|
2020-05-15 14:25:36 +00:00
|
|
|
|
#if BLEND_NORMALS
|
|
|
|
|
if( inter.vertexColor == SVC_IGNORE )
|
|
|
|
|
{
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// RB: this is a bit hacky: use additive blending to blend the normals
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, false, useIBL, false );
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
// draw the final interaction
|
2020-05-15 14:25:36 +00:00
|
|
|
|
#if BLEND_NORMALS
|
|
|
|
|
if( inter.vertexColor == SVC_IGNORE )
|
|
|
|
|
{
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// RB: this is a bit hacky: use additive blending to blend the normals
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-04-16 16:08:50 +00:00
|
|
|
|
DrawSingleInteraction( &inter, false, useIBL, false );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-14 15:55:53 +00:00
|
|
|
|
// disable blending
|
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
|
2015-12-24 15:43:02 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-10 13:27:31 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-18 22:21:53 +00:00
|
|
|
|
if( fillGbuffer )
|
2015-12-31 17:11:34 +00:00
|
|
|
|
{
|
2020-05-15 14:25:36 +00:00
|
|
|
|
// go back to main render target
|
2016-01-18 22:21:53 +00:00
|
|
|
|
if( hdrIsActive )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.hdrFBO->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Framebuffer::Unbind();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-18 22:21:53 +00:00
|
|
|
|
renderProgManager.Unbind();
|
2020-05-14 15:55:53 +00:00
|
|
|
|
|
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
renderLog.CloseMainBlock();
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( drawSurfs == NULL )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
RENDERLOG_PRINTF( "---------- RB_StencilShadowPass ----------\n" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderProgManager.BindShader_Shadow();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
uint64 glState = 0;
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_PolygonOffset( r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat() );
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
// Two Sided Stencil reduces two draw calls to one for slightly faster shadows
|
|
|
|
|
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 |
|
|
|
|
|
GLS_CULL_TWOSIDED );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-04 23:21:29 +00:00
|
|
|
|
pc.cpuShadowMicroSec += end - start;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentScissor = drawSurf->scissorRect;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentSpace = drawSurf->space;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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.
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
const bool renderZPass = ( drawSurf->renderZFail == 0 ) || r_forceZPassStencilShadows.GetBool();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-03 19:14:28 +00:00
|
|
|
|
DrawStencilShadowPass( drawSurf, renderZPass );
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// cleanup the shadow specific rendering state
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2019-11-08 19:09:57 +00:00
|
|
|
|
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_FRONTSIDED );
|
2019-11-11 19:27:44 +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
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Stencil Select", colorPink );
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentScissor = vLight->scissorRect;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// clear stencil buffer to 0 (not drawable)
|
|
|
|
|
uint64 glStateMinusStencil = GL_GetCurrentStateMinusStencil();
|
2019-11-08 19:09:57 +00:00
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// set the depthbounds
|
|
|
|
|
GL_DepthBoundsTest( vLight->scissorRect.zmin, vLight->scissorRect.zmax );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GL_State(
|
|
|
|
|
GLS_COLORMASK |
|
|
|
|
|
GLS_ALPHAMASK |
|
|
|
|
|
GLS_CULL_TWOSIDED |
|
|
|
|
|
GLS_DEPTHMASK |
|
|
|
|
|
GLS_DEPTHFUNC_LESS |
|
|
|
|
|
GLS_STENCIL_FUNC_ALWAYS |
|
2019-11-08 19:09:57 +00:00
|
|
|
|
GLS_STENCIL_OP_FAIL_KEEP | GLS_STENCIL_OP_ZFAIL_REPLACE | GLS_STENCIL_OP_PASS_ZERO |
|
|
|
|
|
GLS_BACK_STENCIL_OP_FAIL_KEEP | GLS_BACK_STENCIL_OP_ZFAIL_ZERO | GLS_BACK_STENCIL_OP_PASS_REPLACE |
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GLS_STENCIL_MAKE_REF( STENCIL_SHADOW_TEST_VALUE ) |
|
|
|
|
|
GLS_STENCIL_MAKE_MASK( STENCIL_SHADOW_MASK_VALUE ) );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderProgManager.BindShader_Depth();
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &zeroOneCubeSurface );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// reset stencil state
|
2019-11-08 19:09:57 +00:00
|
|
|
|
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_FRONTSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderProgManager.Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// unset the depthbounds
|
|
|
|
|
GL_DepthBoundsTest( 0.0f, 0.0f );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
scaleX = 2.0f / ( maxs[0] - mins[0] );
|
|
|
|
|
scaleY = 2.0f / ( maxs[1] - mins[1] );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
offsetX = -0.5f * ( maxs[0] + mins[0] ) * scaleX;
|
|
|
|
|
offsetY = -0.5f * ( maxs[1] + mins[1] ) * scaleY;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
scaleZ = 1.0f / ( maxs[2] - mins[2] );
|
|
|
|
|
offsetZ = -mins[2] * scaleZ;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
sideN = dir.Cross( up );
|
|
|
|
|
sideN.Normalize();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
upN = sideN.Cross( dir );
|
|
|
|
|
upN.Normalize();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
dirN = dir;
|
|
|
|
|
dirN.Normalize();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( drawSurfs == NULL )
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
RENDERLOG_PRINTF( "---------- RB_ShadowMapPass( side = %i ) ----------\n", side );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
renderProgManager.BindShader_Depth();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
uint64 glState = 0;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +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
|
2014-05-11 20:30:01 +00:00
|
|
|
|
GL_State( glState | GLS_POLYGON_OFFSET );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 20:30:01 +00:00
|
|
|
|
switch( r_shadowMapOccluderFacing.GetInteger() )
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
2019-11-08 19:09:57 +00:00
|
|
|
|
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_FRONTSIDED );
|
2014-05-11 20:30:01 +00:00
|
|
|
|
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
|
|
|
|
|
break;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 20:30:01 +00:00
|
|
|
|
case 1:
|
2019-11-08 19:09:57 +00:00
|
|
|
|
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_BACKSIDED );
|
2014-05-11 20:30:01 +00:00
|
|
|
|
GL_PolygonOffset( -r_shadowMapPolygonFactor.GetFloat(), -r_shadowMapPolygonOffset.GetFloat() );
|
|
|
|
|
break;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 20:30:01 +00:00
|
|
|
|
default:
|
2019-11-08 19:09:57 +00:00
|
|
|
|
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_TWOSIDED );
|
2014-05-11 20:30:01 +00:00
|
|
|
|
GL_PolygonOffset( r_shadowMapPolygonFactor.GetFloat(), r_shadowMapPolygonOffset.GetFloat() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix lightProjectionRenderMatrix;
|
|
|
|
|
idRenderMatrix lightViewRenderMatrix;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( vLight->parallel && side >= 0 )
|
|
|
|
|
{
|
|
|
|
|
assert( side >= 0 && side < 6 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// original light direction is from surface to light origin
|
|
|
|
|
idVec3 lightDir = -vLight->lightCenter;
|
|
|
|
|
if( lightDir.Normalize() == 0.0f )
|
|
|
|
|
{
|
|
|
|
|
lightDir[2] = -1.0f;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idMat3 rotation = lightDir.ToMat3();
|
|
|
|
|
//idAngles angles = lightDir.ToAngles();
|
|
|
|
|
//idMat3 rotation = angles.ToMat3();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
const idVec3 viewDir = viewDef->renderView.viewaxis[0];
|
|
|
|
|
const idVec3 viewPos = viewDef->renderView.vieworg;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idBounds lightBounds;
|
|
|
|
|
lightBounds.Clear();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
ALIGNTYPE16 frustumCorners_t corners;
|
|
|
|
|
idRenderMatrix::GetFrustumCorners( corners, vLight->inverseBaseLightProject, bounds_zeroOneCube );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
lightViewRenderMatrix.TransformPoint( point, transf );
|
|
|
|
|
transf[0] /= transf[3];
|
|
|
|
|
transf[1] /= transf[3];
|
|
|
|
|
transf[2] /= transf[3];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
lightBounds.AddPoint( transf.ToVec3() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// '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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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" );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// splitFrustumCorners in global space
|
|
|
|
|
ALIGNTYPE16 frustumCorners_t splitFrustumCorners;
|
|
|
|
|
idRenderMatrix::GetFrustumCorners( splitFrustumCorners, splitFrustumInverse, bounds_unitCube );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
#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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
splitFrustumBounds.AddPoint( point.ToVec3() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idVec3 center = splitFrustumBounds.GetCenter();
|
|
|
|
|
float radius = splitFrustumBounds.GetRadius( center );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
//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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix lightViewProjectionRenderMatrix;
|
|
|
|
|
idRenderMatrix::Multiply( lightProjectionRenderMatrix, lightViewRenderMatrix, lightViewProjectionRenderMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// 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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
lightViewRenderMatrix.TransformPoint( point, transf );
|
|
|
|
|
transf[0] /= transf[3];
|
|
|
|
|
transf[1] /= transf[3];
|
|
|
|
|
transf[2] /= transf[3];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
cropBounds.AddPoint( transf.ToVec3() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// 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];
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( cropBounds[0][1] < lightBounds[0][1] )
|
|
|
|
|
{
|
|
|
|
|
cropBounds[0][1] = lightBounds[0][1];
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( cropBounds[1][0] > lightBounds[1][0] )
|
|
|
|
|
{
|
|
|
|
|
cropBounds[1][0] = lightBounds[1][0];
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( cropBounds[1][1] > lightBounds[1][1] )
|
|
|
|
|
{
|
|
|
|
|
cropBounds[1][1] = lightBounds[1][1];
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
cropBounds[0][2] = lightBounds[0][2];
|
|
|
|
|
cropBounds[1][2] = lightBounds[1][2];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
//float cropMatrix[16];
|
|
|
|
|
//MatrixCrop(cropMatrix, cropBounds[0], cropBounds[1]);
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
//idRenderMatrix cropRenderMatrix;
|
|
|
|
|
//idRenderMatrix::Transpose( *( idRenderMatrix* )cropMatrix, cropRenderMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
//idRenderMatrix tmp = lightProjectionRenderMatrix;
|
|
|
|
|
//idRenderMatrix::Multiply( cropRenderMatrix, tmp, lightProjectionRenderMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// FIXME OPTIMIZE no memset
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
float viewMatrix[16];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idVec3 vec;
|
|
|
|
|
idVec3 origin = vLight->globalLightOrigin;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// 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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
viewMatrix[3] = 0;
|
|
|
|
|
viewMatrix[7] = 0;
|
|
|
|
|
viewMatrix[11] = 0;
|
|
|
|
|
viewMatrix[15] = 1;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// from world space to light origin, looking down the X axis
|
|
|
|
|
float unflippedLightViewMatrix[16];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// from world space to OpenGL view space, looking down the negative Z axis
|
|
|
|
|
float lightViewMatrix[16];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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
|
|
|
|
|
};
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
memcpy( unflippedLightViewMatrix, viewMatrix, sizeof( unflippedLightViewMatrix ) );
|
|
|
|
|
R_MatrixMultiply( viewMatrix, s_flipMatrix, lightViewMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix::Transpose( *( idRenderMatrix* )lightViewMatrix, lightViewRenderMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// set up 90 degree projection matrix
|
|
|
|
|
const float zNear = 4;
|
|
|
|
|
const float fov = r_shadowMapFrustumFOV.GetFloat();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
float ymax = zNear * tan( fov * idMath::PI / 360.0f );
|
|
|
|
|
float ymin = -ymax;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
float xmax = zNear * tan( fov * idMath::PI / 360.0f );
|
|
|
|
|
float xmin = -xmax;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
const float width = xmax - xmin;
|
|
|
|
|
const float height = ymax - ymin;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// from OpenGL view space to OpenGL NDC ( -1 : 1 in XYZ )
|
|
|
|
|
float lightProjectionMatrix[16];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// 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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
lightProjectionMatrix[0 * 4 + 3] = 0.0f;
|
|
|
|
|
lightProjectionMatrix[1 * 4 + 3] = 0.0f;
|
|
|
|
|
lightProjectionMatrix[2 * 4 + 3] = -1.0f;
|
|
|
|
|
lightProjectionMatrix[3 * 4 + 3] = 0.0f;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix::Transpose( *( idRenderMatrix* )lightProjectionMatrix, lightProjectionRenderMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
shadowV[0] = lightViewRenderMatrix;
|
|
|
|
|
shadowP[0] = lightProjectionRenderMatrix;
|
2014-05-10 12:40:01 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 20:30:01 +00:00
|
|
|
|
globalFramebuffers.shadowFBO[vLight->shadowLOD]->Check();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 20:30:01 +00:00
|
|
|
|
GL_ViewportAndScissor( 0, 0, shadowMapResolutions[vLight->shadowLOD], shadowMapResolutions[vLight->shadowLOD] );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
glClear( GL_DEPTH_BUFFER_BIT );
|
2018-10-03 19:14:28 +00:00
|
|
|
|
#endif
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
for( const drawSurf_t* drawSurf = drawSurfs; drawSurf != NULL; drawSurf = drawSurf->nextOnLight )
|
|
|
|
|
{
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
#if 1
|
|
|
|
|
// make sure the shadow occluder geometry is done
|
|
|
|
|
if( drawSurf->shadowVolumeState != SHADOWVOLUME_DONE )
|
|
|
|
|
{
|
|
|
|
|
assert( drawSurf->shadowVolumeState == SHADOWVOLUME_UNFINISHED || drawSurf->shadowVolumeState == SHADOWVOLUME_DONE );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
uint64 start = Sys_Microseconds();
|
|
|
|
|
while( drawSurf->shadowVolumeState == SHADOWVOLUME_UNFINISHED )
|
|
|
|
|
{
|
|
|
|
|
Sys_Yield();
|
|
|
|
|
}
|
|
|
|
|
uint64 end = Sys_Microseconds();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-04 23:21:29 +00:00
|
|
|
|
pc.cpuShadowMicroSec += end - start;
|
2014-05-10 12:40:01 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( drawSurf->numIndexes == 0 )
|
|
|
|
|
{
|
|
|
|
|
continue; // a job may have created an empty shadow geometry
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix modelToLightRenderMatrix;
|
|
|
|
|
idRenderMatrix::Multiply( lightViewRenderMatrix, modelRenderMatrix, modelToLightRenderMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
idRenderMatrix clipMVP;
|
|
|
|
|
idRenderMatrix::Multiply( lightProjectionRenderMatrix, modelToLightRenderMatrix, clipMVP );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( vLight->parallel )
|
|
|
|
|
{
|
|
|
|
|
idRenderMatrix MVP;
|
|
|
|
|
idRenderMatrix::Multiply( renderMatrix_clipSpaceToWindowSpace, clipMVP, MVP );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
RB_SetMVP( MVP );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RB_SetMVP( clipMVP );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +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() );
|
|
|
|
|
*/
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentSpace = drawSurf->space;
|
2014-05-10 12:40:01 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
bool didDraw = false;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
const idMaterial* shader = drawSurf->material;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// get the expressions for conditionals / color / texcoords
|
|
|
|
|
const float* regs = drawSurf->shaderRegisters;
|
|
|
|
|
idVec4 color( 0, 0, 0, 1 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
uint64 surfGLState = 0;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// 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
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
if( !pStage->hasAlphaTest )
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// check the stage enable condition
|
|
|
|
|
if( regs[ pStage->conditionRegister ] == 0 )
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// if we at least tried to draw an alpha tested stage,
|
|
|
|
|
// we won't draw the opaque surface
|
|
|
|
|
didDraw = true;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// set the alpha modulate
|
|
|
|
|
color[3] = regs[ pStage->color.registers[3] ];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// skip the entire stage if alpha would be black
|
|
|
|
|
if( color[3] <= 0.0f )
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
uint64 stageGLState = surfGLState;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// set privatePolygonOffset if necessary
|
|
|
|
|
if( pStage->privatePolygonOffset )
|
|
|
|
|
{
|
|
|
|
|
GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * pStage->privatePolygonOffset );
|
|
|
|
|
stageGLState |= GLS_POLYGON_OFFSET;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
GL_Color( color );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
GL_State( stageGLState );
|
|
|
|
|
idVec4 alphaTestValue( regs[ pStage->alphaTestRegister ] );
|
|
|
|
|
SetFragmentParm( RENDERPARM_ALPHA_TEST, alphaTestValue.ToFloatPtr() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
if( drawSurf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_TextureVertexColorSkinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_TextureVertexColor();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
RB_SetVertexColorParms( SVC_IGNORE );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// bind the texture
|
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
pStage->texture.image->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// set texture matrix and texGens
|
2017-09-03 21:17:44 +00:00
|
|
|
|
PrepareStageTexturing( pStage, drawSurf );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// draw it
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( drawSurf );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
// clean up
|
2017-09-03 21:17:44 +00:00
|
|
|
|
FinishStageTexturing( pStage, drawSurf );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
if( !didDraw )
|
|
|
|
|
{
|
|
|
|
|
if( drawSurf->jointCache )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_DepthSkinned();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Depth();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
GL_State( GLS_DEFAULT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-11 12:36:51 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_ALPHA_TEST, vec4_zero.ToFloatPtr() );
|
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
|
|
|
|
{
|
2020-05-09 14:48:55 +00:00
|
|
|
|
if( r_skipInteractions.GetBool() || viewDef->viewLights == NULL )
|
2012-11-28 15:47:07 +00:00
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.OpenMainBlock( MRB_DRAW_INTERACTIONS );
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Render_Interactions", colorYellow );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
const bool useLightDepthBounds = r_useLightDepthBounds.GetBool() && !r_useShadowMapping.GetBool();
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
const idMaterial* lightShader = vLight->lightShader;
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( lightShader->GetName(), colorMdGrey );
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( vLight->localInteractions != NULL )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Local Light Interactions", colorPurple );
|
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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( vLight->globalInteractions != NULL )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Global Light Interactions", colorPurple );
|
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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
// 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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( vLight->globalShadows != NULL )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Global Light Shadows", colorBrown );
|
2017-09-03 21:17:44 +00:00
|
|
|
|
StencilShadowPass( vLight->globalShadows, vLight );
|
2014-05-10 12:40:01 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( vLight->localInteractions != NULL )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Local Light Interactions", colorPurple );
|
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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( vLight->localShadows != NULL )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Local Light Shadows", colorBrown );
|
2017-09-03 21:17:44 +00:00
|
|
|
|
StencilShadowPass( vLight->localShadows, vLight );
|
2014-05-10 12:40:01 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2014-05-10 12:40:01 +00:00
|
|
|
|
if( vLight->globalInteractions != NULL )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Global Light Interactions", colorPurple );
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( vLight->translucentInteractions != NULL && !r_skipTranslucent.GetBool() )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Translucent Interactions", colorCyan );
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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.
|
2019-11-11 19:27:44 +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.
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
RenderInteractions( vLight->translucentInteractions, vLight, GLS_DEPTHFUNC_LESS, false, false );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// disable stencil shadow test
|
|
|
|
|
GL_State( GLS_DEFAULT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// unbind texture units
|
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Render_GenericShaderPasses", colorBlue );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( !shader->HasAmbient() )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( shader->IsPortalSky() )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( shader->SuppressInSubview() )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( shader->GetName(), colorMdGrey );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-09 12:57:48 +00:00
|
|
|
|
const viewEntity_t* space = currentSpace;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-09 12:57:48 +00:00
|
|
|
|
currentScissor = surf->scissorRect;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// set face culling appropriately
|
2018-11-01 15:30:05 +00:00
|
|
|
|
uint64 cullMode;
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( surf->space->isGuiSurface )
|
|
|
|
|
{
|
2018-11-01 15:30:05 +00:00
|
|
|
|
cullMode = GLS_CULL_TWOSIDED;
|
2012-11-28 15:47:07 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-11-01 15:30:05 +00:00
|
|
|
|
switch( shader->GetCullType() )
|
|
|
|
|
{
|
|
|
|
|
case CT_TWO_SIDED:
|
|
|
|
|
cullMode = GLS_CULL_TWOSIDED;
|
|
|
|
|
break;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
case CT_BACK_SIDED:
|
|
|
|
|
cullMode = GLS_CULL_BACKSIDED;
|
|
|
|
|
break;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
case CT_FRONT_SIDED:
|
|
|
|
|
default:
|
|
|
|
|
cullMode = GLS_CULL_FRONTSIDED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
uint64 surfGLState = surf->extraGLState | cullMode;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// set polygon offset if necessary
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( shader->TestMaterialFlag( MF_POLYGONOFFSET ) )
|
|
|
|
|
{
|
2019-01-20 12:32:22 +00:00
|
|
|
|
GL_PolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
|
2019-10-31 16:33:19 +00:00
|
|
|
|
surfGLState = GLS_POLYGON_OFFSET;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
for( int stage = 0; stage < shader->GetNumStages(); stage++ )
|
|
|
|
|
{
|
|
|
|
|
const shaderStage_t* pStage = shader->GetStage( stage );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Custom Renderproc Shader Stage", colorRed );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_State( stageGLState );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-13 16:34:29 +00:00
|
|
|
|
renderProgManager.BindProgram( newStage->glslProgram );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +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() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// draw it
|
2017-09-09 12:57:48 +00:00
|
|
|
|
DrawElementsWithCounters( surf );
|
2019-11-11 19:27:44 +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() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
renderProgManager.Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
//--------------------------
|
|
|
|
|
//
|
|
|
|
|
// old style stages
|
|
|
|
|
//
|
|
|
|
|
//--------------------------
|
2019-11-11 19:27:44 +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] ];
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
stageVertexColor_t svc = pStage->vertexColor;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Standard Shader Stage", colorGreen );
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_Color( color );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
RB_SetVertexColorParms( svc );
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2019-10-31 16:33:19 +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
|
|
|
|
stageGLState |= GLS_POLYGON_OFFSET;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// set the state
|
|
|
|
|
GL_State( stageGLState );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-09 12:57:48 +00:00
|
|
|
|
PrepareStageTexturing( pStage, surf );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// draw it
|
2017-09-09 12:57:48 +00:00
|
|
|
|
DrawElementsWithCounters( surf );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-09 12:57:48 +00:00
|
|
|
|
FinishStageTexturing( pStage, surf );
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_Color( 1.0f, 1.0f, 1.0f );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-11 18:00:20 +00:00
|
|
|
|
// disable stencil shadow test
|
|
|
|
|
GL_State( GLS_DEFAULT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-11 18:00:20 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentScissor = drawSurf->scissorRect;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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] );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentSpace = drawSurf->space;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( vLight->lightShader->GetName(), colorPink );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
const idMaterial* lightShader = vLight->lightShader;
|
|
|
|
|
const float* regs = vLight->shaderRegisters;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// texture 1 will get the falloff texture
|
|
|
|
|
GL_SelectTexture( 1 );
|
|
|
|
|
vLight->falloffImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// texture 0 will get the projected texture
|
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderProgManager.BindShader_BlendLight();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
for( int i = 0; i < lightShader->GetNumStages(); i++ )
|
|
|
|
|
{
|
|
|
|
|
const shaderStage_t* stage = lightShader->GetStage( i );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( !regs[ stage->conditionRegister ] )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_State( GLS_DEPTHMASK | stage->drawStateBits | GLS_DEPTHFUNC_EQUAL );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
stage->texture.image->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentScissor = drawSurf->scissorRect;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentSpace = ( inverseBaseLightProject == NULL ) ? drawSurf->space : NULL;
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( vLight->lightShader->GetName(), colorCyan );
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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] ];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_Color( lightColor );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// calculate the falloff planes
|
|
|
|
|
float a;
|
2019-11-11 19:27:44 +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];
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// texture 0 is the falloff image
|
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->fogImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// texture 1 is the entering plane fade correction
|
|
|
|
|
GL_SelectTexture( 1 );
|
|
|
|
|
globalImages->fogEnterImage->Bind();
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
const float FOG_SCALE = 0.001f;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
idPlane fogPlanes[4];
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_LESS | GLS_CULL_BACKSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
zeroOneCubeSurface.space = &viewDef->worldSpace;
|
|
|
|
|
zeroOneCubeSurface.scissorRect = viewDef->scissor;
|
|
|
|
|
T_BasicFog( &zeroOneCubeSurface, fogPlanes, &vLight->inverseBaseLightProject );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2019-11-08 19:09:57 +00:00
|
|
|
|
GL_State( ( glStateBits & ~( GLS_CULL_MASK ) ) | GLS_CULL_FRONTSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderProgManager.Unbind();
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2020-05-16 15:40:30 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderLog.OpenMainBlock( MRB_FOG_ALL_LIGHTS );
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Render_FogAllLights", colorBlue );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-13 23:59:41 +00:00
|
|
|
|
// calculate the average scene luminance
|
|
|
|
|
globalFramebuffers.hdr64FBO->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-13 23:59:41 +00:00
|
|
|
|
luminance = ( color.x * LUMINANCE_SRGB.x + color.y * LUMINANCE_SRGB.y + color.z * LUMINANCE_SRGB.z ) + 0.0001f;
|
|
|
|
|
if( luminance > maxLuminance )
|
|
|
|
|
{
|
|
|
|
|
maxLuminance = luminance;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-13 23:59:41 +00:00
|
|
|
|
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
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
deltaTime = curTime - hdrTime;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 ) );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
hdrTime = curTime;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
Framebuffer::Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
int screenWidth = renderSystem->GetWidth();
|
|
|
|
|
int screenHeight = renderSystem->GetHeight();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// set the window clipping
|
|
|
|
|
GL_Viewport( 0, 0, screenWidth, screenHeight );
|
|
|
|
|
GL_Scissor( 0, 0, screenWidth, screenHeight );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-21 10:39:19 +00:00
|
|
|
|
GL_SelectTexture( 1 );
|
|
|
|
|
globalImages->heatmap7Image->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-21 10:39:19 +00:00
|
|
|
|
if( r_hdrDebug.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_HDRDebug();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_Tonemap();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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() ) );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-17 11:49:04 +00:00
|
|
|
|
float exposureOffset = Lerp( -0.01f, 0.01f, idMath::ClampFloat( 0.0, 1.0, r_exposure.GetFloat() ) );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-17 11:49:04 +00:00
|
|
|
|
screenCorrectionParm[0] = 0.015f + exposureOffset;
|
|
|
|
|
screenCorrectionParm[1] = 0.005f;
|
|
|
|
|
screenCorrectionParm[2] = 1;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-17 11:49:04 +00:00
|
|
|
|
// 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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// Draw
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
renderProgManager.Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
GL_State( GLS_DEFAULT );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
RENDERLOG_PRINTF( "---------- RB_Bloom( avg = %f, max = %f, key = %f ) ----------\n", hdrAverageLuminance, hdrMaxLuminance, hdrKey );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// BRIGHTPASS
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
//GL_CheckErrors();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
//Framebuffer::Unbind();
|
|
|
|
|
//globalFramebuffers.hdrQuarterFBO->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GL_State( /*GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO |*/ GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
int screenWidth = renderSystem->GetWidth();
|
|
|
|
|
int screenHeight = renderSystem->GetHeight();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// set the window clipping
|
|
|
|
|
GL_Viewport( 0, 0, screenWidth / 4, screenHeight / 4 );
|
|
|
|
|
GL_Scissor( 0, 0, screenWidth / 4, screenHeight / 4 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
globalFramebuffers.bloomRenderFBO[ 0 ]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
if( r_useHDR.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
globalImages->currentRenderHDRImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
RENDERLOG_PRINTF( "Resolve to %i x %i buffer\n", w, h );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// resolve the screen
|
|
|
|
|
globalImages->currentRenderImage->CopyFramebuffer( x, y, w, h );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
renderProgManager.BindShader_Brightpass();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// Draw
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// BLOOM PING PONG rendering
|
|
|
|
|
renderProgManager.BindShader_HDRGlareChromatic();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
int j;
|
|
|
|
|
for( j = 0; j < r_hdrGlarePasses.GetInteger(); j++ )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.bloomRenderFBO[( j + 1 ) % 2 ]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-06 21:37:16 +00:00
|
|
|
|
globalImages->bloomRenderImage[j % 2]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2015-12-20 11:28:46 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// add filtered glare back to main context
|
|
|
|
|
Framebuffer::Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
ResetViewportAndScissorToDefaultCamera( _viewDef );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
renderProgManager.BindShader_Screen();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-06 21:37:16 +00:00
|
|
|
|
globalImages->bloomRenderImage[( j + 1 ) % 2]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
renderProgManager.Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
GL_State( GLS_DEFAULT );
|
|
|
|
|
}
|
2016-01-02 18:28:49 +00:00
|
|
|
|
|
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef, bool downModulateScreen )
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-13 23:59:41 +00:00
|
|
|
|
if( r_useSSAO.GetInteger() <= 0 )
|
2016-01-02 18:28:49 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
// skip this in subviews because it is very expensive
|
2017-09-03 21:17:44 +00:00
|
|
|
|
if( _viewDef->isSubview )
|
2016-01-02 18:28:49 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenMainBlock( MRB_SSAO_PASS );
|
|
|
|
|
renderLog.OpenBlock( "Render_SSAO", colorBlue );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentSpace = &viewDef->worldSpace;
|
|
|
|
|
RB_SetMVP( viewDef->worldSpace.mvp );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 12:38:49 +00:00
|
|
|
|
const bool hdrIsActive = ( r_useHDR.GetBool() && globalFramebuffers.hdrFBO != NULL && globalFramebuffers.hdrFBO->IsBound() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-02 18:28:49 +00:00
|
|
|
|
int screenWidth = renderSystem->GetWidth();
|
|
|
|
|
int screenHeight = renderSystem->GetHeight();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 12:38:49 +00:00
|
|
|
|
// build hierarchical depth buffer
|
|
|
|
|
if( r_useHierarchicalDepthBuffer.GetBool() )
|
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Render_HiZ", colorDkGrey );
|
|
|
|
|
|
2016-01-09 12:38:49 +00:00
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionMinify();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-14 15:55:53 +00:00
|
|
|
|
GL_Color( 0, 0, 0, 1 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 12:38:49 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2016-01-09 15:23:49 +00:00
|
|
|
|
//globalImages->currentDepthImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-14 15:55:53 +00:00
|
|
|
|
globalFramebuffers.csDepthFBO[i]->Bind();
|
|
|
|
|
|
2016-01-09 12:38:49 +00:00
|
|
|
|
GL_Viewport( 0, 0, width, height );
|
|
|
|
|
GL_Scissor( 0, 0, width, height );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-14 15:55:53 +00:00
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 12:38:49 +00:00
|
|
|
|
glClear( GL_COLOR_BUFFER_BIT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 15:23:49 +00:00
|
|
|
|
if( i == 0 )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionReconstructCSZ();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 15:23:49 +00:00
|
|
|
|
globalImages->currentDepthImage->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionMinify();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 15:23:49 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->hierarchicalZbufferImage->Bind();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 15:23:49 +00:00
|
|
|
|
float jitterTexScale[4];
|
|
|
|
|
jitterTexScale[0] = i - 1;
|
|
|
|
|
jitterTexScale[1] = 0;
|
|
|
|
|
jitterTexScale[2] = 0;
|
|
|
|
|
jitterTexScale[3] = 0;
|
|
|
|
|
SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
|
2020-05-03 11:39:38 +00:00
|
|
|
|
|
2016-01-09 12:38:49 +00:00
|
|
|
|
float screenCorrectionParm[4];
|
|
|
|
|
screenCorrectionParm[0] = 1.0f / width;
|
|
|
|
|
screenCorrectionParm[1] = 1.0f / height;
|
|
|
|
|
screenCorrectionParm[2] = width;
|
|
|
|
|
screenCorrectionParm[3] = height;
|
|
|
|
|
SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2016-01-09 12:38:49 +00:00
|
|
|
|
}
|
2020-05-03 11:39:38 +00:00
|
|
|
|
|
|
|
|
|
renderLog.CloseBlock();
|
2016-01-09 12:38:49 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-02 18:28:49 +00:00
|
|
|
|
// set the window clipping
|
2020-05-10 10:58:14 +00:00
|
|
|
|
int aoScreenWidth = globalFramebuffers.ambientOcclusionFBO[0]->GetWidth();
|
|
|
|
|
int aoScreenHeight = globalFramebuffers.ambientOcclusionFBO[0]->GetHeight();
|
|
|
|
|
|
|
|
|
|
GL_Viewport( 0, 0, aoScreenWidth, aoScreenHeight );
|
|
|
|
|
GL_Scissor( 0, 0, aoScreenWidth, aoScreenHeight );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-14 15:55:53 +00:00
|
|
|
|
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
if( downModulateScreen )
|
2016-01-08 18:30:21 +00:00
|
|
|
|
{
|
2020-04-25 16:30:40 +00:00
|
|
|
|
if( r_ssaoFiltering.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.ambientOcclusionFBO[0]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
glClearColor( 0, 0, 0, 0 );
|
|
|
|
|
glClear( GL_COLOR_BUFFER_BIT );
|
|
|
|
|
|
|
|
|
|
renderProgManager.BindShader_AmbientOcclusion();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( r_ssaoDebug.GetInteger() <= 0 )
|
|
|
|
|
{
|
|
|
|
|
GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_ALPHAMASK | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( hdrIsActive )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.hdrFBO->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Framebuffer::Unbind();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionAndOutput();
|
|
|
|
|
}
|
2016-01-08 18:30:21 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-04-25 16:30:40 +00:00
|
|
|
|
globalFramebuffers.ambientOcclusionFBO[0]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-14 15:55:53 +00:00
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
|
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
glClearColor( 0, 0, 0, 0 );
|
|
|
|
|
glClear( GL_COLOR_BUFFER_BIT );
|
|
|
|
|
|
|
|
|
|
if( r_ssaoFiltering.GetBool() )
|
2016-01-09 12:38:49 +00:00
|
|
|
|
{
|
2020-04-25 16:30:40 +00:00
|
|
|
|
renderProgManager.BindShader_AmbientOcclusion();
|
2016-01-09 12:38:49 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-04-25 16:30:40 +00:00
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionAndOutput();
|
2016-01-09 12:38:49 +00:00
|
|
|
|
}
|
2016-01-08 18:30:21 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-02 18:28:49 +00:00
|
|
|
|
float screenCorrectionParm[4];
|
2020-05-10 10:58:14 +00:00
|
|
|
|
screenCorrectionParm[0] = float( screenWidth ) / aoScreenWidth;
|
|
|
|
|
screenCorrectionParm[1] = float( screenHeight ) / aoScreenHeight;
|
|
|
|
|
screenCorrectionParm[2] = 0.0f;
|
|
|
|
|
screenCorrectionParm[3] = 1.0f;
|
2016-01-02 18:28:49 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-10 10:58:14 +00:00
|
|
|
|
// window coord to 0.0 to 1.0 conversion
|
|
|
|
|
float windowCoordParm[4];
|
|
|
|
|
windowCoordParm[0] = 1.0f / aoScreenWidth;
|
|
|
|
|
windowCoordParm[1] = 1.0f / aoScreenHeight;
|
|
|
|
|
windowCoordParm[2] = aoScreenWidth;
|
|
|
|
|
windowCoordParm[3] = aoScreenHeight;
|
|
|
|
|
SetFragmentParm( RENDERPARM_WINDOWCOORD, windowCoordParm ); // rpWindowCoord
|
|
|
|
|
|
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" );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-02 22:59:44 +00:00
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-10 13:05:46 +00:00
|
|
|
|
const float jitterSampleScale = 1.0f;
|
|
|
|
|
|
|
|
|
|
float jitterTexScale[4];
|
|
|
|
|
jitterTexScale[0] = r_shadowMapJitterScale.GetFloat() * jitterSampleScale; // TODO shadow buffer size fraction shadowMapSize / maxShadowMapSize
|
|
|
|
|
jitterTexScale[1] = r_shadowMapJitterScale.GetFloat() * jitterSampleScale;
|
|
|
|
|
jitterTexScale[2] = -r_shadowMapBiasScale.GetFloat();
|
|
|
|
|
jitterTexScale[3] = 0.0f;
|
|
|
|
|
SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
|
|
|
|
|
|
2016-01-02 22:59:44 +00:00
|
|
|
|
float jitterTexOffset[4];
|
2020-05-10 20:10:32 +00:00
|
|
|
|
jitterTexOffset[0] = 1.0f / globalImages->blueNoiseImage256->GetUploadWidth();
|
|
|
|
|
jitterTexOffset[1] = 1.0f / globalImages->blueNoiseImage256->GetUploadHeight();
|
2020-05-10 13:05:46 +00:00
|
|
|
|
|
2016-01-02 22:59:44 +00:00
|
|
|
|
if( r_shadowMapRandomizeJitter.GetBool() )
|
|
|
|
|
{
|
2020-05-10 13:05:46 +00:00
|
|
|
|
jitterTexOffset[2] = Sys_Milliseconds() / 1000.0f;
|
2020-05-10 20:10:32 +00:00
|
|
|
|
jitterTexOffset[3] = tr.frameCount % 256;
|
2016-01-02 22:59:44 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-05-10 13:05:46 +00:00
|
|
|
|
jitterTexOffset[2] = 0.0f;
|
|
|
|
|
jitterTexOffset[3] = 0.0f;
|
2016-01-02 22:59:44 +00:00
|
|
|
|
}
|
2020-05-10 13:05:46 +00:00
|
|
|
|
|
2016-01-02 22:59:44 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_JITTERTEXOFFSET, jitterTexOffset ); // rpJitterTexOffset
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-02 18:28:49 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->currentNormalsImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-02 18:28:49 +00:00
|
|
|
|
GL_SelectTexture( 1 );
|
2016-01-09 12:38:49 +00:00
|
|
|
|
if( r_useHierarchicalDepthBuffer.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
globalImages->hierarchicalZbufferImage->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
globalImages->currentDepthImage->Bind();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-10 13:05:46 +00:00
|
|
|
|
GL_SelectTexture( 2 );
|
|
|
|
|
globalImages->blueNoiseImage256->Bind();
|
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-08 18:30:21 +00:00
|
|
|
|
if( r_ssaoFiltering.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
float jitterTexScale[4];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-08 18:30:21 +00:00
|
|
|
|
// AO blur X
|
|
|
|
|
globalFramebuffers.ambientOcclusionFBO[1]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-08 18:30:21 +00:00
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionBlur();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-08 18:30:21 +00:00
|
|
|
|
// set axis parameter
|
|
|
|
|
jitterTexScale[0] = 1;
|
|
|
|
|
jitterTexScale[1] = 0;
|
|
|
|
|
jitterTexScale[2] = 0;
|
|
|
|
|
jitterTexScale[3] = 0;
|
|
|
|
|
SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-11 18:00:20 +00:00
|
|
|
|
GL_SelectTexture( 2 );
|
2016-01-08 18:30:21 +00:00
|
|
|
|
globalImages->ambientOcclusionImage[0]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-08 18:30:21 +00:00
|
|
|
|
// AO blur Y
|
2020-04-25 16:30:40 +00:00
|
|
|
|
if( downModulateScreen )
|
2016-01-08 18:30:21 +00:00
|
|
|
|
{
|
2020-04-25 16:30:40 +00:00
|
|
|
|
if( hdrIsActive )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.hdrFBO->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Framebuffer::Unbind();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( r_ssaoDebug.GetInteger() <= 0 )
|
|
|
|
|
{
|
|
|
|
|
GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
|
|
|
|
|
}
|
2016-01-08 18:30:21 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-04-25 16:30:40 +00:00
|
|
|
|
globalFramebuffers.ambientOcclusionFBO[0]->Bind();
|
2016-01-08 18:30:21 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-08 18:30:21 +00:00
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionBlurAndOutput();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-08 18:30:21 +00:00
|
|
|
|
// set axis parameter
|
|
|
|
|
jitterTexScale[0] = 0;
|
|
|
|
|
jitterTexScale[1] = 1;
|
|
|
|
|
jitterTexScale[2] = 0;
|
|
|
|
|
jitterTexScale[3] = 0;
|
|
|
|
|
SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-11 18:00:20 +00:00
|
|
|
|
GL_SelectTexture( 2 );
|
2016-01-08 18:30:21 +00:00
|
|
|
|
globalImages->ambientOcclusionImage[1]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2016-01-06 21:37:16 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-04-25 16:30:40 +00:00
|
|
|
|
if( !downModulateScreen )
|
|
|
|
|
{
|
|
|
|
|
// go back to main scene render target
|
|
|
|
|
if( hdrIsActive )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.hdrFBO->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Framebuffer::Unbind();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 10:58:14 +00:00
|
|
|
|
//
|
|
|
|
|
// reset state
|
|
|
|
|
//
|
2016-01-09 19:17:09 +00:00
|
|
|
|
renderProgManager.Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-10 10:58:14 +00:00
|
|
|
|
GL_Viewport( 0, 0, screenWidth, screenHeight );
|
|
|
|
|
GL_Scissor( 0, 0, screenWidth, screenHeight );
|
|
|
|
|
|
2016-01-09 19:17:09 +00:00
|
|
|
|
GL_State( GLS_DEFAULT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
renderLog.CloseMainBlock();
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
if( r_useSSGI.GetInteger() <= 0 )
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
// 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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
RENDERLOG_PRINTF( "---------- RB_SSGI() ----------\n" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
currentSpace = &viewDef->worldSpace;
|
|
|
|
|
RB_SetMVP( viewDef->worldSpace.mvp );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
const bool hdrIsActive = ( r_useHDR.GetBool() && globalFramebuffers.hdrFBO != NULL && globalFramebuffers.hdrFBO->IsBound() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
int screenWidth = renderSystem->GetWidth();
|
|
|
|
|
int screenHeight = renderSystem->GetHeight();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-10 16:20:38 +00:00
|
|
|
|
// set the window clipping
|
|
|
|
|
GL_Viewport( 0, 0, screenWidth, screenHeight );
|
|
|
|
|
GL_Scissor( 0, 0, screenWidth, screenHeight );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-10 16:20:38 +00:00
|
|
|
|
if( !hdrIsActive )
|
|
|
|
|
{
|
|
|
|
|
const idScreenRect& viewport = viewDef->viewport;
|
|
|
|
|
globalImages->currentRenderImage->CopyFramebuffer( viewport.x1, viewport.y1, viewport.GetWidth(), viewport.GetHeight() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
// build hierarchical depth buffer
|
|
|
|
|
if( r_useHierarchicalDepthBuffer.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionMinify();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
glClearColor( 0, 0, 0, 1 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
//globalImages->currentDepthImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
for( int i = 0; i < MAX_HIERARCHICAL_ZBUFFERS; i++ )
|
|
|
|
|
{
|
|
|
|
|
int width = globalFramebuffers.csDepthFBO[i]->GetWidth();
|
|
|
|
|
int height = globalFramebuffers.csDepthFBO[i]->GetHeight();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
GL_Viewport( 0, 0, width, height );
|
|
|
|
|
GL_Scissor( 0, 0, width, height );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
globalFramebuffers.csDepthFBO[i]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
glClear( GL_COLOR_BUFFER_BIT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
if( i == 0 )
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionReconstructCSZ();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
globalImages->currentDepthImage->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
renderProgManager.BindShader_AmbientOcclusionMinify();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->hierarchicalZbufferImage->Bind();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2016-01-09 21:24:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
// set the window clipping
|
|
|
|
|
GL_Viewport( 0, 0, screenWidth, screenHeight );
|
|
|
|
|
GL_Scissor( 0, 0, screenWidth, screenHeight );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-10 16:20:38 +00:00
|
|
|
|
if( r_ssgiFiltering.GetBool() )
|
2016-01-09 21:24:57 +00:00
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.ambientOcclusionFBO[0]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
if( hdrIsActive )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.hdrFBO->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Framebuffer::Unbind();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
renderProgManager.BindShader_DeepGBufferRadiosity();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +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-09 21:24:57 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
#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" );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
|
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->currentNormalsImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
GL_SelectTexture( 1 );
|
|
|
|
|
if( r_useHierarchicalDepthBuffer.GetBool() )
|
|
|
|
|
{
|
|
|
|
|
globalImages->hierarchicalZbufferImage->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
globalImages->currentDepthImage->Bind();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
GL_SelectTexture( 2 );
|
2016-01-10 22:47:16 +00:00
|
|
|
|
if( hdrIsActive )
|
|
|
|
|
{
|
|
|
|
|
globalImages->currentRenderHDRImage->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
globalImages->currentRenderImage->Bind();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2019-11-11 19:27:44 +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];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
// AO blur X
|
|
|
|
|
#if 1
|
|
|
|
|
globalFramebuffers.ambientOcclusionFBO[1]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-10 16:20:38 +00:00
|
|
|
|
renderProgManager.BindShader_DeepGBufferRadiosityBlur();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-11 18:00:20 +00:00
|
|
|
|
GL_SelectTexture( 2 );
|
2016-01-09 21:24:57 +00:00
|
|
|
|
globalImages->ambientOcclusionImage[0]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2016-01-09 21:24:57 +00:00
|
|
|
|
#endif
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
// AO blur Y
|
|
|
|
|
if( hdrIsActive )
|
|
|
|
|
{
|
|
|
|
|
globalFramebuffers.hdrFBO->Bind();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Framebuffer::Unbind();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-10 16:20:38 +00:00
|
|
|
|
renderProgManager.BindShader_DeepGBufferRadiosityBlurAndOutput();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-11 18:00:20 +00:00
|
|
|
|
GL_SelectTexture( 2 );
|
2016-01-09 21:24:57 +00:00
|
|
|
|
globalImages->ambientOcclusionImage[1]->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2016-01-09 21:24:57 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
renderProgManager.Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
GL_State( GLS_DEFAULT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
//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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
resolutionScale.SetCurrentGPUFrameTime( commonLocal.GetRendererGPUMicroseconds() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-02 15:53:36 +00:00
|
|
|
|
ResizeImages();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
renderLog.StartFrame();
|
|
|
|
|
GL_StartFrame();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
if( cmds->commandId == RC_NOP && !cmds->next )
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
if( renderSystem->GetStereo3DMode() != STEREO3D_OFF )
|
|
|
|
|
{
|
|
|
|
|
StereoRenderExecuteBackEndCommands( cmds );
|
|
|
|
|
renderLog.EndFrame();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
uint64 backEndStartTime = Sys_Microseconds();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
// needed for editor rendering
|
|
|
|
|
GL_SetDefaultState();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
for( ; cmds != NULL; cmds = ( const emptyCommand_t* )cmds->next )
|
|
|
|
|
{
|
|
|
|
|
switch( cmds->commandId )
|
|
|
|
|
{
|
|
|
|
|
case RC_NOP:
|
|
|
|
|
break;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
case RC_SET_BUFFER:
|
2018-11-04 18:57:53 +00:00
|
|
|
|
SetBuffer( cmds );
|
2018-10-06 15:21:49 +00:00
|
|
|
|
c_setBuffers++;
|
|
|
|
|
break;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
case RC_COPY_RENDER:
|
|
|
|
|
CopyRender( cmds );
|
|
|
|
|
c_copyRenders++;
|
|
|
|
|
break;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
case RC_POST_PROCESS:
|
2020-05-04 15:22:51 +00:00
|
|
|
|
{
|
|
|
|
|
// apply optional post processing
|
2018-10-06 15:21:49 +00:00
|
|
|
|
PostProcess( cmds );
|
|
|
|
|
break;
|
2020-05-04 15:22:51 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
default:
|
|
|
|
|
common->Error( "RB_ExecuteBackEndCommands: bad commandId" );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
DrawFlickerBox();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
GL_EndFrame();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
// stop rendering on this thread
|
|
|
|
|
uint64 backEndFinishTime = Sys_Microseconds();
|
2020-05-04 23:21:29 +00:00
|
|
|
|
pc.cpuTotalMicroSec = backEndFinishTime - backEndStartTime;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-06 15:21:49 +00:00
|
|
|
|
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
|
|
|
|
{
|
2020-05-03 11:39:38 +00:00
|
|
|
|
renderLog.OpenBlock( "Render_DrawViewInternal", colorRed );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// ensures that depth writes are enabled for the depth clear
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GL_State( GLS_DEFAULT | GLS_CULL_FRONTSIDED, true );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
//GL_CheckErrors();
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-01-09 21:24:57 +00:00
|
|
|
|
//GL_CheckErrors();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
#if !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
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
SetVertexParm( RENDERPARM_GLOBALEYEPOS, parm ); // rpGlobalEyePos
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-24 15:43:02 +00:00
|
|
|
|
//-------------------------------------------------
|
2020-04-25 16:30:40 +00:00
|
|
|
|
// build hierarchical depth buffer and SSAO render target
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
DrawScreenSpaceAmbientOcclusion( _viewDef, false );
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// render static lighting and consider SSAO results
|
2015-12-24 15:43:02 +00:00
|
|
|
|
//-------------------------------------------------
|
2017-09-03 21:17:44 +00:00
|
|
|
|
AmbientPass( drawSurfs, numDrawSurfs, false );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
//-------------------------------------------------
|
|
|
|
|
// main light renderer
|
|
|
|
|
//-------------------------------------------------
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawInteractions( _viewDef );
|
2019-11-11 19:27:44 +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() );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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
|
|
|
|
//-------------------------------------------------
|
2020-04-25 16:30:40 +00:00
|
|
|
|
//DrawScreenSpaceAmbientOcclusion( _viewDef );
|
2017-09-03 21:17:44 +00:00
|
|
|
|
//RB_SSGI( _viewDef );
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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();
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
RENDERLOG_PRINTF( "Resolve to %i x %i buffer\n", w, h );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
// RENDERPARM_SCREENCORRECTIONFACTOR amd RENDERPARM_WINDOWCOORD overlap
|
|
|
|
|
// diffuseScale and specularScale
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
GL_Viewport( viewDef->viewport.x1,
|
|
|
|
|
viewDef->viewport.y1,
|
|
|
|
|
viewDef->viewport.x2 + 1 - viewDef->viewport.x1,
|
|
|
|
|
viewDef->viewport.y2 + 1 - viewDef->viewport.y1 );
|
|
|
|
|
*/
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
/*
|
|
|
|
|
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 );
|
|
|
|
|
*/
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-20 11:28:46 +00:00
|
|
|
|
// 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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
CalculateAutomaticExposure();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
Tonemap( _viewDef );
|
2015-12-20 11:28:46 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
Bloom( _viewDef );
|
2018-10-03 21:40:35 +00:00
|
|
|
|
#endif
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_CheckErrors();
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-03 21:40:35 +00:00
|
|
|
|
#endif
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +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 ];
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
2019-11-11 19:27:44 +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();
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_State( GLS_DEPTHFUNC_ALWAYS );
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
prevMVP[mvpIndex] = viewDef->worldSpace.mvp;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
RB_SetMVP( motionMatrix );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
renderProgManager.BindShader_MotionBlur();
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->currentRenderImage->Bind();
|
2020-04-22 20:49:24 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
GL_SelectTexture( 1 );
|
|
|
|
|
globalImages->currentDepthImage->Bind();
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
viewDef = cmd->viewDef;
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-12-11 22:17:23 +00:00
|
|
|
|
// RB: not really needed
|
|
|
|
|
//if( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys )
|
|
|
|
|
//{
|
|
|
|
|
// GLimp_DeactivateContext();
|
|
|
|
|
//}
|
|
|
|
|
// RB end
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
pc.c_surfaces += viewDef->numDrawSurfs;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-09 12:57:48 +00:00
|
|
|
|
DBG_ShowOverdraw();
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2017-09-03 21:17:44 +00:00
|
|
|
|
MotionBlur();
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-28 15:47:07 +00:00
|
|
|
|
if( r_skipCopyTexture.GetBool() )
|
|
|
|
|
{
|
2012-11-26 18:58:24 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
RENDERLOG_PRINTF( "***************** RB_CopyRender *****************\n" );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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 );
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +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;
|
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-09 14:48:55 +00:00
|
|
|
|
renderLog.OpenMainBlock( MRB_POSTPROCESS );
|
|
|
|
|
renderLog.OpenBlock( "Render_PostProcessing", colorBlue );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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;
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-11-01 15:30:05 +00:00
|
|
|
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2012-11-26 18:58:24 +00:00
|
|
|
|
int screenWidth = renderSystem->GetWidth();
|
|
|
|
|
int screenHeight = renderSystem->GetHeight();
|
2019-11-11 19:27:44 +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 );
|
2019-11-11 19:27:44 +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|
|
|
|
|
|
*/
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2016-10-24 01:55:16 +00:00
|
|
|
|
globalImages->smaaInputImage->CopyFramebuffer( 0, 0, screenWidth, screenHeight );
|
2019-11-11 19:27:44 +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
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 12:34:39 +00:00
|
|
|
|
globalFramebuffers.smaaEdgesFBO->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 12:34:39 +00:00
|
|
|
|
glClearColor( 0, 0, 0, 0 );
|
|
|
|
|
glClear( GL_COLOR_BUFFER_BIT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-30 11:07:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->smaaInputImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 10:42:11 +00:00
|
|
|
|
renderProgManager.BindShader_SMAA_EdgeDetection();
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 22:22:58 +00:00
|
|
|
|
globalFramebuffers.smaaBlendFBO->Bind();
|
|
|
|
|
//Framebuffer::Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 12:34:39 +00:00
|
|
|
|
glClear( GL_COLOR_BUFFER_BIT );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 20:36:25 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->smaaEdgesImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 10:42:11 +00:00
|
|
|
|
GL_SelectTexture( 1 );
|
|
|
|
|
globalImages->smaaAreaImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 10:42:11 +00:00
|
|
|
|
GL_SelectTexture( 2 );
|
|
|
|
|
globalImages->smaaSearchImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 10:42:11 +00:00
|
|
|
|
renderProgManager.BindShader_SMAA_BlendingWeightCalculation();
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 12:34:39 +00:00
|
|
|
|
Framebuffer::Unbind();
|
2015-12-28 20:36:25 +00:00
|
|
|
|
#endif
|
2019-11-11 19:27:44 +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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 12:34:39 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
2015-12-28 20:36:25 +00:00
|
|
|
|
globalImages->smaaInputImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 12:34:39 +00:00
|
|
|
|
GL_SelectTexture( 1 );
|
|
|
|
|
globalImages->smaaBlendImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 12:34:39 +00:00
|
|
|
|
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
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
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() );
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-30 11:07:24 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
globalImages->currentRenderImage->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-30 11:07:24 +00:00
|
|
|
|
GL_SelectTexture( 1 );
|
2020-04-28 23:19:53 +00:00
|
|
|
|
globalImages->blueNoiseImage256->Bind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-30 11:07:24 +00:00
|
|
|
|
renderProgManager.BindShader_PostProcess();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-30 11:07:24 +00:00
|
|
|
|
float jitterTexOffset[4];
|
2020-05-10 20:10:32 +00:00
|
|
|
|
jitterTexOffset[0] = 1.0f / globalImages->blueNoiseImage256->GetUploadWidth();
|
|
|
|
|
jitterTexOffset[1] = 1.0f / globalImages->blueNoiseImage256->GetUploadHeight();
|
|
|
|
|
|
2015-12-30 11:07:24 +00:00
|
|
|
|
if( r_shadowMapRandomizeJitter.GetBool() )
|
|
|
|
|
{
|
2020-04-22 20:49:24 +00:00
|
|
|
|
jitterTexOffset[2] = Sys_Milliseconds() / 1000.0f;
|
2020-05-10 20:10:32 +00:00
|
|
|
|
jitterTexOffset[3] = tr.frameCount % 256;
|
2015-12-30 11:07:24 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-04-22 20:49:24 +00:00
|
|
|
|
jitterTexOffset[2] = 0.0f;
|
2020-04-28 23:19:53 +00:00
|
|
|
|
jitterTexOffset[3] = 0.0f;
|
2015-12-30 11:07:24 +00:00
|
|
|
|
}
|
2020-04-22 20:49:24 +00:00
|
|
|
|
|
2015-12-30 11:07:24 +00:00
|
|
|
|
SetFragmentParm( RENDERPARM_JITTERTEXOFFSET, jitterTexOffset ); // rpJitterTexOffset
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-30 11:07:24 +00:00
|
|
|
|
// Draw
|
2017-09-03 21:17:44 +00:00
|
|
|
|
DrawElementsWithCounters( &unitSquareSurface );
|
2015-12-23 12:53:21 +00:00
|
|
|
|
}
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2015-12-28 10:42:11 +00:00
|
|
|
|
GL_SelectTexture( 0 );
|
|
|
|
|
renderProgManager.Unbind();
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2018-10-03 21:40:35 +00:00
|
|
|
|
#endif
|
2019-11-11 19:27:44 +00:00
|
|
|
|
|
2020-05-09 14:48:55 +00:00
|
|
|
|
renderLog.CloseBlock();
|
|
|
|
|
renderLog.CloseMainBlock();
|
2012-11-26 18:58:24 +00:00
|
|
|
|
}
|