X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=r_shadow.c;h=19ae463ef4a6d54a63ade706f48909d132aace71;hb=1eaa970ae7a209880c9913650cac2683c628a08c;hp=077c2b04a868ae3543fd0b080fa183c6628b0c0b;hpb=c369a6525246f38a19a0d04ce47d352196dd37f0;p=xonotic%2Fdarkplaces.git diff --git a/r_shadow.c b/r_shadow.c index 077c2b04..19ae463e 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -196,6 +196,7 @@ int r_shadow_shadowmapdepthbits; int r_shadow_shadowmapmaxsize; qboolean r_shadow_shadowmapvsdct; qboolean r_shadow_shadowmapsampler; +qboolean r_shadow_shadowmapshadowsampler; int r_shadow_shadowmappcf; int r_shadow_shadowmapborder; matrix4x4_t r_shadow_shadowmapmatrix; @@ -244,8 +245,8 @@ rtexture_t *r_shadow_attenuationgradienttexture; rtexture_t *r_shadow_attenuation2dtexture; rtexture_t *r_shadow_attenuation3dtexture; skinframe_t *r_shadow_lightcorona; -rtexture_t *r_shadow_shadowmap2dtexture; -rtexture_t *r_shadow_shadowmap2dcolortexture; +rtexture_t *r_shadow_shadowmap2ddepthbuffer; +rtexture_t *r_shadow_shadowmap2ddepthtexture; rtexture_t *r_shadow_shadowmapvsdcttexture; int r_shadow_shadowmapsize; // changes for each light based on distance int r_shadow_shadowmaplod; // changes for each light based on distance @@ -255,8 +256,7 @@ GLuint r_shadow_prepasslightingdiffusespecularfbo; GLuint r_shadow_prepasslightingdiffusefbo; int r_shadow_prepass_width; int r_shadow_prepass_height; -rtexture_t *r_shadow_prepassgeometrydepthtexture; -rtexture_t *r_shadow_prepassgeometrydepthcolortexture; +rtexture_t *r_shadow_prepassgeometrydepthbuffer; rtexture_t *r_shadow_prepassgeometrynormalmaptexture; rtexture_t *r_shadow_prepasslightingdiffusetexture; rtexture_t *r_shadow_prepasslightingspeculartexture; @@ -272,16 +272,10 @@ char r_shadow_mapname[MAX_QPATH]; // used only for light filters (cubemaps) rtexturepool_t *r_shadow_filters_texturepool; -#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"}; cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"}; cvar_t r_shadow_deferred = {CVAR_SAVE, "r_shadow_deferred", "0", "uses image-based lighting instead of geometry-based lighting, the method used renders a depth image and a normalmap image, renders lights into separate diffuse and specular images, and then combines this into the normal rendering, requires r_shadow_shadowmapping"}; -cvar_t r_shadow_deferred_8bitrange = {CVAR_SAVE, "r_shadow_deferred_8bitrange", "4", "dynamic range of image-based lighting when using 32bit color (does not apply to fp)"}; -//cvar_t r_shadow_deferred_fp = {CVAR_SAVE, "r_shadow_deferred_fp", "0", "use 16bit (1) or 32bit (2) floating point for accumulation of image-based lighting"}; cvar_t r_shadow_usebihculling = {0, "r_shadow_usebihculling", "1", "use BIH (Bounding Interval Hierarchy) for culling lit surfaces instead of BSP (Binary Space Partitioning)"}; cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"}; cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"}; @@ -310,6 +304,7 @@ cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_wor cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"}; cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "1", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"}; cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"}; +cvar_t r_shadow_shadowmapping_useshadowsampler = {CVAR_SAVE, "r_shadow_shadowmapping_useshadowsampler", "1", "whether to use sampler2DShadow if available"}; cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"}; cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"}; cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"}; @@ -434,6 +429,7 @@ static void R_Shadow_SetShadowMode(void) r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4); r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20; r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer; + r_shadow_shadowmapshadowsampler = r_shadow_shadowmapping_useshadowsampler.integer != 0; r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer; r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16); r_shadow_shadowmaplod = -1; @@ -448,27 +444,29 @@ static void R_Shadow_SetShadowMode(void) case RENDERPATH_GL20: if(r_shadow_shadowmapfilterquality < 0) { - if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) + if (!r_fb.usedepthtextures) + r_shadow_shadowmappcf = 1; + else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) r_shadow_shadowmappcf = 1; else if(strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) { - r_shadow_shadowmapsampler = vid.support.arb_shadow; + r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler; r_shadow_shadowmappcf = 1; } else if(strstr(gl_vendor, "ATI")) r_shadow_shadowmappcf = 1; else - r_shadow_shadowmapsampler = vid.support.arb_shadow; + r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler; } else { switch (r_shadow_shadowmapfilterquality) { case 1: - r_shadow_shadowmapsampler = vid.support.arb_shadow; + r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler; break; case 2: - r_shadow_shadowmapsampler = vid.support.arb_shadow; + r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler; r_shadow_shadowmappcf = 1; break; case 3: @@ -479,6 +477,8 @@ static void R_Shadow_SetShadowMode(void) break; } } + if (!r_fb.usedepthtextures) + r_shadow_shadowmapsampler = false; r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D; break; case RENDERPATH_D3D9: @@ -517,13 +517,13 @@ static void R_Shadow_FreeShadowMaps(void) r_shadow_fbo2d = 0; - if (r_shadow_shadowmap2dtexture) - R_FreeTexture(r_shadow_shadowmap2dtexture); - r_shadow_shadowmap2dtexture = NULL; + if (r_shadow_shadowmap2ddepthtexture) + R_FreeTexture(r_shadow_shadowmap2ddepthtexture); + r_shadow_shadowmap2ddepthtexture = NULL; - if (r_shadow_shadowmap2dcolortexture) - R_FreeTexture(r_shadow_shadowmap2dcolortexture); - r_shadow_shadowmap2dcolortexture = NULL; + if (r_shadow_shadowmap2ddepthbuffer) + R_FreeTexture(r_shadow_shadowmap2ddepthbuffer); + r_shadow_shadowmap2ddepthbuffer = NULL; if (r_shadow_shadowmapvsdcttexture) R_FreeTexture(r_shadow_shadowmapvsdcttexture); @@ -542,8 +542,8 @@ static void r_shadow_start(void) r_shadow_attenuation2dtexture = NULL; r_shadow_attenuation3dtexture = NULL; r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL; - r_shadow_shadowmap2dtexture = NULL; - r_shadow_shadowmap2dcolortexture = NULL; + r_shadow_shadowmap2ddepthtexture = NULL; + r_shadow_shadowmap2ddepthbuffer = NULL; r_shadow_shadowmapvsdcttexture = NULL; r_shadow_shadowmapmaxsize = 0; r_shadow_shadowmapsize = 0; @@ -701,8 +701,6 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_usenormalmap); Cvar_RegisterVariable(&r_shadow_debuglight); Cvar_RegisterVariable(&r_shadow_deferred); - Cvar_RegisterVariable(&r_shadow_deferred_8bitrange); -// Cvar_RegisterVariable(&r_shadow_deferred_fp); Cvar_RegisterVariable(&r_shadow_gloss); Cvar_RegisterVariable(&r_shadow_gloss2intensity); Cvar_RegisterVariable(&r_shadow_glossintensity); @@ -730,6 +728,7 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_shadowmapping); Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct); Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality); + Cvar_RegisterVariable(&r_shadow_shadowmapping_useshadowsampler); Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits); Cvar_RegisterVariable(&r_shadow_shadowmapping_precision); Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize); @@ -2057,7 +2056,7 @@ void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass) GL_ColorMask(0, 0, 0, 0); GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR GL_CullFace(GL_NONE); - R_SetupShader_DepthOrShadow(false); + R_SetupShader_DepthOrShadow(false, false); r_shadow_rendermode = mode; switch(mode) { @@ -2099,43 +2098,23 @@ static void R_Shadow_MakeShadowMap(int side, int size) switch (r_shadow_shadowmode) { case R_SHADOW_SHADOWMODE_SHADOWMAP2D: - if (r_shadow_shadowmap2dtexture) return; - r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler, false); - r_shadow_shadowmap2dcolortexture = NULL; - switch(vid.renderpath) + if (r_shadow_shadowmap2ddepthtexture) return; + if (r_fb.usedepthtextures) { -#ifdef SUPPORTD3D - case RENDERPATH_D3D9: - r_shadow_shadowmap2dcolortexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), NULL, TEXTYPE_BGRA, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL); - r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL); - break; -#endif - default: - r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, NULL, NULL, NULL, NULL); - break; + r_shadow_shadowmap2ddepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits >= 24 ? (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP24_COMP : TEXTYPE_SHADOWMAP24_RAW) : (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP16_COMP : TEXTYPE_SHADOWMAP16_RAW), false); + r_shadow_shadowmap2ddepthbuffer = NULL; + r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL); + } + else + { + r_shadow_shadowmap2ddepthtexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL); + r_shadow_shadowmap2ddepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits >= 24 ? TEXTYPE_DEPTHBUFFER24 : TEXTYPE_DEPTHBUFFER16); + r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL); } break; default: 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);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 } static void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) @@ -2161,17 +2140,20 @@ static void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) // complex unrolled cube approach (more flexible) if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture) R_Shadow_MakeVSDCT(); - if (!r_shadow_shadowmap2dtexture) + if (!r_shadow_shadowmap2ddepthtexture) R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize); - 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); + fbo2d = r_shadow_fbo2d; + r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2ddepthtexture); + r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2ddepthtexture); r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D; R_Mesh_ResetTextureState(); R_Shadow_RenderMode_Reset(); - R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL); - R_SetupShader_DepthOrShadow(true); + if (r_shadow_shadowmap2ddepthbuffer) + R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL); + else + R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL); + R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL); GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value); GL_DepthMask(true); GL_DepthTest(true); @@ -2181,6 +2163,17 @@ init_done: flipped = (side & 1) ^ (side >> 2); r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front; r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back; + if (r_shadow_shadowmap2ddepthbuffer) + { + // completely different meaning than in depthtexture approach + r_shadow_shadowmap_parameters[1] = 0; + r_shadow_shadowmap_parameters[3] = -bias; + } + Vector4Set(clearcolor, 1,1,1,1); + if (r_shadow_shadowmap2ddepthbuffer) + GL_ColorMask(1,1,1,1); + else + GL_ColorMask(0,0,0,0); switch(vid.renderpath) { case RENDERPATH_GL11: @@ -2199,33 +2192,30 @@ init_done: int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size); int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size); GL_Scissor(x1, y1, x2 - x1, y2 - y1); - GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0); + if (clear) + { + if (r_shadow_shadowmap2ddepthbuffer) + GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0); + else + GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0); + } } GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: case RENDERPATH_D3D11: - Vector4Set(clearcolor, 1,1,1,1); - // completely different meaning than in OpenGL path - r_shadow_shadowmap_parameters[1] = 0; - r_shadow_shadowmap_parameters[3] = -bias; // we invert the cull mode because we flip the projection matrix // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided... GL_CullFace(r_refdef.view.cullface_front); // D3D considers it an error to use a scissor larger than the viewport... clear just this view GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); - if (r_shadow_shadowmapsampler) + if (clear) { - GL_ColorMask(0,0,0,0); - if (clear) - GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0); - } - else - { - GL_ColorMask(1,1,1,1); - if (clear) + if (r_shadow_shadowmap2ddepthbuffer) GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0); + else + GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0); } break; } @@ -2294,9 +2284,9 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow // stencil is 128 (values other than this mean shadow) R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255); if (rsurface.rtlight->specularscale > 0 && r_shadow_gloss.integer > 0) - R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); + R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); else - R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL); + R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL); r_shadow_usingshadowmap2d = shadowmapping; @@ -3931,6 +3921,18 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight) qboolean nolight; rtlight->draw = false; + rtlight->cached_numlightentities = 0; + rtlight->cached_numlightentities_noselfshadow = 0; + rtlight->cached_numshadowentities = 0; + rtlight->cached_numshadowentities_noselfshadow = 0; + rtlight->cached_numsurfaces = 0; + rtlight->cached_lightentities = NULL; + rtlight->cached_lightentities_noselfshadow = NULL; + rtlight->cached_shadowentities = NULL; + rtlight->cached_shadowentities_noselfshadow = NULL; + rtlight->cached_shadowtrispvs = NULL; + rtlight->cached_lighttrispvs = NULL; + rtlight->cached_surfacelist = NULL; // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights) // skip lights that are basically invisible (color 0 0 0) @@ -3978,6 +3980,10 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight) R_Shadow_ComputeShadowCasterCullingPlanes(rtlight); + // don't allow lights to be drawn if using r_shadow_bouncegrid 2, except if we're using static bouncegrid where dynamic lights still need to draw + if (r_shadow_bouncegrid.integer == 2 && (rtlight->isstatic || !r_shadow_bouncegrid_static.integer)) + return; + if (rtlight->compiled && r_shadow_realtime_world_compile.integer) { // compiled light, world available and can receive realtime lighting @@ -4393,13 +4399,9 @@ static void R_Shadow_FreeDeferred(void) R_Mesh_DestroyFramebufferObject(r_shadow_prepasslightingdiffusefbo); r_shadow_prepasslightingdiffusefbo = 0; - if (r_shadow_prepassgeometrydepthtexture) - R_FreeTexture(r_shadow_prepassgeometrydepthtexture); - r_shadow_prepassgeometrydepthtexture = NULL; - - if (r_shadow_prepassgeometrydepthcolortexture) - R_FreeTexture(r_shadow_prepassgeometrydepthcolortexture); - r_shadow_prepassgeometrydepthcolortexture = NULL; + if (r_shadow_prepassgeometrydepthbuffer) + R_FreeTexture(r_shadow_prepassgeometrydepthbuffer); + r_shadow_prepassgeometrydepthbuffer = NULL; if (r_shadow_prepassgeometrynormalmaptexture) R_FreeTexture(r_shadow_prepassgeometrynormalmaptexture); @@ -4431,7 +4433,7 @@ void R_Shadow_DrawPrepass(void) GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(1,1,1,1); GL_DepthTest(true); - R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, r_shadow_prepassgeometrydepthcolortexture, NULL, NULL); + R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL); Vector4Set(clearcolor, 0.5f,0.5f,0.5f,1.0f); GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0); if (r_timereport_active) @@ -4458,7 +4460,7 @@ void R_Shadow_DrawPrepass(void) GL_ColorMask(1,1,1,1); GL_Color(1,1,1,1); GL_DepthTest(true); - R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); + R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); Vector4Set(clearcolor, 0, 0, 0, 0); GL_Clear(GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0); if (r_timereport_active) @@ -4504,12 +4506,12 @@ void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *color dlight_t *light; size_t range; float f; - GLenum status; if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4) || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) || r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20) || r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer || + r_shadow_shadowmapshadowsampler != (vid.support.arb_shadow && r_shadow_shadowmapping_useshadowsampler.integer) || r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer || r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16)) R_Shadow_FreeShadowMaps(); @@ -4544,73 +4546,29 @@ void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *color r_shadow_usingdeferredprepass = true; r_shadow_prepass_width = vid.width; r_shadow_prepass_height = vid.height; - r_shadow_prepassgeometrydepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "prepassgeometrydepthmap", vid.width, vid.height, 24, false, false); - switch (vid.renderpath) - { - case RENDERPATH_D3D9: - 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, 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); + r_shadow_prepassgeometrydepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "prepassgeometrydepthbuffer", vid.width, vid.height, TEXTYPE_DEPTHBUFFER24); + r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, 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_COLORBUFFER16F, 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_COLORBUFFER16F, 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); - R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, r_shadow_prepassgeometrydepthcolortexture, NULL, NULL); - // render depth into one texture and normalmap into the other - if (qglDrawBuffersARB) - { - qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR - qglReadBuffer(GL_NONE);CHECKGLERROR - 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); - r_shadow_usingdeferredprepass = false; - } - } + r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL); + R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL); + // render depth into a renderbuffer and other important properties into the normalmap texture // set up the lighting pass fbo (diffuse + specular) - r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); - R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); + r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); + R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); // render diffuse into one texture and specular into another, // with depth and normalmap bound as textures, // with depth bound as attachment as well - if (qglDrawBuffersARB) - { - qglDrawBuffersARB(2, r_shadow_prepasslightingdrawbuffers);CHECKGLERROR - qglReadBuffer(GL_NONE);CHECKGLERROR - 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); - r_shadow_usingdeferredprepass = false; - } - } // set up the lighting pass fbo (diffuse) - r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL); - R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL); + r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL); + R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL); // render diffuse into one texture, // with depth and normalmap bound as textures, // with depth bound as attachment as well - if (qglDrawBuffersARB) - { - qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR - qglReadBuffer(GL_NONE);CHECKGLERROR - 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); - r_shadow_usingdeferredprepass = false; - } - } } #endif break; @@ -4625,25 +4583,22 @@ void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *color R_Shadow_EnlargeLeafSurfaceTrisBuffer(r_refdef.scene.worldmodel->brush.num_leafs, r_refdef.scene.worldmodel->num_surfaces, r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, r_refdef.scene.worldmodel->surfmesh.num_triangles); flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; - if (r_shadow_bouncegrid.integer != 2) + if (r_shadow_debuglight.integer >= 0) { - if (r_shadow_debuglight.integer >= 0) + lightindex = r_shadow_debuglight.integer; + light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (light) + R_Shadow_PrepareLight(&light->rtlight); + } + else + { + range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked + for (lightindex = 0;lightindex < range;lightindex++) { - lightindex = r_shadow_debuglight.integer; light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); - if (light) + if (light && (light->flags & flag)) R_Shadow_PrepareLight(&light->rtlight); } - else - { - range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked - for (lightindex = 0;lightindex < range;lightindex++) - { - light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); - if (light && (light->flags & flag)) - R_Shadow_PrepareLight(&light->rtlight); - } - } } if (r_refdef.scene.rtdlight) { @@ -4674,26 +4629,23 @@ void R_Shadow_DrawLights(void) R_Shadow_RenderMode_Begin(); - if (r_shadow_bouncegrid.integer != 2) + flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; + if (r_shadow_debuglight.integer >= 0) { - flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; - if (r_shadow_debuglight.integer >= 0) + lightindex = r_shadow_debuglight.integer; + light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (light) + R_Shadow_DrawLight(&light->rtlight); + } + else + { + range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked + for (lightindex = 0;lightindex < range;lightindex++) { - lightindex = r_shadow_debuglight.integer; light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); - if (light) + if (light && (light->flags & flag)) R_Shadow_DrawLight(&light->rtlight); } - else - { - range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked - for (lightindex = 0;lightindex < range;lightindex++) - { - light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); - if (light && (light->flags & flag)) - R_Shadow_DrawLight(&light->rtlight); - } - } } if (r_refdef.scene.rtdlight) for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++) @@ -4808,11 +4760,11 @@ void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colort switch (r_shadow_shadowmode) { case R_SHADOW_SHADOWMODE_SHADOWMAP2D: - if (!r_shadow_shadowmap2dtexture) + if (!r_shadow_shadowmap2ddepthtexture) R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize); shadowfbo = 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_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2ddepthtexture); + r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2ddepthtexture); r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D; break; default: @@ -4860,8 +4812,11 @@ void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colort VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin); - R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL); - R_SetupShader_DepthOrShadow(true); + if (r_shadow_shadowmap2ddepthbuffer) + R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL); + else + R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL); + R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL); GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value); GL_DepthMask(true); GL_DepthTest(true); @@ -4870,7 +4825,7 @@ void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colort Vector4Set(clearcolor, 1,1,1,1); // in D3D9 we have to render to a color texture shadowmap // in GL we render directly to a depth texture only - if (r_shadow_shadowmap2dtexture) + if (r_shadow_shadowmap2ddepthbuffer) GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0); else GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0); @@ -5489,10 +5444,10 @@ void R_Shadow_DrawLightSprites(void) { light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); if (light) - R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight); + R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight); } if (!r_editlights_lockcursor) - R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL); + R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL); } int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)