2012-09-30 05:52:03 +00:00
# include "quakedef.h"
# ifdef D3D11QUAKE
# include "glquake.h"
# include "gl_draw.h"
# include "shader.h"
# define COBJMACROS
# include <d3d11.h>
extern ID3D11Device * pD3DDev11 ;
extern ID3D11DeviceContext * d3ddevctx ;
2015-09-06 05:50:16 +00:00
extern ID3D11DepthStencilView * fb_backdepthstencil ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
extern cvar_t r_shadow_realtime_world_lightmaps ;
extern cvar_t gl_overbright ;
2014-03-30 08:55:06 +00:00
extern cvar_t r_portalrecursion ;
2013-11-21 23:02:28 +00:00
2015-09-06 03:30:28 +00:00
extern cvar_t r_polygonoffset_shadowmap_offset , r_polygonoffset_shadowmap_factor ;
2013-11-21 23:02:28 +00:00
void D3D11_TerminateShadowMap ( void ) ;
void D3D11BE_BeginShadowmapFace ( void ) ;
2015-09-06 03:30:28 +00:00
# ifdef _DEBUG
# define d3dcheck(foo) do{HRESULT err = foo; if (FAILED(err)) Sys_Error("D3D11 reported error on backend line %i - error 0x%x\n", __LINE__, (unsigned int)err);} while(0)
# else
# define d3dcheck(foo) foo
# endif
2012-09-30 05:52:03 +00:00
2012-11-27 03:23:19 +00:00
# define MAX_TMUS 16
2012-09-30 05:52:03 +00:00
static void BE_RotateForEntity ( const entity_t * e , const model_t * mod ) ;
2013-11-21 23:02:28 +00:00
void D3D11BE_SetupLightCBuffer ( dlight_t * l , vec3_t colour ) ;
texid_t D3D11_GetShadowMap ( int id ) ;
2012-09-30 05:52:03 +00:00
/*========================================== tables for deforms =====================================*/
# define frand() (rand()*(1.0 / RAND_MAX))
# define FTABLE_SIZE 1024
# define FTABLE_CLAMP(x) (((int)((x)*FTABLE_SIZE) & (FTABLE_SIZE-1)))
# define FTABLE_EVALUATE(table,x) (table ? table[FTABLE_CLAMP(x)] : frand()*((x)-floor(x)))
2015-09-06 03:30:28 +00:00
# define R_FastSin(x) r_sintable[FTABLE_CLAMP(x)]
2012-09-30 05:52:03 +00:00
static float r_sintable [ FTABLE_SIZE ] ;
static float r_triangletable [ FTABLE_SIZE ] ;
static float r_squaretable [ FTABLE_SIZE ] ;
static float r_sawtoothtable [ FTABLE_SIZE ] ;
static float r_inversesawtoothtable [ FTABLE_SIZE ] ;
static float * FTableForFunc ( unsigned int func )
{
switch ( func )
{
case SHADER_FUNC_SIN :
return r_sintable ;
case SHADER_FUNC_TRIANGLE :
return r_triangletable ;
case SHADER_FUNC_SQUARE :
return r_squaretable ;
case SHADER_FUNC_SAWTOOTH :
return r_sawtoothtable ;
case SHADER_FUNC_INVERSESAWTOOTH :
return r_inversesawtoothtable ;
}
//bad values allow us to crash (so I can debug em)
return NULL ;
}
static void FTable_Init ( void )
{
unsigned int i ;
double t ;
for ( i = 0 ; i < FTABLE_SIZE ; i + + )
{
t = ( double ) i / ( double ) FTABLE_SIZE ;
r_sintable [ i ] = sin ( t * 2 * M_PI ) ;
if ( t < 0.25 )
r_triangletable [ i ] = t * 4.0 ;
else if ( t < 0.75 )
r_triangletable [ i ] = 2 - 4.0 * t ;
else
r_triangletable [ i ] = ( t - 0.75 ) * 4.0 - 1.0 ;
if ( t < 0.5 )
r_squaretable [ i ] = 1.0f ;
else
r_squaretable [ i ] = - 1.0f ;
r_sawtoothtable [ i ] = t ;
r_inversesawtoothtable [ i ] = 1.0 - t ;
}
}
typedef vec3_t mat3_t [ 3 ] ;
static mat3_t axisDefault = { { 1 , 0 , 0 } ,
{ 0 , 1 , 0 } ,
{ 0 , 0 , 1 } } ;
static void Matrix3_Transpose ( mat3_t in , mat3_t out )
{
out [ 0 ] [ 0 ] = in [ 0 ] [ 0 ] ;
out [ 1 ] [ 1 ] = in [ 1 ] [ 1 ] ;
out [ 2 ] [ 2 ] = in [ 2 ] [ 2 ] ;
out [ 0 ] [ 1 ] = in [ 1 ] [ 0 ] ;
out [ 0 ] [ 2 ] = in [ 2 ] [ 0 ] ;
out [ 1 ] [ 0 ] = in [ 0 ] [ 1 ] ;
out [ 1 ] [ 2 ] = in [ 2 ] [ 1 ] ;
out [ 2 ] [ 0 ] = in [ 0 ] [ 2 ] ;
out [ 2 ] [ 1 ] = in [ 1 ] [ 2 ] ;
}
static void Matrix3_Multiply_Vec3 ( const mat3_t a , const vec3_t b , vec3_t product )
{
product [ 0 ] = a [ 0 ] [ 0 ] * b [ 0 ] + a [ 0 ] [ 1 ] * b [ 1 ] + a [ 0 ] [ 2 ] * b [ 2 ] ;
product [ 1 ] = a [ 1 ] [ 0 ] * b [ 0 ] + a [ 1 ] [ 1 ] * b [ 1 ] + a [ 1 ] [ 2 ] * b [ 2 ] ;
product [ 2 ] = a [ 2 ] [ 0 ] * b [ 0 ] + a [ 2 ] [ 1 ] * b [ 1 ] + a [ 2 ] [ 2 ] * b [ 2 ] ;
}
static int Matrix3_Compare ( const mat3_t in , const mat3_t out )
{
return ! memcmp ( in , out , sizeof ( mat3_t ) ) ;
}
2015-09-06 03:30:28 +00:00
2012-09-30 05:52:03 +00:00
/*================================================*/
//global constant-buffer
typedef struct
{
float m_view [ 16 ] ;
float m_projection [ 16 ] ;
2013-11-21 23:02:28 +00:00
vec3_t v_eyepos ; float v_time ;
vec3_t e_light_ambient ; float pad1 ;
vec3_t e_light_dir ; float pad2 ;
vec3_t e_light_mul ; float pad3 ;
2012-09-30 05:52:03 +00:00
} cbuf_view_t ;
2013-11-21 23:02:28 +00:00
typedef struct
{
float l_cubematrix [ 16 ] ;
vec3_t l_lightposition ; float padl1 ;
vec3_t l_colour ; float pad2 ;
vec3_t l_lightcolourscale ; float l_lightradius ;
vec4_t l_shadowmapproj ;
vec2_t l_shadowmapscale ; vec2_t pad3 ;
} cbuf_light_t ;
2012-09-30 05:52:03 +00:00
//entity-specific constant-buffer
typedef struct
{
float m_model [ 16 ] ;
vec3_t e_eyepos ;
float e_time ;
vec3_t e_light_ambient ; float pad1 ;
vec3_t e_light_dir ; float pad2 ;
vec3_t e_light_mul ; float pad3 ;
2013-11-21 23:02:28 +00:00
vec4_t e_lmscale [ 4 ] ;
2016-12-07 18:45:25 +00:00
vec4_t e_uppercolour ;
vec4_t e_lowercolour ;
2012-09-30 05:52:03 +00:00
} cbuf_entity_t ;
//vertex attributes
typedef struct
{
vecV_t coord ;
vec2_t tex ;
vec2_t lm ;
vec3_t ndir ;
vec3_t sdir ;
vec3_t tdir ;
byte_vec4_t colorsb ;
} vbovdata_t ;
2015-09-06 03:30:28 +00:00
enum
{
//pos1 is always used
D3D_VDEC_COL4B = 1 < < 0 ,
D3D_VDEC_ST0 = 1 < < 1 , //base or tcgen/tcmod
D3D_VDEC_ST1 = 1 < < 2 , //lm or so
// D3D_VDEC_ST2 = 1<<3,
// D3D_VDEC_ST3 = 1<<4,
D3D_VDEC_NORM = 1 < < 3 , //normal+sdir+tdir
// D3D_VDEC_SKEL = 1<<4,
// D3D_VDEC_POS2 = 1<<5,
D3D_VDEC_MAX = 1 < < 5 ,
} ;
2013-11-21 23:02:28 +00:00
typedef struct blendstates_s
{
struct blendstates_s * next ;
ID3D11BlendState * val ;
unsigned int bits ;
} blendstates_t ;
2016-07-12 00:40:13 +00:00
/*
2015-09-06 03:30:28 +00:00
typedef struct d3d11renderqueue_s
{
ID3D11SamplerState * cursamplerstate [ MAX_TMUS ] ;
ID3D11ShaderResourceView * pendingtextures [ MAX_TMUS ] ;
unsigned int shaderbits ;
ID3D11Buffer * stream_buffer [ D3D11_BUFF_MAX ] ;
unsigned int stream_stride [ D3D11_BUFF_MAX ] ;
unsigned int stream_offset [ D3D11_BUFF_MAX ] ;
2016-07-12 00:40:13 +00:00
} d3d11renderqueue_t ;
*/
2015-09-06 03:30:28 +00:00
2012-09-30 05:52:03 +00:00
typedef struct
{
2013-11-21 23:02:28 +00:00
unsigned int inited ;
2012-09-30 05:52:03 +00:00
backendmode_t mode ;
unsigned int flags ;
2013-11-21 23:02:28 +00:00
float identitylighting ;
2012-09-30 05:52:03 +00:00
float curtime ;
const entity_t * curentity ;
const dlight_t * curdlight ;
vec3_t curdlight_colours ;
shader_t * curshader ;
2013-11-21 23:02:28 +00:00
shader_t * depthonly ;
2012-09-30 05:52:03 +00:00
texnums_t * curtexnums ;
int curvertdecl ;
unsigned int shaderbits ;
unsigned int curcull ;
float depthbias ;
float depthfactor ;
float m_model [ 16 ] ;
unsigned int lastpasscount ;
vbo_t * batchvbo ;
batch_t * curbatch ;
batch_t dummybatch ;
2013-11-21 23:02:28 +00:00
vec4_t lightshadowmapproj ;
vec2_t lightshadowmapscale ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
unsigned int curlmode ;
shader_t * shader_rtlight [ LSHADER_MODES ] ;
2014-10-05 20:04:11 +00:00
unsigned int texflags [ MAX_TMUS ] ;
2012-09-30 05:52:03 +00:00
unsigned int tmuflags [ MAX_TMUS ] ;
ID3D11SamplerState * cursamplerstate [ MAX_TMUS ] ;
2017-07-12 08:15:27 +00:00
ID3D11SamplerState * sampstate [ SHADER_PASS_IMAGE_FLAGS_D3D11 + 1 ] ;
2013-11-21 23:02:28 +00:00
ID3D11DepthStencilState * depthstates [ 1u < < 4 ] ; //index, its fairly short.
blendstates_t * blendstates ; //list. this could get big.
2012-09-30 05:52:03 +00:00
2015-09-06 03:30:28 +00:00
//pending buffer state
ID3D11Buffer * stream_buffer [ D3D11_BUFF_MAX ] ;
unsigned int stream_stride [ D3D11_BUFF_MAX ] ;
unsigned int stream_offset [ D3D11_BUFF_MAX ] ;
program_t * programfixedemu [ 4 ] ;
2012-09-30 05:52:03 +00:00
mesh_t * * meshlist ;
unsigned int nummeshes ;
2012-12-04 19:37:57 +00:00
# define NUMECBUFFERS 8
2013-11-21 23:02:28 +00:00
ID3D11Buffer * lcbuffer ;
2012-12-04 19:37:57 +00:00
ID3D11Buffer * vcbuffer ;
ID3D11Buffer * ecbuffers [ NUMECBUFFERS ] ;
int ecbufferidx ;
2012-09-30 05:52:03 +00:00
unsigned int wbatch ;
unsigned int maxwbatches ;
batch_t * wbatches ;
2012-12-04 19:37:57 +00:00
qboolean textureschanged ;
ID3D11ShaderResourceView * pendingtextures [ MAX_TMUS ] ;
float depthrange ;
qboolean purgevertexstream ;
2014-03-30 08:55:06 +00:00
# define NUMVBUFFERS 3
ID3D11Buffer * vertexstream [ NUMVBUFFERS ] ;
int vertexstreamcycle ;
2012-12-04 19:37:57 +00:00
int vertexstreamoffset ;
qboolean purgeindexstream ;
2014-03-30 08:55:06 +00:00
# define NUMIBUFFERS 3
ID3D11Buffer * indexstream [ NUMIBUFFERS ] ;
int indexstreamcycle ;
2012-12-04 19:37:57 +00:00
int indexstreamoffset ;
2013-11-21 23:02:28 +00:00
2015-07-31 13:23:32 +00:00
texid_t currentrender ;
2013-11-21 23:02:28 +00:00
int numlivevbos ;
int numliveshadowbuffers ;
2012-09-30 05:52:03 +00:00
} d3d11backend_t ;
2015-07-31 13:23:32 +00:00
extern D3D_FEATURE_LEVEL d3dfeaturelevel ;
2012-09-30 05:52:03 +00:00
2012-12-04 19:37:57 +00:00
# define VERTEXSTREAMSIZE (1024*1024*2) //2mb = 1 PAE jumbo page
2012-09-30 05:52:03 +00:00
# define DYNVBUFFSIZE 65536
2017-06-22 10:29:06 +00:00
# define DYNIBUFFSIZE 65536*3
2012-09-30 05:52:03 +00:00
2015-09-06 03:30:28 +00:00
static vecV_t tmpbuf [ 65536 ] ; //max verts per mesh
2012-09-30 05:52:03 +00:00
static d3d11backend_t shaderstate ;
extern int be_maxpasses ;
2014-10-05 20:04:11 +00:00
void D3D11_UpdateFiltering ( image_t * imagelist , int filtermip [ 3 ] , int filterpic [ 3 ] , int mipcap [ 2 ] , float anis )
2012-09-30 05:52:03 +00:00
{
D3D11_SAMPLER_DESC sampdesc ;
int flags ;
2017-07-12 08:15:27 +00:00
for ( flags = 0 ; flags < = ( SHADER_PASS_IMAGE_FLAGS_D3D11 ) ; flags + + )
2012-09-30 05:52:03 +00:00
{
2014-10-05 20:04:11 +00:00
int * filter ;
sampdesc . Filter = 0 ;
filter = ( flags & SHADER_PASS_UIPIC ) ? filterpic : filtermip ;
if ( ( filter [ 2 ] & & ! ( flags & SHADER_PASS_NEAREST ) ) | | ( flags & SHADER_PASS_LINEAR ) )
sampdesc . Filter | = D3D11_FILTER_TYPE_LINEAR < < D3D11_MAG_FILTER_SHIFT ;
else
sampdesc . Filter | = D3D11_FILTER_TYPE_POINT < < D3D11_MAG_FILTER_SHIFT ;
//d3d11 has no no-mip feature
if ( ( filter [ 1 ] = = 1 & & ! ( flags & SHADER_PASS_NEAREST ) ) | | ( flags & SHADER_PASS_LINEAR ) )
sampdesc . Filter | = D3D11_FILTER_TYPE_LINEAR < < D3D11_MIP_FILTER_SHIFT ;
else
sampdesc . Filter | = D3D11_FILTER_TYPE_POINT < < D3D11_MIP_FILTER_SHIFT ;
if ( ( filter [ 0 ] & & ! ( flags & SHADER_PASS_NEAREST ) ) | | ( flags & SHADER_PASS_LINEAR ) )
sampdesc . Filter | = D3D11_FILTER_TYPE_LINEAR < < D3D11_MIN_FILTER_SHIFT ;
else
sampdesc . Filter | = D3D11_FILTER_TYPE_POINT < < D3D11_MIN_FILTER_SHIFT ;
//switch to anisotropic filtering if all three filters are linear and anis is set
if ( sampdesc . Filter = = D3D11_FILTER_MIN_MAG_MIP_LINEAR & & anis > 1 )
sampdesc . Filter = D3D11_FILTER_ANISOTROPIC ;
if ( flags & SHADER_PASS_DEPTHCMP )
sampdesc . Filter | = D3D11_COMPARISON_FILTERING_BIT ;
2013-11-21 23:02:28 +00:00
if ( flags & SHADER_PASS_DEPTHCMP )
sampdesc . ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL ;
2012-09-30 05:52:03 +00:00
else
2013-11-21 23:02:28 +00:00
sampdesc . ComparisonFunc = D3D11_COMPARISON_NEVER ;
2012-09-30 05:52:03 +00:00
if ( flags & SHADER_PASS_CLAMP )
{
sampdesc . AddressU = D3D11_TEXTURE_ADDRESS_CLAMP ;
sampdesc . AddressV = D3D11_TEXTURE_ADDRESS_CLAMP ;
sampdesc . AddressW = D3D11_TEXTURE_ADDRESS_CLAMP ;
}
else
{
sampdesc . AddressU = D3D11_TEXTURE_ADDRESS_WRAP ;
sampdesc . AddressV = D3D11_TEXTURE_ADDRESS_WRAP ;
sampdesc . AddressW = D3D11_TEXTURE_ADDRESS_WRAP ;
}
sampdesc . MipLODBias = 0.0f ;
2014-10-05 20:04:11 +00:00
sampdesc . MaxAnisotropy = bound ( 1 , anis , 16 ) ;
2012-09-30 05:52:03 +00:00
sampdesc . BorderColor [ 0 ] = 0 ;
sampdesc . BorderColor [ 1 ] = 0 ;
sampdesc . BorderColor [ 2 ] = 0 ;
sampdesc . BorderColor [ 3 ] = 0 ;
2014-10-05 20:04:11 +00:00
if ( flags & SHADER_PASS_NOMIPMAP )
{ //only ever use the biggest mip if multiple are present
sampdesc . MinLOD = 0 ;
sampdesc . MaxLOD = 0 ;
}
else
{
sampdesc . MinLOD = mipcap [ 0 ] ;
sampdesc . MaxLOD = mipcap [ 1 ] ;
}
2012-09-30 05:52:03 +00:00
2015-07-31 13:23:32 +00:00
if ( d3dfeaturelevel < D3D_FEATURE_LEVEL_10_0 ) //9.* sucks
sampdesc . MaxLOD = FLT_MAX ;
2014-10-05 20:04:11 +00:00
if ( shaderstate . sampstate [ flags ] )
ID3D11SamplerState_Release ( shaderstate . sampstate [ flags ] ) ;
shaderstate . sampstate [ flags ] = NULL ;
//returns the same pointer for dupes, supposedly, so no need to check that
2012-09-30 05:52:03 +00:00
ID3D11Device_CreateSamplerState ( pD3DDev11 , & sampdesc , & shaderstate . sampstate [ flags ] ) ;
}
}
2013-11-21 23:02:28 +00:00
static void BE_DestroyVariousStates ( void )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
blendstates_t * bs ;
2012-09-30 05:52:03 +00:00
int flags ;
2013-11-21 23:02:28 +00:00
int i ;
for ( i = 0 ; i < MAX_TMUS /*shaderstate.lastpasscount*/ ; i + + )
{
shaderstate . cursamplerstate [ i ] = NULL ;
}
if ( d3ddevctx & & i )
ID3D11DeviceContext_PSSetSamplers ( d3ddevctx , 0 , i , shaderstate . cursamplerstate ) ;
2017-07-12 08:15:27 +00:00
for ( flags = 0 ; flags < = SHADER_PASS_IMAGE_FLAGS_D3D11 ; flags + + )
2012-09-30 05:52:03 +00:00
{
2012-12-04 19:37:57 +00:00
if ( shaderstate . sampstate [ flags ] )
ID3D11SamplerState_Release ( shaderstate . sampstate [ flags ] ) ;
2012-09-30 05:52:03 +00:00
shaderstate . sampstate [ flags ] = NULL ;
}
2013-11-21 23:02:28 +00:00
if ( d3ddevctx )
ID3D11DeviceContext_OMSetDepthStencilState ( d3ddevctx , NULL , 0 ) ;
for ( i = 0 ; i < ( 1u < < 4 ) ; i + + )
{
if ( shaderstate . depthstates [ i ] )
ID3D11DepthStencilState_Release ( shaderstate . depthstates [ i ] ) ;
shaderstate . depthstates [ i ] = NULL ;
}
if ( d3ddevctx )
ID3D11DeviceContext_OMSetBlendState ( d3ddevctx , NULL , NULL , 0xffffffff ) ;
//hopefully the caches inside shaders should get flushed too...
while ( shaderstate . blendstates )
{
bs = shaderstate . blendstates ;
shaderstate . blendstates = bs - > next ;
if ( bs - > val )
ID3D11BlendState_Release ( bs - > val ) ;
BZ_Free ( bs ) ;
}
2014-03-30 08:55:06 +00:00
for ( i = 0 ; i < NUMIBUFFERS ; i + + )
{
if ( shaderstate . indexstream [ i ] )
ID3D11Buffer_Release ( shaderstate . indexstream [ i ] ) ;
shaderstate . indexstream [ i ] = NULL ;
}
2013-11-21 23:02:28 +00:00
2014-03-30 08:55:06 +00:00
for ( i = 0 ; i < NUMVBUFFERS ; i + + )
{
if ( shaderstate . vertexstream [ i ] )
ID3D11Buffer_Release ( shaderstate . vertexstream [ i ] ) ;
shaderstate . vertexstream [ i ] = NULL ;
}
2013-11-21 23:02:28 +00:00
if ( shaderstate . lcbuffer )
ID3D11Buffer_Release ( shaderstate . lcbuffer ) ;
shaderstate . lcbuffer = NULL ;
if ( shaderstate . vcbuffer )
ID3D11Buffer_Release ( shaderstate . vcbuffer ) ;
shaderstate . vcbuffer = NULL ;
for ( i = 0 ; i < NUMECBUFFERS ; i + + )
{
if ( shaderstate . ecbuffers [ i ] )
ID3D11Buffer_Release ( shaderstate . ecbuffers [ i ] ) ;
shaderstate . ecbuffers [ i ] = NULL ;
}
2015-07-31 13:23:32 +00:00
D3D11_DestroyTexture ( shaderstate . currentrender ) ;
2013-11-21 23:02:28 +00:00
//make sure the device doesn't have any textures still referenced.
for ( i = 0 ; i < MAX_TMUS /*shaderstate.lastpasscount*/ ; i + + )
{
shaderstate . pendingtextures [ i ] = NULL ;
}
if ( d3ddevctx & & i )
ID3D11DeviceContext_PSSetShaderResources ( d3ddevctx , 0 , i , shaderstate . pendingtextures ) ;
2012-09-30 05:52:03 +00:00
}
static void BE_ApplyTMUState ( unsigned int tu , unsigned int flags )
{
ID3D11SamplerState * nstate ;
2017-07-12 08:15:27 +00:00
flags = ( flags & SHADER_PASS_IMAGE_FLAGS_D3D11 ) ;
2014-10-05 20:04:11 +00:00
flags | = shaderstate . texflags [ tu ] ;
2012-09-30 05:52:03 +00:00
nstate = shaderstate . sampstate [ flags ] ;
if ( nstate ! = shaderstate . cursamplerstate [ tu ] )
{
shaderstate . cursamplerstate [ tu ] = nstate ;
//fixme: is it significant to bulk-apply this later?
ID3D11DeviceContext_PSSetSamplers ( d3ddevctx , tu , 1 , & nstate ) ;
}
/*
if ( ( flags ^ shaderstate . tmuflags [ tu ] ) & ( SHADER_PASS_NEAREST | SHADER_PASS_CLAMP ) )
{
D3D11_SAMPLER_DESC sampdesc ;
ID3D11SamplerState * sstate ;
shaderstate . tmuflags [ tu ] = flags ;
if ( flags & SHADER_PASS_NEAREST )
sampdesc . Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR ;
else
sampdesc . Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR ;
if ( flags & SHADER_PASS_CLAMP )
{
sampdesc . AddressU = D3D11_TEXTURE_ADDRESS_CLAMP ;
sampdesc . AddressV = D3D11_TEXTURE_ADDRESS_CLAMP ;
sampdesc . AddressW = D3D11_TEXTURE_ADDRESS_CLAMP ;
}
else
{
sampdesc . AddressU = D3D11_TEXTURE_ADDRESS_WRAP ;
sampdesc . AddressV = D3D11_TEXTURE_ADDRESS_WRAP ;
sampdesc . AddressW = D3D11_TEXTURE_ADDRESS_WRAP ;
}
sampdesc . MipLODBias = 0.0f ;
sampdesc . MaxAnisotropy = 1 ;
sampdesc . ComparisonFunc = D3D11_COMPARISON_ALWAYS ;
sampdesc . BorderColor [ 0 ] = 0 ;
sampdesc . BorderColor [ 1 ] = 0 ;
sampdesc . BorderColor [ 2 ] = 0 ;
sampdesc . BorderColor [ 3 ] = 0 ;
sampdesc . MinLOD = 0 ;
sampdesc . MaxLOD = D3D11_FLOAT32_MAX ;
if ( ! FAILED ( ID3D11Device_CreateSamplerState ( pD3DDev11 , & sampdesc , & sstate ) ) )
{
ID3D11DeviceContext_PSSetSamplers ( d3ddevctx , tu , 1 , & sstate ) ;
ID3D11SamplerState_Release ( sstate ) ;
}
}
*/
}
2013-11-21 23:02:28 +00:00
static void * D3D11BE_GenerateBlendState ( unsigned int bits )
{
D3D11_BLEND_DESC blend = { 0 } ;
ID3D11BlendState * newblendstate ;
blend . IndependentBlendEnable = FALSE ;
blend . AlphaToCoverageEnable = FALSE ; //FIXME
if ( bits & SBITS_BLEND_BITS )
{
switch ( bits & SBITS_SRCBLEND_BITS )
{
2015-09-06 03:30:28 +00:00
case SBITS_SRCBLEND_ZERO : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_ZERO ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_ZERO ; break ;
case SBITS_SRCBLEND_ONE : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_ONE ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_ONE ; break ;
case SBITS_SRCBLEND_DST_COLOR : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_DEST_COLOR ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA ; break ;
case SBITS_SRCBLEND_ONE_MINUS_DST_COLOR : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_INV_DEST_COLOR ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA ; break ;
case SBITS_SRCBLEND_SRC_ALPHA : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_SRC_ALPHA ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA ; break ;
case SBITS_SRCBLEND_ONE_MINUS_SRC_ALPHA : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_INV_SRC_ALPHA ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA ; break ;
case SBITS_SRCBLEND_DST_ALPHA : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_DEST_ALPHA ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA ; break ;
case SBITS_SRCBLEND_ONE_MINUS_DST_ALPHA : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_INV_DEST_ALPHA ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA ; break ;
case SBITS_SRCBLEND_ALPHA_SATURATE : blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_SRC_ALPHA_SAT ; blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA_SAT ; break ;
2013-11-21 23:02:28 +00:00
default : Sys_Error ( " Bad shader blend src \n " ) ; return NULL ;
}
switch ( bits & SBITS_DSTBLEND_BITS )
{
2015-09-06 03:30:28 +00:00
case SBITS_DSTBLEND_ZERO : blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_ZERO ; blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_ZERO ; break ;
case SBITS_DSTBLEND_ONE : blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_ONE ; blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_ONE ; break ;
case SBITS_DSTBLEND_SRC_ALPHA : blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_SRC_ALPHA ; blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_SRC_ALPHA ; break ;
case SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA : blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_INV_SRC_ALPHA ; blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA ; break ;
case SBITS_DSTBLEND_DST_ALPHA : blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_DEST_ALPHA ; blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_DEST_ALPHA ; break ;
case SBITS_DSTBLEND_ONE_MINUS_DST_ALPHA : blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_INV_DEST_ALPHA ; blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA ; break ;
case SBITS_DSTBLEND_SRC_COLOR : blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_SRC_COLOR ; blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_SRC_ALPHA ; break ;
case SBITS_DSTBLEND_ONE_MINUS_SRC_COLOR : blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_INV_SRC_COLOR ; blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA ; break ;
2013-11-21 23:02:28 +00:00
default : Sys_Error ( " Bad shader blend dst \n " ) ; return NULL ;
}
blend . RenderTarget [ 0 ] . BlendEnable = TRUE ;
}
else
{
2015-09-06 03:30:28 +00:00
blend . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_ONE ;
2013-11-21 23:02:28 +00:00
blend . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_ZERO ;
2015-09-06 03:30:28 +00:00
blend . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_ONE ;
blend . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_ZERO ;
2013-11-21 23:02:28 +00:00
blend . RenderTarget [ 0 ] . BlendEnable = FALSE ;
}
blend . RenderTarget [ 0 ] . BlendOp = D3D11_BLEND_OP_ADD ;
2015-09-06 03:30:28 +00:00
blend . RenderTarget [ 0 ] . BlendOpAlpha = D3D11_BLEND_OP_ADD ;
2013-11-21 23:02:28 +00:00
if ( bits & SBITS_MASK_BITS )
{
blend . RenderTarget [ 0 ] . RenderTargetWriteMask = 0 ;
if ( ! ( bits & SBITS_MASK_RED ) )
blend . RenderTarget [ 0 ] . RenderTargetWriteMask | = D3D11_COLOR_WRITE_ENABLE_RED ;
if ( ! ( bits & SBITS_MASK_GREEN ) )
blend . RenderTarget [ 0 ] . RenderTargetWriteMask | = D3D11_COLOR_WRITE_ENABLE_GREEN ;
if ( ! ( bits & SBITS_MASK_BLUE ) )
blend . RenderTarget [ 0 ] . RenderTargetWriteMask | = D3D11_COLOR_WRITE_ENABLE_BLUE ;
if ( ! ( bits & SBITS_MASK_ALPHA ) )
blend . RenderTarget [ 0 ] . RenderTargetWriteMask | = D3D11_COLOR_WRITE_ENABLE_ALPHA ;
}
else
blend . RenderTarget [ 0 ] . RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL ;
if ( ! FAILED ( ID3D11Device_CreateBlendState ( pD3DDev11 , & blend , & newblendstate ) ) )
return newblendstate ;
return NULL ;
}
static void D3D11BE_ApplyShaderBits ( unsigned int bits , void * * blendstatecache )
2012-09-30 05:52:03 +00:00
{
unsigned int delta ;
if ( shaderstate . flags & ( BEF_FORCEADDITIVE | BEF_FORCETRANSPARENT | BEF_FORCENODEPTH | BEF_FORCEDEPTHTEST | BEF_FORCEDEPTHWRITE ) )
{
2013-11-21 23:02:28 +00:00
blendstatecache = NULL ;
2012-09-30 05:52:03 +00:00
if ( shaderstate . flags & BEF_FORCEADDITIVE )
bits = ( bits & ~ ( SBITS_MISC_DEPTHWRITE | SBITS_BLEND_BITS | SBITS_ATEST_BITS ) )
| ( SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE ) ;
else if ( shaderstate . flags & BEF_FORCETRANSPARENT )
{
if ( ( bits & SBITS_BLEND_BITS ) = = ( SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ZERO ) | | ! ( bits & SBITS_BLEND_BITS ) ) /*if transparency is forced, clear alpha test bits*/
bits = ( bits & ~ ( SBITS_MISC_DEPTHWRITE | SBITS_BLEND_BITS | SBITS_ATEST_BITS ) )
| ( SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) ;
}
if ( shaderstate . flags & BEF_FORCENODEPTH ) /*EF_NODEPTHTEST dp extension*/
bits | = SBITS_MISC_NODEPTHTEST ;
else
{
if ( shaderstate . flags & BEF_FORCEDEPTHTEST )
bits & = ~ SBITS_MISC_NODEPTHTEST ;
if ( shaderstate . flags & BEF_FORCEDEPTHWRITE )
bits | = SBITS_MISC_DEPTHWRITE ;
}
}
delta = bits ^ shaderstate . shaderbits ;
if ( ! delta )
return ;
shaderstate . shaderbits = bits ;
if ( delta & ( SBITS_BLEND_BITS | SBITS_MASK_BITS ) )
{
2013-11-21 23:02:28 +00:00
int sbits = bits & ( SBITS_BLEND_BITS | SBITS_MASK_BITS ) ;
if ( blendstatecache & & * blendstatecache )
ID3D11DeviceContext_OMSetBlendState ( d3ddevctx , * blendstatecache , NULL , 0xffffffff ) ;
else
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
blendstates_t * bs ;
for ( bs = shaderstate . blendstates ; bs ; bs = bs - > next )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
if ( bs - > bits = = sbits )
break ;
2012-09-30 05:52:03 +00:00
}
2013-11-21 23:02:28 +00:00
if ( ! bs )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
bs = BZ_Malloc ( sizeof ( * bs ) ) ;
bs - > next = shaderstate . blendstates ;
shaderstate . blendstates = bs ;
bs - > bits = sbits ;
bs - > val = D3D11BE_GenerateBlendState ( sbits ) ;
2012-09-30 05:52:03 +00:00
}
2013-11-21 23:02:28 +00:00
ID3D11DeviceContext_OMSetBlendState ( d3ddevctx , bs - > val , NULL , 0xffffffff ) ;
if ( blendstatecache )
* blendstatecache = bs - > val ;
2012-09-30 05:52:03 +00:00
}
}
if ( delta & SBITS_ATEST_BITS )
{
/*
switch ( bits & SBITS_ATEST_BITS )
{
case SBITS_ATEST_NONE :
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHATESTENABLE , FALSE ) ;
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAREF, 0);
// IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHAFUNC, 0);
break ;
case SBITS_ATEST_GT0 :
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHATESTENABLE , TRUE ) ;
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHAREF , 0 ) ;
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHAFUNC , D3DCMP_GREATER ) ;
break ;
case SBITS_ATEST_LT128 :
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHATESTENABLE , TRUE ) ;
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHAREF , 128 ) ;
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHAFUNC , D3DCMP_LESS ) ;
break ;
case SBITS_ATEST_GE128 :
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHATESTENABLE , TRUE ) ;
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHAREF , 128 ) ;
IDirect3DDevice9_SetRenderState ( pD3DDev9 , D3DRS_ALPHAFUNC , D3DCMP_GREATEREQUAL ) ;
break ;
}
*/
}
if ( delta & ( SBITS_MISC_DEPTHEQUALONLY | SBITS_MISC_DEPTHCLOSERONLY | SBITS_MISC_NODEPTHTEST | SBITS_MISC_DEPTHWRITE ) )
{
2013-11-21 23:02:28 +00:00
unsigned int key = 0 ;
if ( bits & SBITS_MISC_DEPTHEQUALONLY )
key | = 1u < < 0 ;
if ( bits & SBITS_MISC_DEPTHCLOSERONLY )
key | = 1u < < 1 ;
2012-09-30 05:52:03 +00:00
if ( bits & SBITS_MISC_NODEPTHTEST )
2013-11-21 23:02:28 +00:00
key | = 1u < < 2 ;
2012-09-30 05:52:03 +00:00
if ( bits & SBITS_MISC_DEPTHWRITE )
2013-11-21 23:02:28 +00:00
key | = 1u < < 3 ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
if ( shaderstate . depthstates [ key ] )
ID3D11DeviceContext_OMSetDepthStencilState ( d3ddevctx , shaderstate . depthstates [ key ] , 0 ) ;
else
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
D3D11_DEPTH_STENCIL_DESC depthdesc ;
if ( bits & SBITS_MISC_NODEPTHTEST )
depthdesc . DepthEnable = false ;
else
depthdesc . DepthEnable = true ;
if ( bits & SBITS_MISC_DEPTHWRITE )
depthdesc . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL ;
else
depthdesc . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO ;
switch ( bits & ( SBITS_MISC_DEPTHEQUALONLY | SBITS_MISC_DEPTHCLOSERONLY ) )
{
default :
case 0 :
depthdesc . DepthFunc = D3D11_COMPARISON_LESS_EQUAL ;
break ;
case SBITS_MISC_DEPTHEQUALONLY :
depthdesc . DepthFunc = D3D11_COMPARISON_EQUAL ;
break ;
case SBITS_MISC_DEPTHCLOSERONLY :
depthdesc . DepthFunc = D3D11_COMPARISON_LESS ;
break ;
}
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
//make sure the stencil part is actually valid, even if we're not using it.
depthdesc . StencilEnable = false ;
depthdesc . StencilReadMask = 0xFF ;
depthdesc . StencilWriteMask = 0xFF ;
depthdesc . FrontFace . StencilFailOp = D3D11_STENCIL_OP_KEEP ;
depthdesc . FrontFace . StencilDepthFailOp = D3D11_STENCIL_OP_KEEP ;
depthdesc . FrontFace . StencilPassOp = D3D11_STENCIL_OP_KEEP ;
depthdesc . FrontFace . StencilFunc = D3D11_COMPARISON_ALWAYS ;
depthdesc . BackFace . StencilFailOp = D3D11_STENCIL_OP_KEEP ;
depthdesc . BackFace . StencilDepthFailOp = D3D11_STENCIL_OP_KEEP ;
depthdesc . BackFace . StencilPassOp = D3D11_STENCIL_OP_KEEP ;
depthdesc . BackFace . StencilFunc = D3D11_COMPARISON_ALWAYS ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
//and change it
if ( ! FAILED ( ID3D11Device_CreateDepthStencilState ( pD3DDev11 , & depthdesc , & shaderstate . depthstates [ key ] ) ) )
ID3D11DeviceContext_OMSetDepthStencilState ( d3ddevctx , shaderstate . depthstates [ key ] , 0 ) ;
2012-09-30 05:52:03 +00:00
}
}
}
void D3D11BE_Reset ( qboolean before )
{
int i ;
2013-11-21 23:02:28 +00:00
if ( ! shaderstate . inited )
return ;
2012-09-30 05:52:03 +00:00
if ( before )
{
/*backbuffer is going away, release stuff so it can be destroyed cleanly*/
}
else
{
/*we have a new backbuffer etc, reassert state*/
for ( i = 0 ; i < MAX_TMUS ; i + + )
{
shaderstate . tmuflags [ i ] = ~ 0 ;
BE_ApplyTMUState ( i , 0 ) ;
}
/*force all state to change, thus setting a known state*/
shaderstate . shaderbits = ~ 0 ;
2013-11-21 23:02:28 +00:00
D3D11BE_ApplyShaderBits ( 0 , NULL ) ;
2012-09-30 05:52:03 +00:00
}
}
static const char LIGHTPASS_SHADER [ ] = " \
{ \ n \
program rtlight \ n \
{ \ n \
blendfunc add \ n \
} \ n \
} " ;
void D3D11BE_Init ( void )
{
D3D11_BUFFER_DESC bd ;
int i ;
2015-09-06 03:30:28 +00:00
be_maxpasses = 1 ;
2012-09-30 05:52:03 +00:00
memset ( & shaderstate , 0 , sizeof ( shaderstate ) ) ;
2013-11-21 23:02:28 +00:00
shaderstate . inited = true ;
2012-09-30 05:52:03 +00:00
shaderstate . curvertdecl = - 1 ;
2013-10-08 16:13:18 +00:00
for ( i = 0 ; i < MAXRLIGHTMAPS ; i + + )
2012-09-30 05:52:03 +00:00
shaderstate . dummybatch . lightmap [ i ] = - 1 ;
2015-09-06 03:30:28 +00:00
FTable_Init ( ) ;
2014-10-05 20:04:11 +00:00
// BE_CreateSamplerStates();
2012-09-30 05:52:03 +00:00
// FTable_Init();
/* shaderstate.dynxyz_size = sizeof(vecV_t) * DYNVBUFFSIZE;
shaderstate . dyncol_size = sizeof ( byte_vec4_t ) * DYNVBUFFSIZE ;
shaderstate . dynst_size = sizeof ( vec2_t ) * DYNVBUFFSIZE ;
shaderstate . dynidx_size = sizeof ( index_t ) * DYNIBUFFSIZE ;
*/
D3D11BE_Reset ( false ) ;
//set up the constant buffers
2012-12-04 19:37:57 +00:00
for ( i = 0 ; i < NUMECBUFFERS ; i + + )
{
bd . Usage = D3D11_USAGE_DYNAMIC ;
bd . ByteWidth = sizeof ( cbuf_entity_t ) ;
bd . BindFlags = D3D11_BIND_CONSTANT_BUFFER ;
bd . CPUAccessFlags = D3D11_CPU_ACCESS_WRITE ;
bd . MiscFlags = 0 ;
bd . StructureByteStride = 0 ;
if ( FAILED ( ID3D11Device_CreateBuffer ( pD3DDev11 , & bd , NULL , & shaderstate . ecbuffers [ i ] ) ) )
return ;
}
2012-09-30 05:52:03 +00:00
bd . Usage = D3D11_USAGE_DYNAMIC ;
2012-12-04 19:37:57 +00:00
bd . ByteWidth = sizeof ( cbuf_view_t ) ;
2012-09-30 05:52:03 +00:00
bd . BindFlags = D3D11_BIND_CONSTANT_BUFFER ;
bd . CPUAccessFlags = D3D11_CPU_ACCESS_WRITE ;
bd . MiscFlags = 0 ;
bd . StructureByteStride = 0 ;
2012-12-04 19:37:57 +00:00
if ( FAILED ( ID3D11Device_CreateBuffer ( pD3DDev11 , & bd , NULL , & shaderstate . vcbuffer ) ) )
2012-09-30 05:52:03 +00:00
return ;
2012-12-04 19:37:57 +00:00
2013-11-21 23:02:28 +00:00
bd . Usage = D3D11_USAGE_DYNAMIC ;
bd . ByteWidth = sizeof ( cbuf_light_t ) ;
bd . BindFlags = D3D11_BIND_CONSTANT_BUFFER ;
bd . CPUAccessFlags = D3D11_CPU_ACCESS_WRITE ;
bd . MiscFlags = 0 ;
bd . StructureByteStride = 0 ;
if ( FAILED ( ID3D11Device_CreateBuffer ( pD3DDev11 , & bd , NULL , & shaderstate . lcbuffer ) ) )
return ;
2012-12-04 19:37:57 +00:00
//generate the streaming buffers for stuff that doesn't provide info in nice static vbos
2014-03-30 08:55:06 +00:00
for ( i = 0 ; i < NUMIBUFFERS ; i + + )
{
bd . BindFlags = D3D11_BIND_INDEX_BUFFER ;
bd . ByteWidth = VERTEXSTREAMSIZE ;
bd . CPUAccessFlags = D3D11_CPU_ACCESS_WRITE ;
bd . MiscFlags = 0 ;
bd . StructureByteStride = 0 ;
bd . Usage = D3D11_USAGE_DYNAMIC ;
if ( FAILED ( ID3D11Device_CreateBuffer ( pD3DDev11 , & bd , NULL , & shaderstate . indexstream [ i ] ) ) )
return ;
}
for ( i = 0 ; i < NUMVBUFFERS ; i + + )
{
bd . BindFlags = D3D11_BIND_VERTEX_BUFFER ;
bd . ByteWidth = VERTEXSTREAMSIZE ;
bd . CPUAccessFlags = D3D11_CPU_ACCESS_WRITE ;
bd . MiscFlags = 0 ;
bd . StructureByteStride = 0 ;
bd . Usage = D3D11_USAGE_DYNAMIC ;
if ( FAILED ( ID3D11Device_CreateBuffer ( pD3DDev11 , & bd , NULL , & shaderstate . vertexstream [ i ] ) ) )
return ;
}
2012-09-30 05:52:03 +00:00
2014-03-30 08:55:06 +00:00
/*
2013-11-21 23:02:28 +00:00
for ( i = 0 ; i < LSHADER_MODES ; i + + )
{
if ( ( i & LSHADER_CUBE ) & & ( i & LSHADER_SPOT ) )
continue ;
shaderstate . shader_rtlight [ i ] = R_RegisterShader ( va ( " rtlight%s%s%s " ,
( i & LSHADER_SMAP ) ? " #PCF " : " " ,
( i & LSHADER_SPOT ) ? " #SPOT " : " " ,
( i & LSHADER_CUBE ) ? " #CUBE " : " " )
, SUF_NONE , LIGHTPASS_SHADER ) ;
}
2014-03-30 08:55:06 +00:00
*/
2013-11-21 23:02:28 +00:00
// shaderstate.shader_rtlight = R_RegisterShader("rtlight", SUF_NONE, LIGHTPASS_SHADER);
shaderstate . depthonly = R_RegisterShader ( " depthonly " , SUF_NONE ,
" { \n "
" program depthonly \n "
" { \n "
" depthwrite \n "
" maskcolor \n "
" } \n "
" } \n " ) ;
2012-09-30 05:52:03 +00:00
R_InitFlashblends ( ) ;
}
void D3D11BE_Shutdown ( void )
{
2016-07-12 00:40:13 +00:00
unsigned int i ;
2013-11-21 23:02:28 +00:00
shaderstate . inited = false ;
2014-03-30 08:55:06 +00:00
# ifdef RTLIGHTS
2013-11-21 23:02:28 +00:00
D3D11_TerminateShadowMap ( ) ;
2014-03-30 08:55:06 +00:00
# endif
2013-11-21 23:02:28 +00:00
BE_DestroyVariousStates ( ) ;
2012-09-30 05:52:03 +00:00
Z_Free ( shaderstate . wbatches ) ;
shaderstate . wbatches = NULL ;
2016-07-12 00:40:13 +00:00
for ( i = 0 ; i < countof ( shaderstate . programfixedemu ) ; i + + )
Shader_ReleaseGeneric ( shaderstate . programfixedemu [ i ] ) ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
static void allocvertexbuffer ( ID3D11Buffer * * buf , unsigned int * offset , void * * dest , unsigned int sz )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
D3D11_MAPPED_SUBRESOURCE msr ;
unsigned int maptype ;
sz = ( sz + 63 ) & ~ 63 ; //try to align it to a cacheline. I assume the memory is write-through cached.
if ( shaderstate . purgevertexstream | | shaderstate . vertexstreamoffset + sz > VERTEXSTREAMSIZE )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
shaderstate . purgevertexstream = false ;
shaderstate . vertexstreamoffset = 0 ;
maptype = D3D11_MAP_WRITE_DISCARD ;
shaderstate . vertexstreamcycle + + ;
if ( shaderstate . vertexstreamcycle = = NUMVBUFFERS )
shaderstate . vertexstreamcycle = 0 ;
2012-09-30 05:52:03 +00:00
}
else
{
2015-09-06 03:30:28 +00:00
maptype = D3D11_MAP_WRITE_NO_OVERWRITE ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
* buf = shaderstate . vertexstream [ shaderstate . vertexstreamcycle ] ;
if ( FAILED ( ID3D11DeviceContext_Map ( d3ddevctx , ( ID3D11Resource * ) * buf , 0 , maptype , 0 , & msr ) ) )
{
* offset = 0 ;
* buf = NULL ;
* dest = NULL ;
Con_Printf ( " allocvertexbuffer: failed to map vertex buffer \n " ) ;
return ;
}
* dest = ( index_t * ) ( ( qbyte * ) msr . pData + shaderstate . vertexstreamoffset ) ;
* offset = shaderstate . vertexstreamoffset ;
shaderstate . vertexstreamoffset + = sz ;
return ;
2012-09-30 05:52:03 +00:00
}
2016-07-12 00:40:13 +00:00
static unsigned int allocindexbuffer ( index_t * * dest , ID3D11Buffer * * buf , unsigned int entries )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
D3D11_MAPPED_SUBRESOURCE msr ;
unsigned int sz = sizeof ( index_t ) * entries ;
unsigned int maptype ;
unsigned int ret ;
if ( shaderstate . purgeindexstream | | shaderstate . indexstreamoffset + sz > VERTEXSTREAMSIZE )
{
shaderstate . purgeindexstream = false ;
shaderstate . indexstreamoffset = 0 ;
maptype = D3D11_MAP_WRITE_DISCARD ;
shaderstate . indexstreamcycle + + ;
if ( shaderstate . indexstreamcycle = = NUMIBUFFERS )
shaderstate . indexstreamcycle = 0 ;
2012-09-30 05:52:03 +00:00
}
else
{
2015-09-06 03:30:28 +00:00
maptype = D3D11_MAP_WRITE_NO_OVERWRITE ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
* buf = shaderstate . indexstream [ shaderstate . indexstreamcycle ] ;
if ( FAILED ( ID3D11DeviceContext_Map ( d3ddevctx , ( ID3D11Resource * ) * buf , 0 , maptype , 0 , & msr ) ) )
{
* buf = NULL ;
* dest = NULL ;
Con_Printf ( " allocindexbuffer: failed to map index buffer \n " ) ;
return 0 ;
}
* dest = ( index_t * ) ( ( qbyte * ) msr . pData + shaderstate . indexstreamoffset ) ;
ret = shaderstate . indexstreamoffset ;
shaderstate . indexstreamoffset + = sz ;
return ret ;
2012-09-30 05:52:03 +00:00
}
2014-10-05 20:04:11 +00:00
ID3D11ShaderResourceView * D3D11_Image_View ( const texid_t id ) ;
static void BindTexture ( unsigned int tu , const texid_t id )
2012-09-30 05:52:03 +00:00
{
2012-12-04 19:37:57 +00:00
ID3D11ShaderResourceView * view = D3D11_Image_View ( id ) ;
if ( shaderstate . pendingtextures [ tu ] ! = view )
2012-09-30 05:52:03 +00:00
{
2012-12-04 19:37:57 +00:00
shaderstate . textureschanged = true ;
shaderstate . pendingtextures [ tu ] = view ;
2014-10-05 20:04:11 +00:00
if ( id )
2017-07-12 08:15:27 +00:00
shaderstate . texflags [ tu ] = id - > flags & SHADER_PASS_IMAGE_FLAGS_D3D11 ;
2012-09-30 05:52:03 +00:00
}
}
2014-03-30 08:55:06 +00:00
void D3D11BE_UnbindAllTextures ( void )
{
int i ;
for ( i = 0 ; i < shaderstate . lastpasscount ; i + + )
shaderstate . pendingtextures [ i ] = NULL ;
if ( i )
{
ID3D11DeviceContext_PSSetShaderResources ( d3ddevctx , 0 , i , shaderstate . pendingtextures ) ;
shaderstate . lastpasscount = 0 ;
}
}
2015-07-31 13:23:32 +00:00
const GUID DECLSPEC_SELECTANY IID_ID3D11Texture2D = { 0x6f15aaf2 , 0xd208 , 0x4e89 , { 0x9a , 0xb4 , 0x48 , 0x95 , 0x35 , 0xd3 , 0x4f , 0x9c } } ;
static texid_t T_Gen_CurrentRender ( void )
{
2016-07-12 00:40:13 +00:00
// int vwidth, vheight;
// int pwidth = vid.fbpwidth;
// int pheight = vid.fbpheight;
2015-07-31 13:23:32 +00:00
ID3D11Texture2D * backbuf ;
# ifdef WINRT
extern IDXGISwapChain1 * d3dswapchain ;
# else
extern IDXGISwapChain * d3dswapchain ;
# endif
D3D11_TEXTURE2D_DESC tdesc = { 0 } ;
if ( r_refdef . recurse )
return r_nulltex ;
//FIXME: should be willing to use the current rendertargets instead
IDXGISwapChain_GetBuffer ( d3dswapchain , 0 , & IID_ID3D11Texture2D , ( LPVOID * ) & backbuf ) ;
ID3D11Texture2D_GetDesc ( backbuf , & tdesc ) ;
// copy the scene to texture
if ( ! TEXVALID ( shaderstate . currentrender ) | | tdesc . Width ! = shaderstate . currentrender - > width | | tdesc . Height ! = shaderstate . currentrender - > height )
{
if ( ! shaderstate . currentrender )
shaderstate . currentrender = Image_CreateTexture ( " ***$currentrender*** " , NULL , 0 ) ;
if ( ! shaderstate . currentrender )
return r_nulltex ; //err
shaderstate . currentrender - > width = tdesc . Width ;
shaderstate . currentrender - > height = tdesc . Height ;
tdesc . BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE ;
tdesc . CPUAccessFlags = 0 ;
if ( shaderstate . currentrender - > ptr )
ID3D11Texture2D_Release ( ( ID3D11Texture2D * ) shaderstate . currentrender - > ptr ) ;
shaderstate . currentrender - > ptr = NULL ;
ID3D11Device_CreateTexture2D ( pD3DDev11 , & tdesc , NULL , ( ID3D11Texture2D * * ) & shaderstate . currentrender - > ptr ) ;
}
ID3D11DeviceContext_CopyResource ( d3ddevctx , ( ID3D11Resource * ) shaderstate . currentrender - > ptr , ( ID3D11Resource * ) backbuf ) ;
if ( shaderstate . currentrender - > ptr2 )
ID3D11ShaderResourceView_Release ( ( ID3D11ShaderResourceView * ) shaderstate . currentrender - > ptr2 ) ;
shaderstate . currentrender - > ptr2 = NULL ;
return shaderstate . currentrender ;
}
2014-03-30 08:55:06 +00:00
static void SelectPassTexture ( unsigned int tu , const shaderpass_t * pass )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
extern texid_t r_whiteimage , missing_texture_gloss , missing_texture_normal ;
2012-09-30 05:52:03 +00:00
switch ( pass - > texgen )
{
default :
2013-11-21 23:02:28 +00:00
2012-09-30 05:52:03 +00:00
case T_GEN_DIFFUSE :
2014-10-05 20:04:11 +00:00
BindTexture ( tu , shaderstate . curtexnums - > base ) ;
2012-09-30 05:52:03 +00:00
break ;
case T_GEN_NORMALMAP :
2015-05-03 19:57:46 +00:00
if ( TEXLOADED ( shaderstate . curtexnums - > bump ) )
2014-10-05 20:04:11 +00:00
BindTexture ( tu , shaderstate . curtexnums - > bump ) ;
2013-11-21 23:02:28 +00:00
else
2014-10-05 20:04:11 +00:00
BindTexture ( tu , missing_texture_normal ) ;
2012-09-30 05:52:03 +00:00
break ;
case T_GEN_SPECULAR :
2015-05-03 19:57:46 +00:00
if ( TEXLOADED ( shaderstate . curtexnums - > specular ) )
2014-10-05 20:04:11 +00:00
BindTexture ( tu , shaderstate . curtexnums - > specular ) ;
2013-11-21 23:02:28 +00:00
else
2014-10-05 20:04:11 +00:00
BindTexture ( tu , missing_texture_gloss ) ;
2012-09-30 05:52:03 +00:00
break ;
case T_GEN_UPPEROVERLAY :
2014-10-05 20:04:11 +00:00
BindTexture ( tu , shaderstate . curtexnums - > upperoverlay ) ;
2012-09-30 05:52:03 +00:00
break ;
case T_GEN_LOWEROVERLAY :
2014-10-05 20:04:11 +00:00
BindTexture ( tu , shaderstate . curtexnums - > loweroverlay ) ;
2012-09-30 05:52:03 +00:00
break ;
case T_GEN_FULLBRIGHT :
2014-10-05 20:04:11 +00:00
BindTexture ( tu , shaderstate . curtexnums - > fullbright ) ;
2012-09-30 05:52:03 +00:00
break ;
case T_GEN_ANIMMAP :
2014-10-05 20:04:11 +00:00
BindTexture ( tu , pass - > anim_frames [ ( int ) ( pass - > anim_fps * shaderstate . curtime ) % pass - > anim_numframes ] ) ;
2012-09-30 05:52:03 +00:00
break ;
2013-11-21 23:02:28 +00:00
case T_GEN_3DMAP :
case T_GEN_CUBEMAP :
2012-09-30 05:52:03 +00:00
case T_GEN_SINGLEMAP :
2014-10-05 20:04:11 +00:00
BindTexture ( tu , pass - > anim_frames [ 0 ] ) ;
2012-09-30 05:52:03 +00:00
break ;
case T_GEN_DELUXMAP :
{
int lmi = shaderstate . curbatch - > lightmap [ 0 ] ;
if ( lmi < 0 | | ! lightmap [ lmi ] - > hasdeluxe )
2014-10-05 20:04:11 +00:00
BindTexture ( tu , r_nulltex ) ;
2012-09-30 05:52:03 +00:00
else
{
lmi + = 1 ;
2014-10-05 20:04:11 +00:00
BindTexture ( tu , lightmap [ lmi ] - > lightmap_texture ) ;
2012-09-30 05:52:03 +00:00
}
}
break ;
case T_GEN_LIGHTMAP :
{
int lmi = shaderstate . curbatch - > lightmap [ 0 ] ;
if ( lmi < 0 )
2014-10-05 20:04:11 +00:00
BindTexture ( tu , r_whiteimage ) ;
2012-09-30 05:52:03 +00:00
else
2014-10-05 20:04:11 +00:00
BindTexture ( tu , lightmap [ lmi ] - > lightmap_texture ) ;
2012-09-30 05:52:03 +00:00
}
break ;
2015-07-31 13:23:32 +00:00
case T_GEN_CURRENTRENDER :
BindTexture ( tu , T_Gen_CurrentRender ( ) ) ;
break ;
2012-09-30 05:52:03 +00:00
case T_GEN_VIDEOMAP :
2017-02-21 20:22:07 +00:00
# ifdef HAVE_MEDIA_DECODER
2014-03-30 08:55:06 +00:00
if ( pass - > cin )
2012-12-04 19:37:57 +00:00
{
2014-10-05 20:04:11 +00:00
BindTexture ( tu , Media_UpdateForShader ( pass - > cin ) ) ;
2014-03-30 08:55:06 +00:00
break ;
2012-12-04 19:37:57 +00:00
}
2014-03-30 08:55:06 +00:00
# endif
2014-10-05 20:04:11 +00:00
BindTexture ( tu , r_nulltex ) ;
2012-09-30 05:52:03 +00:00
break ;
2013-11-21 23:02:28 +00:00
case T_GEN_LIGHTCUBEMAP : //light's projected cubemap
2015-09-06 03:30:28 +00:00
if ( shaderstate . curdlight )
BindTexture ( tu , shaderstate . curdlight - > cubetexture ) ;
else
BindTexture ( tu , r_nulltex ) ;
2013-11-21 23:02:28 +00:00
break ;
case T_GEN_SHADOWMAP : //light's depth values.
2014-03-30 08:55:06 +00:00
# ifdef RTLIGHTS
if ( shaderstate . curdlight )
{
2014-10-05 20:04:11 +00:00
BindTexture ( tu , D3D11_GetShadowMap ( shaderstate . curdlight - > fov > 0 ) ) ;
2013-11-21 23:02:28 +00:00
break ;
2014-03-30 08:55:06 +00:00
}
# endif
2014-10-05 20:04:11 +00:00
BindTexture ( tu , r_nulltex ) ;
2013-11-21 23:02:28 +00:00
break ;
case T_GEN_SOURCECOLOUR : //used for render-to-texture targets
case T_GEN_SOURCEDEPTH : //used for render-to-texture targets
case T_GEN_REFLECTION : //reflection image (mirror-as-fbo)
case T_GEN_REFRACTION : //refraction image (portal-as-fbo)
case T_GEN_REFRACTIONDEPTH : //refraction image (portal-as-fbo)
case T_GEN_RIPPLEMAP : //ripplemap image (water surface distortions-as-fbo)
case T_GEN_SOURCECUBE : //used for render-to-texture targets
2014-10-05 20:04:11 +00:00
BindTexture ( tu , r_nulltex ) ;
2013-11-21 23:02:28 +00:00
break ;
2012-09-30 05:52:03 +00:00
}
BE_ApplyTMUState ( tu , pass - > flags ) ;
//pass blend modes are skipped - they're really only useful for fixed function. we should just use blend modes instead.
}
static void colourgenbyte ( const shaderpass_t * pass , int cnt , byte_vec4_t * srcb , vec4_t * srcf , byte_vec4_t * dst , const mesh_t * mesh )
{
2015-09-06 03:30:28 +00:00
# define D3DCOLOR unsigned int
# define D3DCOLOR_ARGB(a,r,g,b) ((D3DCOLOR)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
# define D3DCOLOR_COLORVALUE(r,g,b,a) D3DCOLOR_RGBA((DWORD)((r)*255.f),(DWORD)((g)*255.f),(DWORD)((b)*255.f),(DWORD)((a)*255.f))
# define D3DCOLOR_RGBA(r,g,b,a) D3DCOLOR_ARGB(a,r,g,b)
2012-09-30 05:52:03 +00:00
D3DCOLOR block ;
2015-09-06 03:30:28 +00:00
2012-09-30 05:52:03 +00:00
switch ( pass - > rgbgen )
{
case RGB_GEN_ENTITY :
block = D3DCOLOR_COLORVALUE ( shaderstate . curentity - > shaderRGBAf [ 0 ] , shaderstate . curentity - > shaderRGBAf [ 1 ] , shaderstate . curentity - > shaderRGBAf [ 2 ] , shaderstate . curentity - > shaderRGBAf [ 3 ] ) ;
while ( ( cnt ) - - )
{
( ( D3DCOLOR * ) dst ) [ cnt ] = block ;
}
break ;
case RGB_GEN_ONE_MINUS_ENTITY :
block = D3DCOLOR_COLORVALUE ( 1 - shaderstate . curentity - > shaderRGBAf [ 0 ] , 1 - shaderstate . curentity - > shaderRGBAf [ 1 ] , 1 - shaderstate . curentity - > shaderRGBAf [ 2 ] , 1 - shaderstate . curentity - > shaderRGBAf [ 3 ] ) ;
while ( ( cnt ) - - )
{
( ( D3DCOLOR * ) dst ) [ cnt ] = block ;
}
break ;
case RGB_GEN_VERTEX_LIGHTING :
case RGB_GEN_VERTEX_EXACT :
if ( srcb )
{
while ( ( cnt ) - - )
{
qbyte r , g , b ;
r = srcb [ cnt ] [ 0 ] ;
g = srcb [ cnt ] [ 1 ] ;
b = srcb [ cnt ] [ 2 ] ;
dst [ cnt ] [ 0 ] = b ;
dst [ cnt ] [ 1 ] = g ;
dst [ cnt ] [ 2 ] = r ;
}
}
else if ( srcf )
{
while ( ( cnt ) - - )
{
int r , g , b ;
r = srcf [ cnt ] [ 0 ] * 255 ;
g = srcf [ cnt ] [ 1 ] * 255 ;
b = srcf [ cnt ] [ 2 ] * 255 ;
dst [ cnt ] [ 0 ] = bound ( 0 , b , 255 ) ;
dst [ cnt ] [ 1 ] = bound ( 0 , g , 255 ) ;
dst [ cnt ] [ 2 ] = bound ( 0 , r , 255 ) ;
}
}
else
goto identity ;
break ;
case RGB_GEN_ONE_MINUS_VERTEX :
if ( srcb )
{
while ( ( cnt ) - - )
{
qbyte r , g , b ;
r = 255 - srcb [ cnt ] [ 0 ] ;
g = 255 - srcb [ cnt ] [ 1 ] ;
b = 255 - srcb [ cnt ] [ 2 ] ;
dst [ cnt ] [ 0 ] = b ;
dst [ cnt ] [ 1 ] = g ;
dst [ cnt ] [ 2 ] = r ;
}
}
else if ( srcf )
{
while ( ( cnt ) - - )
{
int r , g , b ;
r = 255 - srcf [ cnt ] [ 0 ] * 255 ;
g = 255 - srcf [ cnt ] [ 1 ] * 255 ;
b = 255 - srcf [ cnt ] [ 2 ] * 255 ;
dst [ cnt ] [ 0 ] = bound ( 0 , b , 255 ) ;
dst [ cnt ] [ 1 ] = bound ( 0 , g , 255 ) ;
dst [ cnt ] [ 2 ] = bound ( 0 , r , 255 ) ;
}
}
else
goto identity ;
break ;
case RGB_GEN_IDENTITY_LIGHTING :
//compensate for overbrights
block = D3DCOLOR_RGBA ( 255 , 255 , 255 , 255 ) ; //shaderstate.identitylighting
while ( ( cnt ) - - )
{
( ( D3DCOLOR * ) dst ) [ cnt ] = block ;
}
break ;
default :
identity :
2015-09-06 03:30:28 +00:00
case RGB_GEN_IDENTITY_OVERBRIGHT :
2012-09-30 05:52:03 +00:00
case RGB_GEN_IDENTITY :
block = D3DCOLOR_RGBA ( 255 , 255 , 255 , 255 ) ;
while ( ( cnt ) - - )
{
( ( D3DCOLOR * ) dst ) [ cnt ] = block ;
}
break ;
case RGB_GEN_CONST :
block = D3DCOLOR_COLORVALUE ( pass - > rgbgen_func . args [ 0 ] , pass - > rgbgen_func . args [ 1 ] , pass - > rgbgen_func . args [ 2 ] , 1 ) ;
while ( ( cnt ) - - )
{
( ( D3DCOLOR * ) dst ) [ cnt ] = block ;
}
break ;
case RGB_GEN_LIGHTING_DIFFUSE :
//collect lighting details for mobile entities
if ( ! mesh - > normals_array )
{
block = D3DCOLOR_RGBA ( 255 , 255 , 255 , 255 ) ;
while ( ( cnt ) - - )
{
( ( D3DCOLOR * ) dst ) [ cnt ] = block ;
}
}
else
{
R_LightArraysByte_BGR ( shaderstate . curentity , mesh - > xyz_array , dst , cnt , mesh - > normals_array ) ;
}
break ;
case RGB_GEN_WAVE :
{
float * table ;
float c ;
table = FTableForFunc ( pass - > rgbgen_func . type ) ;
c = pass - > rgbgen_func . args [ 2 ] + shaderstate . curtime * pass - > rgbgen_func . args [ 3 ] ;
c = FTABLE_EVALUATE ( table , c ) * pass - > rgbgen_func . args [ 1 ] + pass - > rgbgen_func . args [ 0 ] ;
c = bound ( 0.0f , c , 1.0f ) ;
block = D3DCOLOR_COLORVALUE ( c , c , c , 1 ) ;
while ( ( cnt ) - - )
{
( ( D3DCOLOR * ) dst ) [ cnt ] = block ;
}
}
break ;
case RGB_GEN_TOPCOLOR :
case RGB_GEN_BOTTOMCOLOR :
# ifdef warningmsg
# pragma warningmsg("fix 24bit player colours")
# endif
block = D3DCOLOR_RGBA ( 255 , 255 , 255 , 255 ) ;
while ( ( cnt ) - - )
{
( ( D3DCOLOR * ) dst ) [ cnt ] = block ;
}
// Con_Printf("RGB_GEN %i not supported\n", pass->rgbgen);
break ;
}
}
static void alphagenbyte ( const shaderpass_t * pass , int cnt , byte_vec4_t * srcb , vec4_t * srcf , byte_vec4_t * dst , const mesh_t * mesh )
{
float * table ;
unsigned char t ;
float f ;
vec3_t v1 , v2 ;
switch ( pass - > alphagen )
{
default :
case ALPHA_GEN_IDENTITY :
if ( shaderstate . flags & BEF_FORCETRANSPARENT )
{
f = shaderstate . curentity - > shaderRGBAf [ 3 ] ;
if ( f < 0 )
t = 0 ;
else if ( f > = 1 )
t = 255 ;
else
t = f * 255 ;
while ( cnt - - )
dst [ cnt ] [ 3 ] = t ;
}
else
{
while ( cnt - - )
dst [ cnt ] [ 3 ] = 255 ;
}
break ;
case ALPHA_GEN_CONST :
t = pass - > alphagen_func . args [ 0 ] * 255 ;
while ( cnt - - )
dst [ cnt ] [ 3 ] = t ;
break ;
case ALPHA_GEN_WAVE :
table = FTableForFunc ( pass - > alphagen_func . type ) ;
f = pass - > alphagen_func . args [ 2 ] + shaderstate . curtime * pass - > alphagen_func . args [ 3 ] ;
f = FTABLE_EVALUATE ( table , f ) * pass - > alphagen_func . args [ 1 ] + pass - > alphagen_func . args [ 0 ] ;
t = bound ( 0.0f , f , 1.0f ) * 255 ;
while ( cnt - - )
dst [ cnt ] [ 3 ] = t ;
break ;
case ALPHA_GEN_PORTAL :
//FIXME: should this be per-vert?
VectorAdd ( mesh - > xyz_array [ 0 ] , shaderstate . curentity - > origin , v1 ) ;
VectorSubtract ( r_origin , v1 , v2 ) ;
f = VectorLength ( v2 ) * ( 1.0 / 255.0 ) ;
t = bound ( 0.0f , f , 1.0f ) * 255 ;
while ( cnt - - )
dst [ cnt ] [ 3 ] = t ;
break ;
case ALPHA_GEN_VERTEX :
if ( srcb )
{
while ( cnt - - )
{
dst [ cnt ] [ 3 ] = srcb [ cnt ] [ 3 ] ;
}
}
else if ( srcf )
{
while ( cnt - - )
{
dst [ cnt ] [ 3 ] = bound ( 0 , srcf [ cnt ] [ 3 ] * 255 , 255 ) ;
}
}
else
{
while ( cnt - - )
{
dst [ cnt ] [ 3 ] = 255 ;
}
}
break ;
case ALPHA_GEN_ENTITY :
t = bound ( 0 , shaderstate . curentity - > shaderRGBAf [ 3 ] , 1 ) * 255 ;
while ( cnt - - )
{
dst [ cnt ] [ 3 ] = t ;
}
break ;
case ALPHA_GEN_SPECULAR :
{
int i ;
VectorSubtract ( r_origin , shaderstate . curentity - > origin , v1 ) ;
if ( ! Matrix3_Compare ( shaderstate . curentity - > axis , ( void * ) axisDefault ) )
{
2015-09-06 03:30:28 +00:00
Matrix3_Multiply_Vec3 ( shaderstate . curentity - > axis , v1 , v2 ) ;
2012-09-30 05:52:03 +00:00
}
else
{
VectorCopy ( v1 , v2 ) ;
}
for ( i = 0 ; i < cnt ; i + + )
{
VectorSubtract ( v2 , mesh - > xyz_array [ i ] , v1 ) ;
2015-09-06 03:30:28 +00:00
f = DotProduct ( v1 , mesh - > normals_array [ i ] ) * Q_rsqrt ( DotProduct ( v1 , v1 ) ) ;
2012-09-30 05:52:03 +00:00
f = f * f * f * f * f ;
2015-09-06 03:30:28 +00:00
dst [ i ] [ 3 ] = bound ( 0 , ( int ) ( f * 255 ) , 255 ) ;
2012-09-30 05:52:03 +00:00
}
}
break ;
}
}
2015-09-06 03:30:28 +00:00
//true if we used an array (flag to use uniforms for it instead if false)
static void BE_GenerateColourMods ( unsigned int vertcount , const shaderpass_t * pass )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
const mesh_t * m = shaderstate . meshlist [ 0 ] ;
2012-09-30 05:52:03 +00:00
if ( pass - > flags & SHADER_PASS_NOCOLORARRAY )
{
2015-09-06 03:30:28 +00:00
ID3D11Buffer * buf ;
unsigned char * map ;
unsigned int offset ;
byte_vec4_t passcolour ;
static byte_vec4_t fakesource = { 0xff , 0xff , 0xff , 0xff } ;
allocvertexbuffer ( & buf , & offset , ( void * * ) & map , sizeof ( byte_vec4_t ) ) ;
colourgenbyte ( pass , 1 , ( byte_vec4_t * ) & fakesource , NULL , ( byte_vec4_t * ) & passcolour , m ) ;
alphagenbyte ( pass , 1 , ( byte_vec4_t * ) & fakesource , NULL , ( byte_vec4_t * ) & passcolour , m ) ;
* ( int * ) map = * ( int * ) passcolour ;
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
shaderstate . stream_buffer [ D3D11_BUFF_COL ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_COL ] = offset ;
shaderstate . stream_stride [ D3D11_BUFF_COL ] = 0 ; //omg that's so lame!
2012-09-30 05:52:03 +00:00
}
else
{
2013-08-27 13:18:09 +00:00
if ( shaderstate . batchvbo & & ( m - > colors4f_array [ 0 ] & &
2012-09-30 05:52:03 +00:00
( ( pass - > rgbgen = = RGB_GEN_VERTEX_LIGHTING ) | |
( pass - > rgbgen = = RGB_GEN_VERTEX_EXACT ) | |
( pass - > rgbgen = = RGB_GEN_ONE_MINUS_VERTEX ) ) & &
( pass - > alphagen = = ALPHA_GEN_VERTEX ) ) )
{
2015-09-06 03:30:28 +00:00
shaderstate . stream_buffer [ D3D11_BUFF_COL ] = shaderstate . batchvbo - > colours [ 0 ] . d3d . buff ;
shaderstate . stream_offset [ D3D11_BUFF_COL ] = shaderstate . batchvbo - > colours [ 0 ] . d3d . offs ;
shaderstate . stream_stride [ D3D11_BUFF_COL ] = sizeof ( vbovdata_t ) ;
2012-09-30 05:52:03 +00:00
}
else
{
2015-09-06 03:30:28 +00:00
ID3D11Buffer * buf ;
byte_vec4_t * map ;
unsigned int mno ;
unsigned int offset ;
allocvertexbuffer ( & buf , & offset , ( void * * ) & map , vertcount * sizeof ( byte_vec4_t ) ) ;
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
2012-09-30 05:52:03 +00:00
{
m = shaderstate . meshlist [ mno ] ;
2015-09-06 03:30:28 +00:00
colourgenbyte ( pass , m - > numvertexes , m - > colors4b_array , m - > colors4f_array [ 0 ] , map , m ) ;
alphagenbyte ( pass , m - > numvertexes , m - > colors4b_array , m - > colors4f_array [ 0 ] , map , m ) ;
map + = m - > numvertexes ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
shaderstate . stream_buffer [ D3D11_BUFF_COL ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_COL ] = offset ;
shaderstate . stream_stride [ D3D11_BUFF_COL ] = sizeof ( byte_vec4_t ) ;
2012-09-30 05:52:03 +00:00
}
}
}
2015-09-06 03:30:28 +00:00
2012-09-30 05:52:03 +00:00
/*********************************************************************************************************/
/*========================================== texture coord generation =====================================*/
static void tcgen_environment ( float * st , unsigned int numverts , float * xyz , float * normal )
{
int i ;
vec3_t viewer , reflected ;
float d ;
vec3_t rorg ;
RotateLightVector ( shaderstate . curentity - > axis , shaderstate . curentity - > origin , r_origin , rorg ) ;
2015-09-06 03:30:28 +00:00
for ( i = 0 ; i < numverts ; i + + , xyz + = sizeof ( vecV_t ) / sizeof ( vec_t ) , normal + = 3 , st + = 2 )
2012-09-30 05:52:03 +00:00
{
VectorSubtract ( rorg , xyz , viewer ) ;
VectorNormalizeFast ( viewer ) ;
d = DotProduct ( normal , viewer ) ;
reflected [ 0 ] = normal [ 0 ] * 2 * d - viewer [ 0 ] ;
reflected [ 1 ] = normal [ 1 ] * 2 * d - viewer [ 1 ] ;
reflected [ 2 ] = normal [ 2 ] * 2 * d - viewer [ 2 ] ;
st [ 0 ] = 0.5 + reflected [ 1 ] * 0.5 ;
st [ 1 ] = 0.5 - reflected [ 2 ] * 0.5 ;
}
}
static float * tcgen ( const shaderpass_t * pass , int cnt , float * dst , const mesh_t * mesh )
{
int i ;
vecV_t * src ;
switch ( pass - > tcgen )
{
default :
case TC_GEN_BASE :
return ( float * ) mesh - > st_array ;
case TC_GEN_LIGHTMAP :
2015-09-06 03:30:28 +00:00
return ( float * ) mesh - > lmst_array [ 0 ] ;
2012-09-30 05:52:03 +00:00
case TC_GEN_NORMAL :
return ( float * ) mesh - > normals_array ;
case TC_GEN_SVECTOR :
return ( float * ) mesh - > snormals_array ;
case TC_GEN_TVECTOR :
return ( float * ) mesh - > tnormals_array ;
case TC_GEN_ENVIRONMENT :
tcgen_environment ( dst , cnt , ( float * ) mesh - > xyz_array , ( float * ) mesh - > normals_array ) ;
return dst ;
case TC_GEN_DOTPRODUCT :
return dst ; //mesh->st_array[0];
case TC_GEN_VECTOR :
src = mesh - > xyz_array ;
for ( i = 0 ; i < cnt ; i + + , dst + = 2 )
{
2016-07-12 00:40:13 +00:00
dst [ 0 ] = DotProduct ( pass - > tcgenvec [ 0 ] , src [ i ] ) ;
dst [ 1 ] = DotProduct ( pass - > tcgenvec [ 1 ] , src [ i ] ) ;
2012-09-30 05:52:03 +00:00
}
return dst ;
}
}
/*src and dst can be the same address when tcmods are chained*/
static void tcmod ( const tcmod_t * tcmod , int cnt , const float * src , float * dst , const mesh_t * mesh )
{
float * table ;
float t1 , t2 ;
float cost , sint ;
int j ;
2015-09-06 03:30:28 +00:00
2012-09-30 05:52:03 +00:00
switch ( tcmod - > type )
{
case SHADER_TCMOD_ROTATE :
cost = tcmod - > args [ 0 ] * shaderstate . curtime ;
sint = R_FastSin ( cost ) ;
cost = R_FastSin ( cost + 0.25 ) ;
for ( j = 0 ; j < cnt ; j + + , dst + = 2 , src + = 2 )
{
t1 = cost * ( src [ 0 ] - 0.5f ) - sint * ( src [ 1 ] - 0.5f ) + 0.5f ;
t2 = cost * ( src [ 1 ] - 0.5f ) + sint * ( src [ 0 ] - 0.5f ) + 0.5f ;
dst [ 0 ] = t1 ;
dst [ 1 ] = t2 ;
}
break ;
case SHADER_TCMOD_SCALE :
t1 = tcmod - > args [ 0 ] ;
t2 = tcmod - > args [ 1 ] ;
for ( j = 0 ; j < cnt ; j + + , dst + = 2 , src + = 2 )
{
dst [ 0 ] = src [ 0 ] * t1 ;
dst [ 1 ] = src [ 1 ] * t2 ;
}
break ;
case SHADER_TCMOD_TURB :
t1 = tcmod - > args [ 2 ] + shaderstate . curtime * tcmod - > args [ 3 ] ;
t2 = tcmod - > args [ 1 ] ;
for ( j = 0 ; j < cnt ; j + + , dst + = 2 , src + = 2 )
{
dst [ 0 ] = src [ 0 ] + R_FastSin ( src [ 0 ] * t2 + t1 ) * t2 ;
dst [ 1 ] = src [ 1 ] + R_FastSin ( src [ 1 ] * t2 + t1 ) * t2 ;
}
break ;
case SHADER_TCMOD_STRETCH :
table = FTableForFunc ( tcmod - > args [ 0 ] ) ;
t2 = tcmod - > args [ 3 ] + shaderstate . curtime * tcmod - > args [ 4 ] ;
t1 = FTABLE_EVALUATE ( table , t2 ) * tcmod - > args [ 2 ] + tcmod - > args [ 1 ] ;
t1 = t1 ? 1.0f / t1 : 1.0f ;
t2 = 0.5f - 0.5f * t1 ;
for ( j = 0 ; j < cnt ; j + + , dst + = 2 , src + = 2 )
{
dst [ 0 ] = src [ 0 ] * t1 + t2 ;
dst [ 1 ] = src [ 1 ] * t1 + t2 ;
}
break ;
case SHADER_TCMOD_SCROLL :
t1 = tcmod - > args [ 0 ] * shaderstate . curtime ;
t2 = tcmod - > args [ 1 ] * shaderstate . curtime ;
for ( j = 0 ; j < cnt ; j + + , dst + = 2 , src + = 2 )
{
dst [ 0 ] = src [ 0 ] + t1 ;
dst [ 1 ] = src [ 1 ] + t2 ;
}
break ;
case SHADER_TCMOD_TRANSFORM :
for ( j = 0 ; j < cnt ; j + + , dst + = 2 , src + = 2 )
{
t1 = src [ 0 ] ;
t2 = src [ 1 ] ;
dst [ 0 ] = t1 * tcmod - > args [ 0 ] + t2 * tcmod - > args [ 2 ] + tcmod - > args [ 4 ] ;
2017-02-19 00:15:42 +00:00
dst [ 1 ] = t1 * tcmod - > args [ 1 ] + t2 * tcmod - > args [ 3 ] + tcmod - > args [ 5 ] ;
2012-09-30 05:52:03 +00:00
}
break ;
default :
break ;
}
}
2015-09-06 03:30:28 +00:00
static void BE_GenerateTCMods ( const shaderpass_t * pass , float * dest )
2012-09-30 05:52:03 +00:00
{
mesh_t * mesh ;
unsigned int mno ;
int i ;
float * src ;
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
mesh = shaderstate . meshlist [ mno ] ;
src = tcgen ( pass , mesh - > numvertexes , dest , mesh ) ;
//tcgen might return unmodified info
if ( pass - > numtcmods )
{
tcmod ( & pass - > tcmods [ 0 ] , mesh - > numvertexes , src , dest , mesh ) ;
for ( i = 1 ; i < pass - > numtcmods ; i + + )
{
tcmod ( & pass - > tcmods [ i ] , mesh - > numvertexes , dest , dest , mesh ) ;
}
}
else if ( src ! = dest )
{
memcpy ( dest , src , sizeof ( vec2_t ) * mesh - > numvertexes ) ;
}
dest + = mesh - > numvertexes * 2 ;
}
}
2015-09-06 03:30:28 +00:00
2012-09-30 05:52:03 +00:00
//end texture coords
/*******************************************************************************************************************/
static void deformgen ( const deformv_t * deformv , int cnt , vecV_t * src , vecV_t * dst , const mesh_t * mesh )
{
float * table ;
int j , k ;
float args [ 4 ] ;
float deflect ;
switch ( deformv - > type )
{
default :
case DEFORMV_NONE :
if ( src ! = dst )
memcpy ( dst , src , sizeof ( * src ) * cnt ) ;
break ;
case DEFORMV_WAVE :
if ( ! mesh - > normals_array )
{
if ( src ! = dst )
memcpy ( dst , src , sizeof ( * src ) * cnt ) ;
return ;
}
args [ 0 ] = deformv - > func . args [ 0 ] ;
args [ 1 ] = deformv - > func . args [ 1 ] ;
args [ 3 ] = deformv - > func . args [ 2 ] + deformv - > func . args [ 3 ] * shaderstate . curtime ;
table = FTableForFunc ( deformv - > func . type ) ;
for ( j = 0 ; j < cnt ; j + + )
{
deflect = deformv - > args [ 0 ] * ( src [ j ] [ 0 ] + src [ j ] [ 1 ] + src [ j ] [ 2 ] ) + args [ 3 ] ;
deflect = FTABLE_EVALUATE ( table , deflect ) * args [ 1 ] + args [ 0 ] ;
// Deflect vertex along its normal by wave amount
VectorMA ( src [ j ] , deflect , mesh - > normals_array [ j ] , dst [ j ] ) ;
}
break ;
case DEFORMV_NORMAL :
//normal does not actually move the verts, but it does change the normals array
//we don't currently support that.
if ( src ! = dst )
memcpy ( dst , src , sizeof ( * src ) * cnt ) ;
/*
args [ 0 ] = deformv - > args [ 1 ] * shaderstate . curtime ;
for ( j = 0 ; j < cnt ; j + + )
{
args [ 1 ] = normalsArray [ j ] [ 2 ] * args [ 0 ] ;
deflect = deformv - > args [ 0 ] * R_FastSin ( args [ 1 ] ) ;
normalsArray [ j ] [ 0 ] * = deflect ;
deflect = deformv - > args [ 0 ] * R_FastSin ( args [ 1 ] + 0.25 ) ;
normalsArray [ j ] [ 1 ] * = deflect ;
VectorNormalizeFast ( normalsArray [ j ] ) ;
}
*/ break ;
case DEFORMV_MOVE :
table = FTableForFunc ( deformv - > func . type ) ;
deflect = deformv - > func . args [ 2 ] + shaderstate . curtime * deformv - > func . args [ 3 ] ;
deflect = FTABLE_EVALUATE ( table , deflect ) * deformv - > func . args [ 1 ] + deformv - > func . args [ 0 ] ;
for ( j = 0 ; j < cnt ; j + + )
VectorMA ( src [ j ] , deflect , deformv - > args , dst [ j ] ) ;
break ;
case DEFORMV_BULGE :
args [ 0 ] = deformv - > args [ 0 ] / ( 2 * M_PI ) ;
args [ 1 ] = deformv - > args [ 1 ] ;
args [ 2 ] = shaderstate . curtime * deformv - > args [ 2 ] / ( 2 * M_PI ) ;
for ( j = 0 ; j < cnt ; j + + )
{
deflect = R_FastSin ( mesh - > st_array [ j ] [ 0 ] * args [ 0 ] + args [ 2 ] ) * args [ 1 ] ;
dst [ j ] [ 0 ] = src [ j ] [ 0 ] + deflect * mesh - > normals_array [ j ] [ 0 ] ;
dst [ j ] [ 1 ] = src [ j ] [ 1 ] + deflect * mesh - > normals_array [ j ] [ 1 ] ;
dst [ j ] [ 2 ] = src [ j ] [ 2 ] + deflect * mesh - > normals_array [ j ] [ 2 ] ;
}
break ;
case DEFORMV_AUTOSPRITE :
if ( mesh - > numindexes < 6 )
break ;
for ( j = 0 ; j < cnt - 3 ; j + = 4 , src + = 4 , dst + = 4 )
{
vec3_t mid , d ;
float radius ;
mid [ 0 ] = 0.25 * ( src [ 0 ] [ 0 ] + src [ 1 ] [ 0 ] + src [ 2 ] [ 0 ] + src [ 3 ] [ 0 ] ) ;
mid [ 1 ] = 0.25 * ( src [ 0 ] [ 1 ] + src [ 1 ] [ 1 ] + src [ 2 ] [ 1 ] + src [ 3 ] [ 1 ] ) ;
mid [ 2 ] = 0.25 * ( src [ 0 ] [ 2 ] + src [ 1 ] [ 2 ] + src [ 2 ] [ 2 ] + src [ 3 ] [ 2 ] ) ;
VectorSubtract ( src [ 0 ] , mid , d ) ;
radius = 2 * VectorLength ( d ) ;
for ( k = 0 ; k < 4 ; k + + )
{
dst [ k ] [ 0 ] = mid [ 0 ] + radius * ( ( mesh - > st_array [ k ] [ 0 ] - 0.5 ) * r_refdef . m_view [ 0 + 0 ] - ( mesh - > st_array [ k ] [ 1 ] - 0.5 ) * r_refdef . m_view [ 0 + 1 ] ) ;
dst [ k ] [ 1 ] = mid [ 1 ] + radius * ( ( mesh - > st_array [ k ] [ 0 ] - 0.5 ) * r_refdef . m_view [ 4 + 0 ] - ( mesh - > st_array [ k ] [ 1 ] - 0.5 ) * r_refdef . m_view [ 4 + 1 ] ) ;
dst [ k ] [ 2 ] = mid [ 2 ] + radius * ( ( mesh - > st_array [ k ] [ 0 ] - 0.5 ) * r_refdef . m_view [ 8 + 0 ] - ( mesh - > st_array [ k ] [ 1 ] - 0.5 ) * r_refdef . m_view [ 8 + 1 ] ) ;
}
}
break ;
case DEFORMV_AUTOSPRITE2 :
if ( mesh - > numindexes < 6 )
break ;
for ( k = 0 ; k < mesh - > numindexes ; k + = 6 )
{
int long_axis , short_axis ;
vec3_t axis ;
float len [ 3 ] ;
mat3_t m0 , m1 , m2 , result ;
float * quad [ 4 ] ;
vec3_t rot_centre , tv ;
quad [ 0 ] = ( float * ) ( dst + mesh - > indexes [ k + 0 ] ) ;
quad [ 1 ] = ( float * ) ( dst + mesh - > indexes [ k + 1 ] ) ;
quad [ 2 ] = ( float * ) ( dst + mesh - > indexes [ k + 2 ] ) ;
for ( j = 2 ; j > = 0 ; j - - )
{
quad [ 3 ] = ( float * ) ( dst + mesh - > indexes [ k + 3 + j ] ) ;
if ( ! VectorEquals ( quad [ 3 ] , quad [ 0 ] ) & &
! VectorEquals ( quad [ 3 ] , quad [ 1 ] ) & &
! VectorEquals ( quad [ 3 ] , quad [ 2 ] ) )
{
break ;
}
}
// build a matrix were the longest axis of the billboard is the Y-Axis
VectorSubtract ( quad [ 1 ] , quad [ 0 ] , m0 [ 0 ] ) ;
VectorSubtract ( quad [ 2 ] , quad [ 0 ] , m0 [ 1 ] ) ;
VectorSubtract ( quad [ 2 ] , quad [ 1 ] , m0 [ 2 ] ) ;
len [ 0 ] = DotProduct ( m0 [ 0 ] , m0 [ 0 ] ) ;
len [ 1 ] = DotProduct ( m0 [ 1 ] , m0 [ 1 ] ) ;
len [ 2 ] = DotProduct ( m0 [ 2 ] , m0 [ 2 ] ) ;
if ( ( len [ 2 ] > len [ 1 ] ) & & ( len [ 2 ] > len [ 0 ] ) )
{
if ( len [ 1 ] > len [ 0 ] )
{
long_axis = 1 ;
short_axis = 0 ;
}
else
{
long_axis = 0 ;
short_axis = 1 ;
}
}
else if ( ( len [ 1 ] > len [ 2 ] ) & & ( len [ 1 ] > len [ 0 ] ) )
{
if ( len [ 2 ] > len [ 0 ] )
{
long_axis = 2 ;
short_axis = 0 ;
}
else
{
long_axis = 0 ;
short_axis = 2 ;
}
}
else //if ( (len[0] > len[1]) && (len[0] > len[2]) )
{
if ( len [ 2 ] > len [ 1 ] )
{
long_axis = 2 ;
short_axis = 1 ;
}
else
{
long_axis = 1 ;
short_axis = 2 ;
}
}
if ( DotProduct ( m0 [ long_axis ] , m0 [ short_axis ] ) )
{
VectorNormalize2 ( m0 [ long_axis ] , axis ) ;
VectorCopy ( axis , m0 [ 1 ] ) ;
if ( axis [ 0 ] | | axis [ 1 ] )
{
VectorVectors ( m0 [ 1 ] , m0 [ 2 ] , m0 [ 0 ] ) ;
}
else
{
VectorVectors ( m0 [ 1 ] , m0 [ 0 ] , m0 [ 2 ] ) ;
}
}
else
{
VectorNormalize2 ( m0 [ long_axis ] , axis ) ;
VectorNormalize2 ( m0 [ short_axis ] , m0 [ 0 ] ) ;
VectorCopy ( axis , m0 [ 1 ] ) ;
CrossProduct ( m0 [ 0 ] , m0 [ 1 ] , m0 [ 2 ] ) ;
}
for ( j = 0 ; j < 3 ; j + + )
rot_centre [ j ] = ( quad [ 0 ] [ j ] + quad [ 1 ] [ j ] + quad [ 2 ] [ j ] + quad [ 3 ] [ j ] ) * 0.25 ;
if ( shaderstate . curentity )
{
VectorAdd ( shaderstate . curentity - > origin , rot_centre , tv ) ;
}
else
{
VectorCopy ( rot_centre , tv ) ;
}
VectorSubtract ( r_origin , tv , tv ) ;
// filter any longest-axis-parts off the camera-direction
deflect = - DotProduct ( tv , axis ) ;
VectorMA ( tv , deflect , axis , m1 [ 2 ] ) ;
VectorNormalizeFast ( m1 [ 2 ] ) ;
VectorCopy ( axis , m1 [ 1 ] ) ;
CrossProduct ( m1 [ 1 ] , m1 [ 2 ] , m1 [ 0 ] ) ;
Matrix3_Transpose ( m1 , m2 ) ;
Matrix3_Multiply ( m2 , m0 , result ) ;
for ( j = 0 ; j < 4 ; j + + )
{
VectorSubtract ( quad [ j ] , rot_centre , tv ) ;
Matrix3_Multiply_Vec3 ( ( void * ) result , tv , quad [ j ] ) ;
VectorAdd ( rot_centre , quad [ j ] , quad [ j ] ) ;
}
}
break ;
// case DEFORMV_PROJECTION_SHADOW:
// break;
}
}
static void BE_ApplyUniforms ( program_t * prog , int permu )
{
2013-11-21 23:02:28 +00:00
ID3D11Buffer * cbuf [ 3 ] =
2012-12-04 19:37:57 +00:00
{
2013-11-21 23:02:28 +00:00
shaderstate . ecbuffers [ shaderstate . ecbufferidx ] , //entity buffer
shaderstate . vcbuffer , //view buffer that changes rarely
shaderstate . lcbuffer //light buffer that changes rarelyish
2012-12-04 19:37:57 +00:00
} ;
2012-09-30 05:52:03 +00:00
//FIXME: how many of these calls can we avoid?
2015-08-07 17:49:49 +00:00
ID3D11DeviceContext_IASetInputLayout ( d3ddevctx , prog - > permu [ permu ] . h . hlsl . layout ) ;
ID3D11DeviceContext_VSSetShader ( d3ddevctx , prog - > permu [ permu ] . h . hlsl . vert , NULL , 0 ) ;
ID3D11DeviceContext_HSSetShader ( d3ddevctx , prog - > permu [ permu ] . h . hlsl . hull , NULL , 0 ) ;
ID3D11DeviceContext_DSSetShader ( d3ddevctx , prog - > permu [ permu ] . h . hlsl . domain , NULL , 0 ) ;
ID3D11DeviceContext_GSSetShader ( d3ddevctx , prog - > permu [ permu ] . h . hlsl . geom , NULL , 0 ) ;
ID3D11DeviceContext_PSSetShader ( d3ddevctx , prog - > permu [ permu ] . h . hlsl . frag , NULL , 0 ) ;
ID3D11DeviceContext_IASetPrimitiveTopology ( d3ddevctx , prog - > permu [ permu ] . h . hlsl . topology ) ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
ID3D11DeviceContext_VSSetConstantBuffers ( d3ddevctx , 0 , 3 , cbuf ) ;
2015-08-07 17:49:49 +00:00
if ( prog - > permu [ permu ] . h . hlsl . hull )
2015-07-31 13:23:32 +00:00
ID3D11DeviceContext_HSSetConstantBuffers ( d3ddevctx , 0 , 3 , cbuf ) ;
2015-08-07 17:49:49 +00:00
if ( prog - > permu [ permu ] . h . hlsl . domain )
2015-07-31 13:23:32 +00:00
ID3D11DeviceContext_DSSetConstantBuffers ( d3ddevctx , 0 , 3 , cbuf ) ;
2015-08-07 17:49:49 +00:00
if ( prog - > permu [ permu ] . h . hlsl . geom )
2015-07-31 13:23:32 +00:00
ID3D11DeviceContext_GSSetConstantBuffers ( d3ddevctx , 0 , 3 , cbuf ) ;
2013-11-21 23:02:28 +00:00
ID3D11DeviceContext_PSSetConstantBuffers ( d3ddevctx , 0 , 3 , cbuf ) ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
static void BE_RenderMeshProgram ( program_t * p , shaderpass_t * pass , unsigned int vertcount , unsigned int idxfirst , unsigned int idxcount )
2012-09-30 05:52:03 +00:00
{
int passno ;
int perm = 0 ;
2015-08-07 17:49:49 +00:00
if ( TEXLOADED ( shaderstate . curtexnums - > bump ) & & p - > permu [ perm | PERMUTATION_BUMPMAP ] . h . loaded )
2012-09-30 05:52:03 +00:00
perm | = PERMUTATION_BUMPMAP ;
2015-08-07 17:49:49 +00:00
if ( TEXLOADED ( shaderstate . curtexnums - > fullbright ) & & p - > permu [ perm | PERMUTATION_FULLBRIGHT ] . h . loaded )
2012-09-30 05:52:03 +00:00
perm | = PERMUTATION_FULLBRIGHT ;
2015-08-07 17:49:49 +00:00
if ( p - > permu [ perm | PERMUTATION_UPPERLOWER ] . h . loaded & & ( TEXLOADED ( shaderstate . curtexnums - > upperoverlay ) | | TEXLOADED ( shaderstate . curtexnums - > loweroverlay ) ) )
2012-09-30 05:52:03 +00:00
perm | = PERMUTATION_UPPERLOWER ;
2015-08-07 17:49:49 +00:00
if ( r_refdef . globalfog . density & & p - > permu [ perm | PERMUTATION_FOG ] . h . loaded )
2012-09-30 05:52:03 +00:00
perm | = PERMUTATION_FOG ;
2015-05-03 19:57:46 +00:00
// if (r_glsl_offsetmapping.ival && TEXLOADED(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert)
2012-09-30 05:52:03 +00:00
// perm |= PERMUTATION_OFFSET;
BE_ApplyUniforms ( p , perm ) ;
2015-09-06 03:30:28 +00:00
D3D11BE_ApplyShaderBits ( pass - > shaderbits , & pass - > becache ) ;
2012-09-30 05:52:03 +00:00
/*activate tmus*/
2015-09-06 03:30:28 +00:00
for ( passno = 0 ; passno < pass - > numMergedPasses ; passno + + )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
SelectPassTexture ( passno , pass + passno ) ;
2012-09-30 05:52:03 +00:00
}
/*deactivate any extras*/
for ( ; passno < shaderstate . lastpasscount ; passno + + )
{
2012-12-04 19:37:57 +00:00
shaderstate . pendingtextures [ passno ] = NULL ;
shaderstate . textureschanged = true ;
2012-09-30 05:52:03 +00:00
}
2012-12-04 19:37:57 +00:00
if ( shaderstate . textureschanged )
2015-09-06 03:30:28 +00:00
ID3D11DeviceContext_PSSetShaderResources ( d3ddevctx , 0 , max ( passno , pass - > numMergedPasses ) , shaderstate . pendingtextures ) ;
shaderstate . lastpasscount = pass - > numMergedPasses ;
2012-09-30 05:52:03 +00:00
2015-09-06 03:30:28 +00:00
ID3D11DeviceContext_DrawIndexed ( d3ddevctx , idxcount , idxfirst , 0 ) ;
RQuantAdd ( RQUANT_DRAWS , 1 ) ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
static void D3D11BE_Cull ( unsigned int cullflags , int depthbias , float depthfactor )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
HRESULT hr ;
2012-09-30 05:52:03 +00:00
D3D11_RASTERIZER_DESC rasterdesc ;
ID3D11RasterizerState * newrasterizerstate ;
2015-07-31 13:23:32 +00:00
if ( shaderstate . flags & BEF_FORCETWOSIDED )
cullflags = 0 ;
else if ( cullflags )
cullflags ^ = r_refdef . flipcull ;
2012-09-30 05:52:03 +00:00
2015-09-06 03:30:28 +00:00
if ( shaderstate . curcull ! = cullflags | | shaderstate . depthbias ! = depthbias | | shaderstate . depthfactor ! = depthfactor )
2012-09-30 05:52:03 +00:00
{
shaderstate . curcull = cullflags ;
2015-09-06 03:30:28 +00:00
shaderstate . depthbias = depthbias ;
shaderstate . depthfactor = depthfactor ;
2012-09-30 05:52:03 +00:00
rasterdesc . AntialiasedLineEnable = false ;
if ( shaderstate . curcull & 1 )
{
if ( shaderstate . curcull & SHADER_CULL_FRONT )
rasterdesc . CullMode = D3D11_CULL_FRONT ;
else if ( shaderstate . curcull & SHADER_CULL_BACK )
rasterdesc . CullMode = D3D11_CULL_BACK ;
else
rasterdesc . CullMode = D3D11_CULL_NONE ;
}
else
{
if ( shaderstate . curcull & SHADER_CULL_FRONT )
rasterdesc . CullMode = D3D11_CULL_BACK ;
else if ( shaderstate . curcull & SHADER_CULL_BACK )
rasterdesc . CullMode = D3D11_CULL_FRONT ;
else
rasterdesc . CullMode = D3D11_CULL_NONE ;
}
2015-09-06 03:30:28 +00:00
rasterdesc . DepthBias = shaderstate . depthbias ;
rasterdesc . SlopeScaledDepthBias = shaderstate . depthfactor ;
2012-09-30 05:52:03 +00:00
rasterdesc . DepthBiasClamp = 0.0f ;
rasterdesc . DepthClipEnable = true ;
2014-03-30 08:55:06 +00:00
rasterdesc . FillMode = 0 ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID ;
2012-09-30 05:52:03 +00:00
rasterdesc . FrontCounterClockwise = false ;
rasterdesc . MultisampleEnable = false ;
2015-07-31 13:23:32 +00:00
rasterdesc . ScissorEnable = true ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
if ( FAILED ( hr = ID3D11Device_CreateRasterizerState ( pD3DDev11 , & rasterdesc , & newrasterizerstate ) ) )
{
if ( hr = = DXGI_ERROR_DEVICE_REMOVED )
{
hr = ID3D11Device_GetDeviceRemovedReason ( pD3DDev11 ) ;
switch ( hr )
{
case DXGI_ERROR_DEVICE_HUNG :
2014-03-30 08:55:06 +00:00
Sys_Error ( " DXGI_ERROR_DEVICE_HUNG \n The application's device failed due to badly formed commands sent by the application. \n " ) ;
2013-11-21 23:02:28 +00:00
break ;
case DXGI_ERROR_DEVICE_REMOVED :
2014-03-30 08:55:06 +00:00
Sys_Error ( " DXGI_ERROR_DEVICE_REMOVED \n The video card has been physically removed from the system, or a driver upgrade for the video card has occurred. \n " ) ;
2013-11-21 23:02:28 +00:00
break ;
case DXGI_ERROR_DEVICE_RESET :
2014-03-30 08:55:06 +00:00
Sys_Error ( " DXGI_ERROR_DEVICE_RESET \n The device failed due to a badly formed command. \n " ) ;
2013-11-21 23:02:28 +00:00
break ;
case DXGI_ERROR_DRIVER_INTERNAL_ERROR :
2014-03-30 08:55:06 +00:00
Sys_Error ( " DXGI_ERROR_DRIVER_INTERNAL_ERROR \n The driver encountered a problem and was put into the device removed state. \n " ) ;
2013-11-21 23:02:28 +00:00
break ;
case DXGI_ERROR_INVALID_CALL :
Sys_Error ( " invalid call! oh noes! \n " ) ;
break ;
default :
break ;
}
}
else
Con_Printf ( " ID3D11Device_CreateRasterizerState failed \n " ) ;
return ;
}
2012-09-30 05:52:03 +00:00
ID3D11DeviceContext_RSSetState ( d3ddevctx , newrasterizerstate ) ;
ID3D11RasterizerState_Release ( newrasterizerstate ) ;
}
}
static void BE_DrawMeshChain_Internal ( void )
{
2015-09-06 03:30:28 +00:00
shader_t * altshader ;
2012-09-30 05:52:03 +00:00
unsigned int vertcount , idxcount , idxfirst ;
mesh_t * m ;
2015-09-06 03:30:28 +00:00
qboolean vblends ; //software
2012-09-30 05:52:03 +00:00
// void *map;
2013-11-21 23:02:28 +00:00
// int i;
2012-09-30 05:52:03 +00:00
unsigned int mno ;
2015-09-06 03:30:28 +00:00
unsigned int passno ;
2016-07-12 00:40:13 +00:00
// extern cvar_t r_polygonoffset_submodel_factor;
2012-09-30 05:52:03 +00:00
// float pushdepth;
// float pushfactor;
2015-09-06 03:30:28 +00:00
altshader = shaderstate . curshader ;
switch ( shaderstate . mode )
{
case BEM_LIGHT :
altshader = shaderstate . shader_rtlight [ shaderstate . curlmode ] ;
break ;
case BEM_DEPTHONLY :
altshader = shaderstate . curshader - > bemoverrides [ bemoverride_depthonly ] ;
if ( ! altshader )
altshader = shaderstate . depthonly ;
break ;
default :
case BEM_STANDARD :
altshader = shaderstate . curshader ;
break ;
}
if ( ! altshader )
return ;
2014-03-30 08:55:06 +00:00
if ( 0 ) //shaderstate.force2d)
{
RQuantAdd ( RQUANT_2DBATCHES , 1 ) ;
}
else if ( shaderstate . curentity = = & r_worldentity )
{
RQuantAdd ( RQUANT_WORLDBATCHES , 1 ) ;
}
else
{
RQuantAdd ( RQUANT_ENTBATCHES , 1 ) ;
}
2015-09-06 03:30:28 +00:00
D3D11BE_Cull ( shaderstate . curshader - > flags & ( SHADER_CULL_FRONT | SHADER_CULL_BACK ) , shaderstate . curshader - > polyoffset . unit , shaderstate . curshader - > polyoffset . factor ) ;
2014-03-30 08:55:06 +00:00
2015-09-06 03:30:28 +00:00
memset ( shaderstate . stream_buffer , 0 , sizeof ( shaderstate . stream_buffer ) ) ;
//if this flag is set, then we have to generate our own arrays. to avoid processing extra verticies this may require that we re-pack the verts
if ( shaderstate . meshlist [ 0 ] - > xyz2_array ) // && !altshader->prog)
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
vblends = true ;
shaderstate . batchvbo = NULL ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
else
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
vblends = false ;
if ( altshader - > flags & SHADER_NEEDSARRAYS )
shaderstate . batchvbo = NULL ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
/*so are index buffers*/
if ( shaderstate . batchvbo & & shaderstate . nummeshes = = 1 )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
m = shaderstate . meshlist [ 0 ] ;
2016-07-21 19:27:59 +00:00
ID3D11DeviceContext_IASetIndexBuffer ( d3ddevctx , shaderstate . batchvbo - > indicies . d3d . buff , DXGI_FORMAT_INDEX_UINT , shaderstate . batchvbo - > indicies . d3d . offs ) ;
2015-09-06 03:30:28 +00:00
idxfirst = m - > vbofirstelement ;
vertcount = m - > vbofirstvert + m - > numvertexes ;
idxcount = m - > numindexes ;
}
else if ( shaderstate . batchvbo )
{ /*however, we still want to try to avoid discontinuities, because that would otherwise be more draw calls. we can have gaps in verts though*/
index_t * map ;
ID3D11Buffer * buf ;
unsigned int i ;
unsigned int byteofs ;
2012-09-30 05:52:03 +00:00
vertcount = shaderstate . batchvbo - > vertcount ;
2015-09-06 03:30:28 +00:00
for ( mno = 0 , idxcount = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
idxcount + = m - > numindexes ;
}
byteofs = allocindexbuffer ( & map , & buf , idxcount ) ;
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
for ( i = 0 ; i < m - > numindexes ; i + + )
map [ i ] = m - > indexes [ i ] + m - > vbofirstvert ;
map + = m - > numindexes ;
}
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
2016-07-21 19:27:59 +00:00
ID3D11DeviceContext_IASetIndexBuffer ( d3ddevctx , buf , DXGI_FORMAT_INDEX_UINT , byteofs ) ;
2015-09-06 03:30:28 +00:00
idxfirst = 0 ;
2012-09-30 05:52:03 +00:00
}
else
2015-09-06 03:30:28 +00:00
{ /*we're going to be using dynamic array stuff here, so generate an index array list that has no vertex gaps*/
index_t * map ;
ID3D11Buffer * buf ;
unsigned int i ;
unsigned int byteofs ;
2012-09-30 05:52:03 +00:00
for ( mno = 0 , vertcount = 0 , idxcount = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
vertcount + = m - > numvertexes ;
idxcount + = m - > numindexes ;
}
2015-09-06 03:30:28 +00:00
byteofs = allocindexbuffer ( & map , & buf , idxcount ) ;
for ( mno = 0 , vertcount = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
for ( i = 0 ; i < m - > numindexes ; i + + )
map [ i ] = m - > indexes [ i ] + vertcount ;
map + = m - > numindexes ;
vertcount + = m - > numvertexes ;
}
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
2016-07-21 19:27:59 +00:00
ID3D11DeviceContext_IASetIndexBuffer ( d3ddevctx , buf , DXGI_FORMAT_INDEX_UINT , byteofs ) ;
2015-09-06 03:30:28 +00:00
idxfirst = 0 ;
2012-09-30 05:52:03 +00:00
}
/*vertex buffers are common to all passes*/
2015-09-06 03:30:28 +00:00
if ( shaderstate . batchvbo & & ! vblends )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
shaderstate . stream_buffer [ D3D11_BUFF_POS ] = shaderstate . batchvbo - > coord . d3d . buff ;
shaderstate . stream_offset [ D3D11_BUFF_POS ] = shaderstate . batchvbo - > coord . d3d . offs ;
shaderstate . stream_stride [ D3D11_BUFF_POS ] = sizeof ( vbovdata_t ) ;
2012-09-30 05:52:03 +00:00
}
else
{
2015-09-06 03:30:28 +00:00
ID3D11Buffer * buf ;
vecV_t * map ;
const mesh_t * m ;
unsigned int mno ;
unsigned int offset , i ;
allocvertexbuffer ( & buf , & offset , ( void * * ) & map , vertcount * sizeof ( vecV_t ) ) ;
if ( vblends )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
const mesh_t * m = shaderstate . meshlist [ mno ] ;
vecV_t * ov = shaderstate . curshader - > numdeforms ? tmpbuf : map ;
vecV_t * iv1 = m - > xyz_array ;
vecV_t * iv2 = m - > xyz2_array ;
float w1 = m - > xyz_blendw [ 0 ] ;
float w2 = m - > xyz_blendw [ 1 ] ;
for ( i = 0 ; i < m - > numvertexes ; i + + )
{
ov [ i ] [ 0 ] = iv1 [ i ] [ 0 ] * w1 + iv2 [ i ] [ 0 ] * w2 ;
ov [ i ] [ 1 ] = iv1 [ i ] [ 1 ] * w1 + iv2 [ i ] [ 1 ] * w2 ;
ov [ i ] [ 2 ] = iv1 [ i ] [ 2 ] * w1 + iv2 [ i ] [ 2 ] * w2 ;
}
if ( shaderstate . curshader - > numdeforms )
{
for ( i = 0 ; i < shaderstate . curshader - > numdeforms - 1 ; i + + )
deformgen ( & shaderstate . curshader - > deforms [ i ] , m - > numvertexes , tmpbuf , tmpbuf , m ) ;
deformgen ( & shaderstate . curshader - > deforms [ i ] , m - > numvertexes , tmpbuf , ( vecV_t * ) map , m ) ;
}
map + = m - > numvertexes ;
2012-09-30 05:52:03 +00:00
}
}
2015-09-06 03:30:28 +00:00
else if ( shaderstate . curshader - > numdeforms > 1 )
{ //horrible code, because multiple deforms would otherwise READ from the gpu memory
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
deformgen ( & shaderstate . curshader - > deforms [ 0 ] , m - > numvertexes , m - > xyz_array , tmpbuf , m ) ;
for ( i = 1 ; i < shaderstate . curshader - > numdeforms - 1 ; i + + )
deformgen ( & shaderstate . curshader - > deforms [ i ] , m - > numvertexes , tmpbuf , tmpbuf , m ) ;
deformgen ( & shaderstate . curshader - > deforms [ i ] , m - > numvertexes , tmpbuf , ( vecV_t * ) map , m ) ;
map + = m - > numvertexes ;
}
}
else
{
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
deformgen ( & shaderstate . curshader - > deforms [ 0 ] , m - > numvertexes , m - > xyz_array , ( vecV_t * ) map , m ) ;
map + = m - > numvertexes ;
}
}
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
shaderstate . stream_buffer [ D3D11_BUFF_POS ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_POS ] = offset ;
shaderstate . stream_stride [ D3D11_BUFF_POS ] = sizeof ( vecV_t ) ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
if ( altshader - > prog )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
if ( shaderstate . batchvbo )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
shaderstate . stream_buffer [ D3D11_BUFF_COL ] = shaderstate . batchvbo - > colours [ 0 ] . d3d . buff ;
shaderstate . stream_offset [ D3D11_BUFF_COL ] = shaderstate . batchvbo - > colours [ 0 ] . d3d . offs ;
shaderstate . stream_stride [ D3D11_BUFF_COL ] = sizeof ( vbovdata_t ) ;
shaderstate . stream_buffer [ D3D11_BUFF_TC ] = shaderstate . batchvbo - > texcoord . d3d . buff ;
shaderstate . stream_offset [ D3D11_BUFF_TC ] = shaderstate . batchvbo - > texcoord . d3d . offs ;
shaderstate . stream_stride [ D3D11_BUFF_TC ] = sizeof ( vbovdata_t ) ;
shaderstate . stream_buffer [ D3D11_BUFF_LMTC ] = shaderstate . batchvbo - > lmcoord [ 0 ] . d3d . buff ;
shaderstate . stream_offset [ D3D11_BUFF_LMTC ] = shaderstate . batchvbo - > lmcoord [ 0 ] . d3d . offs ;
shaderstate . stream_stride [ D3D11_BUFF_LMTC ] = sizeof ( vbovdata_t ) ;
shaderstate . stream_buffer [ D3D11_BUFF_NORM ] = shaderstate . batchvbo - > normals . d3d . buff ;
shaderstate . stream_offset [ D3D11_BUFF_NORM ] = shaderstate . batchvbo - > normals . d3d . offs ;
shaderstate . stream_stride [ D3D11_BUFF_NORM ] = sizeof ( vbovdata_t ) ;
2012-09-30 05:52:03 +00:00
}
2015-09-06 03:30:28 +00:00
else
{
ID3D11Buffer * buf ;
vec2_t * map ;
vec2_t * lmmap ;
const mesh_t * m ;
unsigned int mno ;
unsigned int offset , i ;
2012-09-30 05:52:03 +00:00
2015-09-06 03:30:28 +00:00
if ( shaderstate . meshlist [ 0 ] - > colors4f_array [ 0 ] )
{
byte_vec4_t * map ;
allocvertexbuffer ( & buf , & offset , ( void * * ) & map , vertcount * sizeof ( byte_vec4_t ) ) ;
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
for ( i = 0 ; i < m - > numvertexes ; i + + )
( ( int * ) map ) [ i ] = D3DCOLOR_COLORVALUE ( m - > colors4f_array [ 0 ] [ i ] [ 2 ] , m - > colors4f_array [ 0 ] [ i ] [ 1 ] , m - > colors4f_array [ 0 ] [ i ] [ 0 ] , m - > colors4f_array [ 0 ] [ i ] [ 3 ] ) ;
map + = m - > numvertexes ;
}
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
shaderstate . stream_buffer [ D3D11_BUFF_COL ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_COL ] = offset ;
shaderstate . stream_stride [ D3D11_BUFF_COL ] = sizeof ( byte_vec4_t ) ;
}
else if ( shaderstate . meshlist [ 0 ] - > colors4b_array )
{
byte_vec4_t * map ;
allocvertexbuffer ( & buf , & offset , ( void * * ) & map , vertcount * sizeof ( byte_vec4_t ) ) ;
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
for ( i = 0 ; i < m - > numvertexes ; i + + )
memcpy ( map , m - > colors4b_array , vertcount * sizeof ( byte_vec4_t ) ) ;
map + = m - > numvertexes ;
}
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
shaderstate . stream_buffer [ D3D11_BUFF_COL ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_COL ] = offset ;
shaderstate . stream_stride [ D3D11_BUFF_COL ] = sizeof ( byte_vec4_t ) ;
}
else
{
shaderstate . stream_buffer [ D3D11_BUFF_COL ] = 0 ;
shaderstate . stream_offset [ D3D11_BUFF_COL ] = 0 ;
shaderstate . stream_stride [ D3D11_BUFF_COL ] = 0 ;
}
if ( shaderstate . meshlist [ 0 ] - > lmst_array [ 0 ] )
{
allocvertexbuffer ( & buf , & offset , ( void * * ) & map , vertcount * sizeof ( vec4_t ) ) ;
lmmap = map + vertcount ;
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
for ( i = 0 ; i < m - > numvertexes ; i + + )
{
map [ i ] [ 0 ] = m - > st_array [ i ] [ 0 ] ;
map [ i ] [ 1 ] = m - > st_array [ i ] [ 1 ] ;
lmmap [ i ] [ 0 ] = m - > lmst_array [ 0 ] [ i ] [ 0 ] ;
lmmap [ i ] [ 1 ] = m - > lmst_array [ 0 ] [ i ] [ 1 ] ;
}
map + = m - > numvertexes ;
lmmap + = m - > numvertexes ;
}
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
shaderstate . stream_buffer [ D3D11_BUFF_TC ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_TC ] = offset ;
shaderstate . stream_stride [ D3D11_BUFF_TC ] = sizeof ( vec2_t ) ;
shaderstate . stream_buffer [ D3D11_BUFF_LMTC ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_LMTC ] = offset + vertcount * sizeof ( vec2_t ) ;
shaderstate . stream_stride [ D3D11_BUFF_LMTC ] = sizeof ( vec2_t ) ;
}
else
{
allocvertexbuffer ( & buf , & offset , ( void * * ) & map , vertcount * sizeof ( vec2_t ) ) ;
for ( mno = 0 ; mno < shaderstate . nummeshes ; mno + + )
{
m = shaderstate . meshlist [ mno ] ;
for ( i = 0 ; i < m - > numvertexes ; i + + )
{
map [ i ] [ 0 ] = m - > st_array [ i ] [ 0 ] ;
map [ i ] [ 1 ] = m - > st_array [ i ] [ 1 ] ;
}
map + = m - > numvertexes ;
}
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
shaderstate . stream_buffer [ D3D11_BUFF_TC ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_TC ] = offset ;
shaderstate . stream_stride [ D3D11_BUFF_TC ] = sizeof ( vec2_t ) ;
shaderstate . stream_buffer [ D3D11_BUFF_LMTC ] = NULL ;
shaderstate . stream_offset [ D3D11_BUFF_LMTC ] = 0 ;
shaderstate . stream_stride [ D3D11_BUFF_LMTC ] = 0 ;
}
}
ID3D11DeviceContext_IASetVertexBuffers ( d3ddevctx , 0 , D3D11_BUFF_MAX , ( ID3D11Buffer * * ) shaderstate . stream_buffer , shaderstate . stream_stride , shaderstate . stream_offset ) ;
BE_RenderMeshProgram ( altshader - > prog , altshader - > passes , vertcount , idxfirst , idxcount ) ;
}
else if ( 1 )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
shaderpass_t * p ;
//d3d11 has no fixed function pipeline. we emulate it.
for ( passno = 0 ; passno < altshader - > numpasses ; passno + = p - > numMergedPasses )
2012-09-30 05:52:03 +00:00
{
2015-09-06 03:30:28 +00:00
int emumode ;
p = & altshader - > passes [ passno ] ;
emumode = 0 ;
emumode = ( p - > shaderbits & SBITS_ATEST_BITS ) > > SBITS_ATEST_SHIFT ;
BE_GenerateColourMods ( vertcount , p ) ;
if ( shaderstate . batchvbo )
{ //texcoords are all compatible with static arrays, supposedly
if ( p - > tcgen = = TC_GEN_LIGHTMAP )
{
shaderstate . stream_buffer [ D3D11_BUFF_TC ] = shaderstate . batchvbo - > lmcoord [ 0 ] . d3d . buff ;
shaderstate . stream_offset [ D3D11_BUFF_TC ] = shaderstate . batchvbo - > lmcoord [ 0 ] . d3d . offs ;
shaderstate . stream_stride [ D3D11_BUFF_TC ] = sizeof ( vbovdata_t ) ;
}
else if ( p - > tcgen = = TC_GEN_BASE )
{
shaderstate . stream_buffer [ D3D11_BUFF_TC ] = shaderstate . batchvbo - > texcoord . d3d . buff ;
shaderstate . stream_offset [ D3D11_BUFF_TC ] = shaderstate . batchvbo - > texcoord . d3d . offs ;
shaderstate . stream_stride [ D3D11_BUFF_TC ] = sizeof ( vbovdata_t ) ;
}
else
{
Con_Printf ( " should be unreachable \n " ) ;
}
}
else
{
ID3D11Buffer * buf ;
float * map ;
unsigned int offset ;
allocvertexbuffer ( & buf , & offset , ( void * * ) & map , vertcount * sizeof ( vec2_t ) ) ;
BE_GenerateTCMods ( p , map ) ;
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) buf , 0 ) ;
shaderstate . stream_buffer [ D3D11_BUFF_TC ] = buf ;
shaderstate . stream_offset [ D3D11_BUFF_TC ] = offset ;
shaderstate . stream_stride [ D3D11_BUFF_TC ] = sizeof ( vec2_t ) ;
}
if ( ! shaderstate . programfixedemu [ emumode ] )
{
char * modes [ ] = {
" " , " #ALPHATEST=>0.0 " , " #ALPHATEST=<0.5 " , " #ALPHATEST=>=0.5 "
} ;
shaderstate . programfixedemu [ emumode ] = Shader_FindGeneric ( va ( " fixedemu%s " , modes [ emumode ] ) , QR_DIRECT3D11 ) ;
if ( ! shaderstate . programfixedemu [ emumode ] )
break ;
}
ID3D11DeviceContext_IASetVertexBuffers ( d3ddevctx , 0 , D3D11_BUFF_MAX , ( ID3D11Buffer * * ) shaderstate . stream_buffer , shaderstate . stream_stride , shaderstate . stream_offset ) ;
BE_RenderMeshProgram ( shaderstate . programfixedemu [ emumode ] , p , vertcount , idxfirst , idxcount ) ;
2012-09-30 05:52:03 +00:00
}
}
}
void D3D11BE_SelectMode ( backendmode_t mode )
{
shaderstate . mode = mode ;
if ( mode = = BEM_STENCIL )
2013-11-21 23:02:28 +00:00
D3D11BE_ApplyShaderBits ( SBITS_MASK_BITS , NULL ) ;
2012-09-30 05:52:03 +00:00
}
2014-03-30 08:55:06 +00:00
qboolean D3D11BE_GenerateRTLightShader ( unsigned int lmode )
{
if ( ! shaderstate . shader_rtlight [ lmode ] )
{
shaderstate . shader_rtlight [ lmode ] = R_RegisterShader ( va ( " rtlight%s%s%s " ,
( lmode & LSHADER_SMAP ) ? " #PCF " : " " ,
( lmode & LSHADER_SPOT ) ? " #SPOT " : " " ,
( lmode & LSHADER_CUBE ) ? " #CUBE " : " " )
, SUF_NONE , LIGHTPASS_SHADER ) ;
}
if ( ! shaderstate . shader_rtlight [ lmode ] - > prog )
return false ;
return true ;
}
2014-10-05 20:04:11 +00:00
qboolean D3D11BE_SelectDLight ( dlight_t * dl , vec3_t colour , vec3_t axis [ 3 ] , unsigned int lmode )
2012-09-30 05:52:03 +00:00
{
2014-03-30 08:55:06 +00:00
if ( ! D3D11BE_GenerateRTLightShader ( lmode ) )
{
lmode & = ~ ( LSHADER_SMAP | LSHADER_CUBE ) ;
if ( ! D3D11BE_GenerateRTLightShader ( lmode ) )
return false ;
}
2012-09-30 05:52:03 +00:00
shaderstate . curdlight = dl ;
2013-11-21 23:02:28 +00:00
shaderstate . curlmode = lmode ;
2012-09-30 05:52:03 +00:00
VectorCopy ( colour , shaderstate . curdlight_colours ) ;
2013-10-08 16:13:18 +00:00
2013-11-21 23:02:28 +00:00
D3D11BE_SetupLightCBuffer ( dl , colour ) ;
2013-10-08 16:13:18 +00:00
return true ;
2012-09-30 05:52:03 +00:00
}
2014-03-30 08:55:06 +00:00
# ifdef RTLIGHTS
2013-11-21 23:02:28 +00:00
void D3D11BE_SetupForShadowMap ( dlight_t * dl , qboolean isspot , int texwidth , int texheight , float shadowscale )
{
# define SHADOWMAP_SIZE 512
extern cvar_t r_shadow_shadowmapping_nearclip , r_shadow_shadowmapping_bias ;
float nc = r_shadow_shadowmapping_nearclip . value ;
float bias = r_shadow_shadowmapping_bias . value ;
//much of the projection matrix cancels out due to symmetry and stuff
//we need to scale between -0.5,0.5 within the sub-image. the fragment shader will center on the subimage based upon the major axis.
//in d3d, the depth value is scaled between 0 and 1 (gl is -1 to 1).
//d3d's framebuffer is upside down or something annoying like that.
shaderstate . lightshadowmapproj [ 0 ] = shadowscale * ( 1.0 - ( 1.0 / texwidth ) ) * 0.5 / 3.0 ; //pinch x inwards
shaderstate . lightshadowmapproj [ 1 ] = - shadowscale * ( 1.0 - ( 1.0 / texheight ) ) * 0.5 / 2.0 ; //pinch y inwards
shaderstate . lightshadowmapproj [ 2 ] = 0.5 * ( dl - > radius + nc ) / ( nc - dl - > radius ) ; //proj matrix 10
shaderstate . lightshadowmapproj [ 3 ] = ( dl - > radius * nc ) / ( nc - dl - > radius ) - bias * nc * ( 1024 / texheight ) ; //proj matrix 14
shaderstate . lightshadowmapscale [ 0 ] = 1.0 / ( SHADOWMAP_SIZE * 3 ) ;
shaderstate . lightshadowmapscale [ 1 ] = - 1.0 / ( SHADOWMAP_SIZE * 2 ) ;
}
2014-03-30 08:55:06 +00:00
# endif
2013-11-21 23:02:28 +00:00
2012-09-30 05:52:03 +00:00
void D3D11BE_SelectEntity ( entity_t * ent )
{
BE_RotateForEntity ( ent , ent - > model ) ;
}
void D3D11BE_GenBatchVBOs ( vbo_t * * vbochain , batch_t * firstbatch , batch_t * stopbatch )
{
int maxvboelements ;
int maxvboverts ;
int vert = 0 , idx = 0 ;
batch_t * batch ;
vbo_t * vbo ;
int i , j ;
mesh_t * m ;
ID3D11Buffer * vbuff ;
ID3D11Buffer * ebuff ;
index_t * vboedata , * vboedatastart ;
vbovdata_t * vbovdata , * vbovdatastart ;
D3D11_BUFFER_DESC vbodesc ;
D3D11_BUFFER_DESC ebodesc ;
D3D11_SUBRESOURCE_DATA srd ;
vbo = Z_Malloc ( sizeof ( * vbo ) ) ;
maxvboverts = 0 ;
maxvboelements = 0 ;
for ( batch = firstbatch ; batch ! = stopbatch ; batch = batch - > next )
{
for ( i = 0 ; i < batch - > maxmeshes ; i + + )
{
m = batch - > mesh [ i ] ;
maxvboelements + = m - > numindexes ;
maxvboverts + = m - > numvertexes ;
}
}
vbovdatastart = vbovdata = BZ_Malloc ( sizeof ( * vbovdata ) * maxvboverts ) ;
vboedatastart = vboedata = BZ_Malloc ( sizeof ( * vboedata ) * maxvboelements ) ;
for ( batch = firstbatch ; batch ! = stopbatch ; batch = batch - > next )
{
batch - > vbo = vbo ;
for ( j = 0 ; j < batch - > maxmeshes ; j + + )
{
m = batch - > mesh [ j ] ;
m - > vbofirstvert = vert ;
for ( i = 0 ; i < m - > numvertexes ; i + + )
{
VectorCopy ( m - > xyz_array [ i ] , vbovdata - > coord ) ;
vbovdata - > coord [ 3 ] = 1 ;
Vector2Copy ( m - > st_array [ i ] , vbovdata - > tex ) ;
if ( m - > lmst_array [ 0 ] )
Vector2Copy ( m - > lmst_array [ 0 ] [ i ] , vbovdata - > lm ) ;
else
Vector2Copy ( m - > st_array [ i ] , vbovdata - > tex ) ;
if ( m - > normals_array )
VectorCopy ( m - > normals_array [ i ] , vbovdata - > ndir ) ;
else
VectorSet ( vbovdata - > ndir , 0 , 0 , 1 ) ;
if ( m - > snormals_array )
VectorCopy ( m - > snormals_array [ i ] , vbovdata - > sdir ) ;
else
VectorSet ( vbovdata - > sdir , 1 , 0 , 0 ) ;
if ( m - > tnormals_array )
VectorCopy ( m - > tnormals_array [ i ] , vbovdata - > tdir ) ;
else
VectorSet ( vbovdata - > tdir , 0 , 1 , 0 ) ;
2013-08-27 13:18:09 +00:00
if ( m - > colors4f_array [ 0 ] )
Vector4Scale ( m - > colors4f_array [ 0 ] [ i ] , 255 , vbovdata - > colorsb ) ;
2012-09-30 05:52:03 +00:00
else if ( m - > colors4b_array )
Vector4Copy ( m - > colors4b_array [ i ] , vbovdata - > colorsb ) ;
else
Vector4Set ( vbovdata - > colorsb , 255 , 255 , 255 , 255 ) ;
vbovdata + + ;
}
m - > vbofirstelement = idx ;
for ( i = 0 ; i < m - > numindexes ; i + + )
{
* vboedata + + = vert + m - > indexes [ i ] ;
}
idx + = m - > numindexes ;
vert + = m - > numvertexes ;
}
}
//generate the ebo, and submit the data to the driver
ebodesc . BindFlags = D3D11_BIND_INDEX_BUFFER ;
ebodesc . ByteWidth = sizeof ( * vboedata ) * maxvboelements ;
ebodesc . CPUAccessFlags = 0 ;
ebodesc . MiscFlags = 0 ;
ebodesc . StructureByteStride = 0 ;
ebodesc . Usage = D3D11_USAGE_DEFAULT ;
srd . pSysMem = vboedatastart ;
srd . SysMemPitch = 0 ;
srd . SysMemSlicePitch = 0 ;
ID3D11Device_CreateBuffer ( pD3DDev11 , & ebodesc , & srd , & ebuff ) ;
2013-11-21 23:02:28 +00:00
shaderstate . numlivevbos + + ;
2012-09-30 05:52:03 +00:00
BZ_Free ( vboedatastart ) ;
//generate the vbo, and submit the data to the driver
vbodesc . BindFlags = D3D11_BIND_VERTEX_BUFFER ;
vbodesc . ByteWidth = sizeof ( * vbovdata ) * maxvboverts ;
vbodesc . CPUAccessFlags = 0 ;
vbodesc . MiscFlags = 0 ;
vbodesc . StructureByteStride = 0 ;
vbodesc . Usage = D3D11_USAGE_DEFAULT ;
srd . pSysMem = vbovdatastart ;
srd . SysMemPitch = 0 ;
srd . SysMemSlicePitch = 0 ;
ID3D11Device_CreateBuffer ( pD3DDev11 , & vbodesc , & srd , & vbuff ) ;
2013-11-21 23:02:28 +00:00
shaderstate . numlivevbos + + ;
2012-09-30 05:52:03 +00:00
BZ_Free ( vbovdatastart ) ;
vbovdata = NULL ;
vbo - > coord . d3d . buff = vbuff ;
vbo - > coord . d3d . offs = ( quintptr_t ) & vbovdata - > coord ;
vbo - > texcoord . d3d . buff = vbuff ;
vbo - > texcoord . d3d . offs = ( quintptr_t ) & vbovdata - > tex ;
vbo - > lmcoord [ 0 ] . d3d . buff = vbuff ;
vbo - > lmcoord [ 0 ] . d3d . offs = ( quintptr_t ) & vbovdata - > lm ;
vbo - > normals . d3d . buff = vbuff ;
vbo - > normals . d3d . offs = ( quintptr_t ) & vbovdata - > ndir ;
vbo - > svector . d3d . buff = vbuff ;
vbo - > svector . d3d . offs = ( quintptr_t ) & vbovdata - > sdir ;
vbo - > tvector . d3d . buff = vbuff ;
vbo - > tvector . d3d . offs = ( quintptr_t ) & vbovdata - > tdir ;
2013-08-27 13:18:09 +00:00
vbo - > colours [ 0 ] . d3d . buff = vbuff ;
vbo - > colours [ 0 ] . d3d . offs = ( quintptr_t ) & vbovdata - > colorsb ;
2012-09-30 05:52:03 +00:00
vbo - > indicies . d3d . buff = ebuff ;
vbo - > indicies . d3d . offs = 0 ;
vbo - > indexcount = maxvboelements ;
vbo - > vertcount = maxvboverts ;
vbo - > next = * vbochain ;
* vbochain = vbo ;
}
void D3D11BE_GenBrushModelVBO ( model_t * mod )
{
2017-06-22 10:29:06 +00:00
unsigned int vcount , cvcount ;
2012-09-30 05:52:03 +00:00
batch_t * batch , * fbatch ;
int sortid ;
int i ;
fbatch = NULL ;
vcount = 0 ;
for ( sortid = 0 ; sortid < SHADER_SORT_COUNT ; sortid + + )
{
if ( ! mod - > batches [ sortid ] )
continue ;
for ( fbatch = batch = mod - > batches [ sortid ] ; batch ! = NULL ; batch = batch - > next )
{
2017-06-22 10:29:06 +00:00
for ( i = 0 , cvcount = 0 ; i < batch - > maxmeshes ; i + + )
cvcount + = batch - > mesh [ i ] - > numvertexes ;
2012-09-30 05:52:03 +00:00
//firstmesh got reused as the number of verticies in each batch
2017-06-22 10:29:06 +00:00
if ( vcount + cvcount > MAX_INDICIES )
2012-09-30 05:52:03 +00:00
{
D3D11BE_GenBatchVBOs ( & mod - > vbos , fbatch , batch ) ;
fbatch = batch ;
vcount = 0 ;
}
2017-06-22 10:29:06 +00:00
vcount + = cvcount ;
2012-09-30 05:52:03 +00:00
}
D3D11BE_GenBatchVBOs ( & mod - > vbos , fbatch , batch ) ;
}
}
/*Wipes a vbo*/
void D3D11BE_ClearVBO ( vbo_t * vbo )
{
ID3D11Buffer * vbuff = vbo - > coord . d3d . buff ;
ID3D11Buffer * ebuff = vbo - > indicies . d3d . buff ;
if ( vbuff )
2013-11-21 23:02:28 +00:00
{
2012-09-30 05:52:03 +00:00
ID3D11Buffer_Release ( vbuff ) ;
2013-11-21 23:02:28 +00:00
shaderstate . numlivevbos - - ;
}
2012-09-30 05:52:03 +00:00
if ( ebuff )
2013-11-21 23:02:28 +00:00
{
2012-09-30 05:52:03 +00:00
ID3D11Buffer_Release ( ebuff ) ;
2013-11-21 23:02:28 +00:00
shaderstate . numlivevbos - - ;
}
2012-09-30 05:52:03 +00:00
vbo - > coord . d3d . buff = NULL ;
vbo - > indicies . d3d . buff = NULL ;
BZ_Free ( vbo ) ;
}
/*upload all lightmaps at the start to reduce lags*/
static void BE_UploadLightmaps ( qboolean force )
{
int i ;
for ( i = 0 ; i < numlightmaps ; i + + )
{
if ( ! lightmap [ i ] )
continue ;
if ( force )
{
lightmap [ i ] - > rectchange . l = 0 ;
lightmap [ i ] - > rectchange . t = 0 ;
2015-10-11 12:01:29 +00:00
lightmap [ i ] - > rectchange . r = lightmap [ i ] - > width ;
lightmap [ i ] - > rectchange . b = lightmap [ i ] - > height ;
2012-09-30 05:52:03 +00:00
lightmap [ i ] - > modified = true ;
}
if ( lightmap [ i ] - > modified )
{
D3D11_UploadLightmap ( lightmap [ i ] ) ;
}
}
}
void D3D11BE_UploadAllLightmaps ( void )
{
BE_UploadLightmaps ( true ) ;
}
qboolean D3D11BE_LightCullModel ( vec3_t org , model_t * model )
{
# ifdef RTLIGHTS
if ( ( shaderstate . mode = = BEM_LIGHT | | shaderstate . mode = = BEM_STENCIL ) )
{
/*true if hidden from current light*/
/*we have no rtlight support, so mneh*/
}
# endif
return false ;
}
batch_t * D3D11BE_GetTempBatch ( void )
{
if ( shaderstate . wbatch > = shaderstate . maxwbatches )
{
shaderstate . wbatch + + ;
return NULL ;
}
return & shaderstate . wbatches [ shaderstate . wbatch + + ] ;
}
2013-11-21 23:02:28 +00:00
float projd3dtogl [ 16 ] =
{
1.0 , 0.0 , 0.0 , 0.0 ,
0.0 , 1.0 , 0.0 , 0.0 ,
0.0 , 0.0 , 2.0 , 0.0 ,
0.0 , 0.0 , - 1.0 , 1.0
} ;
float projgltod3d [ 16 ] =
{
1.0 , 0.0 , 0.0 , 0.0 ,
0.0 , 1.0 , 0.0 , 0.0 ,
0.0 , 0.0 , 0.5 , 0.0 ,
0.0 , 0.0 , 0.5 , 1.0
} ;
2012-09-30 05:52:03 +00:00
void D3D11BE_SetupViewCBuffer ( void )
{
cbuf_view_t * cbv ;
D3D11_MAPPED_SUBRESOURCE msr ;
2012-12-04 19:37:57 +00:00
if ( FAILED ( ID3D11DeviceContext_Map ( d3ddevctx , ( ID3D11Resource * ) shaderstate . vcbuffer , 0 , D3D11_MAP_WRITE_DISCARD , 0 , & msr ) ) )
2012-09-30 05:52:03 +00:00
{
Con_Printf ( " BE_RotateForEntity: failed to map constant buffer \n " ) ;
return ;
}
cbv = ( cbuf_view_t * ) msr . pData ;
2013-11-21 23:02:28 +00:00
//we internally use gl-style projection matricies.
//gl's viewport is based upon -1 to 1 depth.
//d3d uses 0 to 1 depth.
//so we scale the projection matrix by a bias
# if 1
Matrix4_Multiply ( projgltod3d , r_refdef . m_projection , cbv - > m_projection ) ;
# else
memcpy ( cbv - > m_projection , r_refdef . m_projection , sizeof ( cbv - > m_projection ) ) ;
cbv - > m_projection [ 10 ] = r_refdef . m_projection [ 10 ] * 0.5 ;
# endif
2012-09-30 05:52:03 +00:00
memcpy ( cbv - > m_view , r_refdef . m_view , sizeof ( cbv - > m_view ) ) ;
VectorCopy ( r_origin , cbv - > v_eyepos ) ;
cbv - > v_time = r_refdef . time ;
2012-12-04 19:37:57 +00:00
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) shaderstate . vcbuffer , 0 ) ;
2012-09-30 05:52:03 +00:00
}
2013-11-21 23:02:28 +00:00
void D3D11BE_SetupLightCBuffer ( dlight_t * l , vec3_t colour )
{
extern cvar_t gl_specular ;
cbuf_light_t * cbl ;
D3D11_MAPPED_SUBRESOURCE msr ;
if ( FAILED ( ID3D11DeviceContext_Map ( d3ddevctx , ( ID3D11Resource * ) shaderstate . lcbuffer , 0 , D3D11_MAP_WRITE_DISCARD , 0 , & msr ) ) )
{
Con_Printf ( " BE_RotateForEntity: failed to map constant buffer \n " ) ;
return ;
}
cbl = ( cbuf_light_t * ) msr . pData ;
cbl - > l_lightradius = l - > radius ;
Matrix4x4_CM_LightMatrixFromAxis ( cbl - > l_cubematrix , l - > axis [ 0 ] , l - > axis [ 1 ] , l - > axis [ 2 ] , l - > origin ) ;
VectorCopy ( l - > origin , cbl - > l_lightposition ) ;
cbl - > padl1 = 0 ;
VectorCopy ( colour , cbl - > l_colour ) ;
2014-03-30 08:55:06 +00:00
# ifdef RTLIGHTS
2013-11-21 23:02:28 +00:00
VectorCopy ( l - > lightcolourscales , cbl - > l_lightcolourscale ) ;
cbl - > l_lightcolourscale [ 0 ] = l - > lightcolourscales [ 0 ] ;
cbl - > l_lightcolourscale [ 1 ] = l - > lightcolourscales [ 1 ] ;
cbl - > l_lightcolourscale [ 2 ] = l - > lightcolourscales [ 2 ] * gl_specular . value ;
2014-03-30 08:55:06 +00:00
# endif
2013-11-21 23:02:28 +00:00
cbl - > l_lightradius = l - > radius ;
Vector4Copy ( shaderstate . lightshadowmapproj , cbl - > l_shadowmapproj ) ;
Vector2Copy ( shaderstate . lightshadowmapscale , cbl - > l_shadowmapscale ) ;
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) shaderstate . lcbuffer , 0 ) ;
}
2016-12-07 18:45:25 +00:00
static void R_FetchPlayerColour ( unsigned int cv , vec4_t rgba )
{
int i ;
if ( cv > = 16 )
{
rgba [ 0 ] = ( ( ( cv & 0xff0000 ) > > 16 ) * * ( ( unsigned char * ) & d_8to24rgbtable [ 15 ] + 0 ) ) / ( 256.0 * 256 ) ;
rgba [ 1 ] = ( ( ( cv & 0x00ff00 ) > > 8 ) * * ( ( unsigned char * ) & d_8to24rgbtable [ 15 ] + 1 ) ) / ( 256.0 * 256 ) ;
rgba [ 2 ] = ( ( ( cv & 0x0000ff ) > > 0 ) * * ( ( unsigned char * ) & d_8to24rgbtable [ 15 ] + 2 ) ) / ( 256.0 * 256 ) ;
rgba [ 3 ] = 1.0 ;
return ;
}
i = cv ;
if ( i > = 8 )
{
i < < = 4 ;
}
else
{
i < < = 4 ;
i + = 15 ;
}
i * = 3 ;
rgba [ 0 ] = host_basepal [ i + 0 ] / 255.0 ;
rgba [ 1 ] = host_basepal [ i + 1 ] / 255.0 ;
rgba [ 2 ] = host_basepal [ i + 2 ] / 255.0 ;
rgba [ 3 ] = 1.0 ;
}
2012-09-30 05:52:03 +00:00
//also updates the entity constant buffer
static void BE_RotateForEntity ( const entity_t * e , const model_t * mod )
{
2013-11-21 23:02:28 +00:00
int i ;
2012-12-04 19:37:57 +00:00
float ndr ;
2015-09-06 05:50:16 +00:00
float modelinv [ 16 ] ;
2012-09-30 05:52:03 +00:00
float * m = shaderstate . m_model ;
cbuf_entity_t * cbe ;
D3D11_MAPPED_SUBRESOURCE msr ;
2012-12-04 19:37:57 +00:00
shaderstate . ecbufferidx = ( shaderstate . ecbufferidx + 1 ) & ( NUMECBUFFERS - 1 ) ;
if ( FAILED ( ID3D11DeviceContext_Map ( d3ddevctx , ( ID3D11Resource * ) shaderstate . ecbuffers [ shaderstate . ecbufferidx ] , 0 , D3D11_MAP_WRITE_DISCARD , 0 , & msr ) ) )
2012-09-30 05:52:03 +00:00
{
Con_Printf ( " BE_RotateForEntity: failed to map constant buffer \n " ) ;
return ;
}
cbe = ( cbuf_entity_t * ) msr . pData ;
shaderstate . curentity = e ;
2015-09-06 03:30:28 +00:00
if ( ( e - > flags & RF_WEAPONMODEL ) & & r_refdef . playerview - > viewentity > 0 )
{
float em [ 16 ] ;
float vm [ 16 ] ;
2016-07-12 00:40:13 +00:00
if ( e - > flags & RF_WEAPONMODELNOBOB )
{
vm [ 0 ] = vpn [ 0 ] ;
vm [ 1 ] = vpn [ 1 ] ;
vm [ 2 ] = vpn [ 2 ] ;
vm [ 3 ] = 0 ;
vm [ 4 ] = - vright [ 0 ] ;
vm [ 5 ] = - vright [ 1 ] ;
vm [ 6 ] = - vright [ 2 ] ;
vm [ 7 ] = 0 ;
2015-09-06 03:30:28 +00:00
2016-07-12 00:40:13 +00:00
vm [ 8 ] = vup [ 0 ] ;
vm [ 9 ] = vup [ 1 ] ;
vm [ 10 ] = vup [ 2 ] ;
vm [ 11 ] = 0 ;
2015-09-06 03:30:28 +00:00
2016-07-12 00:40:13 +00:00
vm [ 12 ] = r_refdef . vieworg [ 0 ] ;
vm [ 13 ] = r_refdef . vieworg [ 1 ] ;
vm [ 14 ] = r_refdef . vieworg [ 2 ] ;
vm [ 15 ] = 1 ;
}
else
{
vm [ 0 ] = r_refdef . playerview - > vw_axis [ 0 ] [ 0 ] ;
vm [ 1 ] = r_refdef . playerview - > vw_axis [ 0 ] [ 1 ] ;
vm [ 2 ] = r_refdef . playerview - > vw_axis [ 0 ] [ 2 ] ;
vm [ 3 ] = 0 ;
2015-09-06 03:30:28 +00:00
2016-07-12 00:40:13 +00:00
vm [ 4 ] = r_refdef . playerview - > vw_axis [ 1 ] [ 0 ] ;
vm [ 5 ] = r_refdef . playerview - > vw_axis [ 1 ] [ 1 ] ;
vm [ 6 ] = r_refdef . playerview - > vw_axis [ 1 ] [ 2 ] ;
vm [ 7 ] = 0 ;
vm [ 8 ] = r_refdef . playerview - > vw_axis [ 2 ] [ 0 ] ;
vm [ 9 ] = r_refdef . playerview - > vw_axis [ 2 ] [ 1 ] ;
vm [ 10 ] = r_refdef . playerview - > vw_axis [ 2 ] [ 2 ] ;
vm [ 11 ] = 0 ;
vm [ 12 ] = r_refdef . playerview - > vw_origin [ 0 ] ;
vm [ 13 ] = r_refdef . playerview - > vw_origin [ 1 ] ;
vm [ 14 ] = r_refdef . playerview - > vw_origin [ 2 ] ;
vm [ 15 ] = 1 ;
}
2015-09-06 03:30:28 +00:00
em [ 0 ] = e - > axis [ 0 ] [ 0 ] ;
em [ 1 ] = e - > axis [ 0 ] [ 1 ] ;
em [ 2 ] = e - > axis [ 0 ] [ 2 ] ;
em [ 3 ] = 0 ;
2012-09-30 05:52:03 +00:00
2015-09-06 03:30:28 +00:00
em [ 4 ] = e - > axis [ 1 ] [ 0 ] ;
em [ 5 ] = e - > axis [ 1 ] [ 1 ] ;
em [ 6 ] = e - > axis [ 1 ] [ 2 ] ;
em [ 7 ] = 0 ;
2012-09-30 05:52:03 +00:00
2015-09-06 03:30:28 +00:00
em [ 8 ] = e - > axis [ 2 ] [ 0 ] ;
em [ 9 ] = e - > axis [ 2 ] [ 1 ] ;
em [ 10 ] = e - > axis [ 2 ] [ 2 ] ;
em [ 11 ] = 0 ;
em [ 12 ] = e - > origin [ 0 ] ;
em [ 13 ] = e - > origin [ 1 ] ;
em [ 14 ] = e - > origin [ 2 ] ;
em [ 15 ] = 1 ;
Matrix4_Multiply ( vm , em , m ) ;
}
else
{
m [ 0 ] = e - > axis [ 0 ] [ 0 ] ;
m [ 1 ] = e - > axis [ 0 ] [ 1 ] ;
m [ 2 ] = e - > axis [ 0 ] [ 2 ] ;
m [ 3 ] = 0 ;
m [ 4 ] = e - > axis [ 1 ] [ 0 ] ;
m [ 5 ] = e - > axis [ 1 ] [ 1 ] ;
m [ 6 ] = e - > axis [ 1 ] [ 2 ] ;
m [ 7 ] = 0 ;
m [ 8 ] = e - > axis [ 2 ] [ 0 ] ;
m [ 9 ] = e - > axis [ 2 ] [ 1 ] ;
m [ 10 ] = e - > axis [ 2 ] [ 2 ] ;
m [ 11 ] = 0 ;
m [ 12 ] = e - > origin [ 0 ] ;
m [ 13 ] = e - > origin [ 1 ] ;
m [ 14 ] = e - > origin [ 2 ] ;
m [ 15 ] = 1 ;
}
2012-09-30 05:52:03 +00:00
if ( e - > scale ! = 1 & & e - > scale ! = 0 ) //hexen 2 stuff
{
2014-09-17 03:04:08 +00:00
# ifdef HEXEN2
2012-09-30 05:52:03 +00:00
float z ;
float escale ;
escale = e - > scale ;
2016-07-12 00:40:13 +00:00
switch ( e - > drawflags & SCALE_TYPE_MASK )
2012-09-30 05:52:03 +00:00
{
default :
case SCALE_TYPE_UNIFORM :
VectorScale ( ( m + 0 ) , escale , ( m + 0 ) ) ;
VectorScale ( ( m + 4 ) , escale , ( m + 4 ) ) ;
VectorScale ( ( m + 8 ) , escale , ( m + 8 ) ) ;
break ;
case SCALE_TYPE_XYONLY :
VectorScale ( ( m + 0 ) , escale , ( m + 0 ) ) ;
VectorScale ( ( m + 4 ) , escale , ( m + 4 ) ) ;
break ;
case SCALE_TYPE_ZONLY :
VectorScale ( ( m + 8 ) , escale , ( m + 8 ) ) ;
break ;
}
2016-07-12 00:40:13 +00:00
if ( mod & & ( e - > drawflags & SCALE_TYPE_MASK ) ! = SCALE_TYPE_XYONLY )
2012-09-30 05:52:03 +00:00
{
2016-07-12 00:40:13 +00:00
switch ( e - > drawflags & SCALE_ORIGIN_MASK )
2012-09-30 05:52:03 +00:00
{
case SCALE_ORIGIN_CENTER :
z = ( ( mod - > maxs [ 2 ] + mod - > mins [ 2 ] ) * ( 1 - escale ) ) / 2 ;
VectorMA ( ( m + 12 ) , z , e - > axis [ 2 ] , ( m + 12 ) ) ;
break ;
case SCALE_ORIGIN_BOTTOM :
VectorMA ( ( m + 12 ) , mod - > mins [ 2 ] * ( 1 - escale ) , e - > axis [ 2 ] , ( m + 12 ) ) ;
break ;
case SCALE_ORIGIN_TOP :
VectorMA ( ( m + 12 ) , - mod - > maxs [ 2 ] , e - > axis [ 2 ] , ( m + 12 ) ) ;
break ;
}
}
2014-09-17 03:04:08 +00:00
# else
VectorScale ( ( m + 0 ) , e - > scale , ( m + 0 ) ) ;
VectorScale ( ( m + 4 ) , e - > scale , ( m + 4 ) ) ;
VectorScale ( ( m + 8 ) , e - > scale , ( m + 8 ) ) ;
# endif
2012-09-30 05:52:03 +00:00
}
else if ( mod & & ! strcmp ( mod - > name , " progs/eyes.mdl " ) )
{
/*resize eyes, to make them easier to see*/
m [ 14 ] - = ( 22 + 8 ) ;
VectorScale ( ( m + 0 ) , 2 , ( m + 0 ) ) ;
VectorScale ( ( m + 4 ) , 2 , ( m + 4 ) ) ;
VectorScale ( ( m + 8 ) , 2 , ( m + 8 ) ) ;
}
if ( mod & & ! ruleset_allow_larger_models . ival & & mod - > clampscale ! = 1 )
{ //possibly this should be on a per-frame basis, but that's a real pain to do
Con_DPrintf ( " Rescaling %s by %f \n " , mod - > name , mod - > clampscale ) ;
VectorScale ( ( m + 0 ) , mod - > clampscale , ( m + 0 ) ) ;
VectorScale ( ( m + 4 ) , mod - > clampscale , ( m + 4 ) ) ;
VectorScale ( ( m + 8 ) , mod - > clampscale , ( m + 8 ) ) ;
}
2015-09-06 03:30:28 +00:00
memcpy ( cbe - > m_model , m , sizeof ( cbe - > m_model ) ) ;
2013-11-21 23:02:28 +00:00
Matrix4_Invert ( shaderstate . m_model , modelinv ) ;
2012-09-30 05:52:03 +00:00
cbe - > e_time = r_refdef . time - shaderstate . curentity - > shaderTime ;
VectorCopy ( e - > light_avg , cbe - > e_light_ambient ) ;
VectorCopy ( e - > light_dir , cbe - > e_light_dir ) ;
VectorCopy ( e - > light_range , cbe - > e_light_mul ) ;
2016-12-07 18:45:25 +00:00
R_FetchPlayerColour ( e - > topcolour , cbe - > e_uppercolour ) ;
R_FetchPlayerColour ( e - > bottomcolour , cbe - > e_lowercolour ) ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
//various stuff in modelspace
Matrix4x4_CM_Transform3 ( modelinv , r_origin , cbe - > e_eyepos ) ;
for ( i = 0 ; i < MAXRLIGHTMAPS ; i + + )
{
extern cvar_t gl_overbright ;
unsigned char s = shaderstate . curbatch ? shaderstate . curbatch - > lmlightstyle [ i ] : 0 ;
float sc ;
if ( s = = 255 )
{
2014-03-30 08:55:06 +00:00
if ( i = = 0 )
{
if ( shaderstate . curentity - > model & & shaderstate . curentity - > model - > engineflags & MDLF_NEEDOVERBRIGHT )
sc = ( 1 < < bound ( 0 , gl_overbright . ival , 2 ) ) * shaderstate . identitylighting ;
else
sc = shaderstate . identitylighting ;
cbe - > e_lmscale [ i ] [ 0 ] = sc ;
cbe - > e_lmscale [ i ] [ 1 ] = sc ;
cbe - > e_lmscale [ i ] [ 2 ] = sc ;
cbe - > e_lmscale [ i ] [ 3 ] = 1 ;
i + + ;
}
2013-11-21 23:02:28 +00:00
for ( ; i < MAXRLIGHTMAPS ; i + + )
{
cbe - > e_lmscale [ i ] [ 0 ] = 0 ;
cbe - > e_lmscale [ i ] [ 1 ] = 0 ;
cbe - > e_lmscale [ i ] [ 2 ] = 0 ;
cbe - > e_lmscale [ i ] [ 3 ] = 1 ;
}
break ;
}
if ( shaderstate . curentity - > model & & shaderstate . curentity - > model - > engineflags & MDLF_NEEDOVERBRIGHT )
sc = ( 1 < < bound ( 0 , gl_overbright . ival , 2 ) ) * shaderstate . identitylighting ;
else
sc = shaderstate . identitylighting ;
sc * = d_lightstylevalue [ s ] / 256.0f ;
Vector4Set ( cbe - > e_lmscale [ i ] , sc , sc , sc , 1 ) ;
}
2012-12-04 19:37:57 +00:00
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) shaderstate . ecbuffers [ shaderstate . ecbufferidx ] , 0 ) ;
2012-09-30 05:52:03 +00:00
2014-03-31 17:06:41 +00:00
ndr = ( e - > flags & RF_DEPTHHACK ) ? 0.333 : 1 ;
2012-12-04 19:37:57 +00:00
if ( ndr ! = shaderstate . depthrange )
2012-09-30 05:52:03 +00:00
{
2012-12-04 19:37:57 +00:00
D3D11_VIEWPORT vport ;
shaderstate . depthrange = ndr ;
2013-11-21 23:02:28 +00:00
vport . TopLeftX = r_refdef . pxrect . x ;
vport . TopLeftY = r_refdef . pxrect . y ;
vport . Width = r_refdef . pxrect . width ;
vport . Height = r_refdef . pxrect . height ;
2012-12-04 19:37:57 +00:00
vport . MinDepth = 0 ;
vport . MaxDepth = shaderstate . depthrange ;
2013-11-21 23:02:28 +00:00
ID3D11DeviceContext_RSSetViewports ( d3ddevctx , 1 , & vport ) ;
2012-09-30 05:52:03 +00:00
}
}
void D3D11BE_SubmitBatch ( batch_t * batch )
{
2015-05-03 19:57:46 +00:00
shader_t * shader = batch - > shader ;
2012-09-30 05:52:03 +00:00
shaderstate . nummeshes = batch - > meshes - batch - > firstmesh ;
if ( ! shaderstate . nummeshes )
return ;
2015-05-03 19:57:46 +00:00
shaderstate . curbatch = batch ;
shaderstate . batchvbo = batch - > vbo ;
shaderstate . meshlist = batch - > mesh + batch - > firstmesh ;
shaderstate . curshader = shader ;
2012-09-30 05:52:03 +00:00
if ( shaderstate . curentity ! = batch - > ent )
{
BE_RotateForEntity ( batch - > ent , batch - > ent - > model ) ;
shaderstate . curtime = r_refdef . time - shaderstate . curentity - > shaderTime ;
}
2015-05-03 19:57:46 +00:00
if ( batch - > skin )
shaderstate . curtexnums = batch - > skin ;
else if ( shader - > numdefaulttextures )
shaderstate . curtexnums = shader - > defaulttextures + ( ( int ) ( shader - > defaulttextures_fps * shaderstate . curtime ) % shader - > numdefaulttextures ) ;
else
shaderstate . curtexnums = shader - > defaulttextures ;
2012-09-30 05:52:03 +00:00
shaderstate . flags = batch - > flags ;
2015-09-06 05:50:16 +00:00
BE_DrawMeshChain_Internal ( ) ;
2012-09-30 05:52:03 +00:00
}
void D3D11BE_DrawMesh_List ( shader_t * shader , int nummeshes , mesh_t * * meshlist , vbo_t * vbo , texnums_t * texnums , unsigned int beflags )
{
shaderstate . curbatch = & shaderstate . dummybatch ;
shaderstate . batchvbo = vbo ;
shaderstate . curshader = shader ;
2015-05-03 19:57:46 +00:00
if ( texnums )
shaderstate . curtexnums = texnums ;
else if ( shader - > numdefaulttextures )
shaderstate . curtexnums = shader - > defaulttextures + ( ( int ) ( shader - > defaulttextures_fps * shaderstate . curtime ) % shader - > numdefaulttextures ) ;
else
shaderstate . curtexnums = shader - > defaulttextures ;
2012-09-30 05:52:03 +00:00
shaderstate . meshlist = meshlist ;
shaderstate . nummeshes = nummeshes ;
shaderstate . flags = beflags ;
2015-09-06 05:50:16 +00:00
BE_DrawMeshChain_Internal ( ) ;
2012-09-30 05:52:03 +00:00
}
2015-05-03 19:57:46 +00:00
void D3D11BE_DrawMesh_Single ( shader_t * shader , mesh_t * meshchain , vbo_t * vbo , unsigned int beflags )
2012-09-30 05:52:03 +00:00
{
shaderstate . curbatch = & shaderstate . dummybatch ;
shaderstate . batchvbo = vbo ;
shaderstate . curtime = realtime ;
shaderstate . curshader = shader ;
2015-05-03 19:57:46 +00:00
if ( shader - > numdefaulttextures )
shaderstate . curtexnums = shader - > defaulttextures + ( ( int ) ( shader - > defaulttextures_fps * shaderstate . curtime ) % shader - > numdefaulttextures ) ;
else
shaderstate . curtexnums = shader - > defaulttextures ;
2012-09-30 05:52:03 +00:00
shaderstate . meshlist = & meshchain ;
shaderstate . nummeshes = 1 ;
shaderstate . flags = beflags ;
2015-09-06 05:50:16 +00:00
BE_DrawMeshChain_Internal ( ) ;
2012-09-30 05:52:03 +00:00
}
static void BE_SubmitMeshesSortList ( batch_t * sortlist )
{
batch_t * batch ;
for ( batch = sortlist ; batch ; batch = batch - > next )
{
if ( batch - > meshes = = batch - > firstmesh )
continue ;
if ( batch - > buildmeshes )
batch - > buildmeshes ( batch ) ;
if ( batch - > shader - > flags & SHADER_NODLIGHT )
2013-10-08 16:13:18 +00:00
if ( shaderstate . mode = = BEM_LIGHT )
2012-09-30 05:52:03 +00:00
continue ;
if ( batch - > shader - > flags & SHADER_SKY )
{
if ( ! batch - > shader - > prog )
{
if ( shaderstate . mode = = BEM_STANDARD )
R_DrawSkyChain ( batch ) ;
continue ;
}
}
BE_SubmitBatch ( batch ) ;
}
}
/*generates a new modelview matrix, as well as vpn vectors*/
static void R_MirrorMatrix ( plane_t * plane )
{
float mirror [ 16 ] ;
float view [ 16 ] ;
float result [ 16 ] ;
vec3_t pnorm ;
VectorNegate ( plane - > normal , pnorm ) ;
mirror [ 0 ] = 1 - 2 * pnorm [ 0 ] * pnorm [ 0 ] ;
mirror [ 1 ] = - 2 * pnorm [ 0 ] * pnorm [ 1 ] ;
mirror [ 2 ] = - 2 * pnorm [ 0 ] * pnorm [ 2 ] ;
mirror [ 3 ] = 0 ;
mirror [ 4 ] = - 2 * pnorm [ 1 ] * pnorm [ 0 ] ;
mirror [ 5 ] = 1 - 2 * pnorm [ 1 ] * pnorm [ 1 ] ;
mirror [ 6 ] = - 2 * pnorm [ 1 ] * pnorm [ 2 ] ;
mirror [ 7 ] = 0 ;
mirror [ 8 ] = - 2 * pnorm [ 2 ] * pnorm [ 0 ] ;
mirror [ 9 ] = - 2 * pnorm [ 2 ] * pnorm [ 1 ] ;
mirror [ 10 ] = 1 - 2 * pnorm [ 2 ] * pnorm [ 2 ] ;
mirror [ 11 ] = 0 ;
mirror [ 12 ] = - 2 * pnorm [ 0 ] * plane - > dist ;
mirror [ 13 ] = - 2 * pnorm [ 1 ] * plane - > dist ;
mirror [ 14 ] = - 2 * pnorm [ 2 ] * plane - > dist ;
mirror [ 15 ] = 1 ;
view [ 0 ] = vpn [ 0 ] ;
view [ 1 ] = vpn [ 1 ] ;
view [ 2 ] = vpn [ 2 ] ;
view [ 3 ] = 0 ;
view [ 4 ] = - vright [ 0 ] ;
view [ 5 ] = - vright [ 1 ] ;
view [ 6 ] = - vright [ 2 ] ;
view [ 7 ] = 0 ;
view [ 8 ] = vup [ 0 ] ;
view [ 9 ] = vup [ 1 ] ;
view [ 10 ] = vup [ 2 ] ;
view [ 11 ] = 0 ;
view [ 12 ] = r_refdef . vieworg [ 0 ] ;
view [ 13 ] = r_refdef . vieworg [ 1 ] ;
view [ 14 ] = r_refdef . vieworg [ 2 ] ;
view [ 15 ] = 1 ;
VectorMA ( r_refdef . vieworg , 0.25 , plane - > normal , r_refdef . pvsorigin ) ;
Matrix4_Multiply ( mirror , view , result ) ;
vpn [ 0 ] = result [ 0 ] ;
vpn [ 1 ] = result [ 1 ] ;
vpn [ 2 ] = result [ 2 ] ;
vright [ 0 ] = - result [ 4 ] ;
vright [ 1 ] = - result [ 5 ] ;
vright [ 2 ] = - result [ 6 ] ;
vup [ 0 ] = result [ 8 ] ;
vup [ 1 ] = result [ 9 ] ;
vup [ 2 ] = result [ 10 ] ;
r_refdef . vieworg [ 0 ] = result [ 12 ] ;
r_refdef . vieworg [ 1 ] = result [ 13 ] ;
r_refdef . vieworg [ 2 ] = result [ 14 ] ;
}
static entity_t * R_NearestPortal ( plane_t * plane )
{
int i ;
entity_t * best = NULL ;
float dist , bestd = 0 ;
2012-11-27 03:23:19 +00:00
//for q3-compat, portals on world scan for a visedict to use for their view.
2012-09-30 05:52:03 +00:00
for ( i = 0 ; i < cl_numvisedicts ; i + + )
{
if ( cl_visedicts [ i ] . rtype = = RT_PORTALSURFACE )
{
dist = DotProduct ( cl_visedicts [ i ] . origin , plane - > normal ) - plane - > dist ;
dist = fabs ( dist ) ;
if ( dist < 64 & & ( ! best | | dist < bestd ) )
best = & cl_visedicts [ i ] ;
}
}
return best ;
}
static void TransformCoord ( vec3_t in , vec3_t planea [ 3 ] , vec3_t planeo , vec3_t viewa [ 3 ] , vec3_t viewo , vec3_t result )
{
int i ;
vec3_t local ;
vec3_t transformed ;
float d ;
local [ 0 ] = in [ 0 ] - planeo [ 0 ] ;
local [ 1 ] = in [ 1 ] - planeo [ 1 ] ;
local [ 2 ] = in [ 2 ] - planeo [ 2 ] ;
VectorClear ( transformed ) ;
for ( i = 0 ; i < 3 ; i + + )
{
d = DotProduct ( local , planea [ i ] ) ;
VectorMA ( transformed , d , viewa [ i ] , transformed ) ;
}
result [ 0 ] = transformed [ 0 ] + viewo [ 0 ] ;
result [ 1 ] = transformed [ 1 ] + viewo [ 1 ] ;
result [ 2 ] = transformed [ 2 ] + viewo [ 2 ] ;
}
static void TransformDir ( vec3_t in , vec3_t planea [ 3 ] , vec3_t viewa [ 3 ] , vec3_t result )
{
int i ;
float d ;
vec3_t tmp ;
VectorCopy ( in , tmp ) ;
VectorClear ( result ) ;
for ( i = 0 ; i < 3 ; i + + )
{
d = DotProduct ( tmp , planea [ i ] ) ;
VectorMA ( result , d , viewa [ i ] , result ) ;
}
}
static void R_DrawPortal ( batch_t * batch , batch_t * * blist )
{
entity_t * view ;
2016-07-12 00:40:13 +00:00
// float glplane[4];
2012-09-30 05:52:03 +00:00
plane_t plane ;
refdef_t oldrefdef ;
mesh_t * mesh = batch - > mesh [ batch - > firstmesh ] ;
int sort ;
2015-09-06 05:50:16 +00:00
if ( r_refdef . recurse ) // || !r_portalrecursion.ival)
2012-09-30 05:52:03 +00:00
return ;
VectorCopy ( mesh - > normals_array [ 0 ] , plane . normal ) ;
plane . dist = DotProduct ( mesh - > xyz_array [ 0 ] , plane . normal ) ;
//if we're too far away from the surface, don't draw anything
if ( batch - > shader - > flags & SHADER_AGEN_PORTAL )
{
/*there's a portal alpha blend on that surface, that fades out after this distance*/
if ( DotProduct ( r_refdef . vieworg , plane . normal ) - plane . dist > batch - > shader - > portaldist )
return ;
}
//if we're behind it, then also don't draw anything.
if ( DotProduct ( r_refdef . vieworg , plane . normal ) - plane . dist < 0 )
return ;
view = R_NearestPortal ( & plane ) ;
//if (!view)
// return;
oldrefdef = r_refdef ;
r_refdef . recurse = true ;
r_refdef . externalview = true ;
if ( ! view | | VectorCompare ( view - > origin , view - > oldorigin ) )
{
2013-10-08 14:28:11 +00:00
r_refdef . flipcull ^ = SHADER_CULL_FLIP ;
2012-09-30 05:52:03 +00:00
R_MirrorMatrix ( & plane ) ;
}
else
{
float d ;
vec3_t paxis [ 3 ] , porigin , vaxis [ 3 ] , vorg ;
void PerpendicularVector ( vec3_t dst , const vec3_t src ) ;
/*calculate where the surface is meant to be*/
VectorCopy ( mesh - > normals_array [ 0 ] , paxis [ 0 ] ) ;
PerpendicularVector ( paxis [ 1 ] , paxis [ 0 ] ) ;
CrossProduct ( paxis [ 0 ] , paxis [ 1 ] , paxis [ 2 ] ) ;
d = DotProduct ( view - > origin , plane . normal ) - plane . dist ;
VectorMA ( view - > origin , - d , paxis [ 0 ] , porigin ) ;
/*grab the camera origin*/
VectorNegate ( view - > axis [ 0 ] , vaxis [ 0 ] ) ;
VectorNegate ( view - > axis [ 1 ] , vaxis [ 1 ] ) ;
VectorCopy ( view - > axis [ 2 ] , vaxis [ 2 ] ) ;
VectorCopy ( view - > oldorigin , vorg ) ;
VectorCopy ( vorg , r_refdef . pvsorigin ) ;
/*rotate it a bit*/
RotatePointAroundVector ( vaxis [ 1 ] , vaxis [ 0 ] , view - > axis [ 1 ] , sin ( realtime ) * 4 ) ;
CrossProduct ( vaxis [ 0 ] , vaxis [ 1 ] , vaxis [ 2 ] ) ;
TransformCoord ( oldrefdef . vieworg , paxis , porigin , vaxis , vorg , r_refdef . vieworg ) ;
TransformDir ( vpn , paxis , vaxis , vpn ) ;
TransformDir ( vright , paxis , vaxis , vright ) ;
TransformDir ( vup , paxis , vaxis , vup ) ;
}
Matrix4x4_CM_ModelViewMatrixFromAxis ( r_refdef . m_view , vpn , vright , vup , r_refdef . vieworg ) ;
2017-02-27 09:53:59 +00:00
VectorAngles ( vpn , vup , r_refdef . viewangles , true ) ;
2012-09-30 05:52:03 +00:00
VectorCopy ( r_refdef . vieworg , r_origin ) ;
/*FIXME: the batch stuff should be done in renderscene*/
/*fixup the first mesh index*/
for ( sort = 0 ; sort < SHADER_SORT_COUNT ; sort + + )
for ( batch = blist [ sort ] ; batch ; batch = batch - > next )
{
batch - > firstmesh = batch - > meshes ;
}
2015-09-06 05:50:16 +00:00
R_SetFrustum ( r_refdef . m_projection , r_refdef . m_view ) ;
/*FIXME: we need to borrow pretty much everything about portal positioning from the gl renderer. make it common code or something, because this is horrendous.
if ( r_refdef . frustum_numplanes < MAXFRUSTUMPLANES )
{
extern int SignbitsForPlane ( mplane_t * out ) ;
mplane_t fp ;
VectorCopy ( plane . normal , fp . normal ) ;
fp . dist = plane . dist ;
fp . type = PLANE_ANYZ ;
fp . signbits = SignbitsForPlane ( & fp ) ;
if ( portaltype = = 1 | | portaltype = = 2 )
R_ObliqueNearClip ( r_refdef . m_view , & fp ) ;
//our own culling should be an epsilon forwards so we don't still draw things behind the line due to precision issues.
fp . dist + = 0.01 ;
r_refdef . frustum [ r_refdef . frustum_numplanes + + ] = fp ;
}
*/
shaderstate . curentity = NULL ;
2015-09-06 03:30:28 +00:00
Surf_SetupFrame ( ) ;
2015-09-06 05:50:16 +00:00
Surf_DrawWorld ( ) ;
2012-09-30 05:52:03 +00:00
for ( sort = 0 ; sort < SHADER_SORT_COUNT ; sort + + )
for ( batch = blist [ sort ] ; batch ; batch = batch - > next )
{
batch - > firstmesh = 0 ;
}
r_refdef = oldrefdef ;
/*broken stuff*/
AngleVectors ( r_refdef . viewangles , vpn , vright , vup ) ;
VectorCopy ( r_refdef . vieworg , r_origin ) ;
R_SetFrustum ( r_refdef . m_projection , r_refdef . m_view ) ;
2015-09-06 05:50:16 +00:00
shaderstate . curentity = NULL ;
D3D11BE_SetupViewCBuffer ( ) ;
//fixme: should be some other variable...
ID3D11DeviceContext_ClearDepthStencilView ( d3ddevctx , fb_backdepthstencil , D3D11_CLEAR_DEPTH , 1 , 0 ) ; //is it faster to clear the stencil too?
//fixme: mask the batch's depth so that later batches don't break it.
2012-09-30 05:52:03 +00:00
}
static void BE_SubmitMeshesPortals ( batch_t * * worldlist , batch_t * dynamiclist )
{
batch_t * batch , * old ;
int i ;
/*attempt to draw portal shaders*/
if ( shaderstate . mode = = BEM_STANDARD )
{
for ( i = 0 ; i < 2 ; i + + )
{
for ( batch = i ? dynamiclist : worldlist [ SHADER_SORT_PORTAL ] ; batch ; batch = batch - > next )
{
if ( batch - > meshes = = batch - > firstmesh )
continue ;
if ( batch - > buildmeshes )
batch - > buildmeshes ( batch ) ;
/*draw already-drawn portals as depth-only, to ensure that their contents are not harmed*/
BE_SelectMode ( BEM_DEPTHONLY ) ;
for ( old = worldlist [ SHADER_SORT_PORTAL ] ; old & & old ! = batch ; old = old - > next )
{
if ( old - > meshes = = old - > firstmesh )
continue ;
BE_SubmitBatch ( old ) ;
}
if ( ! old )
{
for ( old = dynamiclist ; old ! = batch ; old = old - > next )
{
if ( old - > meshes = = old - > firstmesh )
continue ;
BE_SubmitBatch ( old ) ;
}
}
BE_SelectMode ( BEM_STANDARD ) ;
R_DrawPortal ( batch , worldlist ) ;
}
}
}
}
2016-01-18 05:22:07 +00:00
void D3D11BE_SubmitMeshes ( batch_t * * worldbatches , batch_t * * blist , int first , int stop )
2012-09-30 05:52:03 +00:00
{
int i ;
for ( i = first ; i < stop ; i + + )
{
2016-01-18 05:22:07 +00:00
if ( worldbatches )
2012-09-30 05:52:03 +00:00
{
if ( i = = SHADER_SORT_PORTAL /*&& !r_noportals.ival*/ & & ! r_refdef . recurse )
2016-01-18 05:22:07 +00:00
BE_SubmitMeshesPortals ( worldbatches , blist [ i ] ) ;
2012-09-30 05:52:03 +00:00
2016-01-18 05:22:07 +00:00
BE_SubmitMeshesSortList ( worldbatches [ i ] ) ;
2012-09-30 05:52:03 +00:00
}
BE_SubmitMeshesSortList ( blist [ i ] ) ;
}
}
# ifdef RTLIGHTS
void D3D11BE_BaseEntTextures ( void )
{
batch_t * batches [ SHADER_SORT_COUNT ] ;
2013-10-08 16:13:18 +00:00
BE_GenModelBatches ( batches , shaderstate . curdlight , shaderstate . mode ) ;
2017-02-21 20:22:07 +00:00
D3D11BE_SubmitMeshes ( NULL , batches , SHADER_SORT_PORTAL , SHADER_SORT_SEETHROUGH + 1 ) ;
2012-09-30 05:52:03 +00:00
BE_SelectEntity ( & r_worldentity ) ;
}
2013-11-21 23:02:28 +00:00
void D3D11BE_GenerateShadowBuffer ( void * * vbuf_out , vecV_t * verts , int numverts , void * * ibuf_out , index_t * indicies , int numindicies )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
D3D11_BUFFER_DESC desc ;
D3D11_SUBRESOURCE_DATA srd ;
ID3D11Buffer * vbuf ;
ID3D11Buffer * ibuf ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
//generate the ebo, and submit the data to the driver
desc . BindFlags = D3D11_BIND_VERTEX_BUFFER ;
desc . ByteWidth = sizeof ( * verts ) * numverts ;
desc . CPUAccessFlags = 0 ;
desc . MiscFlags = 0 ;
desc . StructureByteStride = 0 ;
desc . Usage = D3D11_USAGE_DEFAULT ;
srd . pSysMem = verts ;
srd . SysMemPitch = 0 ;
srd . SysMemSlicePitch = 0 ;
ID3D11Device_CreateBuffer ( pD3DDev11 , & desc , & srd , & vbuf ) ;
//generate the vbo, and submit the data to the driver
desc . BindFlags = D3D11_BIND_INDEX_BUFFER ;
desc . ByteWidth = sizeof ( * indicies ) * numindicies ;
desc . CPUAccessFlags = 0 ;
desc . MiscFlags = 0 ;
desc . StructureByteStride = 0 ;
desc . Usage = D3D11_USAGE_DEFAULT ;
srd . pSysMem = indicies ;
srd . SysMemPitch = 0 ;
srd . SysMemSlicePitch = 0 ;
ID3D11Device_CreateBuffer ( pD3DDev11 , & desc , & srd , & ibuf ) ;
shaderstate . numliveshadowbuffers + + ;
* vbuf_out = vbuf ;
* ibuf_out = ibuf ;
}
void D3D11_DestroyShadowBuffer ( void * vbuf_in , void * ibuf_in )
{
ID3D11Buffer * vbuf = vbuf_in ;
ID3D11Buffer * ibuf = ibuf_in ;
if ( vbuf & & ibuf )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
ID3D11Buffer_Release ( vbuf ) ;
ID3D11Buffer_Release ( ibuf ) ;
shaderstate . numliveshadowbuffers - - ;
2012-09-30 05:52:03 +00:00
}
2013-11-21 23:02:28 +00:00
}
//draws all depth-only surfaces from the perspective of the light.
void D3D11BE_RenderShadowBuffer ( unsigned int numverts , void * vbuf , unsigned int numindicies , void * ibuf )
{
ID3D11Buffer * vbufs [ ] = { vbuf } ;
int vstrides [ ] = { sizeof ( vecV_t ) } ;
int voffsets [ ] = { 0 } ;
int i ;
2012-09-30 05:52:03 +00:00
2014-03-30 08:55:06 +00:00
if ( ! shaderstate . depthonly - > prog )
return ;
2013-11-21 23:02:28 +00:00
D3D11BE_SetupViewCBuffer ( ) ;
2015-09-06 03:30:28 +00:00
D3D11BE_Cull ( SHADER_CULL_FRONT , r_polygonoffset_shadowmap_offset . ival , r_polygonoffset_shadowmap_factor . value ) ;
2013-11-21 23:02:28 +00:00
for ( i = 0 ; i < shaderstate . lastpasscount ; i + + )
{
shaderstate . pendingtextures [ i ] = NULL ;
shaderstate . textureschanged = true ;
}
if ( shaderstate . textureschanged )
ID3D11DeviceContext_PSSetShaderResources ( d3ddevctx , 0 , shaderstate . lastpasscount , shaderstate . pendingtextures ) ;
shaderstate . lastpasscount = 0 ;
ID3D11DeviceContext_IASetVertexBuffers ( d3ddevctx , 0 , 1 , vbufs , vstrides , voffsets ) ;
2016-07-21 19:27:59 +00:00
ID3D11DeviceContext_IASetIndexBuffer ( d3ddevctx , ibuf , DXGI_FORMAT_INDEX_UINT , 0 ) ;
2013-11-21 23:02:28 +00:00
BE_ApplyUniforms ( shaderstate . depthonly - > prog , 0 ) ;
ID3D11DeviceContext_DrawIndexed ( d3ddevctx , numindicies , 0 , 0 ) ;
}
void D3D11BE_DoneShadows ( void )
{
D3D11BE_SetupViewCBuffer ( ) ;
BE_SelectEntity ( & r_worldentity ) ;
D3D11BE_BeginShadowmapFace ( ) ;
2012-09-30 05:52:03 +00:00
}
# endif
2016-11-20 20:52:41 +00:00
void D3D11BE_DrawWorld ( batch_t * * worldbatches )
2012-09-30 05:52:03 +00:00
{
batch_t * batches [ SHADER_SORT_COUNT ] ;
RSpeedLocals ( ) ;
shaderstate . curentity = NULL ;
2012-12-04 19:37:57 +00:00
shaderstate . depthrange = 0 ;
2012-09-30 05:52:03 +00:00
if ( ! r_refdef . recurse )
{
if ( shaderstate . wbatch > shaderstate . maxwbatches )
{
int newm = shaderstate . wbatch ;
Z_Free ( shaderstate . wbatches ) ;
shaderstate . wbatches = Z_Malloc ( newm * sizeof ( * shaderstate . wbatches ) ) ;
memset ( shaderstate . wbatches + shaderstate . maxwbatches , 0 , ( newm - shaderstate . maxwbatches ) * sizeof ( * shaderstate . wbatches ) ) ;
shaderstate . maxwbatches = newm ;
}
shaderstate . wbatch = 0 ;
}
D3D11BE_SetupViewCBuffer ( ) ;
2013-10-08 16:13:18 +00:00
shaderstate . curdlight = NULL ;
BE_GenModelBatches ( batches , shaderstate . curdlight , BEM_STANDARD ) ;
2012-09-30 05:52:03 +00:00
2016-11-20 20:52:41 +00:00
if ( r_refdef . scenevis )
2012-09-30 05:52:03 +00:00
{
BE_UploadLightmaps ( false ) ;
//make sure the world draws correctly
r_worldentity . shaderRGBAf [ 0 ] = 1 ;
r_worldentity . shaderRGBAf [ 1 ] = 1 ;
r_worldentity . shaderRGBAf [ 2 ] = 1 ;
r_worldentity . shaderRGBAf [ 3 ] = 1 ;
r_worldentity . axis [ 0 ] [ 0 ] = 1 ;
r_worldentity . axis [ 1 ] [ 1 ] = 1 ;
r_worldentity . axis [ 2 ] [ 2 ] = 1 ;
2013-11-21 23:02:28 +00:00
# ifdef RTLIGHTS
2016-11-20 20:52:41 +00:00
if ( r_refdef . scenevis & & r_shadow_realtime_world . ival )
2013-11-21 23:02:28 +00:00
shaderstate . identitylighting = r_shadow_realtime_world_lightmaps . value ;
else
# endif
shaderstate . identitylighting = 1 ;
2016-07-28 13:18:22 +00:00
shaderstate . identitylighting * = r_refdef . hdr_value ;
2013-11-21 23:02:28 +00:00
// shaderstate.identitylightmap = shaderstate.identitylighting / (1<<gl_overbright.ival);
2012-09-30 05:52:03 +00:00
BE_SelectMode ( BEM_STANDARD ) ;
RSpeedRemark ( ) ;
2017-02-21 20:22:07 +00:00
D3D11BE_SubmitMeshes ( worldbatches , batches , SHADER_SORT_PORTAL , SHADER_SORT_SEETHROUGH + 1 ) ;
2012-09-30 05:52:03 +00:00
RSpeedEnd ( RSPEED_WORLD ) ;
# ifdef RTLIGHTS
RSpeedRemark ( ) ;
D3D11BE_SelectEntity ( & r_worldentity ) ;
2016-11-20 20:52:41 +00:00
Sh_DrawLights ( r_refdef . scenevis ) ;
2012-09-30 05:52:03 +00:00
RSpeedEnd ( RSPEED_STENCILSHADOWS ) ;
# endif
2017-02-21 20:22:07 +00:00
D3D11BE_SubmitMeshes ( worldbatches , batches , SHADER_SORT_SEETHROUGH + 1 , SHADER_SORT_COUNT ) ;
2012-09-30 05:52:03 +00:00
}
else
{
RSpeedRemark ( ) ;
2013-11-21 23:02:28 +00:00
shaderstate . identitylighting = 1 ;
2016-01-18 05:22:07 +00:00
D3D11BE_SubmitMeshes ( NULL , batches , SHADER_SORT_PORTAL , SHADER_SORT_COUNT ) ;
2012-09-30 05:52:03 +00:00
RSpeedEnd ( RSPEED_DRAWENTITIES ) ;
}
R_RenderDlights ( ) ;
BE_RotateForEntity ( & r_worldentity , NULL ) ;
}
2015-03-03 00:14:43 +00:00
void D3D11BE_VBO_Begin ( vbobctx_t * ctx , size_t maxsize )
2013-04-06 03:36:00 +00:00
{
}
2015-03-03 00:14:43 +00:00
void D3D11BE_VBO_Data ( vbobctx_t * ctx , void * data , size_t size , vboarray_t * varray )
2013-04-06 03:36:00 +00:00
{
}
2016-07-12 00:40:13 +00:00
void D3D11BE_VBO_Finish ( vbobctx_t * ctx , void * edata , size_t esize , vboarray_t * earray , void * * vbomem , void * * ebomem )
2013-04-06 03:36:00 +00:00
{
}
2016-07-12 00:40:13 +00:00
void D3D11BE_VBO_Destroy ( vboarray_t * vearray , void * mem )
2013-04-06 03:36:00 +00:00
{
}
2012-09-30 05:52:03 +00:00
2013-06-23 02:17:02 +00:00
void D3D11BE_Scissor ( srect_t * rect )
{
2013-08-27 13:18:09 +00:00
D3D11_RECT drect ;
if ( rect )
{
2015-07-31 13:23:32 +00:00
drect . left = ( rect - > x ) * vid . fbpwidth ;
drect . right = ( rect - > x + rect - > width ) * vid . fbpwidth ;
drect . bottom = ( 1 - ( rect - > y ) ) * vid . fbpheight ;
drect . top = ( 1 - ( rect - > y + rect - > height ) ) * vid . fbpheight ;
if ( drect . left < 0 )
drect . left = 0 ;
if ( drect . top < 0 )
drect . top = 0 ;
2013-08-27 13:18:09 +00:00
}
else
{
drect . left = 0 ;
2015-07-31 13:23:32 +00:00
drect . right = vid . fbpwidth ;
2013-08-27 13:18:09 +00:00
drect . top = 0 ;
2015-07-31 13:23:32 +00:00
drect . bottom = vid . fbpheight ;
2013-08-27 13:18:09 +00:00
}
ID3D11DeviceContext_RSSetScissorRects ( d3ddevctx , 1 , & drect ) ;
2013-06-23 02:17:02 +00:00
}
2013-11-21 23:02:28 +00:00
# ifdef RTLIGHTS
void D3D11BE_BeginShadowmapFace ( void )
{
D3D11_VIEWPORT vport ;
vport . TopLeftX = r_refdef . pxrect . x ;
vport . TopLeftY = r_refdef . pxrect . y ;
vport . Width = r_refdef . pxrect . width ;
vport . Height = r_refdef . pxrect . height ;
vport . MinDepth = 0 ;
vport . MaxDepth = 1 ;
ID3D11DeviceContext_RSSetViewports ( d3ddevctx , 1 , & vport ) ;
2015-09-06 03:30:28 +00:00
D3D11BE_Cull ( SHADER_CULL_FRONT , r_polygonoffset_shadowmap_offset . ival , r_polygonoffset_shadowmap_factor . value ) ;
2013-11-21 23:02:28 +00:00
}
# endif
2012-09-30 05:52:03 +00:00
# endif