]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
rename R_MAX_OCCLUSION_QUERIES to MAX_OCCLUSION_QUERIES and move it to
[xonotic/darkplaces.git] / r_shadow.c
index b0467c282f7f3935d9bb1e17b0b0c6fd97ef0b5a..559bad0de9cc6a2a9761e371f3466f23395cd072 100644 (file)
@@ -194,7 +194,7 @@ GLuint r_shadow_fbo2d;
 r_shadow_shadowmode_t r_shadow_shadowmode;
 int r_shadow_shadowmapfilterquality;
 int r_shadow_shadowmaptexturetype;
-int r_shadow_shadowmapprecision;
+int r_shadow_shadowmapdepthbits;
 int r_shadow_shadowmapmaxsize;
 qboolean r_shadow_shadowmapvsdct;
 qboolean r_shadow_shadowmapsampler;
@@ -243,7 +243,7 @@ rtexturepool_t *r_shadow_texturepool;
 rtexture_t *r_shadow_attenuationgradienttexture;
 rtexture_t *r_shadow_attenuation2dtexture;
 rtexture_t *r_shadow_attenuation3dtexture;
-rtexture_t *r_shadow_lightcorona;
+skinframe_t *r_shadow_lightcorona;
 rtexture_t *r_shadow_shadowmaprectangletexture;
 rtexture_t *r_shadow_shadowmap2dtexture;
 rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
@@ -260,6 +260,7 @@ rtexturepool_t *r_shadow_filters_texturepool;
 cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
 cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
+cvar_t r_shadow_dot3 = {CVAR_SAVE, "r_shadow_dot3", "0", "enables use of (slow) per pixel lighting on GL1.3 hardware"};
 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"};
@@ -289,13 +290,13 @@ cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization
 cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
 cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "-1", "shadowmap texture types: -1 = auto-select, 0 = 2D, 1 = rectangle, 2 = cubemap"};
 cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
-cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "24", "requested minimum shadowmap texture precision"};
+cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
 cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
 cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
 cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
-cvar_t r_shadow_shadowmapping_quality = {CVAR_SAVE, "r_shadow_shadowmapping_quality", "0", "Makes shadowmaps to have initial resolution of this number of pixels per light source radius unit. Like, light with radius 200 will have initial shadowmaps with resolution 200. This overrides default LOD-based shadowmaps resolution formula. Might be good in some situations but futher testing is required."};
-cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
-cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
+cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "1", "makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels"};
+//cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
+//cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
 cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
@@ -344,7 +345,6 @@ typedef struct cubemapinfo_s
 }
 cubemapinfo_t;
 
-#define MAX_CUBEMAPS 256
 static int numcubemaps;
 static cubemapinfo_t cubemaps[MAX_CUBEMAPS];
 
@@ -358,22 +358,22 @@ void R_Shadow_EditLights_Reload_f(void);
 void R_Shadow_ValidateCvars(void);
 static void R_Shadow_MakeTextures(void);
 
-// VorteX: custom editor light sprites
 #define EDLIGHTSPRSIZE                 8
-cachepic_t *r_editlights_sprcursor;
-cachepic_t *r_editlights_sprlight;
-cachepic_t *r_editlights_sprnoshadowlight;
-cachepic_t *r_editlights_sprcubemaplight;
-cachepic_t *r_editlights_sprcubemapnoshadowlight;
-cachepic_t *r_editlights_sprselection;
+skinframe_t *r_editlights_sprcursor;
+skinframe_t *r_editlights_sprlight;
+skinframe_t *r_editlights_sprnoshadowlight;
+skinframe_t *r_editlights_sprcubemaplight;
+skinframe_t *r_editlights_sprcubemapnoshadowlight;
+skinframe_t *r_editlights_sprselection;
+extern cvar_t gl_max_size;
 
 void R_Shadow_SetShadowMode(void)
 {
-       r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048);
+       r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, gl_max_size.integer / 4);
        r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0;
        r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
        r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer;
-       r_shadow_shadowmapprecision = r_shadow_shadowmapping_precision.integer;
+       r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
        r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
        r_shadow_shadowmaplod = -1;
        r_shadow_shadowmapsize = 0;
@@ -496,7 +496,7 @@ void r_shadow_start(void)
        r_shadow_shadowmaplod = 0;
        r_shadow_shadowmapfilterquality = -1;
        r_shadow_shadowmaptexturetype = -1;
-       r_shadow_shadowmapprecision = 0;
+       r_shadow_shadowmapdepthbits = 0;
        r_shadow_shadowmapvsdct = false;
        r_shadow_shadowmapsampler = false;
        r_shadow_shadowmappcf = 0;
@@ -617,6 +617,13 @@ void r_shadow_shutdown(void)
 
 void r_shadow_newmap(void)
 {
+       if (r_shadow_lightcorona)                 R_SkinFrame_MarkUsed(r_shadow_lightcorona);
+       if (r_editlights_sprcursor)               R_SkinFrame_MarkUsed(r_editlights_sprcursor);
+       if (r_editlights_sprlight)                R_SkinFrame_MarkUsed(r_editlights_sprlight);
+       if (r_editlights_sprnoshadowlight)        R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight);
+       if (r_editlights_sprcubemaplight)         R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight);
+       if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight);
+       if (r_editlights_sprselection)            R_SkinFrame_MarkUsed(r_editlights_sprselection);
        if (cl.worldmodel && strncmp(cl.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname)))
                R_Shadow_EditLights_Reload_f();
 }
@@ -660,6 +667,7 @@ void R_Shadow_Init(void)
 {
        Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
        Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
+       Cvar_RegisterVariable(&r_shadow_dot3);
        Cvar_RegisterVariable(&r_shadow_usenormalmap);
        Cvar_RegisterVariable(&r_shadow_debuglight);
        Cvar_RegisterVariable(&r_shadow_gloss);
@@ -691,12 +699,12 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
+       Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
-       Cvar_RegisterVariable(&r_shadow_shadowmapping_quality);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
-       Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
-       Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
+//     Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
+//     Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
        Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
@@ -1675,7 +1683,7 @@ static void R_Shadow_MakeTextures_MakeCorona(void)
                        pixels[y][x][3] = 255;
                }
        }
-       r_shadow_lightcorona = R_LoadTexture2D(r_shadow_texturepool, "lightcorona", 32, 32, &pixels[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR, NULL);
+       r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_PRECACHE | TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
 }
 
 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
@@ -1691,6 +1699,7 @@ static void R_Shadow_MakeTextures(void)
        int x, y, z;
        float intensity, dist;
        unsigned int *data;
+       R_Shadow_FreeShadowMaps();
        R_FreeTexturePool(&r_shadow_texturepool);
        r_shadow_texturepool = R_AllocTexturePool();
        r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
@@ -1728,12 +1737,114 @@ static void R_Shadow_MakeTextures(void)
        R_Shadow_MakeTextures_MakeCorona();
 
        // Editor light sprites
-       r_editlights_sprcursor = Draw_CachePic ("gfx/editlights/cursor");
-       r_editlights_sprlight = Draw_CachePic ("gfx/editlights/light");
-       r_editlights_sprnoshadowlight = Draw_CachePic ("gfx/editlights/noshadow");
-       r_editlights_sprcubemaplight = Draw_CachePic ("gfx/editlights/cubemaplight");
-       r_editlights_sprcubemapnoshadowlight = Draw_CachePic ("gfx/editlights/cubemapnoshadowlight");
-       r_editlights_sprselection = Draw_CachePic ("gfx/editlights/selection");
+       r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       "................"
+       ".3............3."
+       "..5...2332...5.."
+       "...7.3....3.7..."
+       "....7......7...."
+       "...3.7....7.3..."
+       "..2...7..7...2.."
+       "..3..........3.."
+       "..3..........3.."
+       "..2...7..7...2.."
+       "...3.7....7.3..."
+       "....7......7...."
+       "...7.3....3.7..."
+       "..5...2332...5.."
+       ".3............3."
+       "................"
+       , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+       r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       "................"
+       "................"
+       "......1111......"
+       "....11233211...."
+       "...1234554321..."
+       "...1356776531..."
+       "..124677776421.."
+       "..135777777531.."
+       "..135777777531.."
+       "..124677776421.."
+       "...1356776531..."
+       "...1234554321..."
+       "....11233211...."
+       "......1111......"
+       "................"
+       "................"
+       , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+       r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       "................"
+       "................"
+       "......1111......"
+       "....11233211...."
+       "...1234554321..."
+       "...1356226531..."
+       "..12462..26421.."
+       "..1352....2531.."
+       "..1352....2531.."
+       "..12462..26421.."
+       "...1356226531..."
+       "...1234554321..."
+       "....11233211...."
+       "......1111......"
+       "................"
+       "................"
+       , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+       r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       "................"
+       "................"
+       "......2772......"
+       "....27755772...."
+       "..277533335772.."
+       "..753333333357.."
+       "..777533335777.."
+       "..735775577537.."
+       "..733357753337.."
+       "..733337733337.."
+       "..753337733357.."
+       "..277537735772.."
+       "....27777772...."
+       "......2772......"
+       "................"
+       "................"
+       , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+       r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+       "................"
+       "................"
+       "......2772......"
+       "....27722772...."
+       "..2772....2772.."
+       "..72........27.."
+       "..7772....2777.."
+       "..7.27722772.7.."
+       "..7...2772...7.."
+       "..7....77....7.."
+       "..72...77...27.."
+       "..2772.77.2772.."
+       "....27777772...."
+       "......2772......"
+       "................"
+       "................"
+       , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+       r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
+       "................"
+       ".777752..257777."
+       ".742........247."
+       ".72..........27."
+       ".7............7."
+       ".5............5."
+       ".2............2."
+       "................"
+       "................"
+       ".2............2."
+       ".5............5."
+       ".7............7."
+       ".72..........27."
+       ".742........247."
+       ".777752..257777."
+       "................"
+       , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
 }
 
 void R_Shadow_ValidateCvars(void)
@@ -1791,7 +1902,7 @@ void R_Shadow_RenderMode_Begin(void)
 
        if (r_glsl.integer && gl_support_fragment_shader)
                r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
-       else if (gl_dot3arb && gl_texturecubemap && r_textureunits.integer >= 2 && gl_combine.integer && gl_stencil)
+       else if (gl_dot3arb && gl_texturecubemap && r_shadow_dot3.integer && gl_stencil)
                r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_DOT3;
        else
                r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
@@ -1960,7 +2071,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
                {
 #if 1
                        int w = maxsize*2, h = gl_support_arb_texture_non_power_of_two ? maxsize*3 : maxsize*4;
-                       r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
+                       r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
                        qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
                        qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
                        qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
@@ -1994,7 +2105,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
                if (!r_shadow_shadowmaprectangletexture)
                {
 #if 1
-                       r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
+                       r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
                        qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
                        qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
                        qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
@@ -2026,7 +2137,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
                if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
                {
  #if 1
-                       r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
+                       r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
                        qglGenFramebuffersEXT(1, &r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
                        qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
                        qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
@@ -2087,6 +2198,13 @@ init_done:
 
 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
 {
+       if (transparent)
+       {
+               r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
+               r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
+               r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
+               r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
+       }
        CHECKGLERROR
        R_Shadow_RenderMode_Reset();
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
@@ -2138,7 +2256,7 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb
        }
        else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_VERTEX)
                R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
-       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+       //GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        CHECKGLERROR
 }
 
@@ -2321,8 +2439,8 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
 
 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, int numtriangles, const int *element3i, const float *diffusecolor, const float *ambientcolor)
 {
-       float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
-       float *normal3f = rsurface.normal3f + 3 * firstvertex;
+       const float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
+       const float *normal3f = rsurface.normal3f + 3 * firstvertex;
        float *color4f = rsurface.array_color4f + 4 * firstvertex;
        float dist, dot, distintensity, shadeintensity, v[3], n[3];
        if (r_textureunits.integer >= 3)
@@ -2343,7 +2461,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                if (r_refdef.fogenabled)
                                {
                                        float f;
-                                       f = FogPoint_Model(vertex3f);
+                                       f = RSurf_FogVertex(vertex3f);
                                        VectorScale(color4f, f, color4f);
                                }
                                color4f[3] = 1;
@@ -2358,7 +2476,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                {
                                        float f;
                                        Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
-                                       f = FogPoint_Model(vertex3f);
+                                       f = RSurf_FogVertex(vertex3f);
                                        VectorScale(color4f, f, color4f);
                                }
                                color4f[3] = 1;
@@ -2391,7 +2509,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        if (r_refdef.fogenabled)
                                        {
                                                float f;
-                                               f = FogPoint_Model(vertex3f);
+                                               f = RSurf_FogVertex(vertex3f);
                                                VectorScale(color4f, f, color4f);
                                        }
                                }
@@ -2413,7 +2531,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        if (r_refdef.fogenabled)
                                        {
                                                float f;
-                                               f = FogPoint_Model(vertex3f);
+                                               f = RSurf_FogVertex(vertex3f);
                                                VectorScale(color4f, f, color4f);
                                        }
                                }
@@ -2450,7 +2568,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        if (r_refdef.fogenabled)
                                        {
                                                float f;
-                                               f = FogPoint_Model(vertex3f);
+                                               f = RSurf_FogVertex(vertex3f);
                                                VectorScale(color4f, f, color4f);
                                        }
                                }
@@ -2473,7 +2591,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        if (r_refdef.fogenabled)
                                        {
                                                float f;
-                                               f = FogPoint_Model(vertex3f);
+                                               f = RSurf_FogVertex(vertex3f);
                                                VectorScale(color4f, f, color4f);
                                        }
                                }
@@ -2519,7 +2637,7 @@ static void R_Shadow_GenTexCoords_Specular_NormalCubeMap(int firstvertex, int nu
        {
                VectorSubtract(rsurface.entitylightorigin, vertex3f, lightdir);
                VectorNormalize(lightdir);
-               VectorSubtract(rsurface.modelorg, vertex3f, eyedir);
+               VectorSubtract(rsurface.localvieworigin, vertex3f, eyedir);
                VectorNormalize(eyedir);
                VectorAdd(lightdir, eyedir, halfdir);
                // the cubemap normalizes this for us
@@ -3291,7 +3409,7 @@ static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertice
                m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
                if (r_textureunits.integer >= 3)
                {
-                       // Voodoo4 or Kyro (or Geforce3/Radeon with gl_combine off)
+                       // Voodoo4 or Kyro (or Geforce3/Radeon with r_shadow_dot3 off)
                        m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
                        m.texmatrix[2] = rsurface.entitytoattenuationz;
                        m.pointer_texcoord3f[2] = rsurface.vertex3f;
@@ -3318,6 +3436,7 @@ extern cvar_t gl_lightmaps;
 void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject)
 {
        float ambientscale, diffusescale, specularscale;
+       qboolean negated;
        vec3_t lightcolorbase, lightcolorpants, lightcolorshirt;
        rtexture_t *nmap;
        // calculate colors to render this texture with
@@ -3335,6 +3454,12 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle
        }
        if ((ambientscale + diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
                return;
+       negated = (lightcolorbase[0] + lightcolorbase[1] + lightcolorbase[2] < 0) && gl_support_ext_blend_subtract;
+       if(negated)
+       {
+               VectorNegate(lightcolorbase, lightcolorbase);
+               qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
+       }
        RSurf_SetupDepthAndCulling();
        nmap = rsurface.texture->currentskinframe->nmap;
        if (gl_lightmaps.integer)
@@ -3401,6 +3526,8 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle
                        break;
                }
        }
+       if(negated)
+               qglBlendEquationEXT(GL_FUNC_ADD_EXT);
 }
 
 void R_RTLight_Update(rtlight_t *rtlight, int isstatic, matrix4x4_t *matrix, vec3_t color, int style, const char *cubemapname, int shadow, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
@@ -4159,12 +4286,9 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
        nearestpoint[2] = bound(rtlight->cullmins[2], r_refdef.view.origin[2], rtlight->cullmaxs[2]);
        distance = VectorDistance(nearestpoint, r_refdef.view.origin);
 
-       // VorteX: loosy quality mode, might be good in some situations
-       if (r_shadow_shadowmapping_quality.value)
-               lodlinear = ( rtlight->radius * r_shadow_shadowmapping_quality.value ) / pow ( max(1.0f,(distance/rtlight->radius)), 0.5 );
-       else
-               lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
-       lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapping_maxsize.integer);
+       lodlinear = (rtlight->radius * r_shadow_shadowmapping_precision.value) / sqrt(max(1.0f, distance/rtlight->radius));
+       //lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
+       lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapmaxsize);
 
        if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE))
        {
@@ -4178,11 +4302,14 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
 
                r_shadow_shadowmaplod = 0;
                for (i = 1;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
-                       if ((r_shadow_shadowmapping_maxsize.integer >> i) > lodlinear)
+                       if ((r_shadow_shadowmapmaxsize >> i) > lodlinear)
                                r_shadow_shadowmaplod = i;
 
-               size = r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE ? r_shadow_shadowmapping_maxsize.integer >> r_shadow_shadowmaplod : lodlinear;
-               size = bound(1, size, 2048);
+               if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
+                       size = max(1, r_shadow_shadowmapmaxsize >> r_shadow_shadowmaplod);
+               else
+                       size = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize);
+                       
                borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
 
                if (numsurfaces)
@@ -4327,13 +4454,14 @@ void R_ShadowVolumeLighting(qboolean visible)
        size_t lightindex;
        dlight_t *light;
        size_t range;
+       float f;
 
-       if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) || 
+       if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, gl_max_size.integer / 4) ||
                (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer && r_glsl.integer && gl_support_fragment_shader && gl_support_ext_framebuffer_object) || 
                r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0) || 
                r_shadow_shadowmaptexturetype != r_shadow_shadowmapping_texturetype.integer ||
                r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer || 
-               r_shadow_shadowmapprecision != r_shadow_shadowmapping_precision.integer || 
+               r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer || 
                r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
                R_Shadow_FreeShadowMaps();
 
@@ -4361,8 +4489,19 @@ void R_ShadowVolumeLighting(qboolean visible)
                }
        }
        if (r_refdef.scene.rtdlight)
+       {
                for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
                        R_DrawRTLight(r_refdef.scene.lights[lnum], visible);
+       }
+       else if(gl_flashblend.integer)
+       {
+               for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
+               {
+                       rtlight_t *rtlight = r_refdef.scene.lights[lnum];
+                       f = (rtlight->style >= 0 ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
+                       VectorScale(rtlight->color, f, rtlight->currentcolor);
+               }
+       }
 
        R_Shadow_RenderMode_End();
 }
@@ -4488,7 +4627,7 @@ void R_DrawModelShadows(void)
        qglStencilFunc(GL_NOTEQUAL, 128, ~0);CHECKGLERROR
 
        // apply the blend to the shadowed areas
-       R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
+       R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
 
        // restore the viewport
        R_SetViewport(&r_refdef.view.viewport);
@@ -4501,8 +4640,9 @@ void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
 {
        float zdist;
        vec3_t centerorigin;
+       float vertex3f[12];
        // if it's too close, skip it
-       if (VectorLength(rtlight->color) < (1.0f / 256.0f))
+       if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
                return;
        zdist = (DotProduct(rtlight->shadoworigin, r_refdef.view.forward) - DotProduct(r_refdef.view.origin, r_refdef.view.forward));
        if (zdist < 32)
@@ -4511,23 +4651,30 @@ void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
        {
                rtlight->corona_queryindex_allpixels = r_queries[r_numqueries++];
                rtlight->corona_queryindex_visiblepixels = r_queries[r_numqueries++];
+               // we count potential samples in the middle of the screen, we count actual samples at the light location, this allows counting potential samples of off-screen lights
                VectorMA(r_refdef.view.origin, zdist, r_refdef.view.forward, centerorigin);
 
                CHECKGLERROR
-               // NOTE: we can't disable depth testing using R_DrawSprite's depthdisable argument, which calls GL_DepthTest, as that's broken in the ATI drivers
+               // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use qglDepthFunc instead
                qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
                qglDepthFunc(GL_ALWAYS);
-               R_DrawSprite(GL_ONE, GL_ZERO, r_shadow_lightcorona, NULL, false, false, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, 1, 1, 1, 1);
+               R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
+               R_Mesh_VertexPointer(vertex3f, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
                qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
                qglDepthFunc(GL_LEQUAL);
                qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
-               R_DrawSprite(GL_ONE, GL_ZERO, r_shadow_lightcorona, NULL, false, false, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, 1, 1, 1, 1);
+               R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
+               R_Mesh_VertexPointer(vertex3f, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
                qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
                CHECKGLERROR
        }
        rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
 }
 
+static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
+
 void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
 {
        vec3_t color;
@@ -4551,9 +4698,22 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
                        return;
        }
-       VectorScale(rtlight->color, cscale, color);
+       VectorScale(rtlight->currentcolor, cscale, color);
        if (VectorLength(color) > (1.0f / 256.0f))
-               R_DrawSprite(GL_ONE, GL_ONE, r_shadow_lightcorona, NULL, true, false, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, color[0], color[1], color[2], 1);
+       {
+               float vertex3f[12];
+               qboolean negated = (color[0] + color[1] + color[2] < 0) && gl_support_ext_blend_subtract;
+               if(negated)
+               {
+                       VectorNegate(color, color);
+                       qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
+               }
+               R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
+               RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, RENDER_NODEPTHTEST, 0, color[0], color[1], color[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
+               R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+               if(negated)
+                       qglBlendEquationEXT(GL_FUNC_ADD_EXT);
+       }
 }
 
 void R_DrawCoronas(void)
@@ -4582,15 +4742,25 @@ void R_DrawCoronas(void)
        {
                GL_ColorMask(0,0,0,0);
                if (r_maxqueries < (range + r_refdef.scene.numlights) * 2)
-               if (r_maxqueries < R_MAX_OCCLUSION_QUERIES)
+               if (r_maxqueries < MAX_OCCLUSION_QUERIES)
                {
                        i = r_maxqueries;
                        r_maxqueries = (range + r_refdef.scene.numlights) * 4;
-                       r_maxqueries = min(r_maxqueries, R_MAX_OCCLUSION_QUERIES);
+                       r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
                        CHECKGLERROR
                        qglGenQueriesARB(r_maxqueries - i, r_queries + i);
                        CHECKGLERROR
                }
+               RSurf_ActiveWorldEntity();
+               GL_BlendFunc(GL_ONE, GL_ZERO);
+               GL_CullFace(GL_NONE);
+               GL_DepthMask(false);
+               GL_DepthRange(0, 1);
+               GL_PolygonOffset(0, 0);
+               GL_DepthTest(true);
+               R_Mesh_ColorPointer(NULL, 0, 0);
+               R_Mesh_ResetTextureState();
+               R_SetupGenericShader(false);
        }
        for (lightindex = 0;lightindex < range;lightindex++)
        {
@@ -4805,9 +4975,14 @@ void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, ve
        light->angles[0] = angles[0] - 360 * floor(angles[0] / 360);
        light->angles[1] = angles[1] - 360 * floor(angles[1] / 360);
        light->angles[2] = angles[2] - 360 * floor(angles[2] / 360);
+       /*
        light->color[0] = max(color[0], 0);
        light->color[1] = max(color[1], 0);
        light->color[2] = max(color[2], 0);
+       */
+       light->color[0] = color[0];
+       light->color[1] = color[1];
+       light->color[2] = color[2];
        light->radius = max(radius, 0);
        light->style = style;
        light->shadow = shadowenable;
@@ -4859,7 +5034,10 @@ void R_Shadow_SelectLight(dlight_t *light)
 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)
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, r_editlights_sprcursor->tex, r_editlights_sprcursor->tex, false, false, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE, 1, 1, 1, 1);
+       float vertex3f[12];
+       R_CalcSprite_Vertex3f(vertex3f, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE);
+       RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
+       R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
 }
 
 void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
@@ -4867,12 +5045,16 @@ void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, co
        float intensity;
        float s;
        vec3_t spritecolor;
-       cachepic_t *pic;
+       skinframe_t *skinframe;
+       float vertex3f[12];
 
        // this is never batched (due to the ent parameter changing every time)
        // so numsurfaces == 1 and surfacelist[0] == lightnumber
        const dlight_t *light = (dlight_t *)ent;
        s = EDLIGHTSPRSIZE;
+
+       R_CalcSprite_Vertex3f(vertex3f, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s);
+
        intensity = 0.5f;
        VectorScale(light->color, intensity, spritecolor);
        if (VectorLength(spritecolor) < 0.1732f)
@@ -4882,18 +5064,24 @@ void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, co
 
        // draw light sprite
        if (light->cubemapname[0] && !light->shadow)
-               pic = r_editlights_sprcubemapnoshadowlight;
+               skinframe = r_editlights_sprcubemapnoshadowlight;
        else if (light->cubemapname[0])
-               pic = r_editlights_sprcubemaplight;
+               skinframe = r_editlights_sprcubemaplight;
        else if (!light->shadow)
-               pic = r_editlights_sprnoshadowlight;
+               skinframe = r_editlights_sprnoshadowlight;
        else
-               pic = r_editlights_sprlight;
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, pic->tex, pic->tex, false, false, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s, spritecolor[0], spritecolor[1], spritecolor[2], 1);
+               skinframe = r_editlights_sprlight;
+
+       RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, spritecolor[0], spritecolor[1], spritecolor[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
+       R_DrawCustomSurface(skinframe, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+
        // draw selection sprite if light is selected
        if (light->selected)
-               R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, r_editlights_sprselection->tex, r_editlights_sprselection->tex, false, false, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s, 1, 1, 1, 1);
-       // VorteX todo: add normalmode/realtime mode light overlay sprites?
+       {
+               RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
+               R_DrawCustomSurface(r_editlights_sprselection, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+               // VorteX todo: add normalmode/realtime mode light overlay sprites?
+       }
 }
 
 void R_Shadow_DrawLightSprites(void)