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.
- Improve parallax mapping
- 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
#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)
// WGL_ARB_create_context
#ifndef WGL_ARB_create_context

View File

@ -167,7 +167,7 @@ void GL_Cull( int cullType ) {
qglEnable( GL_CULL_FACE );
cullFront = (cullType == CT_FRONT_SIDED);
if ( backEnd.viewParms.isMirror && !backEnd.viewParms.isShadowmap )
if ( backEnd.viewParms.isMirror )
{
cullFront = !cullFront;
}
@ -590,127 +590,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
// save original time for entity shader offsets
originalTime = backEnd.refdef.floatTime;
// clear the z buffer, set the modelview, etc
RB_BeginDrawingView ();
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
backEnd.depthFill = qfalse;
oldEntityNum = -1;
backEnd.currentEntity = &tr.worldEntity;
oldShader = NULL;
@ -731,6 +613,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
if ( drawSurf->sort == oldSort ) {
if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
continue;
// fast path, same as previous sort
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
continue;
@ -755,6 +640,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
oldPshadowed = pshadowed;
}
if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
continue;
//
// change the modelview matrix if needed
//
@ -765,7 +653,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
#ifdef REACTION
// 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
if (oldEntityNum != -1 && fbo &&
if (oldEntityNum != -1 && fbo && !backEnd.depthFill &&
RF_SUNFLARE == (backEnd.refdef.entities[oldEntityNum].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
// 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 (fbo) {
VectorCopy(backEnd.currentEntity->e.origin, backEnd.sunFlarePos);
@ -914,7 +802,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
}
#ifdef REACTION
// HACK: flip Z and render black to god rays buffer
if (backEnd.frameHasSunFlare)
if (backEnd.frameHasSunFlare && !backEnd.depthFill)
{
vec4_t black;
VectorSet4(black, 0, 0, 0, 1);
@ -931,18 +819,6 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
//if ( depthRange ) {
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.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);
}
@ -1632,6 +1545,17 @@ const void *RB_PostProcess(const void *data)
}
#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;
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,
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)
{
const char *ptr = Q_stristr( glConfig.extensions_string, ext );
@ -649,4 +652,31 @@ void GLimp_InitExtraExtensions()
{
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
This file is part of Reaction source code.
Reaction source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Reaction source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Reaction source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __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
// extra renderfx flags start at 0x0400
#define RF_SUNFLARE 0x0400
// extra refdef flags start at 0x0008
#define RDF_NOFOG 0x0008 // don't apply fog
#define RDF_EXTRA 0x0010 // Makro - refdefex_t to follow after refdef_t
typedef struct {
float blurFactor;
} refdefex_t;
#endif
/*
===========================================================================
Copyright (C) 2009-2011 Andrei Drexler, Richard Allen, James Canete
This file is part of Reaction source code.
Reaction source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Reaction source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Reaction source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __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
// extra renderfx flags start at 0x0400
#define RF_SUNFLARE 0x0400
// extra refdef flags start at 0x0008
#define RDF_NOFOG 0x0008 // don't apply fog
#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;
float sunDir[3];
float sunCol[3];
} refdefex_t;
#endif

View File

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

View File

@ -67,6 +67,7 @@ typedef unsigned int glIndex_t;
#define MAX_CALC_PSHADOWS 64
#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
#define PSHADOW_MAP_SIZE 512
#define SUNSHADOW_MAP_SIZE 1024
typedef struct dlight_s {
vec3_t origin;
@ -409,10 +410,12 @@ enum
TB_DIFFUSEMAP = 0,
TB_LIGHTMAP = 1,
TB_LEVELSMAP = 1,
TB_NORMALMAP,
TB_DELUXEMAP,
TB_SPECULARMAP,
TB_SHADOWMAP,
TB_SHADOWMAP = 1,
TB_NORMALMAP = 2,
TB_DELUXEMAP = 3,
TB_SHADOWMAP2 = 3,
TB_SPECULARMAP = 4,
TB_SHADOWMAP3 = 5,
NUM_TEXTURE_BUNDLES = 6
};
@ -737,10 +740,12 @@ enum
LIGHTDEF_USE_SPECULARMAP = 0x0008,
LIGHTDEF_USE_DELUXEMAP = 0x0010,
LIGHTDEF_USE_PARALLAXMAP = 0x0020,
LIGHTDEF_TCGEN_ENVIRONMENT = 0x0040,
LIGHTDEF_ENTITY = 0x0080,
LIGHTDEF_ALL = 0x00FF,
LIGHTDEF_COUNT = 0x0100
LIGHTDEF_USE_SHADOWMAP = 0x0040,
LIGHTDEF_USE_SHADOW_CASCADE= 0x0080,
LIGHTDEF_TCGEN_ENVIRONMENT = 0x0100,
LIGHTDEF_ENTITY = 0x0200,
LIGHTDEF_ALL = 0x03FF,
LIGHTDEF_COUNT = 0x0400
};
enum
@ -836,6 +841,8 @@ enum
GENERIC_UNIFORM_DELUXEMAP,
GENERIC_UNIFORM_SPECULARMAP,
GENERIC_UNIFORM_SHADOWMAP,
GENERIC_UNIFORM_SHADOWMAP2,
GENERIC_UNIFORM_SHADOWMAP3,
GENERIC_UNIFORM_DIFFUSETEXMATRIX,
//GENERIC_UNIFORM_NORMALTEXMATRIX,
//GENERIC_UNIFORM_SPECULARTEXMATRIX,
@ -864,6 +871,9 @@ enum
GENERIC_UNIFORM_TIME,
GENERIC_UNIFORM_VERTEXLERP,
GENERIC_UNIFORM_MATERIALINFO,
GENERIC_UNIFORM_SHADOWMVP,
GENERIC_UNIFORM_SHADOWMVP2,
GENERIC_UNIFORM_SHADOWMVP3,
GENERIC_UNIFORM_COUNT
};
@ -913,6 +923,10 @@ typedef struct {
unsigned int dlightMask;
int num_pshadows;
struct pshadow_s *pshadows;
float sunShadowMvp[3][16];
float sunDir[4];
float sunCol[4];
} trRefdef_t;
@ -962,6 +976,7 @@ typedef struct {
cplane_t frustum[5];
vec3_t visBounds[2];
float zFar;
float zNear;
stereoFrame_t stereoFrame;
} viewParms_t;
@ -1636,6 +1651,8 @@ typedef struct {
qboolean texture_srgb;
qboolean framebuffer_srgb;
qboolean depthClamp;
} glRefConfig_t;
@ -1753,6 +1770,7 @@ typedef struct {
image_t *calcLevelsImage;
image_t *targetLevelsImage;
image_t *fixedLevelsImage;
image_t *sunShadowDepthImage[3];
image_t *textureDepthImage;
@ -1766,6 +1784,7 @@ typedef struct {
FBO_t *quarterFbo[2];
FBO_t *calcLevelsFbo;
FBO_t *targetLevelsFbo;
FBO_t *sunShadowFbo[3];
shader_t *defaultShader;
shader_t *shadowShader;
@ -2021,6 +2040,7 @@ extern cvar_t *r_imageUpsample;
extern cvar_t *r_imageUpsampleMaxSize;
extern cvar_t *r_imageUpsampleType;
extern cvar_t *r_genNormalMaps;
extern cvar_t *r_testSunlight;
extern cvar_t *r_greyscale;
@ -2050,6 +2070,7 @@ void R_SwapBuffers( int );
void R_RenderView( viewParms_t *parms );
void R_RenderDlightCubemaps(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_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])
{
int i;
@ -1812,6 +1812,8 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
int pshadowed;
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
if ( numDrawSurfs < 1 ) {
// 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
R_RadixSort( drawSurfs, numDrawSurfs );
if (tr.viewParms.isShadowmap)
if (tr.viewParms.isShadowmap || tr.viewParms.isDepthShadow)
{
R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
return;
@ -1881,7 +1883,7 @@ static void R_AddEntitySurface (int entityNum)
// we don't want the hacked weapon position showing in
// 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;
}
@ -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.
This file is part of Quake III Arena source code.
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
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_mesh.c: triangle model functions
#include "tr_local.h"
static float ProjectRadius( float r, vec3_t location )
{
float pr;
float dist;
float c;
vec3_t p;
float projected[4];
c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin );
dist = DotProduct( tr.viewParms.or.axis[0], location ) - c;
if ( dist <= 0 )
return 0;
p[0] = 0;
p[1] = fabs( r );
p[2] = -dist;
projected[0] = p[0] * tr.viewParms.projectionMatrix[0] +
p[1] * tr.viewParms.projectionMatrix[4] +
p[2] * tr.viewParms.projectionMatrix[8] +
tr.viewParms.projectionMatrix[12];
projected[1] = p[0] * tr.viewParms.projectionMatrix[1] +
p[1] * tr.viewParms.projectionMatrix[5] +
p[2] * tr.viewParms.projectionMatrix[9] +
tr.viewParms.projectionMatrix[13];
projected[2] = p[0] * tr.viewParms.projectionMatrix[2] +
p[1] * tr.viewParms.projectionMatrix[6] +
p[2] * tr.viewParms.projectionMatrix[10] +
tr.viewParms.projectionMatrix[14];
projected[3] = p[0] * tr.viewParms.projectionMatrix[3] +
p[1] * tr.viewParms.projectionMatrix[7] +
p[2] * tr.viewParms.projectionMatrix[11] +
tr.viewParms.projectionMatrix[15];
pr = projected[1] / projected[3];
if ( pr > 1.0f )
pr = 1.0f;
return pr;
}
/*
=============
R_CullModel
=============
*/
static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) {
vec3_t bounds[2];
mdvFrame_t *oldFrame, *newFrame;
int i;
// compute frame pointers
newFrame = model->frames + ent->e.frame;
oldFrame = model->frames + ent->e.oldframe;
// cull bounding sphere ONLY if this is not an upscaled entity
if ( !ent->e.nonNormalizedAxes )
{
if ( ent->e.frame == ent->e.oldframe )
{
switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
{
case CULL_OUT:
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
case CULL_IN:
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_sphere_cull_md3_clip++;
break;
}
}
else
{
int sphereCull, sphereCullB;
sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
if ( newFrame == oldFrame ) {
sphereCullB = sphereCull;
} else {
sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
}
if ( sphereCull == sphereCullB )
{
if ( sphereCull == CULL_OUT )
{
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
}
else if ( sphereCull == CULL_IN )
{
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
}
else
{
tr.pc.c_sphere_cull_md3_clip++;
}
}
}
}
// calculate a bounding box in the current coordinate system
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[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
}
switch ( R_CullLocalBox( bounds ) )
{
case CULL_IN:
tr.pc.c_box_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_box_cull_md3_clip++;
return CULL_CLIP;
case CULL_OUT:
default:
tr.pc.c_box_cull_md3_out++;
return CULL_OUT;
}
}
/*
=================
R_ComputeLOD
=================
*/
int R_ComputeLOD( trRefEntity_t *ent ) {
float radius;
float flod, lodscale;
float projectedRadius;
mdvFrame_t *frame;
#ifdef RAVENMD4
mdrHeader_t *mdr;
mdrFrame_t *mdrframe;
#endif
int lod;
if ( tr.currentModel->numLods < 2 )
{
// model has only 1 LOD level, skip computations and bias
lod = 0;
}
else
{
// multiple LODs exist, so compute projected bounding sphere
// and use that as a criteria for selecting LOD
#ifdef RAVENMD4
if(tr.currentModel->type == MOD_MDR)
{
int frameSize;
mdr = (mdrHeader_t *) tr.currentModel->modelData;
frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]);
mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame);
radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]);
}
else
#endif
{
//frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
frame = tr.currentModel->mdv[0]->frames;
frame += ent->e.frame;
radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );
}
if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
{
lodscale = r_lodscale->value;
if (lodscale > 20) lodscale = 20;
flod = 1.0f - projectedRadius * lodscale;
}
else
{
// object intersects near view plane, e.g. view weapon
flod = 0;
}
flod *= tr.currentModel->numLods;
lod = ri.ftol(flod);
if ( lod < 0 )
{
lod = 0;
}
else if ( lod >= tr.currentModel->numLods )
{
lod = tr.currentModel->numLods - 1;
}
}
lod += r_lodbias->integer;
if ( lod >= tr.currentModel->numLods )
lod = tr.currentModel->numLods - 1;
if ( lod < 0 )
lod = 0;
return lod;
}
/*
=================
R_ComputeFogNum
=================
*/
int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
int i, j;
fog_t *fog;
mdvFrame_t *mdvFrame;
vec3_t localOrigin;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return 0;
}
// FIXME: non-normalized axis issues
mdvFrame = model->frames + ent->e.frame;
VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin );
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
fog = &tr.world->fogs[i];
for ( j = 0 ; j < 3 ; j++ ) {
if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) {
break;
}
if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) {
break;
}
}
if ( j == 3 ) {
return i;
}
}
return 0;
}
/*
=================
R_AddMD3Surfaces
=================
*/
void R_AddMD3Surfaces( trRefEntity_t *ent ) {
int i;
mdvModel_t *model = NULL;
mdvSurface_t *surface = NULL;
shader_t *shader = NULL;
int cull;
int lod;
int fogNum;
qboolean personalModel;
// don't add third_person objects if not in a portal
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal || tr.viewParms.isShadowmap);
if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
ent->e.frame %= tr.currentModel->mdv[0]->numFrames;
ent->e.oldframe %= tr.currentModel->mdv[0]->numFrames;
}
//
// Validate the frames so there is no chance of a crash.
// This will write directly into the entity structure, so
// when the surfaces are rendered, they don't need to be
// range checked again.
//
if ( (ent->e.frame >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.frame < 0)
|| (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.oldframe < 0) ) {
ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
ent->e.oldframe, ent->e.frame,
tr.currentModel->name );
ent->e.frame = 0;
ent->e.oldframe = 0;
}
//
// compute LOD
//
lod = R_ComputeLOD( ent );
model = tr.currentModel->mdv[lod];
//
// cull the entire model if merged bounding box of both frames
// is outside the view frustum.
//
cull = R_CullModel ( model, ent );
if ( cull == CULL_OUT ) {
return;
}
//
// set up lighting now that we know we aren't culled
//
if ( !personalModel || r_shadows->integer > 1 ) {
R_SetupEntityLighting( &tr.refdef, ent );
}
//
// see if we are in a fog volume
//
fogNum = R_ComputeFogNum( model, ent );
//
// draw all surfaces
//
surface = model->surfaces;
for ( i = 0 ; i < model->numSurfaces ; i++ ) {
if ( ent->e.customShader ) {
shader = R_GetShaderByHandle( ent->e.customShader );
} else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) {
skin_t *skin;
int j;
skin = R_GetSkinByHandle( ent->e.customSkin );
// match the surface name to something in the skin file
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
shader = skin->surfaces[j]->shader;
break;
}
}
if (shader == tr.defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name);
}
else if (shader->defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
}
//} else if ( surface->numShaders <= 0 ) {
//shader = tr.defaultShader;
} else {
//md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
//md3Shader += ent->e.skinNum % surface->numShaders;
//shader = tr.shaders[ md3Shader->shaderIndex ];
shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ];
}
// don't add third_person objects if not viewing through a portal
if(!personalModel)
{
srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i];
R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse );
}
surface++;
}
}
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
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
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// tr_mesh.c: triangle model functions
#include "tr_local.h"
static float ProjectRadius( float r, vec3_t location )
{
float pr;
float dist;
float c;
vec3_t p;
float projected[4];
c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin );
dist = DotProduct( tr.viewParms.or.axis[0], location ) - c;
if ( dist <= 0 )
return 0;
p[0] = 0;
p[1] = fabs( r );
p[2] = -dist;
projected[0] = p[0] * tr.viewParms.projectionMatrix[0] +
p[1] * tr.viewParms.projectionMatrix[4] +
p[2] * tr.viewParms.projectionMatrix[8] +
tr.viewParms.projectionMatrix[12];
projected[1] = p[0] * tr.viewParms.projectionMatrix[1] +
p[1] * tr.viewParms.projectionMatrix[5] +
p[2] * tr.viewParms.projectionMatrix[9] +
tr.viewParms.projectionMatrix[13];
projected[2] = p[0] * tr.viewParms.projectionMatrix[2] +
p[1] * tr.viewParms.projectionMatrix[6] +
p[2] * tr.viewParms.projectionMatrix[10] +
tr.viewParms.projectionMatrix[14];
projected[3] = p[0] * tr.viewParms.projectionMatrix[3] +
p[1] * tr.viewParms.projectionMatrix[7] +
p[2] * tr.viewParms.projectionMatrix[11] +
tr.viewParms.projectionMatrix[15];
pr = projected[1] / projected[3];
if ( pr > 1.0f )
pr = 1.0f;
return pr;
}
/*
=============
R_CullModel
=============
*/
static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) {
vec3_t bounds[2];
mdvFrame_t *oldFrame, *newFrame;
int i;
// compute frame pointers
newFrame = model->frames + ent->e.frame;
oldFrame = model->frames + ent->e.oldframe;
// cull bounding sphere ONLY if this is not an upscaled entity
if ( !ent->e.nonNormalizedAxes )
{
if ( ent->e.frame == ent->e.oldframe )
{
switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
{
case CULL_OUT:
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
case CULL_IN:
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_sphere_cull_md3_clip++;
break;
}
}
else
{
int sphereCull, sphereCullB;
sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
if ( newFrame == oldFrame ) {
sphereCullB = sphereCull;
} else {
sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
}
if ( sphereCull == sphereCullB )
{
if ( sphereCull == CULL_OUT )
{
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
}
else if ( sphereCull == CULL_IN )
{
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
}
else
{
tr.pc.c_sphere_cull_md3_clip++;
}
}
}
}
// calculate a bounding box in the current coordinate system
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[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
}
switch ( R_CullLocalBox( bounds ) )
{
case CULL_IN:
tr.pc.c_box_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_box_cull_md3_clip++;
return CULL_CLIP;
case CULL_OUT:
default:
tr.pc.c_box_cull_md3_out++;
return CULL_OUT;
}
}
/*
=================
R_ComputeLOD
=================
*/
int R_ComputeLOD( trRefEntity_t *ent ) {
float radius;
float flod, lodscale;
float projectedRadius;
mdvFrame_t *frame;
#ifdef RAVENMD4
mdrHeader_t *mdr;
mdrFrame_t *mdrframe;
#endif
int lod;
if ( tr.currentModel->numLods < 2 )
{
// model has only 1 LOD level, skip computations and bias
lod = 0;
}
else
{
// multiple LODs exist, so compute projected bounding sphere
// and use that as a criteria for selecting LOD
#ifdef RAVENMD4
if(tr.currentModel->type == MOD_MDR)
{
int frameSize;
mdr = (mdrHeader_t *) tr.currentModel->modelData;
frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]);
mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame);
radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]);
}
else
#endif
{
//frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
frame = tr.currentModel->mdv[0]->frames;
frame += ent->e.frame;
radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );
}
if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
{
lodscale = r_lodscale->value;
if (lodscale > 20) lodscale = 20;
flod = 1.0f - projectedRadius * lodscale;
}
else
{
// object intersects near view plane, e.g. view weapon
flod = 0;
}
flod *= tr.currentModel->numLods;
lod = ri.ftol(flod);
if ( lod < 0 )
{
lod = 0;
}
else if ( lod >= tr.currentModel->numLods )
{
lod = tr.currentModel->numLods - 1;
}
}
lod += r_lodbias->integer;
if ( lod >= tr.currentModel->numLods )
lod = tr.currentModel->numLods - 1;
if ( lod < 0 )
lod = 0;
return lod;
}
/*
=================
R_ComputeFogNum
=================
*/
int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
int i, j;
fog_t *fog;
mdvFrame_t *mdvFrame;
vec3_t localOrigin;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return 0;
}
// FIXME: non-normalized axis issues
mdvFrame = model->frames + ent->e.frame;
VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin );
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
fog = &tr.world->fogs[i];
for ( j = 0 ; j < 3 ; j++ ) {
if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) {
break;
}
if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) {
break;
}
}
if ( j == 3 ) {
return i;
}
}
return 0;
}
/*
=================
R_AddMD3Surfaces
=================
*/
void R_AddMD3Surfaces( trRefEntity_t *ent ) {
int i;
mdvModel_t *model = NULL;
mdvSurface_t *surface = NULL;
shader_t *shader = NULL;
int cull;
int lod;
int fogNum;
qboolean personalModel;
// don't add third_person objects if not in a portal
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal || tr.viewParms.isShadowmap || tr.viewParms.isDepthShadow);
if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
ent->e.frame %= tr.currentModel->mdv[0]->numFrames;
ent->e.oldframe %= tr.currentModel->mdv[0]->numFrames;
}
//
// Validate the frames so there is no chance of a crash.
// This will write directly into the entity structure, so
// when the surfaces are rendered, they don't need to be
// range checked again.
//
if ( (ent->e.frame >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.frame < 0)
|| (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames)
|| (ent->e.oldframe < 0) ) {
ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
ent->e.oldframe, ent->e.frame,
tr.currentModel->name );
ent->e.frame = 0;
ent->e.oldframe = 0;
}
//
// compute LOD
//
lod = R_ComputeLOD( ent );
model = tr.currentModel->mdv[lod];
//
// cull the entire model if merged bounding box of both frames
// is outside the view frustum.
//
cull = R_CullModel ( model, ent );
if ( cull == CULL_OUT ) {
return;
}
//
// set up lighting now that we know we aren't culled
//
if ( !personalModel || r_shadows->integer > 1 ) {
R_SetupEntityLighting( &tr.refdef, ent );
}
//
// see if we are in a fog volume
//
fogNum = R_ComputeFogNum( model, ent );
//
// draw all surfaces
//
surface = model->surfaces;
for ( i = 0 ; i < model->numSurfaces ; i++ ) {
if ( ent->e.customShader ) {
shader = R_GetShaderByHandle( ent->e.customShader );
} else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) {
skin_t *skin;
int j;
skin = R_GetSkinByHandle( ent->e.customSkin );
// match the surface name to something in the skin file
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
shader = skin->surfaces[j]->shader;
break;
}
}
if (shader == tr.defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name);
}
else if (shader->defaultShader) {
ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
}
//} else if ( surface->numShaders <= 0 ) {
//shader = tr.defaultShader;
} else {
//md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
//md3Shader += ent->e.skinNum % surface->numShaders;
//shader = tr.shaders[ md3Shader->shaderIndex ];
shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ];
}
// don't add third_person objects if not viewing through a portal
if(!personalModel)
{
srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i];
R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse );
}
surface++;
}
}

View File

@ -365,15 +365,29 @@ void RE_RenderScene( const refdef_t *fd ) {
}
}
#ifdef REACTION
//#ifdef REACTION
// Makro - copy exta info if present
if (fd->rdflags & RDF_EXTRA) {
const refdefex_t* extra = (const refdefex_t*) (fd+1);
#ifdef REACTION
tr.refdef.blurFactor = extra->blurFactor;
} else {
tr.refdef.blurFactor = 0.f;
}
#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
@ -422,6 +436,14 @@ void RE_RenderScene( const refdef_t *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
//
// 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 ) {
int l;
vec3_t origin;
@ -1183,7 +1376,10 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
//
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 )
{
@ -1275,6 +1471,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
break;
}
if (backEnd.depthFill)
break;
}
}
@ -1389,7 +1588,17 @@ void RB_StageIteratorGeneric( void )
//
// 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
if ( input->shader->polygonOffset )
@ -1403,16 +1612,13 @@ void RB_StageIteratorGeneric( void )
//
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_RenderShadowmap( input );
}
RB_IterateStagesGeneric( input );
//
// 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
//
@ -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
//

File diff suppressed because it is too large Load Diff