Add cascaded shadow mapping, test with r_testSunlight 1.

This commit is contained in:
James Canete 2012-06-26 07:09:48 +00:00
parent 9915d6ea56
commit 3d55fd3731
15 changed files with 2220 additions and 1560 deletions

View File

@ -1,3 +1,4 @@
- Add cascaded shadow mapping, test with r_testSunlight 1.
- Add r_depthPrepass. - Add r_depthPrepass.
- Improve parallax mapping - Improve parallax mapping
- Add AVG_MAP, BLACK_LEVEL, and WHITE_LEVEL defines to tonemap shader - Add AVG_MAP, BLACK_LEVEL, and WHITE_LEVEL defines to tonemap shader

View File

@ -355,6 +355,34 @@ extern void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLs
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F #define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
#endif #endif
// GL_ARB_draw_buffers
extern void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
#ifndef GL_ARB_draw_buffers
#define GL_ARB_draw_buffers
#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
#define GL_DRAW_BUFFER0_ARB 0x8825
#define GL_DRAW_BUFFER1_ARB 0x8826
#define GL_DRAW_BUFFER2_ARB 0x8827
#define GL_DRAW_BUFFER3_ARB 0x8828
#define GL_DRAW_BUFFER4_ARB 0x8829
#define GL_DRAW_BUFFER5_ARB 0x882A
#define GL_DRAW_BUFFER6_ARB 0x882B
#define GL_DRAW_BUFFER7_ARB 0x882C
#define GL_DRAW_BUFFER8_ARB 0x882D
#define GL_DRAW_BUFFER9_ARB 0x882E
#define GL_DRAW_BUFFER10_ARB 0x882F
#define GL_DRAW_BUFFER11_ARB 0x8830
#define GL_DRAW_BUFFER12_ARB 0x8831
#define GL_DRAW_BUFFER13_ARB 0x8832
#define GL_DRAW_BUFFER14_ARB 0x8833
#define GL_DRAW_BUFFER15_ARB 0x8834
#endif
#ifndef GL_ARB_depth_clamp
#define GL_ARB_depth_clamp
#define GL_DEPTH_CLAMP 0x864F
#endif
#if defined(WIN32) #if defined(WIN32)
// WGL_ARB_create_context // WGL_ARB_create_context
#ifndef WGL_ARB_create_context #ifndef WGL_ARB_create_context

View File

@ -167,7 +167,7 @@ void GL_Cull( int cullType ) {
qglEnable( GL_CULL_FACE ); qglEnable( GL_CULL_FACE );
cullFront = (cullType == CT_FRONT_SIDED); cullFront = (cullType == CT_FRONT_SIDED);
if ( backEnd.viewParms.isMirror && !backEnd.viewParms.isShadowmap ) if ( backEnd.viewParms.isMirror )
{ {
cullFront = !cullFront; cullFront = !cullFront;
} }
@ -590,127 +590,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
// save original time for entity shader offsets // save original time for entity shader offsets
originalTime = backEnd.refdef.floatTime; originalTime = backEnd.refdef.floatTime;
// clear the z buffer, set the modelview, etc
RB_BeginDrawingView ();
fbo = glState.currentFBO; fbo = glState.currentFBO;
if (r_depthPrepass->integer)
{
qboolean skip = qfalse;
// do a depth fill with just the static vbos
backEnd.depthFill = qtrue;
oldEntityNum = -1;
backEnd.currentEntity = &tr.worldEntity;
oldShader = NULL;
oldFogNum = -1;
oldDepthRange = qfalse;
wasCrosshair = qfalse;
oldDlighted = qfalse;
oldPshadowed = qfalse;
oldSort = -1;
depthRange = qfalse;
qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
if ( drawSurf->sort == oldSort ) {
// fast path, same as previous sort
if (!skip)
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
continue;
}
oldSort = drawSurf->sort;
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
skip = qfalse;
if (entityNum != ENTITYNUM_WORLD)
{
skip = qtrue;
continue;
}
if (ShaderRequiresCPUDeforms(shader))
{
skip = qtrue;
continue;
}
if (shader->sort != SS_OPAQUE)
{
skip = qtrue;
continue;
}
{
int stage;
shaderStage_t *pStage = NULL;
for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
{
if (shader->stages[stage])
{
pStage = shader->stages[stage];
break;
}
}
if (pStage && (pStage->stateBits & GLS_ATEST_BITS) != 0)
{
skip = qtrue;
continue;
}
}
//
// change the tess parameters if needed
// a "entityMergable" shader is a shader that can have surfaces from seperate
// entities merged into a single batch, like smoke and blood puff sprites
if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed != oldPshadowed
|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) {
if (oldShader != NULL) {
RB_EndSurface();
}
RB_BeginSurface( shader, fogNum );
backEnd.pc.c_surfBatches++;
oldShader = shader;
oldFogNum = fogNum;
oldDlighted = dlighted;
oldPshadowed = pshadowed;
}
//
// change the modelview matrix if needed
//
if ( entityNum != oldEntityNum ) {
backEnd.currentEntity = &tr.worldEntity;
backEnd.refdef.floatTime = originalTime;
backEnd.or = backEnd.viewParms.world;
// we have to reset the shaderTime as well otherwise image animations on
// the world (like water) continue with the wrong frame
tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
GL_SetModelviewMatrix( backEnd.or.modelMatrix );
oldEntityNum = entityNum;
}
// add the triangles for this surface
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
}
// draw the contents of the last shader batch
if (oldShader != NULL) {
RB_EndSurface();
}
qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
}
// draw everything // draw everything
backEnd.depthFill = qfalse;
oldEntityNum = -1; oldEntityNum = -1;
backEnd.currentEntity = &tr.worldEntity; backEnd.currentEntity = &tr.worldEntity;
oldShader = NULL; oldShader = NULL;
@ -731,6 +613,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) { for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
if ( drawSurf->sort == oldSort ) { if ( drawSurf->sort == oldSort ) {
if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
continue;
// fast path, same as previous sort // fast path, same as previous sort
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
continue; continue;
@ -755,6 +640,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
oldPshadowed = pshadowed; oldPshadowed = pshadowed;
} }
if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
continue;
// //
// change the modelview matrix if needed // change the modelview matrix if needed
// //
@ -765,7 +653,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
#ifdef REACTION #ifdef REACTION
// if we were rendering to a FBO and the previous entity was a sunflare // if we were rendering to a FBO and the previous entity was a sunflare
// and the current one isn't, switch back to the main fbo // and the current one isn't, switch back to the main fbo
if (oldEntityNum != -1 && fbo && if (oldEntityNum != -1 && fbo && !backEnd.depthFill &&
RF_SUNFLARE == (backEnd.refdef.entities[oldEntityNum].e.renderfx & RF_SUNFLARE) && RF_SUNFLARE == (backEnd.refdef.entities[oldEntityNum].e.renderfx & RF_SUNFLARE) &&
0 == (backEnd.refdef.entities[entityNum].e.renderfx & RF_SUNFLARE)) 0 == (backEnd.refdef.entities[entityNum].e.renderfx & RF_SUNFLARE))
{ {
@ -795,7 +683,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
#ifdef REACTION #ifdef REACTION
// if the current entity is a sunflare // if the current entity is a sunflare
if(backEnd.currentEntity->e.renderfx & RF_SUNFLARE) { if(backEnd.currentEntity->e.renderfx & RF_SUNFLARE && !backEnd.depthFill) {
// if we're rendering to a fbo // if we're rendering to a fbo
if (fbo) { if (fbo) {
VectorCopy(backEnd.currentEntity->e.origin, backEnd.sunFlarePos); VectorCopy(backEnd.currentEntity->e.origin, backEnd.sunFlarePos);
@ -914,7 +802,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
} }
#ifdef REACTION #ifdef REACTION
// HACK: flip Z and render black to god rays buffer // HACK: flip Z and render black to god rays buffer
if (backEnd.frameHasSunFlare) if (backEnd.frameHasSunFlare && !backEnd.depthFill)
{ {
vec4_t black; vec4_t black;
VectorSet4(black, 0, 0, 0, 1); VectorSet4(black, 0, 0, 0, 1);
@ -931,18 +819,6 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
//if ( depthRange ) { //if ( depthRange ) {
qglDepthRange (0, 1); qglDepthRange (0, 1);
//} //}
#if 0
RB_DrawSun();
#endif
// darken down any stencil shadows
RB_ShadowFinish();
// add light flares on lights that aren't obscured
RB_RenderFlares();
if (glRefConfig.framebufferObject)
FBO_Bind(NULL);
} }
@ -1307,7 +1183,44 @@ const void *RB_DrawSurfs( const void *data ) {
backEnd.refdef = cmd->refdef; backEnd.refdef = cmd->refdef;
backEnd.viewParms = cmd->viewParms; backEnd.viewParms = cmd->viewParms;
RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs ); // clear the z buffer, set the modelview, etc
RB_BeginDrawingView ();
if (backEnd.viewParms.isDepthShadow && glRefConfig.depthClamp)
{
qglEnable(GL_DEPTH_CLAMP);
}
if (r_depthPrepass->integer || backEnd.viewParms.isDepthShadow)
{
backEnd.depthFill = qtrue;
qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs );
qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
backEnd.depthFill = qfalse;
}
if (backEnd.viewParms.isDepthShadow && glRefConfig.depthClamp)
{
qglDisable(GL_DEPTH_CLAMP);
}
if (!backEnd.viewParms.isDepthShadow)
{
RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs );
#if 0
RB_DrawSun();
#endif
// darken down any stencil shadows
RB_ShadowFinish();
// add light flares on lights that aren't obscured
RB_RenderFlares();
}
if (glRefConfig.framebufferObject)
FBO_Bind(NULL);
return (const void *)(cmd + 1); return (const void *)(cmd + 1);
} }
@ -1632,6 +1545,17 @@ const void *RB_PostProcess(const void *data)
} }
#endif #endif
if (0)
{
vec4i_t dstBox;
VectorSet4(dstBox, 0, 0, 128, 128);
FBO_BlitFromTexture(tr.sunShadowDepthImage[0], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
VectorSet4(dstBox, 128, 0, 128, 128);
FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
VectorSet4(dstBox, 256, 0, 128, 128);
FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
}
backEnd.framePostProcessed = qtrue; backEnd.framePostProcessed = qtrue;
return (const void *)(cmd + 1); return (const void *)(cmd + 1);

View File

@ -175,6 +175,9 @@ void (APIENTRY * qglBlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, G
void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples, void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height); GLenum internalformat, GLsizei width, GLsizei height);
// GL_ARB_draw_buffers
void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
static qboolean GLimp_HaveExtension(const char *ext) static qboolean GLimp_HaveExtension(const char *ext)
{ {
const char *ptr = Q_stristr( glConfig.extensions_string, ext ); const char *ptr = Q_stristr( glConfig.extensions_string, ext );
@ -649,4 +652,31 @@ void GLimp_InitExtraExtensions()
{ {
ri.Printf(PRINT_ALL, result[2], extension); ri.Printf(PRINT_ALL, result[2], extension);
} }
// GL_ARB_draw_buffers
extension = "GL_ARB_draw_buffers";
qglDrawBuffersARB = NULL;
if( GLimp_HaveExtension( extension ) )
{
qglDrawBuffersARB = (void *) SDL_GL_GetProcAddress("glDrawBuffersARB");
ri.Printf(PRINT_ALL, result[1], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}
// GL_ARB_depth_clamp
extension = "GL_ARB_depth_clamp";
glRefConfig.depthClamp = qfalse;
if( GLimp_HaveExtension( extension ) )
{
glRefConfig.depthClamp = qtrue;
ri.Printf(PRINT_ALL, result[1], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}
} }

View File

@ -1,40 +1,43 @@
/* /*
=========================================================================== ===========================================================================
Copyright (C) 2009-2011 Andrei Drexler, Richard Allen, James Canete Copyright (C) 2009-2011 Andrei Drexler, Richard Allen, James Canete
This file is part of Reaction source code. This file is part of Reaction source code.
Reaction source code is free software; you can redistribute it Reaction source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License, published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version. or (at your option) any later version.
Reaction source code is distributed in the hope that it will be Reaction source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Reaction source code; if not, write to the Free Software along with Reaction source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=========================================================================== ===========================================================================
*/ */
#ifndef __TR_EXTRATYPES_H__ #ifndef __TR_EXTRATYPES_H__
#define __TR_EXTRATYPES_H__ #define __TR_EXTRATYPES_H__
// tr_extratypes.h, for mods that want to extend tr_types.h without losing compatibility with original VMs // tr_extratypes.h, for mods that want to extend tr_types.h without losing compatibility with original VMs
// extra renderfx flags start at 0x0400 // extra renderfx flags start at 0x0400
#define RF_SUNFLARE 0x0400 #define RF_SUNFLARE 0x0400
// extra refdef flags start at 0x0008 // extra refdef flags start at 0x0008
#define RDF_NOFOG 0x0008 // don't apply fog #define RDF_NOFOG 0x0008 // don't apply fog
#define RDF_EXTRA 0x0010 // Makro - refdefex_t to follow after refdef_t #define RDF_EXTRA 0x0010 // Makro - refdefex_t to follow after refdef_t
#define RDF_SUNLIGHT 0x0020 // SmileTheory - render sunlight and shadows
typedef struct {
float blurFactor; typedef struct {
} refdefex_t; float blurFactor;
float sunDir[3];
#endif float sunCol[3];
} refdefex_t;
#endif

View File

@ -477,6 +477,21 @@ void FBO_Init(void)
R_CheckFBO(tr.pshadowFbos[i]); R_CheckFBO(tr.pshadowFbos[i]);
} }
for ( i = 0; i < 3; i++)
{
tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
FBO_Bind(tr.sunShadowFbo[i]);
//FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0);
//FBO_AttachTextureImage(tr.sunShadowImage, 0);
qglDrawBuffer(GL_NONE);
//FBO_CreateBuffer(tr.sunShadowFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum);
R_CheckFBO(tr.sunShadowFbo[i]);
}
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height); tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height);

View File

@ -302,135 +302,162 @@ static const char *fallbackLightallShader_fp =
"rm sampler2D u_NormalMap;\r\n#endif\r\n\r\n#if defined(USE_DELUXEMAP)\r\nun" "rm sampler2D u_NormalMap;\r\n#endif\r\n\r\n#if defined(USE_DELUXEMAP)\r\nun"
"iform sampler2D u_DeluxeMap;\r\n#endif\r\n\r\n#if defined(USE_SPECULARMAP)" "iform sampler2D u_DeluxeMap;\r\n#endif\r\n\r\n#if defined(USE_SPECULARMAP)"
"\r\nuniform sampler2D u_SpecularMap;\r\n#endif\r\n\r\n#if defined(USE_SHADO" "\r\nuniform sampler2D u_SpecularMap;\r\n#endif\r\n\r\n#if defined(USE_SHADO"
"WMAP)\r\nuniform samplerCube u_ShadowMap;\r\n#endif\r\n\r\nuniform vec3 " "WMAP)\r\nuniform sampler2D u_ShadowMap;\r\n #if defined(USE_SHADOW_CASCADE"
" u_ViewOrigin;\r\n\r\n#if defined(USE_LIGHT_VECTOR)\r\nuniform vec3 u" ")\r\nuniform sampler2D u_ShadowMap2;\r\nuniform sampler2D u_ShadowMap3;\r\n"
"_DirectedLight;\r\nuniform vec3 u_AmbientLight;\r\nuniform float u" " #endif\r\n#endif\r\n\r\nuniform vec3 u_ViewOrigin;\r\n\r\n#if define"
"_LightRadius;\r\n#endif\r\n\r\n#if defined(USE_LIGHT)\r\nuniform vec2 " "d(USE_LIGHT_VECTOR)\r\nuniform vec3 u_DirectedLight;\r\nuniform vec3 "
"u_MaterialInfo;\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\n#if d" " u_AmbientLight;\r\nuniform float u_LightRadius;\r\n#endif\r\n\r\n#i"
"efined(USE_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#endif\r\nvaryin" "f defined(USE_SHADOWMAP)\r\nuniform mat4 u_ShadowMvp;\r\n #if defined"
"g vec4 var_Color;\r\nvarying vec3 var_Position;\r\n\r\nvarying ve" "(USE_SHADOW_CASCADE)\r\nuniform mat4 u_ShadowMvp2;\r\nuniform mat4 "
"c3 var_SampleToView;\r\n\r\nvarying vec3 var_Normal;\r\n#if defin" " u_ShadowMvp3;\r\n #endif\r\n#endif\r\n\r\n#if defined(USE_LIGHT)\r\nunif"
"ed(USE_VERT_TANGENT_SPACE)\r\nvarying vec3 var_Tangent;\r\nvarying vec" "orm vec2 u_MaterialInfo;\r\n#endif\r\n\r\nvarying vec2 var_Diffus"
"3 var_Bitangent;\r\n#endif\r\n\r\n#if defined(USE_LIGHT_VECTOR) && def" "eTex;\r\n#if defined(USE_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#e"
"ined(USE_FAST_LIGHT)\r\nvarying vec3 var_VectLight;\r\n#endif\r\n\r\n#" "ndif\r\nvarying vec4 var_Color;\r\nvarying vec3 var_Position;\r\n"
"if defined(USE_LIGHT) && !defined(USE_DELUXEMAP)\r\nvarying vec3 var_W" "\r\nvarying vec3 var_SampleToView;\r\n\r\nvarying vec3 var_Normal"
"orldLight;\r\n#endif\r\n\r\n#define EPSILON 0.00000001\r\n\r\n#if defined(U" ";\r\n#if defined(USE_VERT_TANGENT_SPACE)\r\nvarying vec3 var_Tangent;"
"SE_PARALLAXMAP)\r\nfloat SampleHeight(sampler2D normalMap, vec2 t)\r\n{\r\n" "\r\nvarying vec3 var_Bitangent;\r\n#endif\r\n\r\n#if defined(USE_LIGHT"
" #if defined(SWIZZLE_NORMALMAP)\r\n\treturn texture2D(normalMap, t).r;\r\n" "_VECTOR) && defined(USE_FAST_LIGHT)\r\nvarying vec3 var_VectLight;\r\n"
" #else\r\n\treturn texture2D(normalMap, t).a;\r\n #endif\r\n}\r\n\r\nfloa" "#endif\r\n\r\n#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP)\r\nvarying "
"t RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)\r\n{\r\n\t" "vec3 var_WorldLight;\r\n#endif\r\n\r\n#define EPSILON 0.00000001\r\n\r"
"const int linearSearchSteps = 16;\r\n\tconst int binarySearchSteps = 6;\r\n" "\n#if defined(USE_PARALLAXMAP)\r\nfloat SampleHeight(sampler2D normalMap, v"
"\r\n\tfloat depthStep = 1.0 / float(linearSearchSteps);\r\n\r\n\t// current" "ec2 t)\r\n{\r\n #if defined(SWIZZLE_NORMALMAP)\r\n\treturn texture2D(norma"
" size of search window\r\n\tfloat size = depthStep;\r\n\r\n\t// current dep" "lMap, t).r;\r\n #else\r\n\treturn texture2D(normalMap, t).a;\r\n #endif\r"
"th position\r\n\tfloat depth = 0.0;\r\n\r\n\t// best match found (starts wi" "\n}\r\n\r\nfloat RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normal"
"th last position 1.0)\r\n\tfloat bestDepth = 1.0;\r\n\r\n\t// search front " "Map)\r\n{\r\n\tconst int linearSearchSteps = 16;\r\n\tconst int binarySearc"
"to back for first point inside object\r\n\tfor(int i = 0; i < linearSearchS" "hSteps = 6;\r\n\r\n\tfloat depthStep = 1.0 / float(linearSearchSteps);\r\n"
"teps - 1; ++i)\r\n\t{\r\n\t\tdepth += size;\r\n\t\t\r\n\t\tfloat t = 1.0 - " "\r\n\t// current size of search window\r\n\tfloat size = depthStep;\r\n\r\n"
"SampleHeight(normalMap, dp + ds * depth);\r\n\t\t\r\n\t\tif(bestDepth > 0.9" "\t// current depth position\r\n\tfloat depth = 0.0;\r\n\r\n\t// best match "
"96)\t\t// if no depth found yet\r\n\t\t\tif(depth >= t)\r\n\t\t\t\tbestDept" "found (starts with last position 1.0)\r\n\tfloat bestDepth = 1.0;\r\n\r\n\t"
"h = depth;\t// store best depth\r\n\t}\r\n\r\n\tdepth = bestDepth;\r\n\t\r" "// search front to back for first point inside object\r\n\tfor(int i = 0; i"
"\n\t// recurse around first point (depth) for closest match\r\n\tfor(int i " " < linearSearchSteps - 1; ++i)\r\n\t{\r\n\t\tdepth += size;\r\n\t\t\r\n\t\t"
"= 0; i < binarySearchSteps; ++i)\r\n\t{\r\n\t\tsize *= 0.5;\r\n\r\n\t\tfloa" "float t = 1.0 - SampleHeight(normalMap, dp + ds * depth);\r\n\t\t\r\n\t\tif"
"t t = 1.0 - SampleHeight(normalMap, dp + ds * depth);\r\n\t\t\r\n\t\tif(dep" "(bestDepth > 0.996)\t\t// if no depth found yet\r\n\t\t\tif(depth >= t)\r\n"
"th >= t)\r\n\t\t{\r\n\t\t\tbestDepth = depth;\r\n\t\t\tdepth -= 2.0 * size;" "\t\t\t\tbestDepth = depth;\t// store best depth\r\n\t}\r\n\r\n\tdepth = bes"
"\r\n\t\t}\r\n\r\n\t\tdepth += size;\r\n\t}\r\n\r\n\treturn bestDepth;\r\n}" "tDepth;\r\n\t\r\n\t// recurse around first point (depth) for closest match"
"\r\n#endif\r\n\r\nfloat CalcDiffuse(vec3 N, vec3 L, vec3 E, float NE, float" "\r\n\tfor(int i = 0; i < binarySearchSteps; ++i)\r\n\t{\r\n\t\tsize *= 0.5;"
" NL, float fzero, float shininess)\r\n{\r\n #if defined(USE_OREN_NAYAR)\r" "\r\n\r\n\t\tfloat t = 1.0 - SampleHeight(normalMap, dp + ds * depth);\r\n\t"
"\n\tfloat roughness = sqrt(2.0 / max(shininess, EPSILON));\r\n\r\n\tfloat g" "\t\r\n\t\tif(depth >= t)\r\n\t\t{\r\n\t\t\tbestDepth = depth;\r\n\t\t\tdept"
"amma = dot(E - N * NE, L - N * NL);\r\n\tfloat r_sq = roughness * roughness" "h -= 2.0 * size;\r\n\t\t}\r\n\r\n\t\tdepth += size;\r\n\t}\r\n\r\n\treturn "
";\r\n\r\n\tfloat A = 1.0 - 0.5 * (r_sq / (r_sq + 0.57));\r\n\tfloat B = 0.4" "bestDepth;\r\n}\r\n#endif\r\n\r\nfloat CalcDiffuse(vec3 N, vec3 L, vec3 E, "
"5 * (r_sq / (r_sq + 0.09));\r\n\r\n\tfloat alpha = max(acos(NE), acos(NL));" "float NE, float NL, float fzero, float shininess)\r\n{\r\n #if defined(USE"
"\r\n\tfloat beta = min(acos(NE), acos(NL));\r\n\r\n\tfloat C = sin(alpha) " "_OREN_NAYAR)\r\n\tfloat roughness = sqrt(2.0 / max(shininess, EPSILON));\r"
"* tan(beta);\r\n\r\n\treturn A + B * clamp(gamma, 0.0, 1.0) * C;\r\n #else" "\n\r\n\tfloat gamma = dot(E - N * NE, L - N * NL);\r\n\tfloat r_sq = roughn"
"\r\n\treturn 1.0 - fzero;\r\n #endif\r\n}\r\n\r\n#if defined(USE_SPECULARM" "ess * roughness;\r\n\r\n\tfloat A = 1.0 - 0.5 * (r_sq / (r_sq + 0.57));\r\n"
"AP)\r\nfloat CalcSpecular(float NH, float NL, float NE, float EH, float fze" "\tfloat B = 0.45 * (r_sq / (r_sq + 0.09));\r\n\r\n\tfloat alpha = max(acos("
"ro, float shininess)\r\n{\r\n #if defined(USE_BLINN) || defined(USE_TRIACE" "NE), acos(NL));\r\n\tfloat beta = min(acos(NE), acos(NL));\r\n\r\n\tfloat "
") || defined(USE_TORRANCE_SPARROW)\r\n\tfloat blinn = pow(NH, shininess);\r" "C = sin(alpha) * tan(beta);\r\n\r\n\treturn A + B * clamp(gamma, 0.0, 1.0) "
"\n #endif\r\n\r\n #if defined(USE_BLINN)\r\n\treturn blinn;\r\n #endif\r" "* C;\r\n #else\r\n\treturn 1.0 - fzero;\r\n #endif\r\n}\r\n\r\n#if define"
"\n\r\n #if defined(USE_COOK_TORRANCE) || defined (USE_TRIACE) || defined (" "d(USE_SPECULARMAP)\r\nfloat CalcSpecular(float NH, float NL, float NE, floa"
"USE_TORRANCE_SPARROW)\r\n\tfloat fresnel = fzero + (1.0 - fzero) * pow(1.0 " "t EH, float fzero, float shininess)\r\n{\r\n #if defined(USE_BLINN) || def"
"- EH, 5);\r\n #endif\r\n\r\n #if defined(USE_COOK_TORRANCE) || defined(US" "ined(USE_TRIACE) || defined(USE_TORRANCE_SPARROW)\r\n\tfloat blinn = pow(NH"
"E_TORRANCE_SPARROW)\r\n\tfloat geo = 2.0 * NH * min(NE, NL);\r\n\tgeo /= ma" ", shininess);\r\n #endif\r\n\r\n #if defined(USE_BLINN)\r\n\treturn blinn"
"x(EH, geo);\r\n #endif \r\n\r\n #if defined(USE_COOK_TORRANCE)\r\n\tfloa" ";\r\n #endif\r\n\r\n #if defined(USE_COOK_TORRANCE) || defined (USE_TRIAC"
"t m = sqrt(2.0 / max(shininess, EPSILON));\r\n\r\n\tfloat m_sq = m * m;\r\n" "E) || defined (USE_TORRANCE_SPARROW)\r\n\tfloat fresnel = fzero + (1.0 - fz"
"\tfloat NH_sq = NH * NH;\r\n\tfloat beckmann = exp((NH_sq - 1.0) / max(m_sq" "ero) * pow(1.0 - EH, 5);\r\n #endif\r\n\r\n #if defined(USE_COOK_TORRANCE"
" * NH_sq, EPSILON)) / max(4.0 * m_sq * NH_sq * NH_sq, EPSILON);\r\n\r\n\tre" ") || defined(USE_TORRANCE_SPARROW)\r\n\tfloat geo = 2.0 * NH * min(NE, NL);"
"turn fresnel * geo * beckmann / max(NE, EPSILON);\r\n #endif\r\n\r\n #if " "\r\n\tgeo /= max(EH, geo);\r\n #endif \r\n\r\n #if defined(USE_COOK_TORR"
"defined(USE_TRIACE)\r\n\tfloat scale = 0.1248582 * shininess + 0.2691817;\r" "ANCE)\r\n\tfloat m = sqrt(2.0 / max(shininess, EPSILON));\r\n\r\n\tfloat m_"
"\n\r\n\treturn fresnel * scale * blinn / max(max(NL, NE), EPSILON);\r\n #e" "sq = m * m;\r\n\tfloat NH_sq = NH * NH;\r\n\tfloat beckmann = exp((NH_sq - "
"ndif\r\n \r\n #if defined(USE_TORRANCE_SPARROW)\r\n\tfloat scale = 0.125 " "1.0) / max(m_sq * NH_sq, EPSILON)) / max(4.0 * m_sq * NH_sq * NH_sq, EPSILO"
"* shininess + 1.0;\r\n\r\n\treturn fresnel * geo * scale * blinn / max(NE, " "N);\r\n\r\n\treturn fresnel * geo * beckmann / max(NE, EPSILON);\r\n #endi"
"EPSILON);\r\n #endif\r\n}\r\n#endif\r\n\r\nvoid main()\r\n{\r\n#if defined" "f\r\n\r\n #if defined(USE_TRIACE)\r\n\tfloat scale = 0.1248582 * shininess"
"(USE_DELUXEMAP)\r\n\tvec3 worldLight = 2.0 * texture2D(u_DeluxeMap, var_Lig" " + 0.2691817;\r\n\r\n\treturn fresnel * scale * blinn / max(max(NL, NE), EP"
"htTex).xyz - vec3(1.0);\r\n\t//worldLight += var_WorldLight * 0.0001;\r\n#e" "SILON);\r\n #endif\r\n \r\n #if defined(USE_TORRANCE_SPARROW)\r\n\tfloat"
"lif defined(USE_LIGHT)\r\n\tvec3 worldLight = var_WorldLight;\r\n#endif\r\n" " scale = 0.125 * shininess + 1.0;\r\n\r\n\treturn fresnel * geo * scale * b"
"\r\n#if defined(USE_LIGHTMAP)\r\n\tvec4 lightSample = texture2D(u_LightMap," "linn / max(NE, EPSILON);\r\n #endif\r\n}\r\n#endif\r\n\r\nfloat PCF(sample"
" var_LightTex).rgba;\r\n #if defined(RGBE_LIGHTMAP)\r\n\tlightSample.rgb *" "r2D shadowmap, vec2 st, float dist)\r\n{\r\n\tfloat mult;\r\n\t\r\n\tmult "
"= exp2(lightSample.a * 255.0 - 128.0);\r\n #endif\r\n\tvec3 directedLight " "= sign(clamp(texture2D(shadowmap, st + vec2(-0.5, -0.5) / 1024.0).r - dist,"
"= lightSample.rgb;\r\n#elif defined(USE_LIGHT_VECTOR)\r\n #if defined(USE_" " 0.0, 1.0));\r\n\tmult += sign(clamp(texture2D(shadowmap, st + vec2( 0.5, -"
"FAST_LIGHT)\r\n\tvec3 directedLight = var_VectLight;\r\n #else\r\n #if " "0.5) / 1024.0).r - dist, 0.0, 1.0));\r\n\tmult += sign(clamp(texture2D(shad"
"defined(USE_INVSQRLIGHT)\r\n\tfloat intensity = 1.0 / dot(worldLight, world" "owmap, st + vec2(-0.5, 0.5) / 1024.0).r - dist, 0.0, 1.0));\r\n\tmult += s"
"Light);\r\n #else\r\n\tfloat intensity = clamp((1.0 - dot(worldLight, wo" "ign(clamp(texture2D(shadowmap, st + vec2( 0.5, 0.5) / 1024.0).r - dist, 0."
"rldLight) / (u_LightRadius * u_LightRadius)) * 1.07, 0.0, 1.0);\r\n #end" "0, 1.0));\r\n\tmult *= 0.25;\r\n\t\r\n\treturn mult;\r\n}\r\n\r\nvoid main("
"if\r\n #if defined(USE_SHADOWMAP)\r\n \tvec3 dist3 = textureCube(u_Shad" ")\r\n{\r\n#if defined(USE_LIGHT) || defined(USE_NORMALMAP)\r\n\tvec3 surfNo"
"owMap, worldLight).rgb;\r\n\tfloat dist = dot(dist3, vec3(1.0 / (256.0 * 25" "rmal = normalize(var_Normal);\r\n#endif\r\n\r\n#if defined(USE_DELUXEMAP)\r"
"6.0), 1.0 / 256.0, 1.0)) * u_LightRadius;\r\n\r\n\tintensity *= clamp(sign(" "\n\tvec3 worldLight = 2.0 * texture2D(u_DeluxeMap, var_LightTex).xyz - vec3"
"dist - length(worldLight)), 0.0, 1.0);\r\n #endif\r\n\tvec3 directedLigh" "(1.0);\r\n\t//worldLight += var_WorldLight * 0.0001;\r\n#elif defined(USE_L"
"t = u_DirectedLight * intensity;\r\n\tvec3 ambientLight = u_AmbientLight;" "IGHT)\r\n\tvec3 worldLight = var_WorldLight;\r\n#endif\r\n\r\n#if defined(U"
"\r\n #endif\r\n#elif defined(USE_LIGHT_VERTEX)\r\n\tvec3 directedLight = v" "SE_LIGHTMAP)\r\n\tvec4 lightSample = texture2D(u_LightMap, var_LightTex).rg"
"ar_Color.rgb;\r\n#endif\r\n\t\r\n#if defined(USE_NORMALMAP) || defined(USE_" "ba;\r\n #if defined(RGBE_LIGHTMAP)\r\n\tlightSample.rgb *= exp2(lightSampl"
"LIGHT) && !defined(USE_FAST_LIGHT)\r\n\tvec3 SampleToView = normalize(var_S" "e.a * 255.0 - 128.0);\r\n #endif\r\n\tvec3 directedLight = lightSample.rgb"
"ampleToView);\r\n#endif\r\n\tvec2 tex = var_DiffuseTex;\r\n\r\n\tfloat ambi" ";\r\n#elif defined(USE_LIGHT_VECTOR)\r\n #if defined(USE_FAST_LIGHT)\r\n\t"
"entDiff = 1.0;\r\n\r\n#if defined(USE_NORMALMAP)\r\n #if defined(USE_VERT_" "vec3 directedLight = var_VectLight;\r\n #else\r\n #if defined(USE_INVSQ"
"TANGENT_SPACE)\r\n vec3 tangent = normalize(var_Tangent);\r\n\tvec3 bi" "RLIGHT)\r\n\tfloat intensity = 1.0 / dot(worldLight, worldLight);\r\n #e"
"tangent = normalize(var_Bitangent);\r\n #else\r\n\tvec3 q0 = dFdx(var_Pos" "lse\r\n\tfloat intensity = clamp((1.0 - dot(worldLight, worldLight) / (u_Li"
"ition.xyz);\r\n\tvec3 q1 = dFdy(var_Position.xyz);\r\n\tvec2 st0 = dFdx(te" "ghtRadius * u_LightRadius)) * 1.07, 0.0, 1.0);\r\n #endif\r\n\r\n\t#if d"
"x);\r\n\tvec2 st1 = dFdy(tex);\r\n\tfloat dir = sign(st1.t * st0.s - st0.t " "efined(USE_SHADOWMAP)\r\n\tvec4 shadowpos = u_ShadowMvp * vec4(var_Position"
"* st1.s);\r\n\r\n\tvec3 tangent = normalize( q0 * st1.t - q1 * st0.t) * d" ", 1.0);\r\n\tfloat outside1 = dot(vec3(1.0, 1.0, 1.0), sign(clamp(abs(shado"
"ir;\r\n\tvec3 bitangent = -normalize( q0 * st1.s - q1 * st0.s) * dir;\r\n " "wpos.xyz) - 1.0, 0.0, 1.0)));\r\n\t\r\n\t #if defined(USE_SHADOW_CASCADE)"
"#endif\r\n\r\n\tmat3 tangentToWorld = mat3(tangent, bitangent, normalize(va" "\r\n\tvec4 shadowpos2 = u_ShadowMvp2 * vec4(var_Position, 1.0);\r\n\tfloat "
"r_Normal.xyz));\r\n\r\n #if defined(USE_PARALLAXMAP)\r\n\tvec3 offsetDir =" "outside2 = dot(vec3(1.0, 1.0, 1.0), sign(clamp(abs(shadowpos2.xyz) - 1.0, 0"
" normalize(SampleToView * tangentToWorld);\r\n #if 0\r\n float height" ".0, 1.0)));\r\n\r\n\tvec4 shadowpos3 = u_ShadowMvp3 * vec4(var_Position, 1."
" = SampleHeight(u_NormalMap, tex);\r\n\tfloat pdist = 0.05 * height - (0.05" "0);\r\n\tfloat outside3 = dot(vec3(1.0, 1.0, 1.0), sign(clamp(abs(shadowpos"
" / 2.0);\r\n #else\r\n\toffsetDir.xy *= -0.05 / offsetDir.z;\r\n\tfloat " "3.xyz) - 1.0, 0.0, 1.0)));\r\n\t\r\n\tif (outside1 < 1.0)\r\n\t{\r\n\t\tsha"
"pdist = RayIntersectDisplaceMap(tex, offsetDir.xy, u_NormalMap);\r\n #en" "dowpos.xyz = shadowpos.xyz * 0.5 + 0.5;\r\n\t\tintensity *= PCF(u_ShadowMap"
"dif\t\r\n\ttex += offsetDir.xy * pdist;\r\n #endif\r\n #if defined(SWIZZL" ", shadowpos.xy, shadowpos.z);\r\n\t}\r\n\telse if (outside2 < 1.0)\r\n\t{\r"
"E_NORMALMAP)\r\n\tvec3 normal = 2.0 * texture2D(u_NormalMap, tex).agb - 1.0" "\n\t\tshadowpos2.xyz = shadowpos2.xyz * 0.5 + 0.5;\r\n\t\tintensity *= PCF("
";\r\n #else\r\n\tvec3 normal = 2.0 * texture2D(u_NormalMap, tex).rgb - 1.0" "u_ShadowMap2, shadowpos2.xy, shadowpos2.z);\r\n\t}\r\n\telse if (outside3 <"
";\r\n #endif\r\n\tnormal.z = sqrt(clamp(1.0 - dot(normal.xy, normal.xy), 0" " 1.0)\r\n\t{\r\n\t\tshadowpos3.xyz = shadowpos3.xyz * 0.5 + 0.5;\r\n\t\tint"
".0, 1.0));\r\n\tvec3 worldNormal = tangentToWorld * normal;\r\n #if define" "ensity *= PCF(u_ShadowMap3, shadowpos3.xy, shadowpos3.z);\r\n\t}\r\n\t #el"
"d(r_normalAmbient)\r\n\tambientDiff = 0.781341 * normal.z + 0.218659;\r\n " "se\r\n\tshadowpos.xyz = shadowpos.xyz * 0.5 + 0.5;\r\n\tintensity *= clamp("
"#endif\r\n#else\r\n\tvec3 worldNormal = var_Normal;\r\n#endif\r\n\r\n\tvec4" "PCF(u_ShadowMap, shadowpos.xy, shadowpos.z) - outside1, 1.0, 0.0);\r\n\t #"
" diffuse = texture2D(u_DiffuseMap, tex);\r\n\r\n#if defined(USE_LIGHT) && d" "endif\r\n\t#endif\r\n\t\r\n\tvec3 directedLight = u_DirectedLight * intensi"
"efined(USE_FAST_LIGHT)\r\n\tdiffuse.rgb *= directedLight;\r\n#elif defined(" "ty;\r\n\tvec3 ambientLight = u_AmbientLight;\r\n #endif\r\n#elif defined("
"USE_LIGHT)\r\n\tworldNormal = normalize(worldNormal);\r\n\tworldLight = nor" "USE_LIGHT_VERTEX)\r\n\tvec3 directedLight = var_Color.rgb;\r\n#endif\r\n\t"
"malize(worldLight);\r\n\r\n #if defined(USE_LIGHTMAP) || defined(USE_LIGHT" "\r\n#if defined(USE_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_L"
"_VERTEX)\r\n\tdirectedLight /= max(dot(normalize(var_Normal), worldLight), " "IGHT)\r\n\tvec3 SampleToView = normalize(var_SampleToView);\r\n#endif\r\n\t"
"0.004);\r\n\r\n #if defined(r_normalAmbient)\r\n\tvec3 ambientLight = di" "vec2 tex = var_DiffuseTex;\r\n\r\n\tfloat ambientDiff = 1.0;\r\n\r\n#if def"
"rectedLight * r_normalAmbient;\r\n\tdirectedLight -= ambientLight;\r\n #" "ined(USE_NORMALMAP)\r\n #if defined(USE_VERT_TANGENT_SPACE)\r\n vec3 "
"else\r\n\tvec3 ambientLight = vec3(0);\r\n #endif\r\n #endif\r\n\r\n\tf" "tangent = normalize(var_Tangent);\r\n\tvec3 bitangent = normalize(var_Bitan"
"loat NL = clamp(dot(worldNormal, worldLight), 0.0, 1.0);\r\n\tfloat NE =" "gent);\r\n #else\r\n\tvec3 q0 = dFdx(var_Position);\r\n\tvec3 q1 = dFdy("
" clamp(dot(worldNormal, SampleToView), 0.0, 1.0);\r\n\t\r\n\tfloat fzero =" "var_Position);\r\n\tvec2 st0 = dFdx(tex);\r\n\tvec2 st1 = dFdy(tex);\r\n\tf"
" u_MaterialInfo.x;\r\n\tfloat shininess = u_MaterialInfo.y;\r\n #if define" "loat dir = sign(st1.t * st0.s - st0.t * st1.s);\r\n\r\n\tvec3 tangent = n"
"d(USE_SPECULARMAP)\r\n\tvec4 specular = texture2D(u_SpecularMap, tex);\r\n" "ormalize( q0 * st1.t - q1 * st0.t) * dir;\r\n\tvec3 bitangent = -normalize("
"\t//specular.rgb = clamp(specular.rgb - diffuse.rgb, 0.0, 1.0);\r\n\tshinin" " q0 * st1.s - q1 * st0.s) * dir;\r\n #endif\r\n\r\n\tmat3 tangentToWorld ="
"ess *= specular.a;\r\n #endif\r\n\tfloat directedDiff = NL * CalcDiffuse(w" " mat3(tangent, bitangent, surfNormal);\r\n\r\n #if defined(USE_PARALLAXMAP"
"orldNormal, worldLight, SampleToView, NE, NL, fzero, shininess);\r\n\tdiffu" ")\r\n\tvec3 offsetDir = normalize(SampleToView * tangentToWorld);\r\n #i"
"se.rgb *= directedLight * directedDiff + ambientDiff * ambientLight;\r\n " "f 0\r\n float height = SampleHeight(u_NormalMap, tex);\r\n\tfloat pdist "
"\r\n #if defined(USE_SPECULARMAP)\r\n\tvec3 halfAngle = normalize(worldLig" "= 0.05 * height - (0.05 / 2.0);\r\n #else\r\n\toffsetDir.xy *= -0.05 / o"
"ht + SampleToView);\r\n\r\n\tfloat EH = clamp(dot(SampleToView, halfAngle)," "ffsetDir.z;\r\n\tfloat pdist = RayIntersectDisplaceMap(tex, offsetDir.xy, u"
" 0.0, 1.0);\r\n\tfloat NH = clamp(dot(worldNormal, halfAngle), 0.0, 1.0);" "_NormalMap);\r\n #endif\t\r\n\ttex += offsetDir.xy * pdist;\r\n #endif"
"\r\n\r\n\tfloat directedSpec = NL * CalcSpecular(NH, NL, NE, EH, fzero, shi" "\r\n #if defined(SWIZZLE_NORMALMAP)\r\n\tvec3 normal = 2.0 * texture2D(u_N"
"niness);\r\n \r\n #if defined(r_normalAmbient)\r\n\tvec3 ambientHalf = " "ormalMap, tex).agb - 1.0;\r\n #else\r\n\tvec3 normal = 2.0 * texture2D(u_N"
"normalize(var_Normal + SampleToView);\r\n\tfloat ambientSpec = max(dot(ambi" "ormalMap, tex).rgb - 1.0;\r\n #endif\r\n\tnormal.z = sqrt(clamp(1.0 - dot("
"entHalf, worldNormal) + 0.5, 0.0);\r\n\tambientSpec *= ambientSpec * 0.44;" "normal.xy, normal.xy), 0.0, 1.0));\r\n\tvec3 worldNormal = tangentToWorld *"
"\r\n\tambientSpec = pow(ambientSpec, shininess) * fzero;\r\n\tspecular.rgb " " normal;\r\n #if defined(r_normalAmbient)\r\n\tambientDiff = 0.781341 * no"
"*= directedSpec * directedLight + ambientSpec * ambientLight;\r\n #else" "rmal.z + 0.218659;\r\n #endif\r\n#elif defined(USE_LIGHT)\r\n\tvec3 worldN"
"\r\n\tspecular.rgb *= directedSpec * directedLight;\r\n #endif\r\n #end" "ormal = surfNormal;\r\n#endif\r\n\r\n\tvec4 diffuse = texture2D(u_DiffuseMa"
"if\r\n#endif\r\n\r\n\tgl_FragColor = diffuse;\r\n\r\n#if defined(USE_SPECUL" "p, tex);\r\n\r\n#if defined(USE_LIGHT) && defined(USE_FAST_LIGHT)\r\n\tdiff"
"ARMAP) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)\r\n\tgl_FragColor." "use.rgb *= directedLight;\r\n#elif defined(USE_LIGHT)\r\n\tworldNormal = no"
"rgb += specular.rgb;\r\n#endif\r\n\r\n#if !defined(USE_LIGHT_VERTEX)\r\n\tg" "rmalize(worldNormal);\r\n\tworldLight = normalize(worldLight);\r\n\r\n #if"
"l_FragColor *= var_Color;\r\n#endif\r\n}\r\n"; " defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX)\r\n\tdirectedLight /= m"
"ax(dot(surfNormal, worldLight), 0.004);\r\n\r\n #if defined(r_normalAmbi"
"ent)\r\n\tvec3 ambientLight = directedLight * r_normalAmbient;\r\n\tdirecte"
"dLight -= ambientLight;\r\n #else\r\n\tvec3 ambientLight = vec3(0);\r\n "
" #endif\r\n #endif\r\n\r\n\tfloat NL = clamp(dot(worldNormal, worldLigh"
"t), 0.0, 1.0);\r\n\tfloat surfNL = clamp(dot(var_Normal, worldLight), "
"0.0, 1.0);\r\n\tNL = min(NL, surfNL * 2.0);\r\n\tfloat NE = clamp(dot(world"
"Normal, SampleToView), 0.0, 1.0);\r\n\t\r\n\tfloat fzero = u_MaterialInfo."
"x;\r\n\tfloat shininess = u_MaterialInfo.y;\r\n #if defined(USE_SPECULARMA"
"P)\r\n\tvec4 specular = texture2D(u_SpecularMap, tex);\r\n\t//specular.rgb "
"= clamp(specular.rgb - diffuse.rgb, 0.0, 1.0);\r\n\tshininess *= specular.a"
";\r\n #endif\r\n\tfloat directedDiff = NL * CalcDiffuse(worldNormal, world"
"Light, SampleToView, NE, NL, fzero, shininess);\r\n\tdiffuse.rgb *= directe"
"dLight * directedDiff + ambientDiff * ambientLight;\r\n \r\n #if defined("
"USE_SPECULARMAP)\r\n\tvec3 halfAngle = normalize(worldLight + SampleToView)"
";\r\n\r\n\tfloat EH = clamp(dot(SampleToView, halfAngle), 0.0, 1.0);\r\n\tf"
"loat NH = clamp(dot(worldNormal, halfAngle), 0.0, 1.0);\r\n\r\n\tfloat dir"
"ectedSpec = NL * CalcSpecular(NH, NL, NE, EH, fzero, shininess);\r\n \r\n "
" #if defined(r_normalAmbient)\r\n\tvec3 ambientHalf = normalize(surfNorma"
"l + SampleToView);\r\n\tfloat ambientSpec = max(dot(ambientHalf, worldNorma"
"l) + 0.5, 0.0);\r\n\tambientSpec *= ambientSpec * 0.44;\r\n\tambientSpec = "
"pow(ambientSpec, shininess) * fzero;\r\n\tspecular.rgb *= directedSpec * di"
"rectedLight + ambientSpec * ambientLight;\r\n #else\r\n\tspecular.rgb *="
" directedSpec * directedLight;\r\n #endif\r\n #endif\r\n#endif\r\n\r\n"
"\tgl_FragColor = diffuse;\r\n\r\n#if defined(USE_SPECULARMAP) && defined(US"
"E_LIGHT) && !defined(USE_FAST_LIGHT)\r\n\tgl_FragColor.rgb += specular.rgb;"
"\r\n#endif\r\n\r\n#if !defined(USE_LIGHT_VERTEX)\r\n\tgl_FragColor *= var_C"
"olor;\r\n#endif\r\n}\r\n";
static const char *fallbackShadowfillShader_vp = static const char *fallbackShadowfillShader_vp =
"attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\nattribute" "attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\nattribute"
@ -1750,6 +1777,17 @@ void GLSL_InitGPUShaders(void)
if (!(i & LIGHTDEF_USE_NORMALMAP) && (i & LIGHTDEF_USE_PARALLAXMAP)) if (!(i & LIGHTDEF_USE_NORMALMAP) && (i & LIGHTDEF_USE_PARALLAXMAP))
continue; continue;
if (!((i & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHT_VECTOR))
{
if (i & LIGHTDEF_USE_SHADOWMAP)
continue;
if (i & LIGHTDEF_USE_SHADOW_CASCADE)
continue;
}
if ((i & LIGHTDEF_USE_SHADOW_CASCADE) && !(i & LIGHTDEF_USE_SHADOWMAP))
continue;
attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL; attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL;
extradefines[0] = '\0'; extradefines[0] = '\0';
@ -1837,6 +1875,12 @@ void GLSL_InitGPUShaders(void)
if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer) if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer)
Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n"); Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n");
if ((i & LIGHTDEF_USE_SHADOWMAP))
Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
if ((i & LIGHTDEF_USE_SHADOW_CASCADE))
Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n");
if (i & LIGHTDEF_TCGEN_ENVIRONMENT) if (i & LIGHTDEF_TCGEN_ENVIRONMENT)
Q_strcat(extradefines, 1024, "#define TCGEN_ENVIRONMENT\n"); Q_strcat(extradefines, 1024, "#define TCGEN_ENVIRONMENT\n");
@ -1871,6 +1915,8 @@ void GLSL_InitGPUShaders(void)
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, "u_DeluxeMap", GLSL_INT); GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, "u_DeluxeMap", GLSL_INT);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, "u_SpecularMap", GLSL_INT); GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, "u_SpecularMap", GLSL_INT);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, "u_ShadowMap", GLSL_INT); GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, "u_ShadowMap", GLSL_INT);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP2, "u_ShadowMap2", GLSL_INT);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP3, "u_ShadowMap3", GLSL_INT);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3); GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3); GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3);
@ -1883,6 +1929,10 @@ void GLSL_InitGPUShaders(void)
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4); GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT); GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMVP, "u_ShadowMvp", GLSL_MAT16);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMVP2, "u_ShadowMvp2", GLSL_MAT16);
GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMVP3, "u_ShadowMvp3", GLSL_MAT16);
GLSL_EndUniforms(&tr.lightallShader[i]); GLSL_EndUniforms(&tr.lightallShader[i]);
qglUseProgramObjectARB(tr.lightallShader[i].program); qglUseProgramObjectARB(tr.lightallShader[i].program);
@ -1892,6 +1942,8 @@ void GLSL_InitGPUShaders(void)
GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, TB_DELUXEMAP); GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, TB_DELUXEMAP);
GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, TB_SPECULARMAP); GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, TB_SPECULARMAP);
GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, TB_SHADOWMAP); GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, TB_SHADOWMAP);
GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP2, TB_SHADOWMAP2);
GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP3, TB_SHADOWMAP3);
qglUseProgramObjectARB(0); qglUseProgramObjectARB(0);
GLSL_FinishGPUShader(&tr.lightallShader[i]); GLSL_FinishGPUShader(&tr.lightallShader[i]);

View File

@ -2983,6 +2983,12 @@ void R_CreateBuiltinImages( void ) {
{ {
tr.pshadowMaps[x] = R_CreateImage(va("*shadowmap%i", x), NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); tr.pshadowMaps[x] = R_CreateImage(va("*shadowmap%i", x), NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
} }
//tr.sunShadowImage = R_CreateImage("*sunshadowmap", NULL, SUNSHADOW_MAP_SIZE, SUNSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
for ( x = 0; x < 3; x++)
{
tr.sunShadowDepthImage[x] = R_CreateImage(va("*sunshadowdepth%i", x), NULL, SUNSHADOW_MAP_SIZE, SUNSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT16_ARB);
}
} }

View File

@ -128,6 +128,7 @@ cvar_t *r_imageUpsample;
cvar_t *r_imageUpsampleMaxSize; cvar_t *r_imageUpsampleMaxSize;
cvar_t *r_imageUpsampleType; cvar_t *r_imageUpsampleType;
cvar_t *r_genNormalMaps; cvar_t *r_genNormalMaps;
cvar_t *r_testSunlight;
cvar_t *r_ignoreGLErrors; cvar_t *r_ignoreGLErrors;
cvar_t *r_logFile; cvar_t *r_logFile;
@ -1151,6 +1152,7 @@ void R_Register( void )
r_imageUpsampleMaxSize = ri.Cvar_Get( "r_imageUpsampleMaxSize", "1024", CVAR_ARCHIVE | CVAR_LATCH ); r_imageUpsampleMaxSize = ri.Cvar_Get( "r_imageUpsampleMaxSize", "1024", CVAR_ARCHIVE | CVAR_LATCH );
r_imageUpsampleType = ri.Cvar_Get( "r_imageUpsampleType", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_imageUpsampleType = ri.Cvar_Get( "r_imageUpsampleType", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_genNormalMaps = ri.Cvar_Get( "r_genNormalMaps", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_genNormalMaps = ri.Cvar_Get( "r_genNormalMaps", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_testSunlight = ri.Cvar_Get( "r_testSunlight", "0", CVAR_CHEAT );
// //
// temporary latched variables that can only change over a restart // temporary latched variables that can only change over a restart

View File

@ -67,6 +67,7 @@ typedef unsigned int glIndex_t;
#define MAX_CALC_PSHADOWS 64 #define MAX_CALC_PSHADOWS 64
#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces #define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
#define PSHADOW_MAP_SIZE 512 #define PSHADOW_MAP_SIZE 512
#define SUNSHADOW_MAP_SIZE 1024
typedef struct dlight_s { typedef struct dlight_s {
vec3_t origin; vec3_t origin;
@ -409,10 +410,12 @@ enum
TB_DIFFUSEMAP = 0, TB_DIFFUSEMAP = 0,
TB_LIGHTMAP = 1, TB_LIGHTMAP = 1,
TB_LEVELSMAP = 1, TB_LEVELSMAP = 1,
TB_NORMALMAP, TB_SHADOWMAP = 1,
TB_DELUXEMAP, TB_NORMALMAP = 2,
TB_SPECULARMAP, TB_DELUXEMAP = 3,
TB_SHADOWMAP, TB_SHADOWMAP2 = 3,
TB_SPECULARMAP = 4,
TB_SHADOWMAP3 = 5,
NUM_TEXTURE_BUNDLES = 6 NUM_TEXTURE_BUNDLES = 6
}; };
@ -737,10 +740,12 @@ enum
LIGHTDEF_USE_SPECULARMAP = 0x0008, LIGHTDEF_USE_SPECULARMAP = 0x0008,
LIGHTDEF_USE_DELUXEMAP = 0x0010, LIGHTDEF_USE_DELUXEMAP = 0x0010,
LIGHTDEF_USE_PARALLAXMAP = 0x0020, LIGHTDEF_USE_PARALLAXMAP = 0x0020,
LIGHTDEF_TCGEN_ENVIRONMENT = 0x0040, LIGHTDEF_USE_SHADOWMAP = 0x0040,
LIGHTDEF_ENTITY = 0x0080, LIGHTDEF_USE_SHADOW_CASCADE= 0x0080,
LIGHTDEF_ALL = 0x00FF, LIGHTDEF_TCGEN_ENVIRONMENT = 0x0100,
LIGHTDEF_COUNT = 0x0100 LIGHTDEF_ENTITY = 0x0200,
LIGHTDEF_ALL = 0x03FF,
LIGHTDEF_COUNT = 0x0400
}; };
enum enum
@ -836,6 +841,8 @@ enum
GENERIC_UNIFORM_DELUXEMAP, GENERIC_UNIFORM_DELUXEMAP,
GENERIC_UNIFORM_SPECULARMAP, GENERIC_UNIFORM_SPECULARMAP,
GENERIC_UNIFORM_SHADOWMAP, GENERIC_UNIFORM_SHADOWMAP,
GENERIC_UNIFORM_SHADOWMAP2,
GENERIC_UNIFORM_SHADOWMAP3,
GENERIC_UNIFORM_DIFFUSETEXMATRIX, GENERIC_UNIFORM_DIFFUSETEXMATRIX,
//GENERIC_UNIFORM_NORMALTEXMATRIX, //GENERIC_UNIFORM_NORMALTEXMATRIX,
//GENERIC_UNIFORM_SPECULARTEXMATRIX, //GENERIC_UNIFORM_SPECULARTEXMATRIX,
@ -864,6 +871,9 @@ enum
GENERIC_UNIFORM_TIME, GENERIC_UNIFORM_TIME,
GENERIC_UNIFORM_VERTEXLERP, GENERIC_UNIFORM_VERTEXLERP,
GENERIC_UNIFORM_MATERIALINFO, GENERIC_UNIFORM_MATERIALINFO,
GENERIC_UNIFORM_SHADOWMVP,
GENERIC_UNIFORM_SHADOWMVP2,
GENERIC_UNIFORM_SHADOWMVP3,
GENERIC_UNIFORM_COUNT GENERIC_UNIFORM_COUNT
}; };
@ -913,6 +923,10 @@ typedef struct {
unsigned int dlightMask; unsigned int dlightMask;
int num_pshadows; int num_pshadows;
struct pshadow_s *pshadows; struct pshadow_s *pshadows;
float sunShadowMvp[3][16];
float sunDir[4];
float sunCol[4];
} trRefdef_t; } trRefdef_t;
@ -962,6 +976,7 @@ typedef struct {
cplane_t frustum[5]; cplane_t frustum[5];
vec3_t visBounds[2]; vec3_t visBounds[2];
float zFar; float zFar;
float zNear;
stereoFrame_t stereoFrame; stereoFrame_t stereoFrame;
} viewParms_t; } viewParms_t;
@ -1636,6 +1651,8 @@ typedef struct {
qboolean texture_srgb; qboolean texture_srgb;
qboolean framebuffer_srgb; qboolean framebuffer_srgb;
qboolean depthClamp;
} glRefConfig_t; } glRefConfig_t;
@ -1753,6 +1770,7 @@ typedef struct {
image_t *calcLevelsImage; image_t *calcLevelsImage;
image_t *targetLevelsImage; image_t *targetLevelsImage;
image_t *fixedLevelsImage; image_t *fixedLevelsImage;
image_t *sunShadowDepthImage[3];
image_t *textureDepthImage; image_t *textureDepthImage;
@ -1766,6 +1784,7 @@ typedef struct {
FBO_t *quarterFbo[2]; FBO_t *quarterFbo[2];
FBO_t *calcLevelsFbo; FBO_t *calcLevelsFbo;
FBO_t *targetLevelsFbo; FBO_t *targetLevelsFbo;
FBO_t *sunShadowFbo[3];
shader_t *defaultShader; shader_t *defaultShader;
shader_t *shadowShader; shader_t *shadowShader;
@ -2021,6 +2040,7 @@ extern cvar_t *r_imageUpsample;
extern cvar_t *r_imageUpsampleMaxSize; extern cvar_t *r_imageUpsampleMaxSize;
extern cvar_t *r_imageUpsampleType; extern cvar_t *r_imageUpsampleType;
extern cvar_t *r_genNormalMaps; extern cvar_t *r_genNormalMaps;
extern cvar_t *r_testSunlight;
extern cvar_t *r_greyscale; extern cvar_t *r_greyscale;
@ -2050,6 +2070,7 @@ void R_SwapBuffers( int );
void R_RenderView( viewParms_t *parms ); void R_RenderView( viewParms_t *parms );
void R_RenderDlightCubemaps(const refdef_t *fd); void R_RenderDlightCubemaps(const refdef_t *fd);
void R_RenderPshadowMaps(const refdef_t *fd); void R_RenderPshadowMaps(const refdef_t *fd);
void R_RenderSunShadowMaps(const refdef_t *fd, int level);
void R_AddMD3Surfaces( trRefEntity_t *e ); void R_AddMD3Surfaces( trRefEntity_t *e );
void R_AddNullModelSurfaces( trRefEntity_t *e ); void R_AddNullModelSurfaces( trRefEntity_t *e );

View File

@ -438,7 +438,7 @@ void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal,
} }
#ifdef USE_VERT_TANGENT_SPACE #ifdef USE_VERT_TANGENT_SPACE
qboolean R_CalcTangentVectors(srfVert_t * dv[3]) qboolean R_CalcTangentVectors(srfVert_t * dv[3])
{ {
int i; int i;
@ -1812,6 +1812,8 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
int pshadowed; int pshadowed;
int i; int i;
//ri.Printf(PRINT_ALL, "firstDrawSurf %d numDrawSurfs %d\n", (int)(drawSurfs - tr.refdef.drawSurfs), numDrawSurfs);
// it is possible for some views to not have any surfaces // it is possible for some views to not have any surfaces
if ( numDrawSurfs < 1 ) { if ( numDrawSurfs < 1 ) {
// we still need to add it for hyperspace cases // we still need to add it for hyperspace cases
@ -1829,7 +1831,7 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
// sort the drawsurfs by sort type, then orientation, then shader // sort the drawsurfs by sort type, then orientation, then shader
R_RadixSort( drawSurfs, numDrawSurfs ); R_RadixSort( drawSurfs, numDrawSurfs );
if (tr.viewParms.isShadowmap) if (tr.viewParms.isShadowmap || tr.viewParms.isDepthShadow)
{ {
R_AddDrawSurfCmd( drawSurfs, numDrawSurfs ); R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
return; return;
@ -1881,7 +1883,7 @@ static void R_AddEntitySurface (int entityNum)
// we don't want the hacked weapon position showing in // we don't want the hacked weapon position showing in
// mirrors, because the true body position will already be drawn // mirrors, because the true body position will already be drawn
// //
if ( (ent->e.renderfx & RF_FIRST_PERSON) && (tr.viewParms.isPortal || tr.viewParms.isShadowmap)) { if ( (ent->e.renderfx & RF_FIRST_PERSON) && (tr.viewParms.isPortal || tr.viewParms.isShadowmap || tr.viewParms.isDepthShadow)) {
return; return;
} }
@ -2512,3 +2514,325 @@ void R_RenderPshadowMaps(const refdef_t *fd)
} }
} }
} }
void R_RenderSunShadowMaps(const refdef_t *fd, int level)
{
viewParms_t shadowParms;
vec4_t lightDir, lightCol;
vec3_t up;
vec3_t lightViewAxis[3];
vec3_t lightOrigin;
float xmin, xmax, ymin, ymax, znear, zfar, viewznear, viewzfar;
if (r_testSunlight->integer)
{
int scale = 32768;
float angle = (fd->time % scale) / (float)scale * M_PI;
lightDir[0] = cos(angle);
lightDir[1] = sin(35.0f * M_PI / 180.0f);
lightDir[2] = sin(angle) * cos(35.0f * M_PI / 180.0f);
lightDir[3] = 0.0f;
if (1) //((fd->time % (scale * 2)) < scale)
{
lightCol[0] =
lightCol[1] =
lightCol[2] = CLAMP(sin(angle) * 2.0f, 0.0f, 1.0f) * 2.0f;
lightCol[3] = 1.0f;
}
else
{
lightCol[0] =
lightCol[1] =
lightCol[2] = CLAMP(sin(angle) * 2.0f * 0.1f, 0.0f, 0.1f);
lightCol[3] = 1.0f;
}
VectorCopy4(lightDir, tr.refdef.sunDir);
VectorCopy4(lightCol, tr.refdef.sunCol);
}
else
{
VectorCopy4(tr.refdef.sunDir, lightDir);
}
//viewRadius = 128;
//lightRadius = 4096;
switch(level)
{
case 0:
default:
viewznear = r_znear->value;
viewzfar = 256;
break;
case 1:
viewznear = 256;
viewzfar = 768;
break;
case 2:
viewznear = 768;
viewzfar = 2048;
break;
}
VectorCopy(fd->vieworg, lightOrigin);
//VectorMA(fd->vieworg, (zfar - znear) / 2, lightDir, lightOrigin);
//VectorMA(lightOrigin, (xmax - xmin) / 2, fd->viewaxis[0], lightOrigin);
//ri.Printf(PRINT_ALL, "viewOrigin %f %f %f\n", fd->vieworg[0], fd->vieworg[1], fd->vieworg[2]);
//ri.Printf(PRINT_ALL, "forward %f %f %f\n", fd->viewaxis[0][0], fd->viewaxis[0][1], fd->viewaxis[0][2]);
//ri.Printf(PRINT_ALL, "right %f %f %f\n", fd->viewaxis[1][0], fd->viewaxis[1][1], fd->viewaxis[1][2]);
//ri.Printf(PRINT_ALL, "up %f %f %f\n", fd->viewaxis[2][0], fd->viewaxis[2][1], fd->viewaxis[2][2]);
//ri.Printf(PRINT_ALL, "lightOrigin %f %f %f\n", lightOrigin[0], lightOrigin[1], lightOrigin[2]);
// make up a projection
VectorScale(lightDir, -1.0f, lightViewAxis[0]);
// try to use player right as up
VectorCopy(fd->viewaxis[1], up);
//VectorSet(up, 0, 1, 0);
if ( abs(DotProduct(up, lightViewAxis[0])) > 0.9f )
{
VectorCopy(fd->viewaxis[2], up);
//VectorSet(up, 0, 0, 1);
}
CrossProduct(lightViewAxis[0], up, lightViewAxis[1]);
VectorNormalize(lightViewAxis[1]);
CrossProduct(lightViewAxis[0], lightViewAxis[1], lightViewAxis[2]);
{
matrix_t lightViewMatrix;
vec3_t lightviewBounds[2];
vec4_t point, base, lightViewPoint;
float lx, ly;
base[3] = 1;
point[3] = 1;
lightViewPoint[3] = 1;
lightViewMatrix[0] = lightViewAxis[0][0];
lightViewMatrix[1] = lightViewAxis[1][0];
lightViewMatrix[2] = lightViewAxis[2][0];
lightViewMatrix[3] = 0;
lightViewMatrix[4] = lightViewAxis[0][1];
lightViewMatrix[5] = lightViewAxis[1][1];
lightViewMatrix[6] = lightViewAxis[2][1];
lightViewMatrix[7] = 0;
lightViewMatrix[8] = lightViewAxis[0][2];
lightViewMatrix[9] = lightViewAxis[1][2];
lightViewMatrix[10] = lightViewAxis[2][2];
lightViewMatrix[11] = 0;
lightViewMatrix[12] = -DotProduct(lightOrigin, lightViewAxis[0]);
lightViewMatrix[13] = -DotProduct(lightOrigin, lightViewAxis[1]);
lightViewMatrix[14] = -DotProduct(lightOrigin, lightViewAxis[2]);
lightViewMatrix[15] = 1;
ClearBounds(lightviewBounds[0], lightviewBounds[1]);
//viewznear = r_znear->value;
//viewzfar = 512;
// add view near plane
lx = viewznear * tan(fd->fov_x * M_PI / 360.0f);
ly = viewznear * tan(fd->fov_y * M_PI / 360.0f);
VectorMA(fd->vieworg, viewznear, fd->viewaxis[0], base);
VectorMA(base, lx, fd->viewaxis[1], point);
VectorMA(point, ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, -lx, fd->viewaxis[1], point);
VectorMA(point, ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, lx, fd->viewaxis[1], point);
VectorMA(point, -ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, -lx, fd->viewaxis[1], point);
VectorMA(point, -ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
// add view far plane
lx = viewzfar * tan(fd->fov_x * M_PI / 360.0f);
ly = viewzfar * tan(fd->fov_y * M_PI / 360.0f);
VectorMA(fd->vieworg, viewzfar, fd->viewaxis[0], base);
VectorMA(base, lx, fd->viewaxis[1], point);
VectorMA(point, ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, -lx, fd->viewaxis[1], point);
VectorMA(point, ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, lx, fd->viewaxis[1], point);
VectorMA(point, -ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, -lx, fd->viewaxis[1], point);
VectorMA(point, -ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
xmin = lightviewBounds[0][1];
xmax = lightviewBounds[1][1];
ymin = -lightviewBounds[1][2];
ymax = -lightviewBounds[0][2];
zfar = lightviewBounds[1][0];
if (glRefConfig.depthClamp)
znear = lightviewBounds[0][0];
else
znear = zfar - 8192;
//ri.Printf(PRINT_ALL, "znear %f zfar %f\n", lightviewBounds[0][0], lightviewBounds[1][0]);
//ri.Printf(PRINT_ALL, "fovx %f fovy %f xmin %f xmax %f ymin %f ymax %f\n", fd->fov_x, fd->fov_y, xmin, xmax, ymin, ymax);
}
{
int firstDrawSurf;
int j;
Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
if (glRefConfig.framebufferObject)
{
shadowParms.viewportX = 0;
shadowParms.viewportY = 0;
}
else
{
shadowParms.viewportX = tr.refdef.x;
shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + SUNSHADOW_MAP_SIZE );
}
shadowParms.viewportWidth = SUNSHADOW_MAP_SIZE;
shadowParms.viewportHeight = SUNSHADOW_MAP_SIZE;
shadowParms.isPortal = qfalse;
shadowParms.isMirror = qfalse;
shadowParms.fovX = 90;
shadowParms.fovY = 90;
if (glRefConfig.framebufferObject)
shadowParms.targetFbo = tr.sunShadowFbo[level];
shadowParms.isShadowmap = qfalse;
shadowParms.isDepthShadow = qtrue;
shadowParms.zFar = zfar;
VectorCopy(lightOrigin, shadowParms.or.origin);
VectorCopy(lightViewAxis[0], shadowParms.or.axis[0]);
VectorCopy(lightViewAxis[1], shadowParms.or.axis[1]);
VectorCopy(lightViewAxis[2], shadowParms.or.axis[2]);
VectorCopy(lightOrigin, shadowParms.pvsOrigin );
{
tr.viewCount++;
tr.viewParms = shadowParms;
tr.viewParms.frameSceneNum = tr.frameSceneNum;
tr.viewParms.frameCount = tr.frameCount;
firstDrawSurf = tr.refdef.numDrawSurfs;
tr.viewCount++;
// set viewParms.world
R_RotateForViewer ();
{
//float xmin, xmax, ymin, ymax, znear, zfar;
viewParms_t *dest = &tr.viewParms;
vec3_t pop;
dest->projectionMatrix[0] = 2 / (xmax - xmin);
dest->projectionMatrix[4] = 0;
dest->projectionMatrix[8] = 0;
dest->projectionMatrix[12] = (xmax + xmin) / (xmax - xmin);
dest->projectionMatrix[1] = 0;
dest->projectionMatrix[5] = 2 / (ymax - ymin);
dest->projectionMatrix[9] = 0;
dest->projectionMatrix[13] = ( ymax + ymin ) / (ymax - ymin);
dest->projectionMatrix[2] = 0;
dest->projectionMatrix[6] = 0;
dest->projectionMatrix[10] = -2 / (zfar - znear);
dest->projectionMatrix[14] = (zfar + znear) / (znear - zfar);
dest->projectionMatrix[3] = 0;
dest->projectionMatrix[7] = 0;
dest->projectionMatrix[11] = 0;
dest->projectionMatrix[15] = 1;
Matrix16Multiply(dest->projectionMatrix, tr.viewParms.world.modelMatrix, tr.refdef.sunShadowMvp[level]);
VectorScale(dest->or.axis[1], 1.0f, dest->frustum[0].normal);
VectorMA(dest->or.origin, xmin, dest->frustum[0].normal, pop);
dest->frustum[0].dist = DotProduct(pop, dest->frustum[0].normal);
VectorScale(dest->or.axis[1], -1.0f, dest->frustum[1].normal);
VectorMA(dest->or.origin, -xmax, dest->frustum[1].normal, pop);
dest->frustum[1].dist = DotProduct(pop, dest->frustum[1].normal);
VectorScale(dest->or.axis[2], 1.0f, dest->frustum[2].normal);
VectorMA(dest->or.origin, -ymax, dest->frustum[2].normal, pop);
dest->frustum[2].dist = DotProduct(pop, dest->frustum[2].normal);
VectorScale(dest->or.axis[2], -1.0f, dest->frustum[3].normal);
VectorMA(dest->or.origin, ymin, dest->frustum[3].normal, pop);
dest->frustum[3].dist = DotProduct(pop, dest->frustum[3].normal);
VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
VectorMA(dest->or.origin, -zfar, dest->frustum[4].normal, pop);
dest->frustum[4].dist = DotProduct(pop, dest->frustum[4].normal);
for (j = 0; j < 5; j++)
{
dest->frustum[j].type = PLANE_NON_AXIAL;
SetPlaneSignbits (&dest->frustum[j]);
}
}
R_AddWorldSurfaces ();
R_AddPolygonSurfaces();
// set the projection matrix with the minimum zfar
// now that we have the world bounded
// this needs to be done before entities are
// added, because they use the projection
// matrix for lod calculation
// dynamically compute far clip plane distance
//R_SetFarClip();
// we know the size of the clipping volume. Now set the rest of the projection matrix.
//R_SetupProjectionZ (&tr.viewParms);
R_AddEntitySurfaces ();
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
}
}
}

View File

@ -1,404 +1,404 @@
/* /*
=========================================================================== ===========================================================================
Copyright (C) 1999-2005 Id Software, Inc. Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code. This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License, published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version. or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=========================================================================== ===========================================================================
*/ */
// tr_mesh.c: triangle model functions // tr_mesh.c: triangle model functions
#include "tr_local.h" #include "tr_local.h"
static float ProjectRadius( float r, vec3_t location ) static float ProjectRadius( float r, vec3_t location )
{ {
float pr; float pr;
float dist; float dist;
float c; float c;
vec3_t p; vec3_t p;
float projected[4]; float projected[4];
c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin ); c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin );
dist = DotProduct( tr.viewParms.or.axis[0], location ) - c; dist = DotProduct( tr.viewParms.or.axis[0], location ) - c;
if ( dist <= 0 ) if ( dist <= 0 )
return 0; return 0;
p[0] = 0; p[0] = 0;
p[1] = fabs( r ); p[1] = fabs( r );
p[2] = -dist; p[2] = -dist;
projected[0] = p[0] * tr.viewParms.projectionMatrix[0] + projected[0] = p[0] * tr.viewParms.projectionMatrix[0] +
p[1] * tr.viewParms.projectionMatrix[4] + p[1] * tr.viewParms.projectionMatrix[4] +
p[2] * tr.viewParms.projectionMatrix[8] + p[2] * tr.viewParms.projectionMatrix[8] +
tr.viewParms.projectionMatrix[12]; tr.viewParms.projectionMatrix[12];
projected[1] = p[0] * tr.viewParms.projectionMatrix[1] + projected[1] = p[0] * tr.viewParms.projectionMatrix[1] +
p[1] * tr.viewParms.projectionMatrix[5] + p[1] * tr.viewParms.projectionMatrix[5] +
p[2] * tr.viewParms.projectionMatrix[9] + p[2] * tr.viewParms.projectionMatrix[9] +
tr.viewParms.projectionMatrix[13]; tr.viewParms.projectionMatrix[13];
projected[2] = p[0] * tr.viewParms.projectionMatrix[2] + projected[2] = p[0] * tr.viewParms.projectionMatrix[2] +
p[1] * tr.viewParms.projectionMatrix[6] + p[1] * tr.viewParms.projectionMatrix[6] +
p[2] * tr.viewParms.projectionMatrix[10] + p[2] * tr.viewParms.projectionMatrix[10] +
tr.viewParms.projectionMatrix[14]; tr.viewParms.projectionMatrix[14];
projected[3] = p[0] * tr.viewParms.projectionMatrix[3] + projected[3] = p[0] * tr.viewParms.projectionMatrix[3] +
p[1] * tr.viewParms.projectionMatrix[7] + p[1] * tr.viewParms.projectionMatrix[7] +
p[2] * tr.viewParms.projectionMatrix[11] + p[2] * tr.viewParms.projectionMatrix[11] +
tr.viewParms.projectionMatrix[15]; tr.viewParms.projectionMatrix[15];
pr = projected[1] / projected[3]; pr = projected[1] / projected[3];
if ( pr > 1.0f ) if ( pr > 1.0f )
pr = 1.0f; pr = 1.0f;
return pr; return pr;
} }
/* /*
============= =============
R_CullModel R_CullModel
============= =============
*/ */
static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) { static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) {
vec3_t bounds[2]; vec3_t bounds[2];
mdvFrame_t *oldFrame, *newFrame; mdvFrame_t *oldFrame, *newFrame;
int i; int i;
// compute frame pointers // compute frame pointers
newFrame = model->frames + ent->e.frame; newFrame = model->frames + ent->e.frame;
oldFrame = model->frames + ent->e.oldframe; oldFrame = model->frames + ent->e.oldframe;
// cull bounding sphere ONLY if this is not an upscaled entity // cull bounding sphere ONLY if this is not an upscaled entity
if ( !ent->e.nonNormalizedAxes ) if ( !ent->e.nonNormalizedAxes )
{ {
if ( ent->e.frame == ent->e.oldframe ) if ( ent->e.frame == ent->e.oldframe )
{ {
switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) ) switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
{ {
case CULL_OUT: case CULL_OUT:
tr.pc.c_sphere_cull_md3_out++; tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT; return CULL_OUT;
case CULL_IN: case CULL_IN:
tr.pc.c_sphere_cull_md3_in++; tr.pc.c_sphere_cull_md3_in++;
return CULL_IN; return CULL_IN;
case CULL_CLIP: case CULL_CLIP:
tr.pc.c_sphere_cull_md3_clip++; tr.pc.c_sphere_cull_md3_clip++;
break; break;
} }
} }
else else
{ {
int sphereCull, sphereCullB; int sphereCull, sphereCullB;
sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ); sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
if ( newFrame == oldFrame ) { if ( newFrame == oldFrame ) {
sphereCullB = sphereCull; sphereCullB = sphereCull;
} else { } else {
sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius ); sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
} }
if ( sphereCull == sphereCullB ) if ( sphereCull == sphereCullB )
{ {
if ( sphereCull == CULL_OUT ) if ( sphereCull == CULL_OUT )
{ {
tr.pc.c_sphere_cull_md3_out++; tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT; return CULL_OUT;
} }
else if ( sphereCull == CULL_IN ) else if ( sphereCull == CULL_IN )
{ {
tr.pc.c_sphere_cull_md3_in++; tr.pc.c_sphere_cull_md3_in++;
return CULL_IN; return CULL_IN;
} }
else else
{ {
tr.pc.c_sphere_cull_md3_clip++; tr.pc.c_sphere_cull_md3_clip++;
} }
} }
} }
} }
// calculate a bounding box in the current coordinate system // calculate a bounding box in the current coordinate system
for (i = 0 ; i < 3 ; i++) { for (i = 0 ; i < 3 ; i++) {
bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i]; bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i]; bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
} }
switch ( R_CullLocalBox( bounds ) ) switch ( R_CullLocalBox( bounds ) )
{ {
case CULL_IN: case CULL_IN:
tr.pc.c_box_cull_md3_in++; tr.pc.c_box_cull_md3_in++;
return CULL_IN; return CULL_IN;
case CULL_CLIP: case CULL_CLIP:
tr.pc.c_box_cull_md3_clip++; tr.pc.c_box_cull_md3_clip++;
return CULL_CLIP; return CULL_CLIP;
case CULL_OUT: case CULL_OUT:
default: default:
tr.pc.c_box_cull_md3_out++; tr.pc.c_box_cull_md3_out++;
return CULL_OUT; return CULL_OUT;
} }
} }
/* /*
================= =================
R_ComputeLOD R_ComputeLOD
================= =================
*/ */
int R_ComputeLOD( trRefEntity_t *ent ) { int R_ComputeLOD( trRefEntity_t *ent ) {
float radius; float radius;
float flod, lodscale; float flod, lodscale;
float projectedRadius; float projectedRadius;
mdvFrame_t *frame; mdvFrame_t *frame;
#ifdef RAVENMD4 #ifdef RAVENMD4
mdrHeader_t *mdr; mdrHeader_t *mdr;
mdrFrame_t *mdrframe; mdrFrame_t *mdrframe;
#endif #endif
int lod; int lod;
if ( tr.currentModel->numLods < 2 ) if ( tr.currentModel->numLods < 2 )
{ {
// model has only 1 LOD level, skip computations and bias // model has only 1 LOD level, skip computations and bias
lod = 0; lod = 0;
} }
else else
{ {
// multiple LODs exist, so compute projected bounding sphere // multiple LODs exist, so compute projected bounding sphere
// and use that as a criteria for selecting LOD // and use that as a criteria for selecting LOD
#ifdef RAVENMD4 #ifdef RAVENMD4
if(tr.currentModel->type == MOD_MDR) if(tr.currentModel->type == MOD_MDR)
{ {
int frameSize; int frameSize;
mdr = (mdrHeader_t *) tr.currentModel->modelData; mdr = (mdrHeader_t *) tr.currentModel->modelData;
frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]); frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]);
mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame); mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame);
radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]); radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]);
} }
else else
#endif #endif
{ {
//frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames ); //frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
frame = tr.currentModel->mdv[0]->frames; frame = tr.currentModel->mdv[0]->frames;
frame += ent->e.frame; frame += ent->e.frame;
radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] ); radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );
} }
if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 ) if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
{ {
lodscale = r_lodscale->value; lodscale = r_lodscale->value;
if (lodscale > 20) lodscale = 20; if (lodscale > 20) lodscale = 20;
flod = 1.0f - projectedRadius * lodscale; flod = 1.0f - projectedRadius * lodscale;
} }
else else
{ {
// object intersects near view plane, e.g. view weapon // object intersects near view plane, e.g. view weapon
flod = 0; flod = 0;
} }
flod *= tr.currentModel->numLods; flod *= tr.currentModel->numLods;
lod = ri.ftol(flod); lod = ri.ftol(flod);
if ( lod < 0 ) if ( lod < 0 )
{ {
lod = 0; lod = 0;
} }
else if ( lod >= tr.currentModel->numLods ) else if ( lod >= tr.currentModel->numLods )
{ {
lod = tr.currentModel->numLods - 1; lod = tr.currentModel->numLods - 1;
} }
} }
lod += r_lodbias->integer; lod += r_lodbias->integer;
if ( lod >= tr.currentModel->numLods ) if ( lod >= tr.currentModel->numLods )
lod = tr.currentModel->numLods - 1; lod = tr.currentModel->numLods - 1;
if ( lod < 0 ) if ( lod < 0 )
lod = 0; lod = 0;
return lod; return lod;
} }
/* /*
================= =================
R_ComputeFogNum R_ComputeFogNum
================= =================
*/ */
int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) { int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
int i, j; int i, j;
fog_t *fog; fog_t *fog;
mdvFrame_t *mdvFrame; mdvFrame_t *mdvFrame;
vec3_t localOrigin; vec3_t localOrigin;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return 0; return 0;
} }
// FIXME: non-normalized axis issues // FIXME: non-normalized axis issues
mdvFrame = model->frames + ent->e.frame; mdvFrame = model->frames + ent->e.frame;
VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin ); VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin );
for ( i = 1 ; i < tr.world->numfogs ; i++ ) { for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
fog = &tr.world->fogs[i]; fog = &tr.world->fogs[i];
for ( j = 0 ; j < 3 ; j++ ) { for ( j = 0 ; j < 3 ; j++ ) {
if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) { if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) {
break; break;
} }
if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) { if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) {
break; break;
} }
} }
if ( j == 3 ) { if ( j == 3 ) {
return i; return i;
} }
} }
return 0; return 0;
} }
/* /*
================= =================
R_AddMD3Surfaces R_AddMD3Surfaces
================= =================
*/ */
void R_AddMD3Surfaces( trRefEntity_t *ent ) { void R_AddMD3Surfaces( trRefEntity_t *ent ) {
int i; int i;
mdvModel_t *model = NULL; mdvModel_t *model = NULL;
mdvSurface_t *surface = NULL; mdvSurface_t *surface = NULL;
shader_t *shader = NULL; shader_t *shader = NULL;
int cull; int cull;
int lod; int lod;
int fogNum; int fogNum;
qboolean personalModel; qboolean personalModel;
// don't add third_person objects if not in a portal // don't add third_person objects if not in a portal
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal || tr.viewParms.isShadowmap); personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal || tr.viewParms.isShadowmap || tr.viewParms.isDepthShadow);
if ( ent->e.renderfx & RF_WRAP_FRAMES ) { if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
ent->e.frame %= tr.currentModel->mdv[0]->numFrames; ent->e.frame %= tr.currentModel->mdv[0]->numFrames;
ent->e.oldframe %= tr.currentModel->mdv[0]->numFrames; ent->e.oldframe %= tr.currentModel->mdv[0]->numFrames;
} }
// //
// Validate the frames so there is no chance of a crash. // Validate the frames so there is no chance of a crash.
// This will write directly into the entity structure, so // This will write directly into the entity structure, so
// when the surfaces are rendered, they don't need to be // when the surfaces are rendered, they don't need to be
// range checked again. // range checked again.
// //
if ( (ent->e.frame >= tr.currentModel->mdv[0]->numFrames) if ( (ent->e.frame >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.frame < 0) || (ent->e.frame < 0)
|| (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames) || (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.oldframe < 0) ) { || (ent->e.oldframe < 0) ) {
ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n", ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
ent->e.oldframe, ent->e.frame, ent->e.oldframe, ent->e.frame,
tr.currentModel->name ); tr.currentModel->name );
ent->e.frame = 0; ent->e.frame = 0;
ent->e.oldframe = 0; ent->e.oldframe = 0;
} }
// //
// compute LOD // compute LOD
// //
lod = R_ComputeLOD( ent ); lod = R_ComputeLOD( ent );
model = tr.currentModel->mdv[lod]; model = tr.currentModel->mdv[lod];
// //
// cull the entire model if merged bounding box of both frames // cull the entire model if merged bounding box of both frames
// is outside the view frustum. // is outside the view frustum.
// //
cull = R_CullModel ( model, ent ); cull = R_CullModel ( model, ent );
if ( cull == CULL_OUT ) { if ( cull == CULL_OUT ) {
return; return;
} }
// //
// set up lighting now that we know we aren't culled // set up lighting now that we know we aren't culled
// //
if ( !personalModel || r_shadows->integer > 1 ) { if ( !personalModel || r_shadows->integer > 1 ) {
R_SetupEntityLighting( &tr.refdef, ent ); R_SetupEntityLighting( &tr.refdef, ent );
} }
// //
// see if we are in a fog volume // see if we are in a fog volume
// //
fogNum = R_ComputeFogNum( model, ent ); fogNum = R_ComputeFogNum( model, ent );
// //
// draw all surfaces // draw all surfaces
// //
surface = model->surfaces; surface = model->surfaces;
for ( i = 0 ; i < model->numSurfaces ; i++ ) { for ( i = 0 ; i < model->numSurfaces ; i++ ) {
if ( ent->e.customShader ) { if ( ent->e.customShader ) {
shader = R_GetShaderByHandle( ent->e.customShader ); shader = R_GetShaderByHandle( ent->e.customShader );
} else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) { } else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) {
skin_t *skin; skin_t *skin;
int j; int j;
skin = R_GetSkinByHandle( ent->e.customSkin ); skin = R_GetSkinByHandle( ent->e.customSkin );
// match the surface name to something in the skin file // match the surface name to something in the skin file
shader = tr.defaultShader; shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) { for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased // the names have both been lowercased
if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) { if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
shader = skin->surfaces[j]->shader; shader = skin->surfaces[j]->shader;
break; break;
} }
} }
if (shader == tr.defaultShader) { if (shader == tr.defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name); ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name);
} }
else if (shader->defaultShader) { else if (shader->defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name); ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
} }
//} else if ( surface->numShaders <= 0 ) { //} else if ( surface->numShaders <= 0 ) {
//shader = tr.defaultShader; //shader = tr.defaultShader;
} else { } else {
//md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders ); //md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
//md3Shader += ent->e.skinNum % surface->numShaders; //md3Shader += ent->e.skinNum % surface->numShaders;
//shader = tr.shaders[ md3Shader->shaderIndex ]; //shader = tr.shaders[ md3Shader->shaderIndex ];
shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ]; shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ];
} }
// don't add third_person objects if not viewing through a portal // don't add third_person objects if not viewing through a portal
if(!personalModel) if(!personalModel)
{ {
srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i]; srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i];
R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse ); R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse );
} }
surface++; surface++;
} }
} }

View File

@ -365,15 +365,29 @@ void RE_RenderScene( const refdef_t *fd ) {
} }
} }
#ifdef REACTION //#ifdef REACTION
// Makro - copy exta info if present // Makro - copy exta info if present
if (fd->rdflags & RDF_EXTRA) { if (fd->rdflags & RDF_EXTRA) {
const refdefex_t* extra = (const refdefex_t*) (fd+1); const refdefex_t* extra = (const refdefex_t*) (fd+1);
#ifdef REACTION
tr.refdef.blurFactor = extra->blurFactor; tr.refdef.blurFactor = extra->blurFactor;
} else {
tr.refdef.blurFactor = 0.f;
}
#endif #endif
if (fd->rdflags & RDF_SUNLIGHT)
{
VectorCopy(extra->sunDir, tr.refdef.sunDir);
tr.refdef.sunDir[3] = 0.0f;
VectorCopy(extra->sunCol, tr.refdef.sunCol);
tr.refdef.sunCol[3] = 1.0f;
}
} else {
#ifdef REACTION
tr.refdef.blurFactor = 0.f;
#endif
VectorSet4(tr.refdef.sunDir, 0.0f, 1.0f, 0.0f, 0.0f);
VectorSet4(tr.refdef.sunCol, 1.0f, 1.0f, 1.0f, 1.0f);
}
//#endif
// derived info // derived info
@ -422,6 +436,14 @@ void RE_RenderScene( const refdef_t *fd ) {
R_RenderPshadowMaps(fd); R_RenderPshadowMaps(fd);
} }
// playing with even more shadows
if(!( fd->rdflags & RDF_NOWORLDMODEL ) && ((fd->rdflags & RDF_SUNLIGHT) || r_testSunlight->integer))
{
R_RenderSunShadowMaps(fd, 0);
R_RenderSunShadowMaps(fd, 1);
R_RenderSunShadowMaps(fd, 2);
}
// setup view parms for the initial view // setup view parms for the initial view
// //
// set up viewport // set up viewport

View File

@ -850,6 +850,199 @@ static void ForwardDlight( void ) {
} }
static void ForwardSunlight( void ) {
int l;
//vec3_t origin;
//float scale;
int stage;
int stageGlState[2];
qboolean alphaOverride = qfalse;
int deformGen;
vec5_t deformParams;
vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
float eyeT = 0;
shaderCommands_t *input = &tess;
ComputeDeformValues(&deformGen, deformParams);
ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT);
// deal with vertex alpha blended surfaces
if (input->xstages[0] && input->xstages[1] &&
(input->xstages[1]->alphaGen == AGEN_VERTEX || input->xstages[1]->alphaGen == AGEN_ONE_MINUS_VERTEX))
{
stageGlState[0] = input->xstages[0]->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS);
if (stageGlState[0] == 0 || stageGlState[0] == (GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO))
{
stageGlState[1] = input->xstages[1]->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS);
if (stageGlState[1] == (GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA))
{
alphaOverride = qtrue;
stageGlState[0] = GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
stageGlState[1] = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
}
else if (stageGlState[1] == (GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_SRC_ALPHA))
{
alphaOverride = qtrue;
stageGlState[0] = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
stageGlState[1] = GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
}
}
}
if (!alphaOverride)
{
stageGlState[0] =
stageGlState[1] = GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
}
for ( stage = 0; stage < 2 /*MAX_SHADER_STAGES */; stage++ )
{
shaderStage_t *pStage = input->xstages[stage];
shaderProgram_t *sp;
vec4_t vector;
matrix_t matrix;
if ( !pStage )
{
break;
}
//VectorCopy( dl->transformed, origin );
//if (pStage->glslShaderGroup == tr.lightallShader)
{
int index = pStage->glslShaderIndex;
index &= ~(LIGHTDEF_LIGHTTYPE_MASK | LIGHTDEF_USE_DELUXEMAP);
index |= LIGHTDEF_USE_LIGHT_VECTOR | LIGHTDEF_USE_SHADOWMAP | LIGHTDEF_USE_SHADOW_CASCADE;
sp = &tr.lightallShader[index];
}
backEnd.pc.c_lightallDraws++;
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen);
if (deformGen != DGEN_NONE)
{
GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
}
if ( input->fogNum ) {
vec4_t fogColorMask;
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector);
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT);
ComputeFogColorMask(pStage, fogColorMask);
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask);
}
{
vec4_t baseColor;
vec4_t vertColor;
ComputeShaderColors(pStage, baseColor, vertColor);
if (alphaOverride)
{
if (input->xstages[1]->alphaGen == AGEN_VERTEX)
{
baseColor[3] = 0.0f;
vertColor[3] = 1.0f;
}
else if (input->xstages[1]->alphaGen == AGEN_ONE_MINUS_VERTEX)
{
baseColor[3] = 1.0f;
vertColor[3] = -1.0f;
}
}
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor);
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor);
}
if (pStage->alphaGen == AGEN_PORTAL)
{
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_PORTALRANGE, tess.shader->portalRange);
}
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, pStage->rgbGen);
GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, pStage->alphaGen);
GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DIRECTEDLIGHT, backEnd.refdef.sunCol);
VectorSet(vector, 0, 0, 0);
GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_AMBIENTLIGHT, vector);
//VectorSet4(vector, 0, 0, 1, 0);
//VectorSet4(vector, 0.57735f, 0.57735f, 0.57735f, 0);
GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, backEnd.refdef.sunDir);
GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, 9999999999);
GLSL_SetUniformVec2(sp, GENERIC_UNIFORM_MATERIALINFO, pStage->materialInfo);
GL_State( stageGlState[stage] );
Matrix16Identity(matrix);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, matrix);
if (pStage->bundle[TB_DIFFUSEMAP].image[0])
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP);
if (pStage->bundle[TB_NORMALMAP].image[0])
R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP);
if (pStage->bundle[TB_SPECULARMAP].image[0])
R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP);
{
GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP);
GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2);
GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
}
ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix );
GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, matrix);
//
// draw
//
if (input->multiDrawPrimitives)
{
R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes);
}
else
{
R_DrawElementsVBO(input->numIndexes, input->firstIndex);
}
backEnd.pc.c_totalIndexes += tess.numIndexes;
backEnd.pc.c_dlightIndexes += tess.numIndexes;
}
}
static void ProjectPshadowVBOGLSL( void ) { static void ProjectPshadowVBOGLSL( void ) {
int l; int l;
vec3_t origin; vec3_t origin;
@ -1183,7 +1376,10 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
// //
if ( backEnd.depthFill ) if ( backEnd.depthFill )
{ {
GL_BindToTMU( tr.whiteImage, 0 ); if (!(pStage->stateBits & GLS_ATEST_BITS))
GL_BindToTMU( tr.whiteImage, 0 );
else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
} }
else if ( pStage->glslShaderGroup ) else if ( pStage->glslShaderGroup )
{ {
@ -1275,6 +1471,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{ {
break; break;
} }
if (backEnd.depthFill)
break;
} }
} }
@ -1389,7 +1588,17 @@ void RB_StageIteratorGeneric( void )
// //
// set face culling appropriately // set face culling appropriately
// //
GL_Cull( input->shader->cullType ); if (backEnd.viewParms.isDepthShadow)
{
if (input->shader->cullType == CT_TWO_SIDED)
GL_Cull( CT_TWO_SIDED );
else if (input->shader->cullType == CT_FRONT_SIDED)
GL_Cull( CT_BACK_SIDED );
else
GL_Cull( CT_FRONT_SIDED );
}
else
GL_Cull( input->shader->cullType );
// set polygon offset if necessary // set polygon offset if necessary
if ( input->shader->polygonOffset ) if ( input->shader->polygonOffset )
@ -1403,16 +1612,13 @@ void RB_StageIteratorGeneric( void )
// //
GLSL_VertexAttribsState(vertexAttribs); GLSL_VertexAttribsState(vertexAttribs);
// //
// render shadowmap if in shadowmap mode // render depth if in depthfill mode
// //
if (backEnd.viewParms.isShadowmap) if (backEnd.depthFill)
{ {
if ( input->shader->sort == SS_OPAQUE ) RB_IterateStagesGeneric( input );
{
RB_RenderShadowmap( input );
}
// //
// reset polygon offset // reset polygon offset
// //
@ -1425,12 +1631,14 @@ void RB_StageIteratorGeneric( void )
} }
// //
// render depth if in depthfill mode // render shadowmap if in shadowmap mode
// //
if (backEnd.depthFill) if (backEnd.viewParms.isShadowmap)
{ {
RB_IterateStagesGeneric( input ); if ( input->shader->sort == SS_OPAQUE )
{
RB_RenderShadowmap( input );
}
// //
// reset polygon offset // reset polygon offset
// //
@ -1473,6 +1681,11 @@ void RB_StageIteratorGeneric( void )
} }
} }
if (((backEnd.refdef.rdflags & RDF_SUNLIGHT) || r_testSunlight->integer) && tess.shader->sort <= SS_OPAQUE
&& !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) && tess.xstages[0]->glslShaderGroup == tr.lightallShader) {
ForwardSunlight();
}
// //
// now do fog // now do fog
// //

File diff suppressed because it is too large Load Diff