]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
laid groundwork for a new decal system
[xonotic/darkplaces.git] / r_shadow.c
index 82c9e9717212d45b930a68a71d3e5865c7530c03..03e064440070b3b1bf7f07ba36b8a08bb018a6f3 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"};
@@ -287,17 +288,20 @@ cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compi
 cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation"};
 cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
 cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "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", "0", "shadowmap texture types: 0 = auto-select, 1 = 2D, 2 = rectangle, 3 = cubemap"};
+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_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)"};
+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_culltriangles = {0, "r_shadow_culltriangles", "1", "performs more expensive tests to remove unnecessary triangles of lit surfaces"};
 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)"};
@@ -355,22 +359,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;
@@ -412,16 +416,15 @@ void R_Shadow_SetShadowMode(void)
                                break;
                        }
                }
-               r_shadow_shadowmode = r_shadow_shadowmaptexturetype;
         switch (r_shadow_shadowmaptexturetype)
         {
-        case 1:
+        case 0:
             r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
             break;
-        case 2:
+        case 1:
             r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
             break;
-        case 3:
+        case 2:
             r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE;
             break;
         default:
@@ -492,9 +495,9 @@ void r_shadow_start(void)
        r_shadow_shadowmapmaxsize = 0;
        r_shadow_shadowmapsize = 0;
        r_shadow_shadowmaplod = 0;
-       r_shadow_shadowmapfilterquality = 0;
-       r_shadow_shadowmaptexturetype = 0;
-       r_shadow_shadowmapprecision = 0;
+       r_shadow_shadowmapfilterquality = -1;
+       r_shadow_shadowmaptexturetype = -1;
+       r_shadow_shadowmapdepthbits = 0;
        r_shadow_shadowmapvsdct = false;
        r_shadow_shadowmapsampler = false;
        r_shadow_shadowmappcf = 0;
@@ -615,6 +618,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();
 }
@@ -658,6 +668,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);
@@ -689,14 +700,17 @@ 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_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);
+       Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
+       Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
        Cvar_RegisterVariable(&r_shadow_culltriangles);
        Cvar_RegisterVariable(&r_shadow_polygonfactor);
        Cvar_RegisterVariable(&r_shadow_polygonoffset);
@@ -1670,7 +1684,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)
@@ -1686,6 +1700,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;
@@ -1723,12 +1738,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)
@@ -1786,7 +1903,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;
@@ -1955,7 +2072,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
@@ -1989,7 +2106,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
@@ -2021,7 +2138,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
@@ -2055,7 +2172,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
                qglClearColor(1,1,1,1);CHECKGLERROR
        }
        CHECKGLERROR
-       GL_PolygonOffset(0, 0);
+       GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
        GL_DepthMask(true);
        GL_DepthTest(true);
        qglClearDepth(1);
@@ -2082,6 +2199,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);
@@ -2133,7 +2257,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
 }
 
@@ -2316,8 +2440,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)
@@ -2338,7 +2462,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;
@@ -2353,7 +2477,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;
@@ -2386,7 +2510,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);
                                        }
                                }
@@ -2408,7 +2532,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);
                                        }
                                }
@@ -2445,7 +2569,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);
                                        }
                                }
@@ -2468,7 +2592,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);
                                        }
                                }
@@ -2514,7 +2638,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
@@ -3286,7 +3410,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;
@@ -3313,6 +3437,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
@@ -3330,6 +3455,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)
@@ -3396,6 +3527,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)
@@ -4153,8 +4286,10 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
        nearestpoint[1] = bound(rtlight->cullmins[1], r_refdef.view.origin[1], rtlight->cullmaxs[1]);
        nearestpoint[2] = bound(rtlight->cullmins[2], r_refdef.view.origin[2], rtlight->cullmaxs[2]);
        distance = VectorDistance(nearestpoint, r_refdef.view.origin);
-       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))
        {
@@ -4168,11 +4303,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)
@@ -4317,13 +4455,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();
 
@@ -4351,8 +4490,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();
 }
@@ -4478,7 +4628,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);
@@ -4491,8 +4641,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)
@@ -4501,23 +4652,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;
@@ -4541,9 +4699,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)
@@ -4581,6 +4752,16 @@ void R_DrawCoronas(void)
                        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++)
        {
@@ -4795,9 +4976,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;
@@ -4849,7 +5035,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)
@@ -4857,12 +5046,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)
@@ -4872,18 +5065,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)