]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
fix Collision_ClipTrace_Line_Sphere calculation of impactdist (had a
[xonotic/darkplaces.git] / r_shadow.c
index 76dd1fabb0a8eba63bd281b21b5199be14d955db..fc10e437ef81a64aa66a5fad4e45b59c20faa0a8 100644 (file)
@@ -146,7 +146,7 @@ demonstrated by the game Doom3.
 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
 #endif
 
-extern void R_Shadow_EditLights_Init(void);
+static void R_Shadow_EditLights_Init(void);
 
 typedef enum r_shadow_rendermode_e
 {
@@ -261,6 +261,11 @@ rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
 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];
 
@@ -424,7 +429,7 @@ skinframe_t *r_editlights_sprcubemaplight;
 skinframe_t *r_editlights_sprcubemapnoshadowlight;
 skinframe_t *r_editlights_sprselection;
 
-void R_Shadow_SetShadowMode(void)
+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;
@@ -504,7 +509,7 @@ qboolean R_Shadow_ShadowMappingEnabled(void)
        }
 }
 
-void R_Shadow_FreeShadowMaps(void)
+static void R_Shadow_FreeShadowMaps(void)
 {
        R_Shadow_SetShadowMode();
 
@@ -525,7 +530,7 @@ void R_Shadow_FreeShadowMaps(void)
        r_shadow_shadowmapvsdcttexture = NULL;
 }
 
-void r_shadow_start(void)
+static void r_shadow_start(void)
 {
        // allocate vertex processing arrays
        r_shadow_bouncegridpixels = NULL;
@@ -591,7 +596,7 @@ void r_shadow_start(void)
 }
 
 static void R_Shadow_FreeDeferred(void);
-void r_shadow_shutdown(void)
+static void r_shadow_shutdown(void)
 {
        CHECKGLERROR
        R_Shadow_UncompileWorldLights();
@@ -674,7 +679,7 @@ void r_shadow_shutdown(void)
                Mem_Free(r_shadow_buffer_lighttrispvs);
 }
 
-void r_shadow_newmap(void)
+static void r_shadow_newmap(void)
 {
        if (r_shadow_bouncegridtexture) R_FreeTexture(r_shadow_bouncegridtexture);r_shadow_bouncegridtexture = NULL;
        if (r_shadow_lightcorona)                 R_SkinFrame_MarkUsed(r_shadow_lightcorona);
@@ -821,7 +826,7 @@ matrix4x4_t matrix_attenuationz =
        }
 };
 
-void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
+static void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
 {
        numvertices = ((numvertices + 255) & ~255) * vertscale;
        numtriangles = ((numtriangles + 255) & ~255) * triscale;
@@ -1296,7 +1301,7 @@ void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *inv
        }
 }
 
-qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
+static qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
 {
 #if 1
        return false;
@@ -1451,7 +1456,7 @@ int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t
        return mask;
 }
 
-int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
+static int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
 {
        vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
        float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
@@ -1520,7 +1525,7 @@ int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
     return mask;
 }
 
-int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
+static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
 {
        int i;
        vec3_t p, n;
@@ -2015,10 +2020,10 @@ void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
 
 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);
@@ -2030,7 +2035,7 @@ void R_Shadow_RenderMode_Reset(void)
        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);
@@ -2133,12 +2138,12 @@ static void R_Shadow_MakeShadowMap(int side, int size)
 #endif
 }
 
-void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
+static 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;
@@ -2158,14 +2163,14 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
                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);
@@ -2229,7 +2234,6 @@ init_done:
 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;
@@ -2698,10 +2702,16 @@ void R_Shadow_UpdateBounceGridTexture(void)
                                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)
@@ -3171,8 +3181,8 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve
        int *newe;
        const int *e;
        float *c;
-       int maxtriangles = 4096;
-       static int newelements[4096*3];
+       int maxtriangles = 1024;
+       int newelements[1024*3];
        R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, diffusecolor2, ambientcolor2);
        for (renders = 0;renders < 4;renders++)
        {
@@ -3560,7 +3570,7 @@ void R_Shadow_UncompileWorldLights(void)
        }
 }
 
-void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
+static void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
 {
        int i, j;
        mplane_t plane;
@@ -3729,7 +3739,7 @@ void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
 #endif
 }
 
-void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
+static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
 {
        shadowmesh_t *mesh;
 
@@ -3759,7 +3769,7 @@ void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 }
 
-void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
+static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
 {
        qboolean zpass = false;
        shadowmesh_t *mesh;
@@ -3834,7 +3844,7 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 }
 
-void R_Shadow_DrawEntityShadow(entity_render_t *ent)
+static void R_Shadow_DrawEntityShadow(entity_render_t *ent)
 {
        vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
        vec_t relativeshadowradius;
@@ -3870,7 +3880,7 @@ void R_Shadow_SetupEntityLight(const entity_render_t *ent)
        Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
 }
 
-void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
+static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
 {
        if (!r_refdef.scene.worldmodel->DrawLight)
                return;
@@ -3887,7 +3897,7 @@ void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned c
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 }
 
-void R_Shadow_DrawEntityLight(entity_render_t *ent)
+static void R_Shadow_DrawEntityLight(entity_render_t *ent)
 {
        dp_model_t *model = ent->model;
        if (!model->DrawLight)
@@ -3900,7 +3910,7 @@ void R_Shadow_DrawEntityLight(entity_render_t *ent)
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 }
 
-void R_Shadow_PrepareLight(rtlight_t *rtlight)
+static void R_Shadow_PrepareLight(rtlight_t *rtlight)
 {
        int i;
        float f;
@@ -4134,7 +4144,7 @@ void R_Shadow_PrepareLight(rtlight_t *rtlight)
        }
 }
 
-void R_Shadow_DrawLight(rtlight_t *rtlight)
+static void R_Shadow_DrawLight(rtlight_t *rtlight)
 {
        int i;
        int numsurfaces;
@@ -4479,8 +4489,6 @@ void R_Shadow_DrawPrepass(void)
                        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)
@@ -4488,7 +4496,7 @@ void R_Shadow_DrawPrepass(void)
 }
 
 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;
@@ -4506,6 +4514,10 @@ void R_Shadow_PrepareLights(void)
                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)
@@ -4536,14 +4548,14 @@ void R_Shadow_PrepareLights(void)
                        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);
@@ -4690,19 +4702,6 @@ void R_Shadow_DrawLights(void)
        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;
@@ -4772,7 +4771,7 @@ void R_Shadow_PrepareModelShadows(void)
        }
 }
 
-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;
@@ -4784,7 +4783,7 @@ void R_DrawModelShadowMaps(void)
        float m[12];
        matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
        r_viewport_t viewport;
-       GLuint fbo = 0;
+       GLuint shadowfbo = 0;
        float clearcolor[4];
 
        if (!r_refdef.scene.numentities)
@@ -4798,7 +4797,11 @@ void R_DrawModelShadowMaps(void)
                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);
 
@@ -4807,7 +4810,7 @@ void R_DrawModelShadowMaps(void)
        case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
                if (!r_shadow_shadowmap2dtexture)
                        R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
-               fbo = r_shadow_fbo2d;
+               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_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
@@ -4857,7 +4860,7 @@ void R_DrawModelShadowMaps(void)
 
        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(shadowfbo, 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);
@@ -4878,7 +4881,7 @@ void R_DrawModelShadowMaps(void)
 
 #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);
@@ -4967,7 +4970,7 @@ void R_DrawModelShadowMaps(void)
        }
 }
 
-void R_DrawModelShadows(void)
+void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
 {
        int i;
        float relativethrowdistance;
@@ -4980,7 +4983,11 @@ void R_DrawModelShadows(void)
        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();
@@ -5065,7 +5072,7 @@ void R_DrawModelShadows(void)
        //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);
@@ -5080,7 +5087,7 @@ void R_DrawModelShadows(void)
 
        // 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
@@ -5090,7 +5097,7 @@ void R_DrawModelShadows(void)
        //R_Shadow_RenderMode_End();
 }
 
-void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
+static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
 {
        float zdist;
        vec3_t centerorigin;
@@ -5152,7 +5159,7 @@ void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
 
 static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
 
-void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
+static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
 {
        vec3_t color;
        GLint allpixels = 0, visiblepixels = 0;
@@ -5226,7 +5233,7 @@ void R_Shadow_DrawCoronas(void)
        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);
@@ -5267,7 +5274,7 @@ void R_Shadow_DrawCoronas(void)
                        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;
@@ -5343,12 +5350,12 @@ void R_Shadow_DrawCoronas(void)
 
 
 
-dlight_t *R_Shadow_NewWorldLight(void)
+static dlight_t *R_Shadow_NewWorldLight(void)
 {
        return (dlight_t *)Mem_ExpandableArray_AllocRecord(&r_shadow_worldlightsarray);
 }
 
-void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
+static void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
 {
        matrix4x4_t matrix;
        // validate parameters
@@ -5389,7 +5396,7 @@ void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, ve
        R_RTLight_Update(&light->rtlight, true, &matrix, light->color, light->style, light->cubemapname[0] ? light->cubemapname : NULL, light->shadow, light->corona, light->coronasizescale, light->ambientscale, light->diffusescale, light->specularscale, light->flags);
 }
 
-void R_Shadow_FreeWorldLight(dlight_t *light)
+static void R_Shadow_FreeWorldLight(dlight_t *light)
 {
        if (r_shadow_selectedlight == light)
                r_shadow_selectedlight = NULL;
@@ -5411,7 +5418,7 @@ void R_Shadow_ClearWorldLights(void)
        r_shadow_selectedlight = NULL;
 }
 
-void R_Shadow_SelectLight(dlight_t *light)
+static void R_Shadow_SelectLight(dlight_t *light)
 {
        if (r_shadow_selectedlight)
                r_shadow_selectedlight->selected = false;
@@ -5420,7 +5427,7 @@ void R_Shadow_SelectLight(dlight_t *light)
                r_shadow_selectedlight->selected = true;
 }
 
-void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
        // this is never batched (there can be only one)
        float vertex3f[12];
@@ -5429,7 +5436,7 @@ void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const r
        R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
 }
 
-void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
        float intensity;
        float s;
@@ -5508,7 +5515,7 @@ int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radiu
        return 1;
 }
 
-void R_Shadow_SelectLightInView(void)
+static void R_Shadow_SelectLightInView(void)
 {
        float bestrating, rating, temp[3];
        dlight_t *best;
@@ -5763,6 +5770,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
        const char *data;
        float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
        char key[256], value[MAX_INPUTLINE];
+       char vabuf[1024];
 
        if (cl.worldmodel == NULL)
        {
@@ -5966,14 +5974,14 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                }
                VectorAdd(origin, originhack, origin);
                if (radius >= 1)
-                       R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va("cubemaps/%i", skin) : NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
+                       R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va(vabuf, sizeof(vabuf), "cubemaps/%i", skin) : NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
        }
        if (entfiledata)
                Mem_Free(entfiledata);
 }
 
 
-void R_Shadow_SetCursorLocationForView(void)
+static void R_Shadow_SetCursorLocationForView(void)
 {
        vec_t dist, push;
        vec3_t dest, endpos;
@@ -6010,7 +6018,7 @@ void R_Shadow_UpdateWorldLightSelection(void)
                R_Shadow_SelectLight(NULL);
 }
 
-void R_Shadow_EditLights_Clear_f(void)
+static void R_Shadow_EditLights_Clear_f(void)
 {
        R_Shadow_ClearWorldLights();
 }
@@ -6030,26 +6038,26 @@ void R_Shadow_EditLights_Reload_f(void)
        }
 }
 
-void R_Shadow_EditLights_Save_f(void)
+static void R_Shadow_EditLights_Save_f(void)
 {
        if (!cl.worldmodel)
                return;
        R_Shadow_SaveWorldLights();
 }
 
-void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(void)
+static void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(void)
 {
        R_Shadow_ClearWorldLights();
        R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
 }
 
-void R_Shadow_EditLights_ImportLightsFile_f(void)
+static void R_Shadow_EditLights_ImportLightsFile_f(void)
 {
        R_Shadow_ClearWorldLights();
        R_Shadow_LoadLightsFile();
 }
 
-void R_Shadow_EditLights_Spawn_f(void)
+static void R_Shadow_EditLights_Spawn_f(void)
 {
        vec3_t color;
        if (!r_editlights.integer)
@@ -6066,7 +6074,7 @@ void R_Shadow_EditLights_Spawn_f(void)
        R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), r_editlights_cursorlocation, vec3_origin, color, 200, 0, 0, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
 }
 
-void R_Shadow_EditLights_Edit_f(void)
+static void R_Shadow_EditLights_Edit_f(void)
 {
        vec3_t origin, angles, color;
        vec_t radius, corona, coronasizescale, ambientscale, diffusescale, specularscale;
@@ -6392,7 +6400,7 @@ void R_Shadow_EditLights_Edit_f(void)
        R_Shadow_UpdateWorldLight(r_shadow_selectedlight, origin, angles, color, radius, corona, style, shadows, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
 }
 
-void R_Shadow_EditLights_EditAll_f(void)
+static void R_Shadow_EditLights_EditAll_f(void)
 {
        size_t lightindex;
        dlight_t *light, *oldselected;
@@ -6465,7 +6473,7 @@ void R_Shadow_EditLights_DrawSelectedLightProperties(void)
        dpsnprintf(temp, sizeof(temp), "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
 }
 
-void R_Shadow_EditLights_ToggleShadow_f(void)
+static void R_Shadow_EditLights_ToggleShadow_f(void)
 {
        if (!r_editlights.integer)
        {
@@ -6480,7 +6488,7 @@ void R_Shadow_EditLights_ToggleShadow_f(void)
        R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname, r_shadow_selectedlight->coronasizescale, r_shadow_selectedlight->ambientscale, r_shadow_selectedlight->diffusescale, r_shadow_selectedlight->specularscale, r_shadow_selectedlight->flags);
 }
 
-void R_Shadow_EditLights_ToggleCorona_f(void)
+static void R_Shadow_EditLights_ToggleCorona_f(void)
 {
        if (!r_editlights.integer)
        {
@@ -6495,7 +6503,7 @@ void R_Shadow_EditLights_ToggleCorona_f(void)
        R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname, r_shadow_selectedlight->coronasizescale, r_shadow_selectedlight->ambientscale, r_shadow_selectedlight->diffusescale, r_shadow_selectedlight->specularscale, r_shadow_selectedlight->flags);
 }
 
-void R_Shadow_EditLights_Remove_f(void)
+static void R_Shadow_EditLights_Remove_f(void)
 {
        if (!r_editlights.integer)
        {
@@ -6511,7 +6519,7 @@ void R_Shadow_EditLights_Remove_f(void)
        r_shadow_selectedlight = NULL;
 }
 
-void R_Shadow_EditLights_Help_f(void)
+static void R_Shadow_EditLights_Help_f(void)
 {
        Con_Print(
 "Documentation on r_editlights system:\n"
@@ -6568,7 +6576,7 @@ void R_Shadow_EditLights_Help_f(void)
        );
 }
 
-void R_Shadow_EditLights_CopyInfo_f(void)
+static void R_Shadow_EditLights_CopyInfo_f(void)
 {
        if (!r_editlights.integer)
        {
@@ -6597,7 +6605,7 @@ void R_Shadow_EditLights_CopyInfo_f(void)
        r_shadow_bufferlight.flags = r_shadow_selectedlight->flags;
 }
 
-void R_Shadow_EditLights_PasteInfo_f(void)
+static void R_Shadow_EditLights_PasteInfo_f(void)
 {
        if (!r_editlights.integer)
        {
@@ -6612,7 +6620,7 @@ void R_Shadow_EditLights_PasteInfo_f(void)
        R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_bufferlight.angles, r_shadow_bufferlight.color, r_shadow_bufferlight.radius, r_shadow_bufferlight.corona, r_shadow_bufferlight.style, r_shadow_bufferlight.shadow, r_shadow_bufferlight.cubemapname, r_shadow_bufferlight.coronasizescale, r_shadow_bufferlight.ambientscale, r_shadow_bufferlight.diffusescale, r_shadow_bufferlight.specularscale, r_shadow_bufferlight.flags);
 }
 
-void R_Shadow_EditLights_Lock_f(void)
+static void R_Shadow_EditLights_Lock_f(void)
 {
        if (!r_editlights.integer)
        {
@@ -6632,7 +6640,7 @@ void R_Shadow_EditLights_Lock_f(void)
        r_editlights_lockcursor = true;
 }
 
-void R_Shadow_EditLights_Init(void)
+static void R_Shadow_EditLights_Init(void)
 {
        Cvar_RegisterVariable(&r_editlights);
        Cvar_RegisterVariable(&r_editlights_cursordistance);