]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
added developer_texturelogging
[xonotic/darkplaces.git] / gl_rmain.c
index 253ad2699b0f4165808d19fcb4868f11d4ffb7ce..f46df91638a6d3f15d0e8b6227ee548e2e7d6b1d 100644 (file)
@@ -103,9 +103,18 @@ cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
+
+cvar_t developer_texturelogging = {0, "developer_texturelogging", "1"};
+
 rtexturepool_t *r_main_texturepool;
 rtexture_t *r_bloom_texture_screen;
 rtexture_t *r_bloom_texture_bloom;
+rtexture_t *r_texture_blanknormalmap;
+rtexture_t *r_texture_white;
+rtexture_t *r_texture_black;
+rtexture_t *r_texture_notexture;
+rtexture_t *r_texture_whitecube;
+rtexture_t *r_texture_normalizationcube;
 
 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
 {
@@ -207,9 +216,112 @@ void FOG_registercvars(void)
 
 void gl_main_start(void)
 {
+       int x, y, side;
+       vec3_t v;
+       vec_t s, t, intensity;
+       qbyte pix[16][16][4];
+#define NORMSIZE 64
+       qbyte data[6*NORMSIZE*NORMSIZE*4];
        r_main_texturepool = R_AllocTexturePool();
        r_bloom_texture_screen = NULL;
        r_bloom_texture_bloom = NULL;
+       data[0] = 128; // normal X
+       data[1] = 128; // normal Y
+       data[2] = 255; // normal Z
+       data[3] = 128; // height
+       r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
+       data[0] = 255;
+       data[1] = 255;
+       data[2] = 255;
+       data[3] = 255;
+       r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
+       data[0] = 0;
+       data[1] = 0;
+       data[2] = 0;
+       data[3] = 255;
+       r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
+       // this makes a light grey/dark grey checkerboard texture
+       for (y = 0;y < 16;y++)
+       {
+               for (x = 0;x < 16;x++)
+               {
+                       if ((y < 8) ^ (x < 8))
+                       {
+                               pix[y][x][0] = 128;
+                               pix[y][x][1] = 128;
+                               pix[y][x][2] = 128;
+                               pix[y][x][3] = 255;
+                       }
+                       else
+                       {
+                               pix[y][x][0] = 64;
+                               pix[y][x][1] = 64;
+                               pix[y][x][2] = 64;
+                               pix[y][x][3] = 255;
+                       }
+               }
+       }
+       r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
+       if (gl_texturecubemap)
+       {
+               data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
+               data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
+               data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
+               data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
+               data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
+               data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
+               r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
+               for (side = 0;side < 6;side++)
+               {
+                       for (y = 0;y < NORMSIZE;y++)
+                       {
+                               for (x = 0;x < NORMSIZE;x++)
+                               {
+                                       s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
+                                       t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
+                                       switch(side)
+                                       {
+                                       case 0:
+                                               v[0] = 1;
+                                               v[1] = -t;
+                                               v[2] = -s;
+                                               break;
+                                       case 1:
+                                               v[0] = -1;
+                                               v[1] = -t;
+                                               v[2] = s;
+                                               break;
+                                       case 2:
+                                               v[0] = s;
+                                               v[1] = 1;
+                                               v[2] = t;
+                                               break;
+                                       case 3:
+                                               v[0] = s;
+                                               v[1] = -1;
+                                               v[2] = -t;
+                                               break;
+                                       case 4:
+                                               v[0] = s;
+                                               v[1] = -t;
+                                               v[2] = 1;
+                                               break;
+                                       case 5:
+                                               v[0] = -s;
+                                               v[1] = -t;
+                                               v[2] = -1;
+                                               break;
+                                       }
+                                       intensity = 127.0f / sqrt(DotProduct(v, v));
+                                       data[((side*NORMSIZE+y)*NORMSIZE+x)*4+0] = 128.0f + intensity * v[0];
+                                       data[((side*NORMSIZE+y)*NORMSIZE+x)*4+1] = 128.0f + intensity * v[1];
+                                       data[((side*NORMSIZE+y)*NORMSIZE+x)*4+2] = 128.0f + intensity * v[2];
+                                       data[((side*NORMSIZE+y)*NORMSIZE+x)*4+3] = 255;
+                               }
+                       }
+               }
+               r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
+       }
 }
 
 void gl_main_shutdown(void)
@@ -217,6 +329,11 @@ void gl_main_shutdown(void)
        R_FreeTexturePool(&r_main_texturepool);
        r_bloom_texture_screen = NULL;
        r_bloom_texture_bloom = NULL;
+       r_texture_blanknormalmap = NULL;
+       r_texture_white = NULL;
+       r_texture_black = NULL;
+       r_texture_whitecube = NULL;
+       r_texture_normalizationcube = NULL;
 }
 
 extern void CL_ParseEntityLump(char *entitystring);
@@ -269,6 +386,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_bloom_blur);
        Cvar_RegisterVariable(&r_bloom_resolution);
        Cvar_RegisterVariable(&r_bloom_power);
+       Cvar_RegisterVariable(&developer_texturelogging);
        if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
                Cvar_SetValue("r_fullbrights", 0);
        R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
@@ -418,56 +536,6 @@ int R_CullBox(const vec3_t mins, const vec3_t maxs)
        return false;
 }
 
-int R_BoxVisible(const vec3_t mins, const vec3_t maxs)
-{
-       int side, nodestackindex = 0;
-       mnode_t *node, *nodestack[1024];
-       if (R_CullBox(mins, maxs))
-               return false;
-       if (!r_refdef.worldmodel || !r_refdef.worldmodel->brush.data_nodes)
-               return true;
-       node = r_refdef.worldmodel->brush.data_nodes;
-       for (;;)
-       {
-               if (node->plane)
-               {
-                       // node - recurse down the BSP tree
-                       side = BoxOnPlaneSide(mins, maxs, node->plane) - 1;
-                       if (side < 2)
-                       {
-                               // box is on one side of plane, take that path
-                               node = node->children[side];
-                       }
-                       else
-                       {
-                               // box crosses plane, take one path and remember the other
-                               if (nodestackindex < 1024)
-                                       nodestack[nodestackindex++] = node->children[0];
-                               node = node->children[1];
-                       }
-               }
-               else
-               {
-                       // leaf - check leaf visibility
-                       if (r_worldleafvisible[(mleaf_t *)node - r_refdef.worldmodel->brush.data_leafs])
-                       {
-                               // it is visible, return immediately with the news
-                               return true;
-                       }
-                       else
-                       {
-                               // nothing to see here, try another path we didn't take earlier
-                               if (nodestackindex == 0)
-                                       break;
-                               node = nodestack[--nodestackindex];
-                       }
-               }
-       }
-       // it is not visible
-       return false;
-}
-
-
 //==================================================================================
 
 static void R_MarkEntities (void)
@@ -478,19 +546,42 @@ static void R_MarkEntities (void)
        if (!r_drawentities.integer)
                return;
 
+       r_refdef.worldentity->visframe = r_framecount;
        renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
-       for (i = 0;i < r_refdef.numentities;i++)
+       if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
        {
-               ent = r_refdef.entities[i];
-               Mod_CheckLoaded(ent->model);
-               // some of the renderer still relies on origin...
-               Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
-               // some of the renderer still relies on scale...
-               ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
-               if (!(ent->flags & renderimask) && ((ent->effects & EF_NODEPTHTEST) ? R_CullBox(ent->mins, ent->maxs) : R_BoxVisible(ent->mins, ent->maxs)))
+               // worldmodel can check visibility
+               for (i = 0;i < r_refdef.numentities;i++)
                {
-                       R_UpdateEntLights(ent);
-                       ent->visframe = r_framecount;
+                       ent = r_refdef.entities[i];
+                       Mod_CheckLoaded(ent->model);
+                       // some of the renderer still relies on origin...
+                       Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
+                       // some of the renderer still relies on scale...
+                       ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
+                       if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
+                       {
+                               R_UpdateEntLights(ent);
+                               ent->visframe = r_framecount;
+                       }
+               }
+       }
+       else
+       {
+               // no worldmodel or it can't check visibility
+               for (i = 0;i < r_refdef.numentities;i++)
+               {
+                       ent = r_refdef.entities[i];
+                       Mod_CheckLoaded(ent->model);
+                       // some of the renderer still relies on origin...
+                       Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
+                       // some of the renderer still relies on scale...
+                       ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
+                       if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
+                       {
+                               R_UpdateEntLights(ent);
+                               ent->visframe = r_framecount;
+                       }
                }
        }
 }
@@ -581,6 +672,7 @@ static void R_BlendView(void)
        GL_DepthMask(true);
        GL_DepthTest(false);
        R_Mesh_Matrix(&r_identitymatrix);
+       // vertex coordinates for a quad that covers the screen exactly
        varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
        varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
        varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
@@ -590,10 +682,22 @@ static void R_BlendView(void)
                int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
                float xoffset, yoffset, r;
                c_bloom++;
+               // set the (poorly named) screenwidth and screenheight variables to
+               // a power of 2 at least as large as the screen, these will define the
+               // size of the texture to allocate
                for (screenwidth = 1;screenwidth < vid.realwidth;screenwidth *= 2);
                for (screenheight = 1;screenheight < vid.realheight;screenheight *= 2);
+               // allocate textures as needed
+               if (!r_bloom_texture_screen)
+                       r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+               if (!r_bloom_texture_bloom)
+                       r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+               // set bloomwidth and bloomheight to the bloom resolution that will be
+               // used (often less than the screen resolution for faster rendering)
                bloomwidth = min(r_view_width, r_bloom_resolution.integer);
                bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
+               // set up a texcoord array for the full resolution screen image
+               // (we have to keep this around to copy back during final render)
                varray_texcoord2f[0][0] = 0;
                varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
                varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
@@ -602,6 +706,8 @@ static void R_BlendView(void)
                varray_texcoord2f[0][5] = 0;
                varray_texcoord2f[0][6] = 0;
                varray_texcoord2f[0][7] = 0;
+               // set up a texcoord array for the reduced resolution bloom image
+               // (which will be additive blended over the screen image)
                varray_texcoord2f[1][0] = 0;
                varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
                varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
@@ -610,36 +716,36 @@ static void R_BlendView(void)
                varray_texcoord2f[1][5] = 0;
                varray_texcoord2f[1][6] = 0;
                varray_texcoord2f[1][7] = 0;
-               if (!r_bloom_texture_screen)
-                       r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
-               if (!r_bloom_texture_bloom)
-                       r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
                memset(&m, 0, sizeof(m));
                m.pointer_vertex = varray_vertex3f;
                m.pointer_texcoord[0] = varray_texcoord2f[0];
                m.tex[0] = R_GetTexture(r_bloom_texture_screen);
                R_Mesh_State(&m);
-               // copy view to a texture
+               // copy view into the full resolution screen image texture
                GL_ActiveTexture(0);
                qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
                c_bloomcopies++;
                c_bloomcopypixels += r_view_width * r_view_height;
                // now scale it down to the bloom size and raise to a power of itself
-               qglViewport(r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
+               // to darken it (this leaves the really bright stuff bright, and
+               // everything else becomes very dark)
                // TODO: optimize with multitexture or GLSL
+               qglViewport(r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
                GL_BlendFunc(GL_ONE, GL_ZERO);
                GL_Color(1, 1, 1, 1);
-               R_Mesh_Draw(4, 2, polygonelements);
+               R_Mesh_Draw(0, 4, 2, polygonelements);
                c_bloomdraws++;
                c_bloomdrawpixels += bloomwidth * bloomheight;
+               // render multiple times with a multiply blendfunc to raise to a power
                GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
                for (x = 1;x < r_bloom_power.integer;x++)
                {
-                       R_Mesh_Draw(4, 2, polygonelements);
+                       R_Mesh_Draw(0, 4, 2, polygonelements);
                        c_bloomdraws++;
                        c_bloomdrawpixels += bloomwidth * bloomheight;
                }
-               // copy the bloom view to a texture
+               // we now have a darkened bloom image in the framebuffer, copy it into
+               // the bloom image texture for more processing
                memset(&m, 0, sizeof(m));
                m.pointer_vertex = varray_vertex3f;
                m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
@@ -649,7 +755,7 @@ static void R_BlendView(void)
                qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
                c_bloomcopies++;
                c_bloomcopypixels += bloomwidth * bloomheight;
-               // blend on at multiple offsets vertically
+               // blend on at multiple vertical offsets to achieve a vertical blur
                // TODO: do offset blends using GLSL
                range = r_bloom_blur.integer * bloomwidth / 320;
                GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -657,6 +763,7 @@ static void R_BlendView(void)
                {
                        xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
                        yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
+                       // compute a texcoord array with the specified x and y offset
                        varray_texcoord2f[2][0] = xoffset+0;
                        varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
                        varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
@@ -665,21 +772,25 @@ static void R_BlendView(void)
                        varray_texcoord2f[2][5] = yoffset+0;
                        varray_texcoord2f[2][6] = xoffset+0;
                        varray_texcoord2f[2][7] = yoffset+0;
-                       r = r_bloom_intensity.value/(range*2+1)*(1 - fabs(x*x)/(float)(range*range));
+                       // this r value looks like a 'dot' particle, fading sharply to
+                       // black at the edges
+                       // (probably not realistic but looks good enough)
+                       r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
                        if (r < 0.01f)
                                continue;
                        GL_Color(r, r, r, 1);
-                       R_Mesh_Draw(4, 2, polygonelements);
+                       R_Mesh_Draw(0, 4, 2, polygonelements);
                        c_bloomdraws++;
                        c_bloomdrawpixels += bloomwidth * bloomheight;
                        GL_BlendFunc(GL_ONE, GL_ONE);
                }
-               // copy the blurred bloom view to a texture
+               // copy the vertically blurred bloom view to a texture
                GL_ActiveTexture(0);
                qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
                c_bloomcopies++;
                c_bloomcopypixels += bloomwidth * bloomheight;
-               // blend on at multiple offsets horizontally
+               // blend the vertically blurred image at multiple offsets horizontally
+               // to finish the blur effect
                // TODO: do offset blends using GLSL
                range = r_bloom_blur.integer * bloomwidth / 320;
                GL_BlendFunc(GL_ONE, GL_ZERO);
@@ -687,6 +798,7 @@ static void R_BlendView(void)
                {
                        xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
                        yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
+                       // compute a texcoord array with the specified x and y offset
                        varray_texcoord2f[2][0] = xoffset+0;
                        varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
                        varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
@@ -695,11 +807,14 @@ static void R_BlendView(void)
                        varray_texcoord2f[2][5] = yoffset+0;
                        varray_texcoord2f[2][6] = xoffset+0;
                        varray_texcoord2f[2][7] = yoffset+0;
-                       r = r_bloom_intensity.value/(range*2+1)*(1 - fabs(x*x)/(float)(range*range));
+                       // this r value looks like a 'dot' particle, fading sharply to
+                       // black at the edges
+                       // (probably not realistic but looks good enough)
+                       r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
                        if (r < 0.01f)
                                continue;
                        GL_Color(r, r, r, 1);
-                       R_Mesh_Draw(4, 2, polygonelements);
+                       R_Mesh_Draw(0, 4, 2, polygonelements);
                        c_bloomdraws++;
                        c_bloomdrawpixels += bloomwidth * bloomheight;
                        GL_BlendFunc(GL_ONE, GL_ONE);
@@ -711,7 +826,8 @@ static void R_BlendView(void)
                c_bloomcopypixels += bloomwidth * bloomheight;
                // go back to full view area
                qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
-               // put the original view back in place
+               // put the original screen image back in place and blend the bloom
+               // texture on it
                memset(&m, 0, sizeof(m));
                m.pointer_vertex = varray_vertex3f;
                m.tex[0] = R_GetTexture(r_bloom_texture_screen);
@@ -733,7 +849,7 @@ static void R_BlendView(void)
                R_Mesh_State(&m);
                GL_BlendFunc(GL_ONE, GL_ZERO);
                GL_Color(1,1,1,1);
-               R_Mesh_Draw(4, 2, polygonelements);
+               R_Mesh_Draw(0, 4, 2, polygonelements);
                c_bloomdraws++;
                c_bloomdrawpixels += r_view_width * r_view_height;
                // now blend on the bloom texture if multipass
@@ -746,7 +862,7 @@ static void R_BlendView(void)
                        R_Mesh_State(&m);
                        GL_BlendFunc(GL_ONE, GL_ONE);
                        GL_Color(1,1,1,1);
-                       R_Mesh_Draw(4, 2, polygonelements);
+                       R_Mesh_Draw(0, 4, 2, polygonelements);
                        c_bloomdraws++;
                        c_bloomdrawpixels += r_view_width * r_view_height;
                }
@@ -759,7 +875,7 @@ static void R_BlendView(void)
                R_Mesh_State(&m);
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
-               R_Mesh_Draw(4, 2, polygonelements);
+               R_Mesh_Draw(0, 4, 2, polygonelements);
        }
 }
 
@@ -886,7 +1002,7 @@ void R_RenderScene(void)
                S_ExtraUpdate ();
 
        GL_ShowTrisColor(0, 0, 0.033, 1);
-       R_ShadowVolumeLighting(false);
+       R_ShadowVolumeLighting(false, false);
        R_TimeReport("rtlights");
 
        // don't let sound skip if going slow
@@ -916,9 +1032,9 @@ void R_RenderScene(void)
        R_MeshQueue_Render();
        R_MeshQueue_EndScene();
 
-       if (r_shadow_visiblevolumes.integer && !r_showtrispass)
+       if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
        {
-               R_ShadowVolumeLighting(true);
+               R_ShadowVolumeLighting(r_shadow_visiblelighting.integer, r_shadow_visiblevolumes.integer);
                R_TimeReport("shadowvolume");
        }
 
@@ -1054,7 +1170,7 @@ void R_DrawNoModelCallback(const void *calldata1, int calldata2)
        else
                m.pointer_color = nomodelcolor4f;
        R_Mesh_State(&m);
-       R_Mesh_Draw(6, 8, nomodelelements);
+       R_Mesh_Draw(0, 6, 8, nomodelelements);
 }
 
 void R_DrawNoModel(entity_render_t *ent)
@@ -1132,6 +1248,6 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depth
        m.pointer_vertex = varray_vertex3f;
        R_Mesh_State(&m);
        GL_Color(cr, cg, cb, ca);
-       R_Mesh_Draw(4, 2, polygonelements);
+       R_Mesh_Draw(0, 4, 2, polygonelements);
 }