]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
cleaned up rtlight handling, merging most code between world rtlights and dlights...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 1 Mar 2004 01:58:02 +0000 (01:58 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 1 Mar 2004 01:58:02 +0000 (01:58 +0000)
moved R_ShadowVolumeLighting to r_shadow.c
added RENDER_LIGHT flag to entity_render_t to make rtlighting optional per entity

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3939 d7cf8633-e32d-0410-b094-e92efae38249

14 files changed:
cl_main.c
cl_parse.c
client.h
gl_models.c
gl_rmain.c
gl_rsurf.c
model_shared.h
protocol.h
r_light.c
r_light.h
r_shadow.c
r_shadow.h
render.h
todo

index e45180f064f2edc27f33344c7ce7df265e5b808a..768397e165bfc01a6ed467ab138595305469c161 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -832,6 +832,8 @@ void CL_LinkNetworkEntity(entity_t *e)
                 && !(e->render.flags & RENDER_VIEWMODEL)
                 && ((e - cl_entities) != cl.viewentity || (!cl.intermission && cl.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer)))
                        e->render.flags |= RENDER_SHADOW;
+               if (!(e->render.effects & EF_FULLBRIGHT))
+                       e->render.flags |= RENDER_LIGHT;
                // as soon as player is known we can call V_CalcRefDef
                if ((e - cl_entities) == cl.viewentity)
                        V_CalcRefdef();
index 0a1d5ede033f538d6a83be4da115899354b382cd..04879f66683ade300075c51dc379663a24879f20 100644 (file)
@@ -447,9 +447,9 @@ void CL_ParseServerInfo (void)
        // entire entity array was cleared, so just fill in a few fields
        ent->state_current.active = true;
        ent->render.model = cl.worldmodel = cl.model_precache[1];
-       //ent->render.scale = 1;
+       ent->render.scale = 1; // some of the renderer still relies on scale
        ent->render.alpha = 1;
-       ent->render.flags = RENDER_SHADOW;
+       ent->render.flags = RENDER_SHADOW | RENDER_LIGHT;
        Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
        Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
        CL_BoundingBoxForEntity(&ent->render);
index b8d6c2790c20ea26ed08aa93a0de09fdac1ccb8a..2e8349e1c7626e56dc5f08aee8bdb49e146909c7 100644 (file)
--- a/client.h
+++ b/client.h
@@ -70,30 +70,120 @@ typedef struct
 }
 beam_t;
 
-typedef struct
+typedef struct rtlight_s
 {
-       // location
-       vec3_t  origin;
-       // stop lighting after this time
-       vec_t   die;
-       // color of light
-       vec3_t  color;
-       // brightness (not really radius anymore)
-       vec_t   radius;
-       // drop this each second
-       vec_t   decay;
+       // shadow volumes are done entirely in model space, so there are no matrices for dealing with them...  they just use the origin 
+
+       // note that the world to light matrices are inversely scaled (divided) by lightradius
+
+       // core properties
+       // matrix for transforming world coordinates to light filter coordinates
+       matrix4x4_t matrix_worldtolight;
+       // based on worldtolight this transforms -1 to +1 to 0 to 1 for purposes
+       // of attenuation texturing in full 3D (Z result often ignored)
+       matrix4x4_t matrix_worldtoattenuationxyz;
+       // this transforms only the Z to S, and T is always 0.5
+       matrix4x4_t matrix_worldtoattenuationz;
+       // typically 1 1 1, can be lower (dim) or higher (overbright)
+       vec3_t color;
+       // size of the light (remove?)
+       vec_t radius;
+       // light filter
+       char cubemapname[64];
+       // whether light should render shadows
+       int shadow;
+       // intensity of corona to render
+       vec_t corona;
+       // light style to monitor for brightness
+       int style;
+       
+       // generated properties
+       // used only for shadow volumes
+       vec3_t shadoworigin;
+       // culling
+       vec3_t cullmins;
+       vec3_t cullmaxs;
+       // culling
+       vec_t cullradius;
+       // squared cullradius
+       vec_t cullradius2;
+
+       // lightmap renderer stuff (remove someday!)
+       // the size of the light
+       vec_t lightmap_cullradius;
+       // the size of the light, squared
+       vec_t lightmap_cullradius2;
+       // the brightness of the light
+       vec3_t lightmap_light;
+       // to avoid sudden brightness change at cullradius, subtract this
+       vec_t lightmap_subtract;
+
+       // static light info
+       // true if this light should be compiled as a static light
+       int isstatic;
+       // true if this is a compiled world light, cleared if the light changes
+       int compiled;
+       // premade shadow volumes and lit surfaces to render for world entity
+       shadowmesh_t *static_meshchain_shadow;
+       shadowmesh_t *static_meshchain_light;
+       // used for visibility testing (more exact than bbox)
+       int static_numclusters;
+       int *static_clusterindices;
+}
+rtlight_t;
+
+typedef struct dlight_s
+{
+       // destroy light after this time
+       // (dlight only)
+       vec_t die;
        // the entity that owns this light (can be NULL)
+       // (dlight only)
        struct entity_render_s *ent;
-       // orientation/scaling/location
+       // location
+       // (worldlight: saved to .rtlights file)
+       vec3_t origin;
+       // worldlight orientation
+       // (worldlight only)
+       // (worldlight: saved to .rtlights file)
+       vec3_t angles;
+       // dlight orientation/scaling/location
+       // (dlight only)
        matrix4x4_t matrix;
+       // color of light
+       // (worldlight: saved to .rtlights file)
+       vec3_t color;
        // cubemap number to use on this light
+       // (dlight only)
        int cubemapnum;
+       // cubemap name to use on this light
+       // (worldlight only)
+       // (worldlight: saved to .rtlights file)
+       char cubemapname[64];
+       // make light flash while selected
+       // (worldlight only)
+       int selected;
+       // brightness (not really radius anymore)
+       // (worldlight: saved to .rtlights file)
+       vec_t radius;
+       // drop radius this much each second
+       // (dlight only)
+       vec_t decay;
        // light style which controls intensity of this light
+       // (worldlight: saved to .rtlights file)
        int style;
        // cast shadows
+       // (worldlight: saved to .rtlights file)
        int shadow;
        // corona intensity
+       // (worldlight: saved to .rtlights file)
        vec_t corona;
+       // linked list of world lights
+       // (worldlight only)
+       struct dlight_s *next;
+       // embedded rtlight struct for renderer
+       // (renderer only)      
+       rtlight_t rtlight;
 }
 dlight_t;
 
index 8757229ba9fe52c46e9e9de6eb1691b979a3bada..ca8bdb7de8e09e92583935de7e6dfdfa01252322 100644 (file)
@@ -378,7 +378,7 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
                        if (layer->flags & ALIASLAYER_SPECULAR)
                        {
                                c_alias_polys += mesh->num_triangles;
-                               R_Shadow_SpecularLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor2, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, lightcubemap);
+                               R_Shadow_SpecularLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, relativeeyeorigin, lightcolor2, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, lightcubemap);
                        }
                        else if (layer->flags & ALIASLAYER_DIFFUSE)
                        {
@@ -407,7 +407,7 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
                                        lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
                                }
                                c_alias_polys += mesh->num_triangles;
-                               R_Shadow_DiffuseLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, lightradius, lightcolor2, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, lightcubemap);
+                               R_Shadow_DiffuseLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, lightcolor2, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, lightcubemap);
                        }
                }
        }
index 8e5ae27ca0f9e5eb4662139fbd47260873fc87f3..9053656307293c482e111eff32811ddd1c77cab1 100644 (file)
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // r_main.c
 
 #include "quakedef.h"
+#include "r_shadow.h"
 
 // used for dlight push checking and other things
 int r_framecount;
@@ -55,13 +56,11 @@ unsigned short d_lightstylevalue[256];
 
 cvar_t r_drawentities = {0, "r_drawentities","1"};
 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
-cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
 cvar_t r_speeds = {0, "r_speeds","0"};
 cvar_t r_fullbright = {0, "r_fullbright","0"};
 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
-cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
 
 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
@@ -249,14 +248,12 @@ void GL_Main_Init(void)
        Cmd_AddCommand("timerefresh", R_TimeRefresh_f);
        Cvar_RegisterVariable(&r_drawentities);
        Cvar_RegisterVariable(&r_drawviewmodel);
-       Cvar_RegisterVariable(&r_shadow_staticworldlights);
        Cvar_RegisterVariable(&r_speeds);
        Cvar_RegisterVariable(&r_fullbrights);
        Cvar_RegisterVariable(&r_wateralpha);
        Cvar_RegisterVariable(&r_dynamic);
        Cvar_RegisterVariable(&r_fullbright);
        Cvar_RegisterVariable(&r_textureunits);
-       Cvar_RegisterVariable(&r_shadow_cull);
        Cvar_RegisterVariable(&r_lerpsprites);
        Cvar_RegisterVariable(&r_lerpmodels);
        Cvar_RegisterVariable(&r_waterscroll);
@@ -407,8 +404,6 @@ int R_CullBox(const vec3_t mins, const vec3_t maxs)
        return false;
 }
 
-#define VIS_CullBox(mins,maxs) (R_CullBox((mins), (maxs)) || (cl.worldmodel && cl.worldmodel->brush.BoxTouchingPVS && !cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, r_pvsbits, (mins), (maxs))))
-
 //==================================================================================
 
 static void R_MarkEntities (void)
@@ -508,224 +503,6 @@ void R_DrawModels(void)
        }
 }
 
-#include "r_shadow.h"
-
-int shadowframecount = 0;
-
-void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float cullradius, float lightradius, vec3_t lightmins, vec3_t lightmaxs, vec3_t clipmins, vec3_t clipmaxs, int lightmarked)
-{
-       vec3_t relativelightorigin;
-       // rough checks
-       if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawShadowVolume && !(r_shadow_cull.integer && (ent->maxs[0] < lightmins[0] || ent->mins[0] > lightmaxs[0] || ent->maxs[1] < lightmins[1] || ent->mins[1] > lightmaxs[1] || ent->maxs[2] < lightmins[2] || ent->mins[2] > lightmaxs[2])))
-       {
-               Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
-               ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
-       }
-}
-
-void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
-
-void R_ShadowVolumeLighting(int visiblevolumes)
-{
-       int i;
-       entity_render_t *ent;
-       int lnum;
-       float f, lightradius, cullradius;
-       vec3_t relativelightorigin, relativeeyeorigin, lightcolor, clipmins, clipmaxs;
-       worldlight_t *wl;
-       rdlight_t *rd;
-       rmeshstate_t m;
-       rtexture_t *cubemaptexture;
-       matrix4x4_t matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
-
-       if (visiblevolumes)
-       {
-               memset(&m, 0, sizeof(m));
-               R_Mesh_State_Texture(&m);
-
-               GL_BlendFunc(GL_ONE, GL_ONE);
-               GL_DepthMask(false);
-               GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
-               qglDisable(GL_CULL_FACE);
-               GL_Color(0.0, 0.0125, 0.1, 1);
-       }
-       else
-               R_Shadow_Stage_Begin();
-       shadowframecount++;
-       if (r_shadow_realtime_world.integer)
-       {
-               R_Shadow_LoadWorldLightsIfNeeded();
-               for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
-               {
-                       if (d_lightstylevalue[wl->style] <= 0)
-                               continue;
-                       if (R_CullBox(wl->mins, wl->maxs))
-                               continue;
-                       for (i = 0;i < wl->numclusters;i++)
-                               if (CHECKPVSBIT(r_pvsbits, wl->clusterindices[i]))
-                                       break;
-                       if (i == wl->numclusters)
-                               continue;
-                       if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
-                               continue;
-                       if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
-                               continue;
-
-                       cullradius = wl->cullradius;
-                       lightradius = wl->radius;
-                       VectorCopy(wl->mins, clipmins);
-                       VectorCopy(wl->maxs, clipmaxs);
-
-                       f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
-                       VectorScale(wl->color, f, lightcolor);
-                       if (wl->selected)
-                       {
-                               f = 2 + sin(realtime * M_PI * 4.0);
-                               VectorScale(lightcolor, f, lightcolor);
-                       }
-
-                       if (r_shadow_worldshadows.integer && wl->drawshadows && (gl_stencil || visiblevolumes))
-                       {
-                               if (!visiblevolumes)
-                                       R_Shadow_Stage_ShadowVolumes();
-                               ent = &cl_entities[0].render;
-                               if (r_shadow_staticworldlights.integer)
-                                       R_Shadow_DrawStaticWorldLight_Shadow(wl, &ent->matrix);
-                               else
-                                       R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
-                               if (r_drawentities.integer)
-                                       for (i = 0;i < r_refdef.numentities;i++)
-                                               R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
-                       }
-
-                       if (!visiblevolumes)
-                       {
-                               if (r_shadow_worldshadows.integer && wl->drawshadows && gl_stencil)
-                                       R_Shadow_Stage_LightWithShadows();
-                               else
-                                       R_Shadow_Stage_LightWithoutShadows();
-
-                               ent = &cl_entities[0].render;
-                               if (ent->model && ent->model->DrawLight)
-                               {
-                                       Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
-                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
-                                       Matrix4x4_Concat(&matrix_modeltolight, &wl->matrix_worldtolight, &ent->matrix);
-                                       Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &wl->matrix_worldtoattenuationxyz, &ent->matrix);
-                                       Matrix4x4_Concat(&matrix_modeltoattenuationz, &wl->matrix_worldtoattenuationz, &ent->matrix);
-                                       if (r_shadow_staticworldlights.integer)
-                                               R_Shadow_DrawStaticWorldLight_Light(wl, &ent->matrix, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
-                                       else
-                                               ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
-                               }
-                               if (r_drawentities.integer)
-                               {
-                                       for (i = 0;i < r_refdef.numentities;i++)
-                                       {
-                                               ent = r_refdef.entities[i];
-                                               if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
-                                                && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
-                                                && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
-                                               {
-                                                       Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
-                                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
-                                                       Matrix4x4_Concat(&matrix_modeltolight, &wl->matrix_worldtolight, &ent->matrix);
-                                                       Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &wl->matrix_worldtoattenuationxyz, &ent->matrix);
-                                                       Matrix4x4_Concat(&matrix_modeltoattenuationz, &wl->matrix_worldtoattenuationz, &ent->matrix);
-                                                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, wl->cubemap);
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
-       {
-               for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
-               {
-                       lightradius = rd->radius;
-                       clipmins[0] = rd->origin[0] - lightradius;
-                       clipmins[1] = rd->origin[1] - lightradius;
-                       clipmins[2] = rd->origin[2] - lightradius;
-                       clipmaxs[0] = rd->origin[0] + lightradius;
-                       clipmaxs[1] = rd->origin[1] + lightradius;
-                       clipmaxs[2] = rd->origin[2] + lightradius;
-                       if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
-                               continue;
-
-                       cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
-                       VectorCopy(rd->color, lightcolor);
-
-                       if (rd->cubemapnum > 0)
-                               cubemaptexture = R_Shadow_Cubemap(va("cubemaps/%i", rd->cubemapnum));
-                       else
-                               cubemaptexture = NULL;
-
-                       if (r_shadow_dlightshadows.integer && rd->shadow && (gl_stencil || visiblevolumes))
-                       {
-                               if (!visiblevolumes)
-                                       R_Shadow_Stage_ShadowVolumes();
-                               ent = &cl_entities[0].render;
-                               R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
-                               if (r_drawentities.integer)
-                               {
-                                       for (i = 0;i < r_refdef.numentities;i++)
-                                       {
-                                               ent = r_refdef.entities[i];
-                                               if (ent != rd->ent)
-                                                       R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
-                                       }
-                               }
-                       }
-
-                       if (!visiblevolumes)
-                       {
-                               if (r_shadow_dlightshadows.integer && gl_stencil && rd->shadow)
-                                       R_Shadow_Stage_LightWithShadows();
-                               else
-                                       R_Shadow_Stage_LightWithoutShadows();
-
-                               ent = &cl_entities[0].render;
-                               if (ent->model && ent->model->DrawLight)
-                               {
-                                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
-                                       Matrix4x4_Concat(&matrix_modeltolight, &rd->matrix_worldtolight, &ent->matrix);
-                                       Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rd->matrix_worldtoattenuationxyz, &ent->matrix);
-                                       Matrix4x4_Concat(&matrix_modeltoattenuationz, &rd->matrix_worldtoattenuationz, &ent->matrix);
-                                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
-                               }
-                               if (r_drawentities.integer)
-                               {
-                                       for (i = 0;i < r_refdef.numentities;i++)
-                                       {
-                                               ent = r_refdef.entities[i];
-                                               if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
-                                                && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
-                                                && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
-                                               {
-                                                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
-                                                       Matrix4x4_Concat(&matrix_modeltolight, &rd->matrix_worldtolight, &ent->matrix);
-                                                       Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rd->matrix_worldtoattenuationxyz, &ent->matrix);
-                                                       Matrix4x4_Concat(&matrix_modeltoattenuationz, &rd->matrix_worldtoattenuationz, &ent->matrix);
-                                                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       if (visiblevolumes)
-       {
-               qglEnable(GL_CULL_FACE);
-               GL_Scissor(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
-       }
-       else
-               R_Shadow_Stage_End();
-}
-
 static void R_SetFrustum(void)
 {
        // break apart the viewentity matrix into vectors for various purposes
index 2ff692572f12d8714a2824c57d382979167680e1..8b0fd081cadf4f4fee84c2d19cb9e745d12ccd58 100644 (file)
@@ -46,6 +46,7 @@ static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
        int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract, k;
        unsigned int *bl;
        float dist, impact[3], local[3];
+       dlight_t *light;
 
        lit = false;
 
@@ -53,17 +54,17 @@ static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
        tmax = (surf->extents[1] >> 4) + 1;
        smax3 = smax * 3;
 
-       for (lnum = 0; lnum < r_numdlights; lnum++)
+       for (lnum = 0, light = r_dlight;lnum < r_numdlights;lnum++, light++)
        {
                if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
                        continue;                                       // not lit by this light
 
-               Matrix4x4_Transform(matrix, r_dlight[lnum].origin, local);
+               Matrix4x4_Transform(matrix, light->origin, local);
                dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
 
                // for comparisons to minimum acceptable light
                // compensate for LIGHTOFFSET
-               maxdist = (int) r_dlight[lnum].cullradius2 + LIGHTOFFSET;
+               maxdist = (int) light->rtlight.lightmap_cullradius2 + LIGHTOFFSET;
 
                dist2 = dist * dist;
                dist2 += LIGHTOFFSET;
@@ -98,10 +99,10 @@ static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
                maxdist3 = maxdist - dist2;
 
                // convert to 8.8 blocklights format
-               red = r_dlight[lnum].light[0] * (1.0f / 128.0f);
-               green = r_dlight[lnum].light[1] * (1.0f / 128.0f);
-               blue = r_dlight[lnum].light[2] * (1.0f / 128.0f);
-               subtract = (int) (r_dlight[lnum].subtract * 4194304.0f);
+               red = light->rtlight.lightmap_light[0] * (1.0f / 128.0f);
+               green = light->rtlight.lightmap_light[1] * (1.0f / 128.0f);
+               blue = light->rtlight.lightmap_light[2] * (1.0f / 128.0f);
+               subtract = (int) (light->rtlight.lightmap_subtract * 4194304.0f);
                bl = intblocklights;
 
                i = impactt;
@@ -139,6 +140,7 @@ static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
 {
        int lnum, s, t, smax, tmax, smax3, lit, impacts, impactt;
        float sdtable[256], *bl, k, dist, dist2, maxdist, maxdist2, maxdist3, td1, td, red, green, blue, impact[3], local[3], subtract;
+       dlight_t *light;
 
        lit = false;
 
@@ -146,17 +148,17 @@ static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
        tmax = (surf->extents[1] >> 4) + 1;
        smax3 = smax * 3;
 
-       for (lnum = 0; lnum < r_numdlights; lnum++)
+       for (lnum = 0, light = r_dlight;lnum < r_numdlights;lnum++, light++)
        {
                if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
                        continue;                                       // not lit by this light
 
-               Matrix4x4_Transform(matrix, r_dlight[lnum].origin, local);
+               Matrix4x4_Transform(matrix, light->origin, local);
                dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
 
                // for comparisons to minimum acceptable light
                // compensate for LIGHTOFFSET
-               maxdist = (int) r_dlight[lnum].cullradius2 + LIGHTOFFSET;
+               maxdist = (int) light->rtlight.lightmap_cullradius2 + LIGHTOFFSET;
 
                dist2 = dist * dist;
                dist2 += LIGHTOFFSET;
@@ -191,10 +193,10 @@ static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
                maxdist3 = maxdist - dist2;
 
                // convert to 8.8 blocklights format
-               red = r_dlight[lnum].light[0];
-               green = r_dlight[lnum].light[1];
-               blue = r_dlight[lnum].light[2];
-               subtract = r_dlight[lnum].subtract * 32768.0f;
+               red = light->rtlight.lightmap_light[0];
+               green = light->rtlight.lightmap_light[1];
+               blue = light->rtlight.lightmap_light[2];
+               subtract = light->rtlight.lightmap_subtract * 32768.0f;
                bl = floatblocklights;
 
                td1 = impactt;
@@ -684,21 +686,21 @@ static int RSurf_LightSeparate_Vertex3f_Color4f(const matrix4x4_t *matrix, const
        const float *v;
        float *c;
        int i, l, lit = false;
-       const rdlight_t *rd;
+       const dlight_t *light;
        vec3_t lightorigin;
        for (l = 0;l < r_numdlights;l++)
        {
                if (dlightbits[l >> 5] & (1 << (l & 31)))
                {
-                       rd = &r_dlight[l];
-                       Matrix4x4_Transform(matrix, rd->origin, lightorigin);
+                       light = &r_dlight[l];
+                       Matrix4x4_Transform(matrix, light->origin, lightorigin);
                        for (i = 0, v = vert, c = color;i < numverts;i++, v += 3, c += 4)
                        {
                                f = VectorDistance2(v, lightorigin) + LIGHTOFFSET;
-                               if (f < rd->cullradius2)
+                               if (f < light->rtlight.lightmap_cullradius2)
                                {
-                                       f = ((1.0f / f) - rd->subtract) * scale;
-                                       VectorMA(c, f, rd->light, c);
+                                       f = ((1.0f / f) - light->rtlight.lightmap_subtract) * scale;
+                                       VectorMA(c, f, light->rtlight.lightmap_light, c);
                                        lit = true;
                                }
                        }
@@ -1877,8 +1879,8 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
                                t = surf->texinfo->texture->currentframe;
                                if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
                                {
-                                       R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, lightcubemap);
-                                       R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, lightcubemap);
+                                       R_Shadow_DiffuseLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, lightcubemap);
+                                       R_Shadow_SpecularLighting(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_element3i, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.gloss, t->skin.nmap, lightcubemap);
                                }
                        }
                }
@@ -2397,8 +2399,8 @@ void R_Q3BSP_DrawFaceLight(entity_render_t *ent, q3mface_t *face, vec3_t relativ
 {
        if ((face->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) || !face->num_triangles)
                return;
-       R_Shadow_DiffuseLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.base, face->texture->skin.nmap, lightcubemap);
-       R_Shadow_SpecularLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.gloss, face->texture->skin.nmap, lightcubemap);
+       R_Shadow_DiffuseLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.base, face->texture->skin.nmap, lightcubemap);
+       R_Shadow_SpecularLighting(face->num_vertices, face->num_triangles, face->data_element3i, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, face->texture->skin.gloss, face->texture->skin.nmap, lightcubemap);
 }
 
 void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap)
index 86339635a98bb74e9fa1a843f867ff7c82518257..1cd9d5ba80d0667e73ff0bb2ca4b7a539a4cd2dd 100644 (file)
@@ -47,15 +47,16 @@ animscene_t;
 
 typedef struct skinframe_s
 {
+       rtexture_t *stain; // inverse modulate with background (used for decals and such)
+       rtexture_t *merged; // original texture without glow
        rtexture_t *base; // original texture without pants/shirt/glow
        rtexture_t *pants; // pants only (in greyscale)
        rtexture_t *shirt; // shirt only (in greyscale)
-       rtexture_t *glow; // glow only (fullbrights)
-       rtexture_t *merged; // original texture without glow
-       rtexture_t *fog; // alpha of the base texture (if not opaque)
        rtexture_t *nmap; // normalmap (bumpmap for dot3)
        rtexture_t *gloss; // glossmap (for dot3)
        rtexture_t *detail; // detail texture (silly bumps for non-dot3)
+       rtexture_t *glow; // glow only (fullbrights)
+       rtexture_t *fog; // alpha of the base texture (if not opaque)
 }
 skinframe_t;
 
index b57e4e6e25191677740bf7abc1c17e29b71514e5..4d140b450b23c9c83d6c88e84a533faba2989cbe 100644 (file)
@@ -307,6 +307,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define RENDER_LOWPRECISION 16 // send as low precision coordinates to save bandwidth
 #define RENDER_COLORMAPPED 32
 #define RENDER_SHADOW 64 // cast shadow
+#define RENDER_LIGHT 128 // receive light
 
 typedef struct
 {
index b3ec3a5106b9659113db760a43d7ee140f869f87..aafbbf19ceab78314225d63601d4ff6c1c39e9b9 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "cl_collision.h"
 #include "r_shadow.h"
 
-rdlight_t r_dlight[MAX_DLIGHTS];
+dlight_t r_dlight[MAX_DLIGHTS];
 int r_numdlights = 0;
 
 cvar_t r_modellights = {CVAR_SAVE, "r_modellights", "4"};
@@ -87,8 +87,6 @@ R_UpdateLights
 void R_UpdateLights(void)
 {
        int i, j, k;
-       dlight_t *cd;
-       rdlight_t *rd;
 
 // light animations
 // 'm' is normal light, 'a' is no light, 'z' is double bright
@@ -114,36 +112,13 @@ void R_UpdateLights(void)
 
        for (i = 0;i < MAX_DLIGHTS;i++)
        {
-               cd = cl_dlights + i;
-               if (cd->radius <= 0)
-                       continue;
-               rd = &r_dlight[r_numdlights++];
-               VectorCopy(cd->origin, rd->origin);
-               VectorScale(cd->color, d_lightstylevalue[cd->style] * (1.0f / 256.0f), rd->color);
-               rd->radius = bound(0, cd->radius, 2048.0f);
-               VectorScale(rd->color, rd->radius * 64.0f, rd->light);
-#if 0
-               rd->cullradius2 = DotProduct(rd->light, rd->light) * (0.25f / (64.0f * 64.0f)) + 4096.0f;
-               // clamp radius to avoid overflowing division table in lightmap code
-               rd->cullradius2 = bound(0, rd->cullradius2, 2048.0f*2048.0f);
-               rd->cullradius = sqrt(rd->cullradius2);
-#else
-               rd->cullradius = rd->radius;
-               rd->cullradius2 = rd->cullradius * rd->cullradius;
-#endif
-               rd->subtract = 1.0f / rd->cullradius2;
-               rd->ent = cd->ent;
-               rd->cubemapnum = cd->cubemapnum;
-               rd->shadow = cd->shadow;
-               rd->corona = cd->corona;
-
-               rd->matrix_lighttoworld = cd->matrix;
-               Matrix4x4_ConcatScale(&rd->matrix_lighttoworld, rd->cullradius);
-               Matrix4x4_Invert_Simple(&rd->matrix_worldtolight, &rd->matrix_lighttoworld);
-               Matrix4x4_Concat(&rd->matrix_worldtoattenuationxyz, &matrix_attenuationxyz, &rd->matrix_worldtolight);
-               Matrix4x4_Concat(&rd->matrix_worldtoattenuationz, &matrix_attenuationz, &rd->matrix_worldtolight);
-
-               c_dlights++; // count every dlight in use
+               if (cl_dlights[i].radius > 0)
+               {
+                       R_RTLight_UpdateFromDLight(&cl_dlights[i].rtlight, &cl_dlights[i], false);
+                       // FIXME: use pointer instead of copy
+                       r_dlight[r_numdlights++] = cl_dlights[i];
+                       c_dlights++; // count every dlight in use
+               }
        }
 }
 
@@ -151,37 +126,35 @@ void R_DrawCoronas(void)
 {
        int i, lnum;
        float cscale, scale, viewdist, dist;
-       rdlight_t *rd;
-       worldlight_t *wl;
+       dlight_t *light;
        if (!r_coronas.integer)
                return;
        R_Mesh_Matrix(&r_identitymatrix);
        viewdist = DotProduct(r_vieworigin, r_viewforward);
        if (r_shadow_realtime_world.integer)
        {
-               for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
+               for (lnum = 0, light = r_shadow_worldlightchain;light;light = light->next, lnum++)
                {
-                       if (wl->corona * r_coronas.value > 0 && (r_shadow_debuglight.integer < 0 || r_shadow_debuglight.integer == lnum) && (dist = (DotProduct(wl->origin, r_viewforward) - viewdist)) >= 24.0f && CL_TraceLine(wl->origin, r_vieworigin, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1)
+                       if (light->rtlight.corona * r_coronas.value > 0 && (r_shadow_debuglight.integer < 0 || r_shadow_debuglight.integer == lnum) && (dist = (DotProduct(light->rtlight.shadoworigin, r_viewforward) - viewdist)) >= 24.0f && CL_TraceLine(light->rtlight.shadoworigin, r_vieworigin, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1)
                        {
-                               cscale = wl->corona * r_coronas.value * 0.25f;
-                               scale = wl->radius * 0.25f;
-                               R_DrawSprite(GL_ONE, GL_ONE, lightcorona, true, wl->origin, r_viewright, r_viewup, scale, -scale, -scale, scale, wl->color[0] * cscale, wl->color[1] * cscale, wl->color[2] * cscale, 1);
+                               cscale = light->rtlight.corona * r_coronas.value * 0.25f;
+                               scale = light->rtlight.radius * 0.25f;
+                               R_DrawSprite(GL_ONE, GL_ONE, lightcorona, true, light->rtlight.shadoworigin, r_viewright, r_viewup, scale, -scale, -scale, scale, light->rtlight.color[0] * cscale, light->rtlight.color[1] * cscale, light->rtlight.color[2] * cscale, 1);
                        }
                }
        }
-       for (i = 0;i < r_numdlights;i++)
+       for (i = 0, light = r_dlight;i < r_numdlights;i++, light++)
        {
-               rd = r_dlight + i;
-               if (rd->corona * r_coronas.value > 0 && (dist = (DotProduct(rd->origin, r_viewforward) - viewdist)) >= 24.0f && CL_TraceLine(rd->origin, r_vieworigin, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1)
+               if (light->corona * r_coronas.value > 0 && (dist = (DotProduct(light->origin, r_viewforward) - viewdist)) >= 24.0f && CL_TraceLine(light->origin, r_vieworigin, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1)
                {
-                       cscale = rd->corona * r_coronas.value * 0.25f;
-                       scale = rd->radius * 0.25f;
+                       cscale = light->corona * r_coronas.value * 0.25f;
+                       scale = light->radius * 0.25f;
                        if (gl_flashblend.integer)
                        {
                                cscale *= 4.0f;
                                scale *= 2.0f;
                        }
-                       R_DrawSprite(GL_ONE, GL_ONE, lightcorona, true, rd->origin, r_viewright, r_viewup, scale, -scale, -scale, scale, rd->color[0] * cscale, rd->color[1] * cscale, rd->color[2] * cscale, 1);
+                       R_DrawSprite(GL_ONE, GL_ONE, lightcorona, true, light->origin, r_viewright, r_viewup, scale, -scale, -scale, scale, light->color[0] * cscale, light->color[1] * cscale, light->color[2] * cscale, 1);
                }
        }
 }
@@ -202,7 +175,7 @@ static qbyte lightpvs[(MAX_MAP_LEAFS+7)>>3];
 R_MarkLights
 =============
 */
-static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node, qbyte *pvs, int pvsbits)
+static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, dlight_t *light, int bit, int bitindex, mnode_t *node, qbyte *pvs, int pvsbits)
 {
        int i;
        mleaf_t *leaf;
@@ -212,12 +185,12 @@ static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, rdli
        while(node->contents >= 0)
        {
                dist = PlaneDiff(lightorigin, node->plane);
-               if (dist > rd->cullradius)
+               if (dist > light->rtlight.lightmap_cullradius)
                        node = node->children[0];
                else
                {
-                       if (dist >= -rd->cullradius)
-                               R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, node->children[0], pvs, pvsbits);
+                       if (dist >= -light->rtlight.lightmap_cullradius)
+                               R_RecursiveMarkLights(ent, lightorigin, light, bit, bitindex, node->children[0], pvs, pvsbits);
                        node = node->children[1];
                }
        }
@@ -231,7 +204,7 @@ static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, rdli
                float sdist, maxdist, dist2, impact[3];
                msurface_t *surf;
                // mark the polygons
-               maxdist = rd->cullradius2;
+               maxdist = light->rtlight.lightmap_cullradius2;
                surfacepvsframes = ent->model->brushq1.surfacepvsframes;
                for (i = 0;i < leaf->nummarksurfaces;i++)
                {
@@ -283,19 +256,19 @@ static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, rdli
 void R_MarkLights(entity_render_t *ent)
 {
        int i, bit, bitindex;
-       rdlight_t *rd;
+       dlight_t *light;
        vec3_t lightorigin;
        if (!gl_flashblend.integer && r_dynamic.integer && ent->model && ent->model->brushq1.num_leafs)
        {
-               for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
+               for (i = 0, light = r_dlight;i < r_numdlights;i++, light++)
                {
                        bit = 1 << (i & 31);
                        bitindex = i >> 5;
-                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, lightorigin);
+                       Matrix4x4_Transform(&ent->inversematrix, light->origin, lightorigin);
                        lightpvsbytes = 0;
                        if (r_vismarklights.integer && ent->model->brush.FatPVS)
                                lightpvsbytes = ent->model->brush.FatPVS(ent->model, lightorigin, 0, lightpvs, sizeof(lightpvs));
-                       R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brush.num_pvsclusters));
+                       R_RecursiveMarkLights(ent, lightorigin, light, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brush.num_pvsclusters));
                }
        }
 }
@@ -348,17 +321,17 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu
        {
                int i;
                float f, v[3];
-               rdlight_t *rd;
+               dlight_t *light;
                // FIXME: this really should handle dlights as diffusecolor/diffusenormal somehow
                for (i = 0;i < r_numdlights;i++)
                {
-                       rd = r_dlight + i;
-                       VectorSubtract(p, rd->origin, v);
+                       light = r_dlight + i;
+                       VectorSubtract(p, light->origin, v);
                        f = DotProduct(v, v);
-                       if (f < rd->cullradius2 && CL_TraceLine(p, rd->origin, NULL, NULL, false, NULL, SUPERCONTENTS_SOLID) == 1)
+                       if (f < light->rtlight.lightmap_cullradius2 && CL_TraceLine(p, light->origin, NULL, NULL, false, NULL, SUPERCONTENTS_SOLID) == 1)
                        {
-                               f = (1.0f / (f + LIGHTOFFSET)) - rd->subtract;
-                               VectorMA(ambientcolor, f, rd->light, ambientcolor);
+                               f = (1.0f / (f + LIGHTOFFSET)) - light->rtlight.lightmap_subtract;
+                               VectorMA(ambientcolor, f, light->rtlight.lightmap_light, ambientcolor);
                        }
                }
        }
@@ -388,7 +361,7 @@ int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, co
        float v[3], f, mscale, stylescale, intensity, ambientcolor[3], tempdiffusenormal[3];
        nearlight_t *nl;
        mlight_t *sl;
-       rdlight_t *rd;
+       dlight_t *light;
 
        nearlights = 0;
        maxnearlights = r_modellights.integer;
@@ -474,19 +447,19 @@ int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, co
        {
                for (i = 0;i < r_numdlights;i++)
                {
-                       rd = r_dlight + i;
-                       VectorCopy(rd->origin, v);
+                       light = r_dlight + i;
+                       VectorCopy(light->origin, v);
                        if (v[0] < ent->mins[0]) v[0] = ent->mins[0];if (v[0] > ent->maxs[0]) v[0] = ent->maxs[0];
                        if (v[1] < ent->mins[1]) v[1] = ent->mins[1];if (v[1] > ent->maxs[1]) v[1] = ent->maxs[1];
                        if (v[2] < ent->mins[2]) v[2] = ent->mins[2];if (v[2] > ent->maxs[2]) v[2] = ent->maxs[2];
-                       VectorSubtract (v, rd->origin, v);
-                       if (DotProduct(v, v) < rd->cullradius2)
+                       VectorSubtract (v, light->origin, v);
+                       if (DotProduct(v, v) < light->rtlight.lightmap_cullradius2)
                        {
-                               if (CL_TraceLine(ent->origin, rd->origin, NULL, NULL, false, NULL, SUPERCONTENTS_SOLID) != 1)
+                               if (CL_TraceLine(ent->origin, light->origin, NULL, NULL, false, NULL, SUPERCONTENTS_SOLID) != 1)
                                        continue;
-                               VectorSubtract (ent->origin, rd->origin, v);
-                               f = ((1.0f / (DotProduct(v, v) + LIGHTOFFSET)) - rd->subtract);
-                               VectorScale(rd->light, f, ambientcolor);
+                               VectorSubtract (ent->origin, light->origin, v);
+                               f = ((1.0f / (DotProduct(v, v) + LIGHTOFFSET)) - light->rtlight.lightmap_subtract);
+                               VectorScale(light->rtlight.lightmap_light, f, ambientcolor);
                                intensity = DotProduct(ambientcolor, ambientcolor);
                                if (f < 0)
                                        intensity *= -1.0f;
@@ -517,14 +490,14 @@ int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, co
                                        nl->intensity = intensity;
                                        // transform the light into the model's coordinate system
                                        if (worldcoords)
-                                               VectorCopy(rd->origin, nl->origin);
+                                               VectorCopy(light->origin, nl->origin);
                                        else
                                        {
-                                               Matrix4x4_Transform(&ent->inversematrix, rd->origin, nl->origin);
+                                               Matrix4x4_Transform(&ent->inversematrix, light->origin, nl->origin);
                                                /*
                                                Con_Printf("%i %s : %f %f %f : %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n"
                                                , rd - r_dlight, ent->model->name
-                                               , rd->origin[0], rd->origin[1], rd->origin[2]
+                                               , light->origin[0], light->origin[1], light->origin[2]
                                                , nl->origin[0], nl->origin[1], nl->origin[2]
                                                , ent->inversematrix.m[0][0], ent->inversematrix.m[0][1], ent->inversematrix.m[0][2], ent->inversematrix.m[0][3]
                                                , ent->inversematrix.m[1][0], ent->inversematrix.m[1][1], ent->inversematrix.m[1][2], ent->inversematrix.m[1][3]
@@ -535,10 +508,10 @@ int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, co
                                        // integrate mscale into falloff, for maximum speed
                                        nl->falloff = mscale;
                                        VectorCopy(ambientcolor, nl->ambientlight);
-                                       nl->light[0] = rd->light[0] * colorr * 4.0f;
-                                       nl->light[1] = rd->light[1] * colorg * 4.0f;
-                                       nl->light[2] = rd->light[2] * colorb * 4.0f;
-                                       nl->subtract = rd->subtract;
+                                       nl->light[0] = light->rtlight.lightmap_light[0] * colorr * 4.0f;
+                                       nl->light[1] = light->rtlight.lightmap_light[1] * colorg * 4.0f;
+                                       nl->light[2] = light->rtlight.lightmap_light[2] * colorb * 4.0f;
+                                       nl->subtract = light->rtlight.lightmap_subtract;
                                        nl->offset = LIGHTOFFSET;
                                }
                        }
index 5c7c116b74148adef7e245dcec516b07bcf4836b..5190e00105eaf3e528edb29be5f45278aec48891 100644 (file)
--- a/r_light.h
+++ b/r_light.h
@@ -2,30 +2,8 @@
 #ifndef R_LIGHT_H
 #define R_LIGHT_H
 
-typedef struct
-{
-       vec3_t origin;
-       vec_t cullradius2; // only for culling comparisons, squared version
-       vec3_t light; // the brightness of the light
-       vec_t cullradius; // only for culling comparisons
-       vec_t subtract; // to avoid sudden brightness change at cullradius, subtract this
-       entity_render_t *ent; // owner of this light
-
-       matrix4x4_t matrix_lighttoworld;
-       matrix4x4_t matrix_worldtolight;
-       matrix4x4_t matrix_worldtoattenuationxyz;
-       matrix4x4_t matrix_worldtoattenuationz;
-
-       vec3_t color;
-       vec_t radius;
-       int cubemapnum;
-       int shadow;
-       vec_t corona;
-}
-rdlight_t;
-
 extern int r_numdlights;
-extern rdlight_t r_dlight[MAX_DLIGHTS];
+extern dlight_t r_dlight[MAX_DLIGHTS];
 
 void R_UpdateLights(void);
 void R_MarkLights(entity_render_t *ent);
index 8c083ece236e4fa1b9bfdd4671bd5ac62cf8f45f..5883fb8e5b1fdc5cc7e06d755875263c74e88b06 100644 (file)
@@ -174,6 +174,8 @@ cvar_t r_shadow_singlepassvolumegeneration = {0, "r_shadow_singlepassvolumegener
 cvar_t r_shadow_worldshadows = {0, "r_shadow_worldshadows", "1"};
 cvar_t r_shadow_dlightshadows = {CVAR_SAVE, "r_shadow_dlightshadows", "1"};
 cvar_t r_shadow_showtris = {0, "r_shadow_showtris", "0"};
+cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
+cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
 
 int c_rt_lights, c_rt_clears, c_rt_scissored;
 int c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris;
@@ -297,6 +299,8 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_worldshadows);
        Cvar_RegisterVariable(&r_shadow_dlightshadows);
        Cvar_RegisterVariable(&r_shadow_showtris);
+       Cvar_RegisterVariable(&r_shadow_staticworldlights);
+       Cvar_RegisterVariable(&r_shadow_cull);
        if (gamemode == GAME_TENEBRAE)
        {
                Cvar_SetValue("r_shadow_gloss", 2);
@@ -1285,7 +1289,7 @@ void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out3f, int numverts, co
        }
 }
 
-void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *elements, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *texcoord2f, const float *relativelightorigin, float lightradius, const float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *basetexture, rtexture_t *bumptexture, rtexture_t *lightcubemap)
+void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *elements, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *texcoord2f, const float *relativelightorigin, const float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *basetexture, rtexture_t *bumptexture, rtexture_t *lightcubemap)
 {
        int renders;
        float color[3], color2[3];
@@ -1574,7 +1578,7 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element
        }
 }
 
-void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elements, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *texcoord2f, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap)
+void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elements, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *texcoord2f, const float *relativelightorigin, const float *relativeeyeorigin, const float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap)
 {
        int renders;
        float color[3], color2[3], colorscale;
@@ -1786,264 +1790,70 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen
        }
 }
 
-void R_Shadow_DrawStaticWorldLight_Shadow(worldlight_t *light, matrix4x4_t *matrix)
-{
-       R_Mesh_Matrix(matrix);
-       if (r_shadow_showtris.integer)
-       {
-               shadowmesh_t *mesh;
-               rmeshstate_t m;
-               int depthenabled = qglIsEnabled(GL_DEPTH_TEST);
-               int stencilenabled = qglIsEnabled(GL_STENCIL_TEST);
-               qglDisable(GL_DEPTH_TEST);
-               qglDisable(GL_STENCIL_TEST);
-               //qglDisable(GL_CULL_FACE);
-               qglColorMask(1,1,1,1);
-               memset(&m, 0, sizeof(m));
-               R_Mesh_State_Texture(&m);
-               GL_Color(0,0.1,0,1);
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               for (mesh = light->meshchain_shadow;mesh;mesh = mesh->next)
-               {
-                       GL_VertexPointer(mesh->vertex3f);
-                       R_Mesh_Draw_ShowTris(mesh->numverts, mesh->numtriangles, mesh->element3i);
-               }
-               //qglEnable(GL_CULL_FACE);
-               if (depthenabled)
-                       qglEnable(GL_DEPTH_TEST);
-               if (stencilenabled)
-               {
-                       qglEnable(GL_STENCIL_TEST);
-                       qglColorMask(0,0,0,0);
-               }
-       }
-       R_Shadow_RenderShadowMeshVolume(light->meshchain_shadow);
-}
-
-void R_Shadow_DrawStaticWorldLight_Light(worldlight_t *light, matrix4x4_t *matrix, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz)
-{
-       shadowmesh_t *mesh;
-       R_Mesh_Matrix(matrix);
-       if (r_shadow_showtris.integer)
-       {
-               rmeshstate_t m;
-               int depthenabled = qglIsEnabled(GL_DEPTH_TEST);
-               int stencilenabled = qglIsEnabled(GL_STENCIL_TEST);
-               qglDisable(GL_DEPTH_TEST);
-               qglDisable(GL_STENCIL_TEST);
-               //qglDisable(GL_CULL_FACE);
-               memset(&m, 0, sizeof(m));
-               R_Mesh_State_Texture(&m);
-               GL_Color(0.2,0,0,1);
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               for (mesh = light->meshchain_light;mesh;mesh = mesh->next)
-               {
-                       GL_VertexPointer(mesh->vertex3f);
-                       R_Mesh_Draw_ShowTris(mesh->numverts, mesh->numtriangles, mesh->element3i);
-               }
-               //qglEnable(GL_CULL_FACE);
-               if (depthenabled)
-                       qglEnable(GL_DEPTH_TEST);
-               if (stencilenabled)
-                       qglEnable(GL_STENCIL_TEST);
-       }
-       for (mesh = light->meshchain_light;mesh;mesh = mesh->next)
-       {
-               R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, mesh->map_diffuse, mesh->map_normal, light->cubemap);
-               R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, mesh->map_specular, mesh->map_normal, light->cubemap);
-       }
-}
-
-cvar_t r_editlights = {0, "r_editlights", "0"};
-cvar_t r_editlights_cursordistance = {0, "r_editlights_distance", "1024"};
-cvar_t r_editlights_cursorpushback = {0, "r_editlights_pushback", "0"};
-cvar_t r_editlights_cursorpushoff = {0, "r_editlights_pushoff", "4"};
-cvar_t r_editlights_cursorgrid = {0, "r_editlights_grid", "4"};
-cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "0.8"};
-cvar_t r_editlights_rtlightssizescale = {CVAR_SAVE, "r_editlights_rtlightssizescale", "0.7"};
-cvar_t r_editlights_rtlightscolorscale = {CVAR_SAVE, "r_editlights_rtlightscolorscale", "2"};
-worldlight_t *r_shadow_worldlightchain;
-worldlight_t *r_shadow_selectedlight;
-vec3_t r_editlights_cursorlocation;
-
-static int lightpvsbytes;
-static qbyte lightpvs[(MAX_MAP_LEAFS + 7)/ 8];
-static qbyte lightfullpvs[(MAX_MAP_LEAFS + 7)/ 8];
-
-typedef struct cubemapinfo_s
-{
-       char basename[64];
-       rtexture_t *texture;
-}
-cubemapinfo_t;
-
-#define MAX_CUBEMAPS 128
-static int numcubemaps;
-static cubemapinfo_t cubemaps[MAX_CUBEMAPS];
-
-//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
-typedef struct suffixinfo_s
-{
-       char *suffix;
-       int flipx, flipy, flipdiagonal;
-}
-suffixinfo_t;
-static suffixinfo_t suffix[3][6] =
-{
-       {
-               {"posx", false, false, false},
-               {"negx", false, false, false},
-               {"posy", false, false, false},
-               {"negy", false, false, false},
-               {"posz", false, false, false},
-               {"negz", false, false, false}
-       },
-       {
-               {"px", false, false, false},
-               {"nx", false, false, false},
-               {"py", false, false, false},
-               {"ny", false, false, false},
-               {"pz", false, false, false},
-               {"nz", false, false, false}
-       },
-       {
-               {"ft", true, false, true},
-               {"bk", false, true, true},
-               {"lf", true, true, false},
-               {"rt", false, false, false},
-               {"up", false, false, false},
-               {"dn", false, false, false}
-       }
-};
-
-static int componentorder[4] = {0, 1, 2, 3};
-
-rtexture_t *R_Shadow_LoadCubemap(const char *basename)
-{
-       int i, j, cubemapsize;
-       qbyte *cubemappixels, *image_rgba;
-       rtexture_t *cubemaptexture;
-       char name[256];
-       // must start 0 so the first loadimagepixels has no requested width/height
-       cubemapsize = 0;
-       cubemappixels = NULL;
-       cubemaptexture = NULL;
-       for (j = 0;j < 3 && !cubemappixels;j++)
-       {
-               for (i = 0;i < 6;i++)
-               {
-                       snprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
-                       if ((image_rgba = loadimagepixels(name, false, cubemapsize, cubemapsize)))
-                       {
-                               if (image_width == image_height)
-                               {
-                                       if (!cubemappixels && image_width >= 1)
-                                       {
-                                               cubemapsize = image_width;
-                                               // note this clears to black, so unavailable sizes are black
-                                               cubemappixels = Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
-                                       }
-                                       if (cubemappixels)
-                                               Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_rgba, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
-                               }
-                               else
-                                       Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
-                               Mem_Free(image_rgba);
-                       }
-               }
-       }
-       if (cubemappixels)
-       {
-               if (!r_shadow_filters_texturepool)
-                       r_shadow_filters_texturepool = R_AllocTexturePool();
-               cubemaptexture = R_LoadTextureCubeMap(r_shadow_filters_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
-               Mem_Free(cubemappixels);
-       }
-       else
-       {
-               Con_Printf("Failed to load Cubemap \"%s\", tried ", basename);
-               for (j = 0;j < 3;j++)
-                       for (i = 0;i < 6;i++)
-                               Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
-               Con_Printf(" and was unable to find any of them.\n");
-       }
-       return cubemaptexture;
-}
-
-rtexture_t *R_Shadow_Cubemap(const char *basename)
-{
-       int i;
-       for (i = 0;i < numcubemaps;i++)
-               if (!strcasecmp(cubemaps[i].basename, basename))
-                       return cubemaps[i].texture;
-       if (i >= MAX_CUBEMAPS)
-               return NULL;
-       numcubemaps++;
-       strcpy(cubemaps[i].basename, basename);
-       cubemaps[i].texture = R_Shadow_LoadCubemap(cubemaps[i].basename);
-       return cubemaps[i].texture;
-}
-
-void R_Shadow_FreeCubemaps(void)
-{
-       numcubemaps = 0;
-       R_FreeTexturePool(&r_shadow_filters_texturepool);
+void R_RTLight_UpdateFromDLight(rtlight_t *rtlight, const dlight_t *light, int isstatic)
+{
+       int j, k;
+       float scale;
+       R_RTLight_Uncompile(rtlight);
+       memset(rtlight, 0, sizeof(*rtlight));
+
+       VectorCopy(light->origin, rtlight->shadoworigin);
+       VectorCopy(light->color, rtlight->color);
+       rtlight->radius = light->radius;
+       rtlight->cullradius = rtlight->radius;
+       rtlight->cullradius2 = rtlight->cullradius * rtlight->cullradius;
+       rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->cullradius;
+       rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->cullradius;
+       rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->cullradius;
+       rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->cullradius;
+       rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->cullradius;
+       rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->cullradius;
+       rtlight->cubemapname[0] = 0;
+       if (light->cubemapname[0])
+               strcpy(rtlight->cubemapname, light->cubemapname);
+       else if (light->cubemapnum > 0)
+               sprintf(rtlight->cubemapname, "cubemaps/%i", light->cubemapnum);
+       rtlight->shadow = light->shadow;
+       rtlight->corona = light->corona;
+       rtlight->style = light->style;
+       rtlight->isstatic = isstatic;
+       Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &light->matrix);
+       // ConcatScale won't work here because this needs to scale rotate and
+       // translate, not just rotate
+       scale = 1.0f / rtlight->radius;
+       for (k = 0;k < 3;k++)
+               for (j = 0;j < 4;j++)
+                       rtlight->matrix_worldtolight.m[k][j] *= scale;
+       Matrix4x4_Concat(&rtlight->matrix_worldtoattenuationxyz, &matrix_attenuationxyz, &rtlight->matrix_worldtolight);
+       Matrix4x4_Concat(&rtlight->matrix_worldtoattenuationz, &matrix_attenuationz, &rtlight->matrix_worldtolight);
+
+       rtlight->lightmap_cullradius = bound(0, rtlight->radius, 2048.0f);
+       rtlight->lightmap_cullradius2 = rtlight->lightmap_cullradius * rtlight->lightmap_cullradius;
+       VectorScale(rtlight->color, rtlight->radius * d_lightstylevalue[rtlight->style] * 0.25f, rtlight->lightmap_light);
+       rtlight->lightmap_subtract = 1.0f / rtlight->lightmap_cullradius2;
 }
 
-void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname)
+// compiles rtlight geometry
+// (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
+void R_RTLight_Compile(rtlight_t *rtlight)
 {
        int i, j, k, l, maxverts = 256, tris;
        float *vertex3f = NULL, mins[3], maxs[3];
-       worldlight_t *e;
        shadowmesh_t *mesh, *castmesh = NULL;
-
-       if (radius < 15 || DotProduct(color, color) < 0.03)
-       {
-               Con_Printf("R_Shadow_NewWorldLight: refusing to create a light too small/dim\n");
-               return;
-       }
-
-       e = Mem_Alloc(r_shadow_mempool, sizeof(worldlight_t));
-       VectorCopy(origin, e->origin);
-       VectorCopy(angles, e->angles);
-       VectorCopy(color, e->color);
-       e->radius = radius;
-       e->style = style;
-       if (e->style < 0 || e->style >= MAX_LIGHTSTYLES)
-       {
-               Con_Printf("R_Shadow_NewWorldLight: invalid light style number %i, must be >= 0 and < %i\n", e->style, MAX_LIGHTSTYLES);
-               e->style = 0;
-       }
-       e->drawshadows = shadowenable;
-       e->corona = corona;
-
-       Matrix4x4_CreateFromQuakeEntity(&e->matrix_lighttoworld, e->origin[0], e->origin[1], e->origin[2], e->angles[0], e->angles[1], e->angles[2], e->radius);
-       Matrix4x4_Invert_Simple(&e->matrix_worldtolight, &e->matrix_lighttoworld);
-       Matrix4x4_Concat(&e->matrix_worldtoattenuationxyz, &matrix_attenuationxyz, &e->matrix_worldtolight);
-       Matrix4x4_Concat(&e->matrix_worldtoattenuationz, &matrix_attenuationz, &e->matrix_worldtolight);
-
-       e->cullradius = e->radius;
-       for (k = 0;k < 3;k++)
-       {
-               mins[k] = e->origin[k] - e->radius;
-               maxs[k] = e->origin[k] + e->radius;
-       }
-
-       e->next = r_shadow_worldlightchain;
-       r_shadow_worldlightchain = e;
-       if (cubemapname && cubemapname[0])
-       {
-               e->cubemapname = Mem_Alloc(r_shadow_mempool, strlen(cubemapname) + 1);
-               strcpy(e->cubemapname, cubemapname);
-               e->cubemap = R_Shadow_Cubemap(e->cubemapname);
-       }
-       // FIXME: rewrite this to store ALL geometry into a cache in the light
-       if (e->drawshadows)
+       int lightpvsbytes;
+       qbyte lightpvs[(MAX_MAP_LEAFS + 7)/ 8];
+       qbyte lightfullpvs[(MAX_MAP_LEAFS + 7)/ 8];
+
+       // compile the light
+       rtlight->compiled = true;
+       VectorCopy(rtlight->cullmins, mins);
+       VectorCopy(rtlight->cullmaxs, maxs);
+       if (rtlight->shadow)
                castmesh = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768, 32768, NULL, NULL, NULL, false, false, true);
-       e->meshchain_light = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768, 32768, NULL, NULL, NULL, true, false, true);
+       rtlight->static_meshchain_light = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768, 32768, NULL, NULL, NULL, true, false, true);
        if (cl.worldmodel)
        {
-               lightpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, origin, 0, lightfullpvs, sizeof(lightfullpvs));
+               lightpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, rtlight->shadoworigin, 0, lightfullpvs, sizeof(lightfullpvs));
                memset(lightpvs, 0, lightpvsbytes);
                if (cl.worldmodel->brushq3.num_leafs)
                {
@@ -2056,16 +1866,16 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                        SETPVSBIT(lightpvs, leaf->clusterindex);
 
                        // make a cluster list for fast visibility checking during rendering
-                       for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
+                       for (i = 0, rtlight->static_numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                if (CHECKPVSBIT(lightpvs, i))
-                                       e->numclusters++;
-                       e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
-                       for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
+                                       rtlight->static_numclusters++;
+                       rtlight->static_clusterindices = Mem_Alloc(r_shadow_mempool, rtlight->static_numclusters * sizeof(int));
+                       for (i = 0, rtlight->static_numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                if (CHECKPVSBIT(lightpvs, i))
-                                       e->clusterindices[e->numclusters++] = i;
+                                       rtlight->static_clusterindices[rtlight->static_numclusters++] = i;
 
-                       VectorCopy(e->origin, e->mins);
-                       VectorCopy(e->origin, e->maxs);
+                       VectorCopy(rtlight->shadoworigin, rtlight->cullmins);
+                       VectorCopy(rtlight->shadoworigin, rtlight->cullmaxs);
                        for (i = 0, face = cl.worldmodel->brushq3.data_thismodel->firstface;i < cl.worldmodel->brushq3.data_thismodel->numfaces;i++, face++)
                                face->lighttemp_castshadow = false;
                        for (i = 0, leaf = cl.worldmodel->brushq3.data_leafs;i < cl.worldmodel->brushq3.num_leafs;i++, leaf++)
@@ -2074,8 +1884,8 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                {
                                        for (k = 0;k < 3;k++)
                                        {
-                                               if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k];
-                                               if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k];
+                                               if (rtlight->cullmins[k] > leaf->mins[k]) rtlight->cullmins[k] = leaf->mins[k];
+                                               if (rtlight->cullmaxs[k] < leaf->maxs[k]) rtlight->cullmaxs[k] = leaf->maxs[k];
                                        }
                                        for (j = 0;j < leaf->numleaffaces;j++)
                                        {
@@ -2094,11 +1904,11 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                        face->lighttemp_castshadow = false;
                                        if (!(face->texture->surfaceflags & (Q3SURFACEFLAG_NODRAW | Q3SURFACEFLAG_SKY)))
                                        {
-                                               if (e->drawshadows)
+                                               if (rtlight->shadow)
                                                        if (!(face->texture->nativecontents & CONTENTSQ3_TRANSLUCENT))
                                                                Mod_ShadowMesh_AddMesh(r_shadow_mempool, castmesh, NULL, NULL, NULL, face->data_vertex3f, NULL, NULL, NULL, NULL, face->num_triangles, face->data_element3i);
                                                if (!(face->texture->surfaceflags & Q3SURFACEFLAG_SKY))
-                                                       Mod_ShadowMesh_AddMesh(r_shadow_mempool, e->meshchain_light, face->texture->skin.base, face->texture->skin.gloss, face->texture->skin.nmap, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, face->num_triangles, face->data_element3i);
+                                                       Mod_ShadowMesh_AddMesh(r_shadow_mempool, rtlight->static_meshchain_light, face->texture->skin.base, face->texture->skin.gloss, face->texture->skin.nmap, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, face->num_triangles, face->data_element3i);
                                        }
                                }
                        }
@@ -2107,9 +1917,9 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                {
                        mleaf_t *leaf;
                        msurface_t *surf;
-                       VectorCopy(e->origin, e->mins);
-                       VectorCopy(e->origin, e->maxs);
-                       i = CL_PointQ1Contents(e->origin);
+                       VectorCopy(rtlight->shadoworigin, rtlight->cullmins);
+                       VectorCopy(rtlight->shadoworigin, rtlight->cullmaxs);
+                       i = CL_PointQ1Contents(rtlight->shadoworigin);
 
                        for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++)
                                surf->lighttemp_castshadow = false;
@@ -2122,7 +1932,7 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.num_leafs);
                                bytesurfacepvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numsurfaces);
 
-                               Portal_Visibility(cl.worldmodel, e->origin, byteleafpvs, bytesurfacepvs, NULL, 0, true, mins, maxs, e->mins, e->maxs);
+                               Portal_Visibility(cl.worldmodel, rtlight->shadoworigin, byteleafpvs, bytesurfacepvs, NULL, 0, true, mins, maxs, rtlight->cullmins, rtlight->cullmaxs);
 
                                // make a pvs that only includes things within the box
                                for (i = 0, leaf = cl.worldmodel->brushq1.data_leafs;i < cl.worldmodel->brushq1.num_leafs;i++, leaf++)
@@ -2132,8 +1942,8 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                                SETPVSBIT(lightpvs, leaf->clusterindex);
                                                for (k = 0;k < 3;k++)
                                                {
-                                                       if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k];
-                                                       if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k];
+                                                       if (rtlight->cullmins[k] > leaf->mins[k]) rtlight->cullmins[k] = leaf->mins[k];
+                                                       if (rtlight->cullmaxs[k] < leaf->maxs[k]) rtlight->cullmaxs[k] = leaf->maxs[k];
                                                }
                                        }
                                }
@@ -2146,13 +1956,13 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                Mem_Free(bytesurfacepvs);
        
                                // make a cluster list for fast visibility checking during rendering
-                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
+                               for (i = 0, rtlight->static_numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                        if (CHECKPVSBIT(lightpvs, i))
-                                               e->numclusters++;
-                               e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
-                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
+                                               rtlight->static_numclusters++;
+                               rtlight->static_clusterindices = Mem_Alloc(r_shadow_mempool, rtlight->static_numclusters * sizeof(int));
+                               for (i = 0, rtlight->static_numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                        if (CHECKPVSBIT(lightpvs, i))
-                                               e->clusterindices[e->numclusters++] = i;
+                                               rtlight->static_clusterindices[rtlight->static_numclusters++] = i;
                        }
                        else
                        {
@@ -2164,8 +1974,8 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                                SETPVSBIT(lightpvs, leaf->clusterindex);
                                                for (k = 0;k < 3;k++)
                                                {
-                                                       if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k];
-                                                       if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k];
+                                                       if (rtlight->cullmins[k] > leaf->mins[k]) rtlight->cullmins[k] = leaf->mins[k];
+                                                       if (rtlight->cullmaxs[k] < leaf->maxs[k]) rtlight->cullmaxs[k] = leaf->maxs[k];
                                                }
                                                for (j = 0;j < leaf->nummarksurfaces;j++)
                                                {
@@ -2182,13 +1992,13 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                                SETPVSBIT(lightpvs, leaf->clusterindex);
 
                                // make a cluster list for fast visibility checking during rendering
-                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
+                               for (i = 0, rtlight->static_numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                        if (CHECKPVSBIT(lightpvs, i))
-                                               e->numclusters++;
-                               e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
-                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
+                                               rtlight->static_numclusters++;
+                               rtlight->static_clusterindices = Mem_Alloc(r_shadow_mempool, rtlight->static_numclusters * sizeof(int));
+                               for (i = 0, rtlight->static_numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                        if (CHECKPVSBIT(lightpvs, i))
-                                               e->clusterindices[e->numclusters++] = i;
+                                               rtlight->static_clusterindices[rtlight->static_numclusters++] = i;
                        }
 
                        // add surfaces to shadow casting mesh and light mesh
@@ -2197,10 +2007,10 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                if (surf->lighttemp_castshadow)
                                {
                                        surf->lighttemp_castshadow = false;
-                                       if (e->drawshadows && (surf->flags & SURF_SHADOWCAST))
+                                       if (rtlight->shadow && (surf->flags & SURF_SHADOWCAST))
                                                Mod_ShadowMesh_AddMesh(r_shadow_mempool, castmesh, NULL, NULL, NULL, surf->mesh.data_vertex3f, NULL, NULL, NULL, NULL, surf->mesh.num_triangles, surf->mesh.data_element3i);
                                        if (!(surf->flags & SURF_DRAWSKY))
-                                               Mod_ShadowMesh_AddMesh(r_shadow_mempool, e->meshchain_light, surf->texinfo->texture->skin.base, surf->texinfo->texture->skin.gloss, surf->texinfo->texture->skin.nmap, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, surf->mesh.num_triangles, surf->mesh.data_element3i);
+                                               Mod_ShadowMesh_AddMesh(r_shadow_mempool, rtlight->static_meshchain_light, surf->texinfo->texture->skin.base, surf->texinfo->texture->skin.gloss, surf->texinfo->texture->skin.nmap, surf->mesh.data_vertex3f, surf->mesh.data_svector3f, surf->mesh.data_tvector3f, surf->mesh.data_normal3f, surf->mesh.data_texcoordtexture2f, surf->mesh.num_triangles, surf->mesh.data_element3i);
                                }
                        }
                }
@@ -2209,10 +2019,11 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
        // limit box to light bounds (in case it grew larger)
        for (k = 0;k < 3;k++)
        {
-               if (e->mins[k] < e->origin[k] - e->radius) e->mins[k] = e->origin[k] - e->radius;
-               if (e->maxs[k] > e->origin[k] + e->radius) e->maxs[k] = e->origin[k] + e->radius;
+               if (rtlight->cullmins[k] < rtlight->shadoworigin[k] - rtlight->radius) rtlight->cullmins[k] = rtlight->shadoworigin[k] - rtlight->radius;
+               if (rtlight->cullmaxs[k] > rtlight->shadoworigin[k] + rtlight->radius) rtlight->cullmaxs[k] = rtlight->shadoworigin[k] + rtlight->radius;
        }
-       e->cullradius = RadiusFromBoundsAndOrigin(e->mins, e->maxs, e->origin);
+       rtlight->cullradius = RadiusFromBoundsAndOrigin(rtlight->cullmins, rtlight->cullmaxs, rtlight->shadoworigin);
+       rtlight->cullradius = min(rtlight->cullradius, rtlight->radius);
 
        // cast shadow volume from castmesh
        castmesh = Mod_ShadowMesh_Finish(r_shadow_mempool, castmesh, false, true);
@@ -2230,13 +2041,13 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                        vertex3f = Mem_Alloc(r_shadow_mempool, maxverts * sizeof(float[3]));
                        // now that we have the buffers big enough, construct and add
                        // the shadow volume mesh
-                       if (e->drawshadows)
-                               e->meshchain_shadow = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768, 32768, NULL, NULL, NULL, false, false, true);
+                       if (rtlight->shadow)
+                               rtlight->static_meshchain_shadow = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768, 32768, NULL, NULL, NULL, false, false, true);
                        for (mesh = castmesh;mesh;mesh = mesh->next)
                        {
                                Mod_BuildTriangleNeighbors(mesh->neighbor3i, mesh->element3i, mesh->numtriangles);
-                               if ((tris = R_Shadow_ConstructShadowVolume(castmesh->numverts, 0, castmesh->numtriangles, castmesh->element3i, castmesh->neighbor3i, castmesh->vertex3f, NULL, shadowelements, vertex3f, e->origin, r_shadow_projectdistance.value)))
-                                       Mod_ShadowMesh_AddMesh(r_shadow_mempool, e->meshchain_shadow, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
+                               if ((tris = R_Shadow_ConstructShadowVolume(castmesh->numverts, 0, castmesh->numtriangles, castmesh->element3i, castmesh->neighbor3i, castmesh->vertex3f, NULL, shadowelements, vertex3f, rtlight->shadoworigin, r_shadow_projectdistance.value)))
+                                       Mod_ShadowMesh_AddMesh(r_shadow_mempool, rtlight->static_meshchain_shadow, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
                        }
                        Mem_Free(vertex3f);
                        vertex3f = NULL;
@@ -2245,33 +2056,437 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                Mod_ShadowMesh_Free(castmesh);
        }
 
-       e->meshchain_shadow = Mod_ShadowMesh_Finish(r_shadow_mempool, e->meshchain_shadow, false, false);
-       e->meshchain_light = Mod_ShadowMesh_Finish(r_shadow_mempool, e->meshchain_light, true, false);
+       rtlight->static_meshchain_shadow = Mod_ShadowMesh_Finish(r_shadow_mempool, rtlight->static_meshchain_shadow, false, false);
+       rtlight->static_meshchain_light = Mod_ShadowMesh_Finish(r_shadow_mempool, rtlight->static_meshchain_light, true, false);
 
        k = 0;
-       if (e->meshchain_shadow)
-               for (mesh = e->meshchain_shadow;mesh;mesh = mesh->next)
+       if (rtlight->static_meshchain_shadow)
+               for (mesh = rtlight->static_meshchain_shadow;mesh;mesh = mesh->next)
                        k += mesh->numtriangles;
        l = 0;
-       if (e->meshchain_light)
-               for (mesh = e->meshchain_light;mesh;mesh = mesh->next)
+       if (rtlight->static_meshchain_light)
+               for (mesh = rtlight->static_meshchain_light;mesh;mesh = mesh->next)
                        l += mesh->numtriangles;
-       Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i shadow volume triangles, %i light triangles\n", e->mins[0], e->mins[1], e->mins[2], e->maxs[0], e->maxs[1], e->maxs[2], k, l);
+       Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i shadow volume triangles, %i light triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], k, l);
+}
+
+void R_RTLight_Uncompile(rtlight_t *rtlight)
+{
+       if (rtlight->compiled)
+       {
+               if (rtlight->static_meshchain_shadow)
+                       Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow);
+               rtlight->static_meshchain_shadow = NULL;
+               if (rtlight->static_meshchain_light)
+                       Mod_ShadowMesh_Free(rtlight->static_meshchain_light);
+               rtlight->static_meshchain_light = NULL;
+               if (rtlight->static_clusterindices)
+                       Mem_Free(rtlight->static_clusterindices);
+               rtlight->static_clusterindices = NULL;
+               rtlight->static_numclusters = 0;
+               rtlight->compiled = false;
+       }
+}
+
+int shadowframecount = 0;
+
+void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t shadoworigin, vec_t shadowradius, vec3_t cullmins, vec3_t cullmaxs)
+{
+       // rough checks
+       if ((BoxesOverlap(ent->mins, ent->maxs, cullmins, cullmaxs) || !r_shadow_cull.integer) && (ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawShadowVolume)
+       {
+               vec3_t relativeshadoworigin;
+               Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativeshadoworigin);
+               ent->model->DrawShadowVolume (ent, relativeshadoworigin, shadowradius);
+       }
+}
+
+void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, dlight_t *light);
+
+void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
+{
+       int i, shadow;
+       entity_render_t *ent;
+       float f;
+       vec3_t relativelightorigin, relativeeyeorigin, lightcolor;
+       rtexture_t *cubemaptexture;
+       matrix4x4_t matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
+
+       if (d_lightstylevalue[rtlight->style] <= 0)
+               return;
+       if (rtlight->compiled)
+       {
+               if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs))
+                       return;
+               for (i = 0;i < rtlight->static_numclusters;i++)
+                       if (CHECKPVSBIT(r_pvsbits, rtlight->static_clusterindices[i]))
+                               break;
+               if (i == rtlight->static_numclusters)
+                       return;
+       }
+       else if (VIS_CullBox(rtlight->cullmins, rtlight->cullmaxs))
+               return;
+       if (R_Shadow_ScissorForBBox(rtlight->cullmins, rtlight->cullmaxs))
+               return;
+
+       if (rtlight->isstatic && !rtlight->compiled && r_shadow_staticworldlights.integer)
+               R_RTLight_Compile(rtlight);
+       
+       f = d_lightstylevalue[rtlight->style] * (1.0f / 256.0f);
+       VectorScale(rtlight->color, f, lightcolor);
+       /*
+       if (rtlight->selected)
+       {
+               f = 2 + sin(realtime * M_PI * 4.0);
+               VectorScale(lightcolor, f, lightcolor);
+       }
+       */
+
+       if (rtlight->cubemapname[0])
+               cubemaptexture = R_Shadow_Cubemap(rtlight->cubemapname);
+       else
+               cubemaptexture = NULL;
+
+       shadow = rtlight->shadow && (rtlight->isstatic ? r_shadow_worldshadows.integer : r_shadow_dlightshadows.integer);
+       if (shadow && (gl_stencil || visiblevolumes))
+       {
+               if (!visiblevolumes)
+                       R_Shadow_Stage_ShadowVolumes();
+               ent = &cl_entities[0].render;
+               if (r_shadow_staticworldlights.integer && rtlight->compiled)
+               {
+                       R_Mesh_Matrix(&ent->matrix);
+                       if (r_shadow_showtris.integer)
+                       {
+                               shadowmesh_t *mesh;
+                               rmeshstate_t m;
+                               int depthenabled = qglIsEnabled(GL_DEPTH_TEST);
+                               int stencilenabled = qglIsEnabled(GL_STENCIL_TEST);
+                               qglDisable(GL_DEPTH_TEST);
+                               qglDisable(GL_STENCIL_TEST);
+                               //qglDisable(GL_CULL_FACE);
+                               qglColorMask(1,1,1,1);
+                               memset(&m, 0, sizeof(m));
+                               R_Mesh_State_Texture(&m);
+                               GL_Color(0,0.1,0,1);
+                               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+                               for (mesh = rtlight->static_meshchain_shadow;mesh;mesh = mesh->next)
+                               {
+                                       GL_VertexPointer(mesh->vertex3f);
+                                       R_Mesh_Draw_ShowTris(mesh->numverts, mesh->numtriangles, mesh->element3i);
+                               }
+                               //qglEnable(GL_CULL_FACE);
+                               if (depthenabled)
+                                       qglEnable(GL_DEPTH_TEST);
+                               if (stencilenabled)
+                               {
+                                       qglEnable(GL_STENCIL_TEST);
+                                       qglColorMask(0,0,0,0);
+                               }
+                       }
+                       R_Shadow_RenderShadowMeshVolume(rtlight->static_meshchain_shadow);
+               }
+               else
+                       R_TestAndDrawShadowVolume(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs);
+               if (r_drawentities.integer)
+                       for (i = 0;i < r_refdef.numentities;i++)
+                               if (r_refdef.entities[i]->flags & RENDER_SHADOW)
+                                       R_TestAndDrawShadowVolume(r_refdef.entities[i], rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs);
+       }
+
+       if (!visiblevolumes)
+       {
+               if (shadow && gl_stencil)
+                       R_Shadow_Stage_LightWithShadows();
+               else
+                       R_Shadow_Stage_LightWithoutShadows();
+
+               ent = &cl_entities[0].render;
+               if (ent->model && ent->model->DrawLight)
+               {
+                       Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin);
+                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
+                       Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix);
+                       Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rtlight->matrix_worldtoattenuationxyz, &ent->matrix);
+                       Matrix4x4_Concat(&matrix_modeltoattenuationz, &rtlight->matrix_worldtoattenuationz, &ent->matrix);
+                       if (r_shadow_staticworldlights.integer && rtlight->compiled)
+                       {
+                               //R_Shadow_DrawStaticWorldLight_Light(rtlight, &ent->matrix, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
+                               shadowmesh_t *mesh;
+                               R_Mesh_Matrix(&ent->matrix);
+                               if (r_shadow_showtris.integer)
+                               {
+                                       rmeshstate_t m;
+                                       int depthenabled = qglIsEnabled(GL_DEPTH_TEST);
+                                       int stencilenabled = qglIsEnabled(GL_STENCIL_TEST);
+                                       qglDisable(GL_DEPTH_TEST);
+                                       qglDisable(GL_STENCIL_TEST);
+                                       //qglDisable(GL_CULL_FACE);
+                                       memset(&m, 0, sizeof(m));
+                                       R_Mesh_State_Texture(&m);
+                                       GL_Color(0.2,0,0,1);
+                                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+                                       for (mesh = rtlight->static_meshchain_light;mesh;mesh = mesh->next)
+                                       {
+                                               GL_VertexPointer(mesh->vertex3f);
+                                               R_Mesh_Draw_ShowTris(mesh->numverts, mesh->numtriangles, mesh->element3i);
+                                       }
+                                       //qglEnable(GL_CULL_FACE);
+                                       if (depthenabled)
+                                               qglEnable(GL_DEPTH_TEST);
+                                       if (stencilenabled)
+                                               qglEnable(GL_STENCIL_TEST);
+                               }
+                               for (mesh = rtlight->static_meshchain_light;mesh;mesh = mesh->next)
+                               {
+                                       R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, mesh->map_diffuse, mesh->map_normal, cubemaptexture);
+                                       R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, relativeeyeorigin, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, mesh->map_specular, mesh->map_normal, cubemaptexture);
+                               }
+                       }
+                       else
+                               ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
+               }
+               if (r_drawentities.integer)
+               {
+                       for (i = 0;i < r_refdef.numentities;i++)
+                       {
+                               ent = r_refdef.entities[i];
+                               if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
+                                && BoxesOverlap(ent->mins, ent->maxs, rtlight->cullmins, rtlight->cullmaxs)
+                                && (ent->flags & RENDER_LIGHT))
+                               {
+                                       Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin);
+                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
+                                       Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix);
+                                       Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rtlight->matrix_worldtoattenuationxyz, &ent->matrix);
+                                       Matrix4x4_Concat(&matrix_modeltoattenuationz, &rtlight->matrix_worldtoattenuationz, &ent->matrix);
+                                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture);
+                               }
+                       }
+               }
+       }
+}
+
+void R_ShadowVolumeLighting(int visiblevolumes)
+{
+       int lnum;
+       dlight_t *light;
+       rmeshstate_t m;
+
+       if (visiblevolumes)
+       {
+               memset(&m, 0, sizeof(m));
+               R_Mesh_State_Texture(&m);
+
+               GL_BlendFunc(GL_ONE, GL_ONE);
+               GL_DepthMask(false);
+               GL_DepthTest(r_shadow_visiblevolumes.integer < 2);
+               qglDisable(GL_CULL_FACE);
+               GL_Color(0.0, 0.0125, 0.1, 1);
+       }
+       else
+               R_Shadow_Stage_Begin();
+       shadowframecount++;
+       if (r_shadow_realtime_world.integer)
+       {
+               R_Shadow_LoadWorldLightsIfNeeded();
+               if (r_shadow_debuglight.integer >= 0)
+               {
+                       for (lnum = 0, light = r_shadow_worldlightchain;light;lnum++, light = light->next)
+                               if (lnum == r_shadow_debuglight.integer)
+                                       R_DrawRTLight(&light->rtlight, visiblevolumes);
+               }
+               else
+                       for (lnum = 0, light = r_shadow_worldlightchain;light;lnum++, light = light->next)
+                               R_DrawRTLight(&light->rtlight, visiblevolumes);
+       }
+       if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
+               for (lnum = 0, light = r_dlight;lnum < r_numdlights;lnum++, light++)
+                       R_DrawRTLight(&light->rtlight, visiblevolumes);
+
+       if (visiblevolumes)
+       {
+               qglEnable(GL_CULL_FACE);
+               GL_Scissor(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
+       }
+       else
+               R_Shadow_Stage_End();
 }
 
-void R_Shadow_FreeWorldLight(worldlight_t *light)
+cvar_t r_editlights = {0, "r_editlights", "0"};
+cvar_t r_editlights_cursordistance = {0, "r_editlights_distance", "1024"};
+cvar_t r_editlights_cursorpushback = {0, "r_editlights_pushback", "0"};
+cvar_t r_editlights_cursorpushoff = {0, "r_editlights_pushoff", "4"};
+cvar_t r_editlights_cursorgrid = {0, "r_editlights_grid", "4"};
+cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "0.8"};
+cvar_t r_editlights_rtlightssizescale = {CVAR_SAVE, "r_editlights_rtlightssizescale", "0.7"};
+cvar_t r_editlights_rtlightscolorscale = {CVAR_SAVE, "r_editlights_rtlightscolorscale", "2"};
+dlight_t *r_shadow_worldlightchain;
+dlight_t *r_shadow_selectedlight;
+vec3_t r_editlights_cursorlocation;
+
+typedef struct cubemapinfo_s
 {
-       worldlight_t **lightpointer;
+       char basename[64];
+       rtexture_t *texture;
+}
+cubemapinfo_t;
+
+#define MAX_CUBEMAPS 128
+static int numcubemaps;
+static cubemapinfo_t cubemaps[MAX_CUBEMAPS];
+
+//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
+typedef struct suffixinfo_s
+{
+       char *suffix;
+       int flipx, flipy, flipdiagonal;
+}
+suffixinfo_t;
+static suffixinfo_t suffix[3][6] =
+{
+       {
+               {"posx", false, false, false},
+               {"negx", false, false, false},
+               {"posy", false, false, false},
+               {"negy", false, false, false},
+               {"posz", false, false, false},
+               {"negz", false, false, false}
+       },
+       {
+               {"px", false, false, false},
+               {"nx", false, false, false},
+               {"py", false, false, false},
+               {"ny", false, false, false},
+               {"pz", false, false, false},
+               {"nz", false, false, false}
+       },
+       {
+               {"ft", true, false, true},
+               {"bk", false, true, true},
+               {"lf", true, true, false},
+               {"rt", false, false, false},
+               {"up", false, false, false},
+               {"dn", false, false, false}
+       }
+};
+
+static int componentorder[4] = {0, 1, 2, 3};
+
+rtexture_t *R_Shadow_LoadCubemap(const char *basename)
+{
+       int i, j, cubemapsize;
+       qbyte *cubemappixels, *image_rgba;
+       rtexture_t *cubemaptexture;
+       char name[256];
+       // must start 0 so the first loadimagepixels has no requested width/height
+       cubemapsize = 0;
+       cubemappixels = NULL;
+       cubemaptexture = NULL;
+       for (j = 0;j < 3 && !cubemappixels;j++)
+       {
+               for (i = 0;i < 6;i++)
+               {
+                       snprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
+                       if ((image_rgba = loadimagepixels(name, false, cubemapsize, cubemapsize)))
+                       {
+                               if (image_width == image_height)
+                               {
+                                       if (!cubemappixels && image_width >= 1)
+                                       {
+                                               cubemapsize = image_width;
+                                               // note this clears to black, so unavailable sizes are black
+                                               cubemappixels = Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
+                                       }
+                                       if (cubemappixels)
+                                               Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_rgba, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
+                               }
+                               else
+                                       Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
+                               Mem_Free(image_rgba);
+                       }
+               }
+       }
+       if (cubemappixels)
+       {
+               if (!r_shadow_filters_texturepool)
+                       r_shadow_filters_texturepool = R_AllocTexturePool();
+               cubemaptexture = R_LoadTextureCubeMap(r_shadow_filters_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
+               Mem_Free(cubemappixels);
+       }
+       else
+       {
+               Con_Printf("Failed to load Cubemap \"%s\", tried ", basename);
+               for (j = 0;j < 3;j++)
+                       for (i = 0;i < 6;i++)
+                               Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
+               Con_Printf(" and was unable to find any of them.\n");
+       }
+       return cubemaptexture;
+}
+
+rtexture_t *R_Shadow_Cubemap(const char *basename)
+{
+       int i;
+       for (i = 0;i < numcubemaps;i++)
+               if (!strcasecmp(cubemaps[i].basename, basename))
+                       return cubemaps[i].texture;
+       if (i >= MAX_CUBEMAPS)
+               return NULL;
+       numcubemaps++;
+       strcpy(cubemaps[i].basename, basename);
+       cubemaps[i].texture = R_Shadow_LoadCubemap(cubemaps[i].basename);
+       return cubemaps[i].texture;
+}
+
+void R_Shadow_FreeCubemaps(void)
+{
+       numcubemaps = 0;
+       R_FreeTexturePool(&r_shadow_filters_texturepool);
+}
+
+void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname)
+{
+       dlight_t *light;
+
+       if (radius < 15 || DotProduct(color, color) < 0.03)
+       {
+               Con_Printf("R_Shadow_NewWorldLight: refusing to create a light too small/dim\n");
+               return;
+       }
+
+       light = Mem_Alloc(r_shadow_mempool, sizeof(dlight_t));
+       VectorCopy(origin, light->origin);
+       VectorCopy(angles, light->angles);
+       VectorCopy(color, light->color);
+       light->radius = radius;
+       light->style = style;
+       if (light->style < 0 || light->style >= MAX_LIGHTSTYLES)
+       {
+               Con_Printf("R_Shadow_NewWorldLight: invalid light style number %i, must be >= 0 and < %i\n", light->style, MAX_LIGHTSTYLES);
+               light->style = 0;
+       }
+       light->shadow = shadowenable;
+       light->corona = corona;
+       if (cubemapname && cubemapname[0] && strlen(cubemapname) < sizeof(light->cubemapname))
+               strcpy(light->cubemapname, cubemapname);
+       Matrix4x4_CreateFromQuakeEntity(&light->matrix, light->origin[0], light->origin[1], light->origin[2], light->angles[0], light->angles[1], light->angles[2], 1);
+       light->next = r_shadow_worldlightchain;
+       r_shadow_worldlightchain = light;
+
+       R_RTLight_UpdateFromDLight(&light->rtlight, light, true);
+       if (r_shadow_staticworldlights.integer)
+               R_RTLight_Compile(&light->rtlight);
+}
+
+void R_Shadow_FreeWorldLight(dlight_t *light)
+{
+       dlight_t **lightpointer;
        for (lightpointer = &r_shadow_worldlightchain;*lightpointer && *lightpointer != light;lightpointer = &(*lightpointer)->next);
        if (*lightpointer != light)
                Sys_Error("R_Shadow_FreeWorldLight: light not linked into chain\n");
        *lightpointer = light->next;
-       if (light->cubemapname)
-               Mem_Free(light->cubemapname);
-       if (light->meshchain_shadow)
-               Mod_ShadowMesh_Free(light->meshchain_shadow);
-       if (light->meshchain_light)
-               Mod_ShadowMesh_Free(light->meshchain_light);
+       R_RTLight_Uncompile(&light->rtlight);
        Mem_Free(light);
 }
 
@@ -2283,7 +2498,7 @@ void R_Shadow_ClearWorldLights(void)
        R_Shadow_FreeCubemaps();
 }
 
-void R_Shadow_SelectLight(worldlight_t *light)
+void R_Shadow_SelectLight(dlight_t *light)
 {
        if (r_shadow_selectedlight)
                r_shadow_selectedlight->selected = false;
@@ -2303,12 +2518,12 @@ void R_Shadow_DrawCursorCallback(const void *calldata1, int calldata2)
 void R_Shadow_DrawLightSpriteCallback(const void *calldata1, int calldata2)
 {
        float intensity;
-       const worldlight_t *light;
+       const dlight_t *light;
        light = calldata1;
        intensity = 0.5;
        if (light->selected)
                intensity = 0.75 + 0.25 * sin(realtime * M_PI * 4.0);
-       if (!light->meshchain_shadow)
+       if (!light->shadow)
                intensity *= 0.5f;
        R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[calldata2], false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
 }
@@ -2317,7 +2532,7 @@ void R_Shadow_DrawLightSprites(void)
 {
        int i;
        cachepic_t *pic;
-       worldlight_t *light;
+       dlight_t *light;
 
        for (i = 0;i < 5;i++)
        {
@@ -2334,7 +2549,7 @@ void R_Shadow_DrawLightSprites(void)
 void R_Shadow_SelectLightInView(void)
 {
        float bestrating, rating, temp[3];
-       worldlight_t *best, *light;
+       dlight_t *best, *light;
        best = NULL;
        bestrating = 0;
        for (light = r_shadow_worldlightchain;light;light = light->next)
@@ -2386,18 +2601,17 @@ void R_Shadow_LoadWorldLights(void)
                                shadow = false;
                                t++;
                        }
-                       a = sscanf(t, "%f %f %f %f %f %f %f %d %s %f %f %f %f", &origin[0], &origin[1], &origin[2], &radius, &color[0], &color[1], &color[2], &style, cubemapname, &corona, &angles[0], &angles[1], &angles[2]);
+                       a = sscanf(t, "%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f", &origin[0], &origin[1], &origin[2], &radius, &color[0], &color[1], &color[2], &style, cubemapname, &corona, &angles[0], &angles[1], &angles[2]);
                        if (a < 13)
-                       {
-                               corona = 0;
                                VectorClear(angles);
-                       }
+                       if (a < 10)
+                               corona = 0;
                        if (a < 9)
                                cubemapname[0] = 0;
                        *s = '\n';
                        if (a < 8)
                        {
-                               Con_Printf("found %d parameters on line %i, should be 8 or 9 parameters (origin[0] origin[1] origin[2] radius color[0] color[1] color[2] style cubemapname)\n", a, n + 1);
+                               Con_Printf("found %d parameters on line %i, should be 8 or more parameters (origin[0] origin[1] origin[2] radius color[0] color[1] color[2] style \"cubemapname\" corona angles[0] angles[1] angles[2])\n", a, n + 1);
                                break;
                        }
                        VectorScale(color, r_editlights_rtlightscolorscale.value, color);
@@ -2414,7 +2628,7 @@ void R_Shadow_LoadWorldLights(void)
 
 void R_Shadow_SaveWorldLights(void)
 {
-       worldlight_t *light;
+       dlight_t *light;
        int bufchars, bufmaxchars;
        char *buf, *oldbuf;
        char name[MAX_QPATH];
@@ -2432,7 +2646,7 @@ void R_Shadow_SaveWorldLights(void)
        buf = NULL;
        for (light = r_shadow_worldlightchain;light;light = light->next)
        {
-               sprintf(line, "%s%f %f %f %f %f %f %f %d %s\n", light->drawshadows ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style, light->cubemapname ? light->cubemapname : "");
+               sprintf(line, "%s%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style, light->cubemapname ? light->cubemapname : "", light->corona, light->angles[0], light->angles[1], light->angles[2]);
                if (bufchars + (int) strlen(line) > bufmaxchars)
                {
                        bufmaxchars = bufchars + strlen(line) + 2048;
@@ -2765,7 +2979,7 @@ void R_Shadow_EditLights_Edit_f(void)
                strcpy(cubemapname, r_shadow_selectedlight->cubemapname);
        else
                cubemapname[0] = 0;
-       shadows = r_shadow_selectedlight->drawshadows;
+       shadows = r_shadow_selectedlight->shadow;
        corona = r_shadow_selectedlight->corona;
        if (!strcmp(Cmd_Argv(1), "origin"))
        {
@@ -2950,7 +3164,7 @@ void R_Shadow_EditLights_Edit_f(void)
                Con_Printf("Radius : %f\n", r_shadow_selectedlight->radius);
                Con_Printf("Corona : %f\n", r_shadow_selectedlight->corona);
                Con_Printf("Style  : %i\n", r_shadow_selectedlight->style);
-               Con_Printf("Shadows: %s\n", r_shadow_selectedlight->drawshadows ? "yes" : "no");
+               Con_Printf("Shadows: %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");
                Con_Printf("Cubemap: %s\n", r_shadow_selectedlight->cubemapname);
                return;
        }
@@ -2975,7 +3189,7 @@ void R_Shadow_EditLights_DrawSelectedLightProperties(void)
        sprintf(temp, "Radius  %f", r_shadow_selectedlight->radius);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
        sprintf(temp, "Corona  %f", r_shadow_selectedlight->corona);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
        sprintf(temp, "Style   %i", r_shadow_selectedlight->style);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Shadows %s", r_shadow_selectedlight->drawshadows ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
+       sprintf(temp, "Shadows %s", r_shadow_selectedlight->shadow ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
        sprintf(temp, "Cubemap %s", r_shadow_selectedlight->cubemapname);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
 }
 
@@ -2991,7 +3205,7 @@ void R_Shadow_EditLights_ToggleShadow_f(void)
                Con_Printf("No selected light.\n");
                return;
        }
-       R_Shadow_NewWorldLight(r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->drawshadows, r_shadow_selectedlight->cubemapname);
+       R_Shadow_NewWorldLight(r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname);
        R_Shadow_FreeWorldLight(r_shadow_selectedlight);
        r_shadow_selectedlight = NULL;
 }
@@ -3008,7 +3222,7 @@ void R_Shadow_EditLights_ToggleCorona_f(void)
                Con_Printf("No selected light.\n");
                return;
        }
-       R_Shadow_NewWorldLight(r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->drawshadows, r_shadow_selectedlight->cubemapname);
+       R_Shadow_NewWorldLight(r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname);
        R_Shadow_FreeWorldLight(r_shadow_selectedlight);
        r_shadow_selectedlight = NULL;
 }
index 4e1349a34071fa9fa290280dfeddf20326327f61..3af580feb090f76168f994a53d2fdefb380bc405 100644 (file)
@@ -17,8 +17,8 @@ extern cvar_t r_shadow_dlightshadows;
 
 void R_Shadow_Init(void);
 void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance);
-void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *elements, const float *vertices, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, float lightradius, const float *lightcolor, const matrix4x4_t *matrix_worldtolight, const matrix4x4_t *matrix_worldtoattenuationxyz, const matrix4x4_t *matrix_worldtoattenuationz, rtexture_t *basetexture, rtexture_t *bumptexture, rtexture_t *lightcubemap);
-void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elements, const float *vertices, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, const matrix4x4_t *matrix_worldtolight, const matrix4x4_t *matrix_worldtoattenuationxyz, const matrix4x4_t *matrix_worldtoattenuationz, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap);
+void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *elements, const float *vertices, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *lightcolor, const matrix4x4_t *matrix_worldtolight, const matrix4x4_t *matrix_worldtoattenuationxyz, const matrix4x4_t *matrix_worldtoattenuationz, rtexture_t *basetexture, rtexture_t *bumptexture, rtexture_t *lightcubemap);
+void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elements, const float *vertices, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, const float *lightcolor, const matrix4x4_t *matrix_worldtolight, const matrix4x4_t *matrix_worldtoattenuationxyz, const matrix4x4_t *matrix_worldtoattenuationz, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap);
 void R_Shadow_ClearStencil(void);
 
 void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *mesh);
@@ -36,58 +36,14 @@ extern matrix4x4_t matrix_attenuationz;
 
 rtexture_t *R_Shadow_Cubemap(const char *basename);
 
-typedef struct worldlight_s
-{
-       // saved properties
-       vec3_t origin;
-       vec3_t angles;
-       vec3_t color;
-       vec_t radius;
-       vec_t corona;
-       int drawshadows;
-       char *cubemapname;
-
-       // shadow volumes are done entirely in model space, so there are no matrices for dealing with them...
-
-       // note that the world to light matrices are inversely scaled (divided) by lightradius
-
-       // matrix for transforming world coordinates to light filter coordinates
-       //matrix4x4_t matrix_worldtolight;
-       // based on worldtolight this transforms -1 to +1 to 0 to 1 for purposes
-       // of attenuation texturing in full 3D (z result often ignored)
-       //matrix4x4_t matrix_worldtoattenuationxyz;
-       // this transforms only the Z to S, and T is always 0.5
-       //matrix4x4_t matrix_worldtoattenuationz;
-
-       // generated properties
-       vec3_t mins;
-       vec3_t maxs;
-       vec_t cullradius;
-       struct worldlight_s *next;
-       rtexture_t *cubemap;
-       int style;
-       int selected;
-
-       matrix4x4_t matrix_lighttoworld;
-       matrix4x4_t matrix_worldtolight;
-       matrix4x4_t matrix_worldtoattenuationxyz;
-       matrix4x4_t matrix_worldtoattenuationz;
-
-       // premade shadow volumes and lit surfaces to render
-       shadowmesh_t *meshchain_shadow;
-       shadowmesh_t *meshchain_light;
-       
-       // used for visibility testing
-       int numclusters;
-       int *clusterindices;
-}
-worldlight_t;
-
-extern worldlight_t *r_shadow_worldlightchain;
+extern dlight_t *r_shadow_worldlightchain;
 
 void R_Shadow_UpdateWorldLightSelection(void);
 
-void R_Shadow_DrawStaticWorldLight_Shadow(worldlight_t *light, matrix4x4_t *matrix);
-void R_Shadow_DrawStaticWorldLight_Light(worldlight_t *light, matrix4x4_t *matrix, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz);
+void R_RTLight_UpdateFromDLight(rtlight_t *rtlight, const dlight_t *light, int isstatic);
+void R_RTLight_Compile(rtlight_t *rtlight);
+void R_RTLight_Uncompile(rtlight_t *rtlight);
+
+void R_ShadowVolumeLighting(int visiblevolumes);
 
 #endif
index a85e6604c1d6d962066eaa2f1a87c6d62d37f60b..9a28218f1f024e78c07b63fe709121faeb0dbd12 100644 (file)
--- a/render.h
+++ b/render.h
@@ -127,6 +127,7 @@ void R_DrawExplosions(void);
 //#define PARANOID 1
 
 int R_CullBox(const vec3_t mins, const vec3_t maxs);
+#define VIS_CullBox(mins,maxs) (R_CullBox((mins), (maxs)) || (cl.worldmodel && cl.worldmodel->brush.BoxTouchingPVS && !cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, r_pvsbits, (mins), (maxs))))
 
 extern qboolean fogenabled;
 extern vec3_t fogcolor;
diff --git a/todo b/todo
index e2846a523f5e0b7650118d5062e65b90bf9dc228..bf15b68283f8a3b9a0298a136f7e816ed3317949 100644 (file)
--- a/todo
+++ b/todo
 -n darkplaces: segfault reading memory in windows when starting a new server from menu (yummyluv)
 -n darkplaces: server is starting before the "port" cvar is set by commandline and scripts? (yummyluv)
 -n darkplaces: typing ip in join game menu should show 'trying' and 'no response' after a while, or 'no network' if networking is not initialized (yummyluv)
+d darkplaces: fixed SV_TouchAreaGrid to not crash if SV_IncreaseEdicts is called during a touch function, by making a list of edicts to touch and then running through the list afterward (KGB|romi)
+d darkplaces: moved R_ShadowVolumeLighting to r_shadow.c
+d darkplaces: added RENDER_LIGHT flag to entity_render_t to make rtlighting optional per entity
+d darkplaces: cleaned up rtlight handling, merging most code between world rtlights and dlights
+d darkplaces: safety checked lightmap access in Mod_Q1BSP_RecursiveLightPoint as one map Sajt uses was crashing (Sajt)
+0 darkplaces: upgrade network protocol to send precise angles, and make EF_LOWPRECISION downgrade both origin and angles (Urre)
+0 darkplaces: figure out why cubemap upload scaling crashes (Urre)
+0 darkplaces: make screenshots save to screenshots/fniggium%04i.tga in GAME_FNIGGIUM (Sajt)
+0 darkplaces: make screenshots save to screenshots directory (Sajt)
+2 darkplaces: make corona occlusion testing use GL_ARB_occlusion_query instead of a CL_TraceLine (Riot)
+d darkplaces: default a few cvars accordingly for GAME_TENEBRAE mode
+d darkplaces: add skin and pflags support to light entity loader
+0 darkplaces: add EF_NOSHADOW to make entities that never cast shadows (Urre)
+2 darkplaces: fix fogging in realtime lighting mode, need to split the shaders into two stages, this will also fix decal bugs with fog (Electro, Mitchell)
+0 darkplaces: fix cl_nodelta 1, it's halting updates (Tomaz)
+0 darkplaces: player setup menu network speed is never applying to rate (Mitchell)
 d darkplaces: PF_traceline/PF_tracebox now work with world as the edict
 d darkplaces: make the static light built messages be developer prints (Tomaz)
 d dpmod: use Tomaz's ammo box models (Tomaz) 
@@ -279,7 +295,7 @@ d darkplaces: q1bsp trace bug: scrags frequently fly through ceilings - this nee
 0 sv_user.qc: figure out why looking up/down slows movement and fix it (Vermeulen)
 1 darkplaces: add DP_CLIENTCAMERA extension (.entity clientcamera; sets which entity the client views from) (Wazat for Battlemech, SeienAbunae)
 1 darkplaces: add DP_EF_CLIENTLOCKANGLES extension (prevents client from turning view, takes angles from entity) (Wazat for Battlemech, SeienAbunae)
-1 darkplaces: add DP_EF_PRECISEANGLES extension (sends short angles instead of byte) (Wazat for Battlemech, FrikaC, mashakos, RenegadeC)
+1 darkplaces: add DP_EF_PRECISEANGLES extension (sends short angles instead of byte) (Wazat for Battlemech, FrikaC, mashakos, RenegadeC, Sajt)
 1 darkplaces: add DP_QC_ENDFRAME extension/documentation and post it on wiki (tell Uffe, SeienAbunae)
 1 darkplaces: add DP_SV_READCLIENTINPUT extension (.vector clientinput; works like .movement but for mouse or any other similar controllers) (Wazat for Battlemech, FrikaC, SeienAbunae)
 1 darkplaces: add EndGame function (called on server shutdown or level change) (SeienAbunae, Nexuiz)