]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
move double break in pseudoalpha case to the right case...
[xonotic/darkplaces.git] / r_shadow.c
index 3952e23179af146e609b4029e39bd87496c095e1..1f096039f28d7cf1dbe6e70adf3b8c46cc1a51ad 100644 (file)
@@ -139,6 +139,7 @@ demonstrated by the game Doom3.
 #include "cl_collision.h"
 #include "portals.h"
 #include "image.h"
+#include "dpsoftrast.h"
 
 #ifdef SUPPORTD3D
 #include <d3d9.h>
@@ -273,6 +274,7 @@ cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one
 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", "2", "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)"};
 cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
@@ -312,6 +314,7 @@ cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nea
 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
 cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
 cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
+cvar_t r_shadow_sortsurfaces = {0, "r_shadow_sortsurfaces", "1", "improve performance by sorting illuminated surfaces by texture"};
 cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
 cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
 cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect OpenGL 2.0 render path)"};
@@ -425,6 +428,7 @@ void R_Shadow_SetShadowMode(void)
                case RENDERPATH_D3D9:
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
+               case RENDERPATH_SOFT:
                        r_shadow_shadowmapsampler = false;
                        r_shadow_shadowmappcf = 1;
                        r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
@@ -625,6 +629,7 @@ void R_Shadow_Init(void)
 {
        Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
        Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
+       Cvar_RegisterVariable(&r_shadow_usebihculling);
        Cvar_RegisterVariable(&r_shadow_usenormalmap);
        Cvar_RegisterVariable(&r_shadow_debuglight);
        Cvar_RegisterVariable(&r_shadow_deferred);
@@ -668,6 +673,7 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
+       Cvar_RegisterVariable(&r_shadow_sortsurfaces);
        Cvar_RegisterVariable(&r_shadow_polygonfactor);
        Cvar_RegisterVariable(&r_shadow_polygonoffset);
        Cvar_RegisterVariable(&r_shadow_texture3d);
@@ -1274,7 +1280,7 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f,
        else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
        {
                tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
-               R_Mesh_PrepareVertices_Position_Arrays(outverts, shadowvertex3f);
+               R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL);
                R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
        }
        else
@@ -1308,7 +1314,7 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f,
                        GL_CullFace(r_refdef.view.cullface_back);
                        R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
                }
-               R_Mesh_PrepareVertices_Position_Arrays(outverts, shadowvertex3f);
+               R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL);
                R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
        }
 }
@@ -1844,8 +1850,6 @@ void R_Shadow_ValidateCvars(void)
                Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
 }
 
-//static const r_vertexposition_t resetvertexposition[3] = {{0, 0, 0}};
-
 void R_Shadow_RenderMode_Begin(void)
 {
 #if 0
@@ -1862,7 +1866,6 @@ void R_Shadow_RenderMode_Begin(void)
 
        CHECKGLERROR
        R_Mesh_ResetTextureState();
-//     R_Mesh_PrepareVertices_Position(0, resetvertexposition, NULL);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_DepthRange(0, 1);
        GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
@@ -1896,6 +1899,7 @@ void R_Shadow_RenderMode_Begin(void)
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
+       case RENDERPATH_SOFT:
                r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
                break;
        case RENDERPATH_GL13:
@@ -1933,7 +1937,6 @@ void R_Shadow_RenderMode_Reset(void)
        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();
-//     R_Mesh_PrepareVertices_Position(0, resetvertexposition, NULL);
        GL_DepthRange(0, 1);
        GL_DepthTest(true);
        GL_DepthMask(false);
@@ -2101,6 +2104,7 @@ init_done:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_SOFT:
                GL_CullFace(r_refdef.view.cullface_back);
                // OpenGL lets us scissor larger than the viewport, so go ahead and clear all views at once
                if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask
@@ -2116,6 +2120,8 @@ init_done:
                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;
@@ -2138,14 +2144,6 @@ init_done:
                                GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
                }
                break;
-       case RENDERPATH_D3D10:
-       case RENDERPATH_D3D11:
-               // 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);
-               GL_ColorMask(0,0,0,0);
-               if (clear)
-                       GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
-               break;
        }
 }
 
@@ -2227,7 +2225,7 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow
        GL_DepthTest(true);
        GL_DepthFunc(GL_GREATER);
        GL_CullFace(r_refdef.view.cullface_back);
-       R_Mesh_PrepareVertices_Position_Arrays(8, vertex3f);
+       R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL);
        R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
 }
 
@@ -2317,7 +2315,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
        case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
                if (VectorLength2(diffusecolor) > 0)
                {
-                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
+                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
                        {
                                Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
                                Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
@@ -2339,7 +2337,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                }
                else
                {
-                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
+                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
                        {
                                VectorCopy(ambientcolor, color4f);
                                if (r_refdef.fogenabled)
@@ -2356,7 +2354,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
        case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
                if (VectorLength2(diffusecolor) > 0)
                {
-                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
+                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
                        {
                                Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
                                if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
@@ -2389,7 +2387,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                }
                else
                {
-                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
+                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
                        {
                                Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
                                if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
@@ -2413,7 +2411,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
        case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
                if (VectorLength2(diffusecolor) > 0)
                {
-                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
+                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
                        {
                                Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
                                if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
@@ -2447,7 +2445,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                }
                else
                {
-                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
+                       for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
                        {
                                Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
                                if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
@@ -2521,7 +2519,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve
                // renders them at once
                for (i = 0, e = element3i;i < numtriangles;i++, e += 3)
                {
-                       if (VectorLength2(rsurface.array_passcolor4f + e[0] * 4) + VectorLength2(rsurface.array_passcolor4f + e[1] * 4) + VectorLength2(rsurface.array_passcolor4f + e[2] * 4) >= 0.01)
+                       if (VectorLength2(rsurface.passcolor4f + e[0] * 4) + VectorLength2(rsurface.passcolor4f + e[1] * 4) + VectorLength2(rsurface.passcolor4f + e[2] * 4) >= 0.01)
                        {
                                if (newnumtriangles)
                                {
@@ -2564,7 +2562,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve
                // handling of negative colors
                // (some old drivers even have improper handling of >1 color)
                stop = true;
-               for (i = 0, c = rsurface.array_passcolor4f + 4 * firstvertex;i < numvertices;i++, c += 4)
+               for (i = 0, c = rsurface.passcolor4f + 4 * firstvertex;i < numvertices;i++, c += 4)
                {
                        if (c[0] > 1 || c[1] > 1 || c[2] > 1)
                        {
@@ -2604,9 +2602,10 @@ static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const m
        diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
        ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
        diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
-       RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD, texturenumsurfaces, texturesurfacelist);
+       RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+       rsurface.passcolor4f = R_FrameData_Alloc((rsurface.batchfirstvertex + rsurface.batchnumvertices) * sizeof(float[4]));
        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
-       R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
+       R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
        R_Mesh_TexBind(0, basetexture);
        R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
@@ -2691,6 +2690,9 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_BlendSubtract(true);
+                       break;
                }
        }
        RSurf_SetupDepthAndCulling();
@@ -2734,6 +2736,9 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_BlendSubtract(false);
+                       break;
                }
        }
 }
@@ -2813,7 +2818,9 @@ void R_RTLight_Compile(rtlight_t *rtlight)
        {
                // this variable must be set for the CompileShadowVolume/CompileShadowMap code
                r_shadow_compilingrtlight = rtlight;
+               R_FrameData_SetMark();
                model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs, 0, NULL);
+               R_FrameData_ReturnToMark();
                numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
                numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
                numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
@@ -2838,6 +2845,7 @@ void R_RTLight_Compile(rtlight_t *rtlight)
                        memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
                if (rtlight->static_numlighttrispvsbytes)
                        memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
+               R_FrameData_SetMark();
                switch (rtlight->shadowmode)
                {
                case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
@@ -2849,6 +2857,7 @@ void R_RTLight_Compile(rtlight_t *rtlight)
                                model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
                        break;
                }
+               R_FrameData_ReturnToMark();
                // now we're done compiling the rtlight
                r_shadow_compilingrtlight = NULL;
        }
@@ -3104,17 +3113,20 @@ void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const
        {
                CHECKGLERROR
                GL_CullFace(GL_NONE);
-        mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap;
-        for (;mesh;mesh = mesh->next)
-        {
+               mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap;
+               for (;mesh;mesh = mesh->next)
+               {
                        if (!mesh->sidetotals[r_shadow_shadowmapside])
                                continue;
-            r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside];
-            R_Mesh_PrepareVertices_Position(mesh->numverts, mesh->vertexposition, mesh->vertexpositionbuffer);
-            R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
-        }
-        CHECKGLERROR
-    }
+                       r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside];
+                       if (mesh->vertex3fbuffer)
+                               R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vertex3fbuffer);
+                       else
+                               R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer);
+                       R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
+               }
+               CHECKGLERROR
+       }
        else if (r_refdef.scene.worldentity->model)
                r_refdef.scene.worldmodel->DrawShadowMap(r_shadow_shadowmapside, r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, surfacesides, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
 
@@ -3129,6 +3141,10 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co
        int surfacelistindex;
        msurface_t *surface;
 
+       // if triangle neighbors are disabled, shadowvolumes are disabled
+       if (r_refdef.scene.worldmodel->brush.shadowmesh ? !r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i : !r_refdef.scene.worldmodel->surfmesh.data_neighbor3i)
+               return;
+
        RSurf_ActiveWorldEntity();
 
        if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
@@ -3143,7 +3159,10 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co
                for (;mesh;mesh = mesh->next)
                {
                        r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
-                       R_Mesh_PrepareVertices_Position(mesh->numverts, mesh->vertexposition, mesh->vertexpositionbuffer);
+                       if (mesh->vertex3fbuffer)
+                               R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vertex3fbuffer);
+                       else
+                               R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer);
                        if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
                        {
                                // increment stencil if frontface is infront of depthbuffer
@@ -3182,7 +3201,9 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co
                R_Shadow_VolumeFromList(r_refdef.scene.worldmodel->brush.shadowmesh->numverts, r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles, r_refdef.scene.worldmodel->brush.shadowmesh->vertex3f, r_refdef.scene.worldmodel->brush.shadowmesh->element3i, r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius + r_refdef.scene.worldmodel->radius*2 + r_shadow_projectdistance.value, numshadowmark, shadowmarklist, r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
        }
        else if (numsurfaces)
+       {
                r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
+       }
 
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
 }
@@ -3514,10 +3535,6 @@ void R_Shadow_DrawLight(rtlight_t *rtlight)
        if (!rtlight->draw)
                return;
 
-       // if R_FrameData_Store ran out of space we skip anything dependent on it
-       if (r_framedata_failed)
-               return;
-
        numlightentities = rtlight->cached_numlightentities;
        numlightentities_noselfshadow = rtlight->cached_numlightentities_noselfshadow;
        numshadowentities = rtlight->cached_numshadowentities;
@@ -3818,7 +3835,7 @@ void R_Shadow_DrawPrepass(void)
        {
                lightindex = r_shadow_debuglight.integer;
                light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
-               if (light && (light->flags & flag))
+               if (light && (light->flags & flag) && light->rtlight.draw)
                        R_Shadow_DrawLight(&light->rtlight);
        }
        else
@@ -3827,13 +3844,14 @@ void R_Shadow_DrawPrepass(void)
                for (lightindex = 0;lightindex < range;lightindex++)
                {
                        light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
-                       if (light && (light->flags & flag))
+                       if (light && (light->flags & flag) && light->rtlight.draw)
                                R_Shadow_DrawLight(&light->rtlight);
                }
        }
        if (r_refdef.scene.rtdlight)
                for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
-                       R_Shadow_DrawLight(r_refdef.scene.lights[lnum]);
+                       if (r_refdef.scene.lights[lnum]->draw)
+                               R_Shadow_DrawLight(r_refdef.scene.lights[lnum]);
 
        R_Mesh_ResetRenderTargets();
 
@@ -3871,6 +3889,7 @@ void R_Shadow_PrepareLights(void)
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
+       case RENDERPATH_SOFT:
                if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
                {
                        r_shadow_usingdeferredprepass = false;
@@ -4263,6 +4282,7 @@ void R_DrawModelShadowMaps(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_SOFT:
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -4444,13 +4464,13 @@ void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
                        qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
                        GL_DepthFunc(GL_ALWAYS);
                        R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
-                       R_Mesh_PrepareVertices_Position_Arrays(4, vertex3f);
+                       R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL);
                        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
                        qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
                        GL_DepthFunc(GL_LEQUAL);
                        qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
                        R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
-                       R_Mesh_PrepareVertices_Position_Arrays(4, vertex3f);
+                       R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL);
                        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
                        qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
                        CHECKGLERROR
@@ -4464,6 +4484,9 @@ void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+                       break;
                }
        }
        rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
@@ -4498,6 +4521,9 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+                       break;
                }
                //Con_Printf("%i of %i pixels\n", (int)visiblepixels, (int)allpixels);
                if (visiblepixels < 1 || allpixels < 1)
@@ -4538,6 +4564,9 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                        case RENDERPATH_D3D11:
                                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                                break;
+                       case RENDERPATH_SOFT:
+                               DPSOFTRAST_BlendSubtract(true);
+                               break;
                        }
                }
                R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
@@ -4564,6 +4593,9 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                        case RENDERPATH_D3D11:
                                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                                break;
+                       case RENDERPATH_SOFT:
+                               DPSOFTRAST_BlendSubtract(false);
+                               break;
                        }
                }
        }
@@ -4631,6 +4663,9 @@ void R_Shadow_DrawCoronas(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               break;
        }
        for (lightindex = 0;lightindex < range;lightindex++)
        {
@@ -6001,55 +6036,55 @@ LIGHT SAMPLING
 =============================================================================
 */
 
-void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, qboolean dynamic, qboolean rtworld)
+void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, const int flags)
 {
+       int i, numlights, flag;
+       float f, relativepoint[3], dist, dist2, lightradius2;
+       rtlight_t *light;
+       dlight_t *dlight;
+
        VectorClear(diffusecolor);
        VectorClear(diffusenormal);
 
-       if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
+       if (flags & LP_LIGHTMAP)
        {
-               ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = r_refdef.scene.ambient;
-               r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
+               if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
+               {
+                       ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = r_refdef.scene.ambient;
+                       r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
+               }
+               else
+                       VectorSet(ambientcolor, 1, 1, 1);
        }
-       else
-               VectorSet(ambientcolor, 1, 1, 1);
-
-       if (dynamic)
+       if (flags & LP_RTWORLD)
        {
-               int i, numlights, flag;
-               float f, relativepoint[3], dist, dist2, lightradius2;
-               rtlight_t *light;
-               dlight_t *dlight;
-
-               // sample rtlights
-               if (rtworld)
+               flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
+               numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
+               for (i = 0; i < numlights; i++)
                {
-                       flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
-                       numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
-                       for (i = 0; i < numlights; i++)
-                       {
-                               dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
-                               if (!dlight)
-                                       continue;
-                               light = &dlight->rtlight;
-                               if (!(light->flags & flag))
-                                       continue;
-                               // sample
-                               lightradius2 = light->radius * light->radius;
-                               VectorSubtract(light->shadoworigin, p, relativepoint);
-                               dist2 = VectorLength2(relativepoint);
-                               if (dist2 >= lightradius2)
-                                       continue;
-                               dist = sqrt(dist2) / light->radius;
-                               f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0;
-                               if (f <= 0)
-                                       continue;
-                               // todo: add to both ambient and diffuse
-                               if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
-                                       VectorMA(ambientcolor, f, light->currentcolor, ambientcolor);
-                       }
+                       dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
+                       if (!dlight)
+                               continue;
+                       light = &dlight->rtlight;
+                       if (!(light->flags & flag))
+                               continue;
+                       // sample
+                       lightradius2 = light->radius * light->radius;
+                       VectorSubtract(light->shadoworigin, p, relativepoint);
+                       dist2 = VectorLength2(relativepoint);
+                       if (dist2 >= lightradius2)
+                               continue;
+                       dist = sqrt(dist2) / light->radius;
+                       f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0;
+                       if (f <= 0)
+                               continue;
+                       // todo: add to both ambient and diffuse
+                       if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
+                               VectorMA(ambientcolor, f, light->currentcolor, ambientcolor);
                }
-
+       }
+       if (flags & LP_DYNLIGHT)
+       {
                // sample dlights
                for (i = 0;i < r_refdef.scene.numlights;i++)
                {