rtexture_t *r_shadow_prepasslightingdiffusetexture;
rtexture_t *r_shadow_prepasslightingspeculartexture;
+// keep track of the provided framebuffer info
+static int r_shadow_fb_fbo;
+static rtexture_t *r_shadow_fb_depthtexture;
+static rtexture_t *r_shadow_fb_colortexture;
+
// lights are reloaded when this changes
char r_shadow_mapname[MAX_QPATH];
// used only for light filters (cubemaps)
rtexturepool_t *r_shadow_filters_texturepool;
-static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
+#ifndef USE_GLES2
+static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
+#endif
cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
void R_Shadow_RenderMode_Reset(void)
{
- R_Mesh_SetMainRenderTargets();
+ R_Mesh_ResetTextureState();
+ R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL);
R_SetViewport(&r_refdef.view.viewport);
GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
- R_Mesh_ResetTextureState();
GL_DepthRange(0, 1);
GL_DepthTest(true);
GL_DepthMask(false);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
+ R_SetupShader_Generic_NoTexture(false, false);
r_shadow_usingshadowmap2d = false;
r_shadow_usingshadowmaportho = false;
R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
return;
}
+#ifndef USE_GLES2
// render depth into the fbo, do not render color at all
// validate the fbo now
if (qglDrawBuffer)
int status;
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
+ status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
+ if (status != GL_FRAMEBUFFER_COMPLETE && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
{
Con_Printf("R_Shadow_MakeShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
Cvar_SetValueQuick(&r_shadow_deferred, 0);
}
}
+#endif
}
void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
float nearclip, farclip, bias;
r_viewport_t viewport;
int flipped;
- GLuint fbo = 0;
+ GLuint fbo2d = 0;
float clearcolor[4];
nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
farclip = 1.0f;
R_Shadow_MakeVSDCT();
if (!r_shadow_shadowmap2dtexture)
R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
- if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
+ if (r_shadow_shadowmap2dtexture) fbo2d = r_shadow_fbo2d;
r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
R_Mesh_ResetTextureState();
R_Shadow_RenderMode_Reset();
- R_Mesh_SetRenderTargets(fbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
R_SetupShader_DepthOrShadow(true);
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
{
R_Mesh_ResetTextureState();
- R_Mesh_SetMainRenderTargets();
if (transparent)
{
r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
r_refdef.stats.bouncegrid_traces++;
//r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
//r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
- //if (settings.staticmode)
- // Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask, true);
- //else
+ if (settings.staticmode)
+ {
+ // static mode fires a LOT of rays but none of them are identical, so they are not cached
cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, true, false, NULL, true, true);
+ }
+ else
+ {
+ // dynamic mode fires many rays and most will match the cache from the previous frame
+ cliptrace = CL_Cache_TraceLineSurfaces(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), hitsupercontentsmask);
+ }
if (bouncecount > 0 || settings.includedirectlighting)
{
// calculate second order spherical harmonics values (average, slopeX, slopeY, slopeZ)
qboolean negated;
float lightcolor[3];
VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
- ambientscale = rsurface.rtlight->ambientscale;
- diffusescale = rsurface.rtlight->diffusescale;
+ ambientscale = rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient;
+ diffusescale = rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient);
specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
if (!r_shadow_usenormalmap.integer)
{
if (r_refdef.scene.lights[lnum]->draw)
R_Shadow_DrawLight(r_refdef.scene.lights[lnum]);
- R_Mesh_SetMainRenderTargets();
-
R_Shadow_RenderMode_End();
if (r_timereport_active)
}
void R_Shadow_DrawLightSprites(void);
-void R_Shadow_PrepareLights(void)
+void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
int flag;
int lnum;
r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
R_Shadow_FreeShadowMaps();
+ r_shadow_fb_fbo = fbo;
+ r_shadow_fb_depthtexture = depthtexture;
+ r_shadow_fb_colortexture = colortexture;
+
r_shadow_usingshadowmaportho = false;
switch (vid.renderpath)
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
case RENDERPATH_SOFT:
- case RENDERPATH_GLES2:
+#ifndef USE_GLES2
if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
{
r_shadow_usingdeferredprepass = false;
switch (vid.renderpath)
{
case RENDERPATH_D3D9:
- r_shadow_prepassgeometrydepthcolortexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrydepthcolormap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepassgeometrydepthcolortexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrydepthcolormap", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
break;
default:
break;
}
- r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
- r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
- r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
// set up the geometry pass fbo (depth + normalmap)
r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
// render depth into one texture and normalmap into the other
if (qglDrawBuffersARB)
{
- qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
+ qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
+ if (status != GL_FRAMEBUFFER_COMPLETE)
{
Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_deferred, 0);
{
qglDrawBuffersARB(2, r_shadow_prepasslightingdrawbuffers);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
+ if (status != GL_FRAMEBUFFER_COMPLETE)
{
Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_deferred, 0);
// with depth bound as attachment as well
if (qglDrawBuffersARB)
{
- qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
+ qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
+ if (status != GL_FRAMEBUFFER_COMPLETE)
{
Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_deferred, 0);
}
}
}
+#endif
break;
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
r_shadow_usingdeferredprepass = false;
break;
}
R_Shadow_RenderMode_End();
}
-extern const float r_screenvertex3f[12];
-extern void R_SetupView(qboolean allowwaterclippingplane);
-extern void R_ResetViewRendering3D(void);
-extern void R_ResetViewRendering2D(void);
-extern cvar_t r_shadows;
-extern cvar_t r_shadows_darken;
-extern cvar_t r_shadows_drawafterrtlighting;
-extern cvar_t r_shadows_castfrombmodels;
-extern cvar_t r_shadows_throwdistance;
-extern cvar_t r_shadows_throwdirection;
-extern cvar_t r_shadows_focus;
-extern cvar_t r_shadows_shadowmapscale;
-
void R_Shadow_PrepareModelShadows(void)
{
int i;
}
}
-void R_DrawModelShadowMaps(void)
+void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
int i;
float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2;
float m[12];
matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
r_viewport_t viewport;
- GLuint fbo = 0;
+ GLuint fbo2d = 0;
float clearcolor[4];
if (!r_refdef.scene.numentities)
return;
}
- R_ResetViewRendering3D();
+ r_shadow_fb_fbo = fbo;
+ r_shadow_fb_depthtexture = depthtexture;
+ r_shadow_fb_colortexture = colortexture;
+
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
R_Shadow_RenderMode_Begin();
R_Shadow_RenderMode_ActiveLight(NULL);
VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
- R_Mesh_SetRenderTargets(fbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
R_SetupShader_DepthOrShadow(true);
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
#if 0
// debugging
- R_Mesh_SetMainRenderTargets();
+ R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL);
R_SetupShader_ShowDepth(true);
GL_ColorMask(1,1,1,1);
GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
}
}
-void R_DrawModelShadows(void)
+void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
int i;
float relativethrowdistance;
if (!r_refdef.scene.numentities || !vid.stencil || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
return;
- R_ResetViewRendering3D();
+ r_shadow_fb_fbo = fbo;
+ r_shadow_fb_depthtexture = depthtexture;
+ r_shadow_fb_colortexture = colortexture;
+
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
//GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
//GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
R_Shadow_RenderMode_Begin();
//GL_ScissorTest(true);
//R_EntityMatrix(&identitymatrix);
//R_Mesh_ResetTextureState();
- R_ResetViewRendering2D();
+ R_ResetViewRendering2D(fbo, depthtexture, colortexture);
// set up a darkening blend on shadowed areas
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// apply the blend to the shadowed areas
R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
+ R_SetupShader_Generic_NoTexture(false, true);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
// restore the viewport
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
+#ifdef GL_SAMPLES_PASSED_ARB
CHECKGLERROR
// NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
CHECKGLERROR
+#endif
break;
case RENDERPATH_D3D9:
Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
+#ifdef GL_SAMPLES_PASSED_ARB
CHECKGLERROR
qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
CHECKGLERROR
+#endif
break;
case RENDERPATH_D3D9:
Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
size_t range;
if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
return;
- if (r_waterstate.renderingscene)
+ if (r_fb.water.renderingscene)
return;
flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
R_EntityMatrix(&identitymatrix);
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
+#ifdef GL_SAMPLES_PASSED_ARB
if (usequery)
{
GL_ColorMask(0,0,0,0);
GL_PolygonOffset(0, 0);
GL_DepthTest(true);
R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
+ R_SetupShader_Generic_NoTexture(false, false);
}
+#endif
break;
case RENDERPATH_D3D9:
usequery = false;