]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rsurf.c
thanks to Tomaz for finding a severe bug in CopyTranslateOnly (it was copying the...
[xonotic/darkplaces.git] / gl_rsurf.c
index a587d658a1abb7f7919c657cdc91bc6414383d34..add2b1a223e78415136782edeee1a8a22de640c8 100644 (file)
@@ -419,7 +419,7 @@ static void R_BuildLightMap (const entity_render_t *ent, msurface_t *surf, int d
        }
 }
 
-void R_StainNode (mnode_t *node, model_t *model, vec3_t origin, float radius, float fcolor[8])
+void R_StainNode (mnode_t *node, model_t *model, const vec3_t origin, float radius, const float fcolor[8])
 {
        float ndist, a, ratio, maxdist, maxdist2, maxdist3, invradius, sdtable[256], td, dist2;
        msurface_t *surf, *endsurf;
@@ -541,7 +541,7 @@ loc0:
        }
 }
 
-void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
+void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
 {
        int n;
        float fcolor[8];
@@ -807,7 +807,7 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        float f, colorscale;
        const surfmesh_t *mesh;
        rmeshstate_t m;
-       float alpha = ent->alpha * (surf->flags & SURF_WATERALPHA ? r_wateralpha.value : 1);
+       float alpha;
        float modelorg[3];
        texture_t *texture;
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
@@ -815,7 +815,8 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        R_Mesh_Matrix(&ent->matrix);
 
        memset(&m, 0, sizeof(m));
-       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
+       texture = surf->texinfo->texture->currentframe;
+       alpha = texture->currentalpha;
        if (texture->rendertype == SURFRENDER_ADD)
        {
                m.blendfunc1 = GL_SRC_ALPHA;
@@ -898,22 +899,20 @@ static void RSurfShader_Water(const entity_render_t *ent, const texture_t *textu
                                RSurfShader_Water_Callback(ent, surf - ent->model->surfaces);
 }
 
-static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const msurface_t *surf)
+static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const msurface_t *surf, const texture_t *texture, int rendertype, float currentalpha)
 {
        float base, colorscale;
        const surfmesh_t *mesh;
        rmeshstate_t m;
        float modelorg[3];
-       texture_t *texture;
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
        memset(&m, 0, sizeof(m));
-       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
-       if (texture->rendertype == SURFRENDER_ADD)
+       if (rendertype == SURFRENDER_ADD)
        {
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE;
        }
-       else if (texture->rendertype == SURFRENDER_ALPHA)
+       else if (rendertype == SURFRENDER_ALPHA)
        {
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
@@ -938,7 +937,7 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m
                R_Mesh_ResizeCheck(mesh->numverts);
                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
                memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-               R_FillColors(varray_color, mesh->numverts, base, base, base, ent->alpha);
+               R_FillColors(varray_color, mesh->numverts, base, base, base, currentalpha);
                if (!(ent->effects & EF_FULLBRIGHT))
                {
                        if (surf->dlightframe == r_framecount)
@@ -951,13 +950,11 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m
        }
 }
 
-static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurface_t *surf)
+static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurface_t *surf, const texture_t *texture, int rendertype, float currentalpha)
 {
        const surfmesh_t *mesh;
        rmeshstate_t m;
        float modelorg[3];
-       texture_t *texture;
-       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
@@ -970,18 +967,16 @@ static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurfac
                R_Mesh_ResizeCheck(mesh->numverts);
                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
                memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-               RSurf_FoggedColors(varray_vertex, varray_color, 1, 1, 1, ent->alpha, r_colorscale, mesh->numverts, modelorg);
+               RSurf_FoggedColors(varray_vertex, varray_color, 1, 1, 1, currentalpha, r_colorscale, mesh->numverts, modelorg);
                R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
        }
 }
 
-static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface_t *surf)
+static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface_t *surf, const texture_t *texture, int rendertype, float currentalpha)
 {
        const surfmesh_t *mesh;
        rmeshstate_t m;
        float modelorg[3];
-       texture_t *texture;
-       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
@@ -995,7 +990,7 @@ static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface
                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
                if (m.tex[0])
                        memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-               RSurf_FogPassColors(varray_vertex, varray_color, fogcolor[0], fogcolor[1], fogcolor[2], ent->alpha, r_colorscale, mesh->numverts, modelorg);
+               RSurf_FogPassColors(varray_vertex, varray_color, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha, r_colorscale, mesh->numverts, modelorg);
                R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
        }
 }
@@ -1294,14 +1289,30 @@ static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata
 {
        const entity_render_t *ent = calldata1;
        const msurface_t *surf = ent->model->surfaces + calldata2;
+       int rendertype;
+       float currentalpha;
        texture_t *texture;
-       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
        R_Mesh_Matrix(&ent->matrix);
-       RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+
+       texture = surf->texinfo->texture;
+       if (texture->animated)
+               texture = texture->anim_frames[ent->frame != 0][(texture->anim_total[ent->frame != 0] >= 2) ? ((int) (cl.time * 5.0f) % texture->anim_total[ent->frame != 0]) : 0];
+
+       currentalpha = ent->alpha;
+       if (texture->flags & SURF_WATERALPHA)
+               currentalpha *= r_wateralpha.value;
+       if (ent->effects & EF_ADDITIVE)
+               rendertype = SURFRENDER_ADD;
+       else if (currentalpha < 1 || texture->fogtexture != NULL)
+               rendertype = SURFRENDER_ALPHA;
+       else
+               rendertype = SURFRENDER_OPAQUE;
+
+       RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, rendertype, currentalpha);
        if (texture->glowtexture)
-               RSurfShader_Wall_Pass_Glow(ent, surf);
+               RSurfShader_Wall_Pass_Glow(ent, surf, texture, rendertype, currentalpha);
        if (fogenabled)
-               RSurfShader_Wall_Pass_Fog(ent, surf);
+               RSurfShader_Wall_Pass_Fog(ent, surf, texture, rendertype, currentalpha);
 }
 
 static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
@@ -1320,20 +1331,27 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_
                        }
                }
        }
+       else if (r_shadow_lightingmode >= 2)
+       {
+               // opaque base lighting
+               RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, firstsurf);
+               if (fogenabled)
+                       RSurfShader_OpaqueWall_Pass_Fog(ent, texture, firstsurf);
+       }
        else if (r_vertexsurfaces.integer)
        {
                // opaque vertex shaded from lightmap
                for (surf = firstsurf;surf;surf = surf->texturechain)
                        if (surf->visframe == r_framecount)
-                               RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+                               RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, texture->rendertype, texture->currentalpha);
                if (texture->glowtexture)
                        for (surf = firstsurf;surf;surf = surf->texturechain)
                                if (surf->visframe == r_framecount)
-                                       RSurfShader_Wall_Pass_Glow(ent, surf);
+                                       RSurfShader_Wall_Pass_Glow(ent, surf, texture, texture->rendertype, texture->currentalpha);
                if (fogenabled)
                        for (surf = firstsurf;surf;surf = surf->texturechain)
                                if (surf->visframe == r_framecount)
-                                       RSurfShader_Wall_Pass_Fog(ent, surf);
+                                       RSurfShader_Wall_Pass_Fog(ent, surf, texture, texture->rendertype, texture->currentalpha);
        }
        else
        {
@@ -1365,53 +1383,9 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_
        }
 }
 
-static void RSurfShader_Wall_Lightmap_BaseLighting(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
-{
-       const msurface_t *surf;
-       if (cl.worldmodel->numlights)
-               RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, firstsurf);
-       else if (r_vertexsurfaces.integer)
-       {
-               // opaque vertex shaded from lightmap
-               for (surf = firstsurf;surf;surf = surf->texturechain)
-                       if (surf->visframe == r_framecount)
-                               RSurfShader_Wall_Pass_BaseVertex(ent, surf);
-               if (texture->glowtexture)
-                       for (surf = firstsurf;surf;surf = surf->texturechain)
-                               if (surf->visframe == r_framecount)
-                                       RSurfShader_Wall_Pass_Glow(ent, surf);
-       }
-       else
-       {
-               // opaque lightmapped
-               if (r_textureunits.integer >= 2)
-               {
-                       if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer)
-                               RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, firstsurf);
-                       else
-                       {
-                               RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, firstsurf);
-                               if (r_detailtextures.integer)
-                                       RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
-                       }
-               }
-               else
-               {
-                       RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, firstsurf);
-                       RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, firstsurf);
-                       if (r_detailtextures.integer)
-                               RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
-               }
-               if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT))
-                       RSurfShader_OpaqueWall_Pass_Light(ent, texture, firstsurf);
-               if (texture->glowtexture)
-                       RSurfShader_OpaqueWall_Pass_Glow(ent, texture, firstsurf);
-       }
-}
-
-Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap, RSurfShader_Wall_Lightmap_BaseLighting}, SHADERFLAGS_NEEDLIGHTMAP};
-Cshader_t Cshader_water = {{NULL, RSurfShader_Water, NULL}, 0};
-Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL, NULL}, 0};
+Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap}, SHADERFLAGS_NEEDLIGHTMAP};
+Cshader_t Cshader_water = {{NULL, RSurfShader_Water}, 0};
+Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL}, 0};
 
 int Cshader_count = 3;
 Cshader_t *Cshaders[3] =
@@ -1421,41 +1395,54 @@ Cshader_t *Cshaders[3] =
        &Cshader_sky
 };
 
-void R_PrepareSurfaces(entity_render_t *ent)
+void R_UpdateTextureInfo(entity_render_t *ent)
 {
-       int i, texframe, numsurfaces, *surfacevisframes;
-       model_t *model;
-       msurface_t *surf, *surfaces;
+       int i, texframe, alttextures;
        texture_t *t;
-       vec3_t modelorg;
 
        if (!ent->model)
                return;
 
-       model = ent->model;
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
-       numsurfaces = model->nummodelsurfaces;
-       surfaces = model->surfaces + model->firstmodelsurface;
-       surfacevisframes = model->surfacevisframes + model->firstmodelsurface;
-
+       alttextures = ent->frame != 0;
        texframe = (int)(cl.time * 5.0f);
-       for (i = 0;i < model->numtextures;i++)
+       for (i = 0;i < ent->model->numtextures;i++)
        {
-               t = model->textures + i;
+               t = ent->model->textures + i;
+               t->currentalpha = ent->alpha;
+               if (t->flags & SURF_WATERALPHA)
+                       t->currentalpha *= r_wateralpha.value;
                if (ent->effects & EF_ADDITIVE)
                        t->rendertype = SURFRENDER_ADD;
-               else if (ent->alpha < 1 || (t->flags & SURF_WATERALPHA && r_wateralpha.value < 1) || t->fogtexture != NULL)
+               else if (t->currentalpha < 1 || t->fogtexture != NULL)
                        t->rendertype = SURFRENDER_ALPHA;
                else
                        t->rendertype = SURFRENDER_OPAQUE;
+               // we don't need to set currentframe if t->animated is false because
+               // it was already set up by the texture loader for non-animating
                if (t->animated)
-               {
-                       t->currentframe[0] = t->anim_frames[0][(t->anim_total[0] >= 2) ? (texframe % t->anim_total[0]) : 0];
-                       t->currentframe[1] = t->anim_frames[1][(t->anim_total[1] >= 2) ? (texframe % t->anim_total[1]) : 0];
-               }
+                       t->currentframe = t->anim_frames[alttextures][(t->anim_total[alttextures] >= 2) ? (texframe % t->anim_total[alttextures]) : 0];
        }
+}
+
+void R_PrepareSurfaces(entity_render_t *ent)
+{
+       int i, numsurfaces, *surfacevisframes;
+       model_t *model;
+       msurface_t *surf, *surfaces;
+       vec3_t modelorg;
+
+       if (!ent->model)
+               return;
+
+       model = ent->model;
+       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       numsurfaces = model->nummodelsurfaces;
+       surfaces = model->surfaces + model->firstmodelsurface;
+       surfacevisframes = model->surfacevisframes + model->firstmodelsurface;
+
+       R_UpdateTextureInfo(ent);
 
-       if (r_dynamic.integer)
+       if (r_dynamic.integer && r_shadow_lightingmode < 1)
                R_MarkLights(ent);
 
        for (i = 0, surf = surfaces;i < numsurfaces;i++, surf++)
@@ -1507,8 +1494,8 @@ void R_DrawSurfaces(entity_render_t *ent, int type)
        texture_t *t;
        R_Mesh_Matrix(&ent->matrix);
        for (i = 0, t = ent->model->textures;i < ent->model->numtextures;i++, t++)
-               if (t->shader->shaderfunc[type] && ent->model->texturesurfacechains[i])
-                       t->shader->shaderfunc[type](ent, t, ent->model->texturesurfacechains[i]);
+               if (t->shader->shaderfunc[type] && t->currentframe && ent->model->texturesurfacechains[i])
+                       t->shader->shaderfunc[type](ent, t->currentframe, ent->model->texturesurfacechains[i]);
 }
 
 static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
@@ -1617,101 +1604,47 @@ void R_PrepareBrushModel(entity_render_t *ent)
 
 void R_SurfaceWorldNode (entity_render_t *ent)
 {
-       int i, numsurfaces, *surfacevisframes, *surfacepvsframes;
-       msurface_t *surfaces, *surf;
+       int i, *surfacevisframes, *surfacepvsframes, surfnum;
+       msurface_t *surf;
+       mleaf_t *leaf;
        model_t *model;
        vec3_t modelorg;
 
        model = ent->model;
-       numsurfaces = model->nummodelsurfaces;
-       surfaces = model->surfaces + model->firstmodelsurface;
        surfacevisframes = model->surfacevisframes + model->firstmodelsurface;
        surfacepvsframes = model->surfacepvsframes + model->firstmodelsurface;
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
 
-       for (i = 0, surf = surfaces;i < numsurfaces;i++, surf++)
+       for (leaf = model->pvsleafchain;leaf;leaf = leaf->pvschain)
        {
-               if (surfacepvsframes[i] == model->pvsframecount)
+               if (!R_CullBox (leaf->mins, leaf->maxs))
                {
-#if WORLDNODECULLBACKFACES
-                       if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
-                       {
-                               if ((surf->flags & SURF_PLANEBACK) && R_NotCulledBox (surf->poly_mins, surf->poly_maxs))
-                                       surfacevisframes[i] = r_framecount;
-                       }
-                       else
-                       {
-                               if (!(surf->flags & SURF_PLANEBACK) && R_NotCulledBox (surf->poly_mins, surf->poly_maxs))
-                                       surfacevisframes[i] = r_framecount;
-                       }
-#else
-                       if (R_NotCulledBox (surf->poly_mins, surf->poly_maxs))
-                               surfacevisframes[i] = r_framecount;
-#endif
+                       c_leafs++;
+                       leaf->visframe = r_framecount;
                }
        }
-}
 
-/*
-static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
-{
-       int portalstack, i;
-       mportal_t *p, *pstack[8192];
-       msurface_t *surf, **mark, **endmark;
-       mleaf_t *leaf;
-       // LordHavoc: portal-passage worldnode with PVS;
-       // follows portals leading outward from viewleaf, does not venture
-       // offscreen or into leafs that are not visible, faster than Quake's
-       // RecursiveWorldNode
-       leaf = viewleaf;
-       leaf->worldnodeframe = r_framecount;
-       portalstack = 0;
-loc0:
-       c_leafs++;
-       if (leaf->nummarksurfaces)
+       for (i = 0;i < model->pvssurflistlength;i++)
        {
-               for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
+               surfnum = model->pvssurflist[i];
+               surf = model->surfaces + surfnum;
+#if WORLDNODECULLBACKFACES
+               if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
                {
-                       surf = *mark++;
-                       // make sure surfaces are only processed once
-                       if (surf->worldnodeframe != r_framecount)
-                       {
-                               surf->worldnodeframe = r_framecount;
-                               if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
-                               {
-                                       if (surf->flags & SURF_PLANEBACK)
-                                               surf->visframe = r_framecount;
-                               }
-                               else
-                               {
-                                       if (!(surf->flags & SURF_PLANEBACK))
-                                               surf->visframe = r_framecount;
-                               }
-                       }
+                       if ((surf->flags & SURF_PLANEBACK) && !R_CullBox (surf->poly_mins, surf->poly_maxs))
+                               surfacevisframes[surfnum] = r_framecount;
                }
-       }
-       // follow portals into other leafs
-       for (p = leaf->portals;p;p = p->next)
-       {
-               leaf = p->past;
-               if (leaf->worldnodeframe != r_framecount)
+               else
                {
-                       leaf->worldnodeframe = r_framecount;
-                       // FIXME: R_NotCulledBox is absolute, should be done relative
-                       if (leaf->pvsframe == ent->model->pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
-                       {
-                               p->visframe = r_framecount;
-                               pstack[portalstack++] = p;
-                               goto loc0;
-loc1:
-                               p = pstack[--portalstack];
-                       }
+                       if (!(surf->flags & SURF_PLANEBACK) && !R_CullBox (surf->poly_mins, surf->poly_maxs))
+                               surfacevisframes[surfnum] = r_framecount;
                }
+#else
+               if (!R_CullBox (surf->poly_mins, surf->poly_maxs))
+                       surfacevisframes[surfnum] = r_framecount;
+#endif
        }
-       if (portalstack)
-               goto loc1;
 }
-*/
 
 static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
 {
@@ -1738,6 +1671,7 @@ static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
        {
                c_leafs++;
                leaf = leafstack[--leafstackpos];
+               leaf->visframe = r_framecount;
                // draw any surfaces bounding this leaf
                if (leaf->nummarksurfaces)
                {
@@ -1775,8 +1709,8 @@ static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
                                if (leaf->worldnodeframe != r_framecount)
                                {
                                        leaf->worldnodeframe = r_framecount;
-                                       // FIXME: R_NotCulledBox is absolute, should be done relative
-                                       if (leaf->pvsframe == ent->model->pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
+                                       // FIXME: R_CullBox is absolute, should be done relative
+                                       if (leaf->pvsframe == ent->model->pvsframecount && !R_CullBox(leaf->mins, leaf->maxs))
                                                leafstack[leafstackpos++] = leaf;
                                }
                        }
@@ -1799,6 +1733,8 @@ void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf)
                model->pvsframecount++;
                model->pvsviewleaf = viewleaf;
                model->pvsviewleafnovis = r_novis.integer;
+               model->pvsleafchain = NULL;
+               model->pvssurflistlength = 0;
                if (viewleaf)
                {
                        surfacepvsframes = model->surfacepvsframes;
@@ -1816,24 +1752,30 @@ void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf)
                                                if (bits & (1 << i))
                                                {
                                                        leaf = &model->leafs[j + i + 1];
+                                                       leaf->pvschain = model->pvsleafchain;
+                                                       model->pvsleafchain = leaf;
                                                        leaf->pvsframe = model->pvsframecount;
                                                        // mark surfaces bounding this leaf as visible
-                                                       for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
-                                                               surfacepvsframes[*mark++] = model->pvsframecount;
+                                                       for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--, mark++)
+                                                       {
+                                                               //if (surfacepvsframes[*mark] != model->pvsframecount)
+                                                               //{
+                                                                       surfacepvsframes[*mark] = model->pvsframecount;
+                                                               //      model->pvssurflist[model->pvssurflistlength++] = *mark;
+                                                               //}
+                                                       }
                                                }
                                        }
                                }
                        }
+                       for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+                               if (model->surfacepvsframes[j] == model->pvsframecount)
+                                       model->pvssurflist[model->pvssurflistlength++] = j;
                }
        }
 }
 
-/*
-=============
-R_DrawWorld
-=============
-*/
-void R_DrawWorld (entity_render_t *ent, int baselighting)
+void R_WorldVisibility (entity_render_t *ent)
 {
        vec3_t modelorg;
        mleaf_t *viewleaf;
@@ -1849,12 +1791,13 @@ void R_DrawWorld (entity_render_t *ent, int baselighting)
                R_SurfaceWorldNode (ent);
        else
                R_PortalWorldNode (ent, viewleaf);
+}
+
+void R_DrawWorld (entity_render_t *ent)
+{
        R_PrepareSurfaces(ent);
        R_DrawSurfaces(ent, SHADERSTAGE_SKY);
-       if (baselighting)
-               R_DrawSurfaces(ent, SHADERSTAGE_BASELIGHTING);
-       else
-               R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
+       R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
 }
 
 void R_Model_Brush_DrawSky (entity_render_t *ent)
@@ -1872,183 +1815,151 @@ void R_Model_Brush_Draw (entity_render_t *ent)
        R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
 }
 
-void R_Model_Brush_DrawBaseLighting (entity_render_t *ent)
-{
-       c_bmodels++;
-       if (ent != &cl_entities[0].render)
-               R_PrepareBrushModel(ent);
-       R_DrawSurfaces(ent, SHADERSTAGE_BASELIGHTING);
-       /*
-       shadowmesh_t *mesh;
-       if (!cl.worldmodel->numlights)
-               GL_Color(0.3, 0.3, 0.3, 1);
-       for (mesh = ent->model->shadowmesh;mesh;mesh = mesh->next)
-       {
-               R_Mesh_ResizeCheck(mesh->numverts);
-               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->elements);
-       }
-       if (!cl.worldmodel->numlights)
-               GL_Color(0, 0, 0, 1);
-       */
-}
-
-void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
+void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
 {
-#if 1
-       float projectdistance, temp[3];
-       shadowmesh_t *mesh;
-       VectorSubtract(relativelightorigin, ent->model->shadowmesh_center, temp);
-       projectdistance = lightradius + ent->model->shadowmesh_radius - sqrt(DotProduct(temp, temp));
-       if (projectdistance >= 0.1)
-       {
-               R_Mesh_Matrix(&ent->matrix);
-               for (mesh = ent->model->shadowmesh;mesh;mesh = mesh->next)
-               {
-                       R_Mesh_ResizeCheck(mesh->numverts * 2);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->elements, mesh->neighbors, relativelightorigin, lightradius, projectdistance, visiblevolume);
-               }
-       }
-#else
        int i;
        msurface_t *surf;
        float projectdistance, f, temp[3], lightradius2;
        surfmesh_t *mesh;
        R_Mesh_Matrix(&ent->matrix);
        lightradius2 = lightradius * lightradius;
+       R_UpdateTextureInfo(ent);
+       projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
        for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
        {
-               if (surf->rendertype == SURFRENDER_OPAQUE && surf->flags & SURF_SHADOWCAST)
+               if (surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && surf->flags & SURF_SHADOWCAST)
                {
                        f = PlaneDiff(relativelightorigin, surf->plane);
                        if (surf->flags & SURF_PLANEBACK)
                                f = -f;
-                       // draw shadows only for backfaces
-                       projectdistance = lightradius + f;
-                       if (projectdistance >= 0.1 && projectdistance < lightradius)
+                       // draw shadows only for frontfaces and only if they are close
+                       if (f >= 0.1 && f < lightradius)
                        {
-                               VectorSubtract(relativelightorigin, surf->poly_center, temp);
-                               if (DotProduct(temp, temp) < (surf->poly_radius2 + lightradius2))
+                               temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0];
+                               temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1];
+                               temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2];
+                               if (DotProduct(temp, temp) < lightradius2)
                                {
                                        for (mesh = surf->mesh;mesh;mesh = mesh->chain)
                                        {
                                                R_Mesh_ResizeCheck(mesh->numverts * 2);
                                                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                               R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->index, mesh->triangleneighbors, relativelightorigin, lightradius, projectdistance, visiblevolume);
+                                               R_Shadow_Volume(mesh->numverts, mesh->numtriangles, mesh->index, mesh->triangleneighbors, relativelightorigin, lightradius, projectdistance);
                                        }
                                }
                        }
                }
        }
-#endif
 }
 
-void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+void R_Model_Brush_DrawLightForSurfaceList(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, msurface_t **surflist, int numsurfaces)
 {
-       int tnum;
+       int surfnum;
        msurface_t *surf;
        texture_t *t;
-       float f, lightradius2;
        surfmesh_t *mesh;
        R_Mesh_Matrix(&ent->matrix);
-       if (ent != &cl_entities[0].render)
-               R_PrepareBrushModel(ent);
-       lightradius2 = lightradius * lightradius;
-       for (tnum = 0;tnum < ent->model->numtextures;tnum++)
+       R_UpdateTextureInfo(ent);
+       for (surfnum = 0;surfnum < numsurfaces;surfnum++)
        {
-               t = ent->model->textures + tnum;
-               if (ent->model->texturesurfacechains[tnum] && t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
+               surf = surflist[surfnum];
+               if (surf->visframe == r_framecount)
                {
-                       t = t->currentframe[ent->frame != 0];
-                       for (surf = ent->model->texturesurfacechains[tnum];surf;surf = surf->texturechain)
+                       t = surf->texinfo->texture->currentframe;
+                       if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
                        {
-                               if (surf->visframe == r_framecount)
+                               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
                                {
-                                       f = PlaneDiff(relativelightorigin, surf->plane);
-                                       if (surf->flags & SURF_PLANEBACK)
-                                               f = -f;
-                                       if (f >= -0.1 && f < lightradius)
-                                       {
-                                               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
-                                               {
-                                                       R_Mesh_ResizeCheck(mesh->numverts);
-                                                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                                       R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->texture, t->glosstexture, t->nmaptexture, NULL);
-                                               }
-                                       }
+                                       R_Mesh_ResizeCheck(mesh->numverts);
+                                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                                       R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL);
+                                       R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL);
                                }
                        }
                }
        }
 }
 
-/*
-extern cvar_t r_shadows;
-void R_DrawBrushModelFakeShadow (entity_render_t *ent)
+void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor)
 {
-       int i;
-       vec3_t relativelightorigin;
-       rmeshstate_t m;
-       mlight_t *sl;
-       rdlight_t *rd;
-       svbspmesh_t *mesh;
-
-       if (r_shadows.integer < 2)
-               return;
-
-       memset(&m, 0, sizeof(m));
-       m.blendfunc1 = GL_ONE;
-       m.blendfunc2 = GL_ONE;
-       R_Mesh_State(&m);
+       int surfnum;
+       msurface_t *surf;
+       texture_t *t;
+       float f, lightradius2, temp[3];
+       surfmesh_t *mesh;
        R_Mesh_Matrix(&ent->matrix);
-       GL_Color(0.0125 * r_colorscale, 0.025 * r_colorscale, 0.1 * r_colorscale, 1);
-       if (0)//ent->model == cl.worldmodel)
+       lightradius2 = lightradius * lightradius;
+       R_UpdateTextureInfo(ent);
+       if (ent != &cl_entities[0].render)
        {
-               for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++)
+               // bmodel, cull crudely to view and light
+               for (surfnum = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;surfnum < ent->model->nummodelsurfaces;surfnum++, surf++)
                {
-                       if (d_lightstylevalue[sl->style] > 0 && R_NotCulledBox(sl->shadowvolumemins, sl->shadowvolumemaxs))
+                       temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0];
+                       temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1];
+                       temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2];
+                       if (DotProduct(temp, temp) < lightradius2)
                        {
-                               for (mesh = sl->shadowvolume;mesh;mesh = mesh->next)
+                               f = PlaneDiff(relativelightorigin, surf->plane);
+                               if (surf->flags & SURF_PLANEBACK)
+                                       f = -f;
+                               if (f >= -0.1 && f < lightradius)
                                {
-                                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->elements);
+                                       f = PlaneDiff(relativeeyeorigin, surf->plane);
+                                       if (surf->flags & SURF_PLANEBACK)
+                                               f = -f;
+                                       if (f > 0)
+                                       {
+                                               t = surf->texinfo->texture->currentframe;
+                                               if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
+                                               {
+                                                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                                                       {
+                                                               R_Mesh_ResizeCheck(mesh->numverts);
+                                                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                                                               R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL);
+                                                               R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL);
+                                                       }
+                                               }
+                                       }
                                }
                        }
                }
        }
        else
        {
-               for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++)
+               // world, already culled to view, just cull to light
+               for (surfnum = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;surfnum < ent->model->nummodelsurfaces;surfnum++, surf++)
                {
-                       if (d_lightstylevalue[sl->style] > 0
-                        && ent->maxs[0] >= sl->origin[0] - sl->cullradius
-                        && ent->mins[0] <= sl->origin[0] + sl->cullradius
-                        && ent->maxs[1] >= sl->origin[1] - sl->cullradius
-                        && ent->mins[1] <= sl->origin[1] + sl->cullradius
-                        && ent->maxs[2] >= sl->origin[2] - sl->cullradius
-                        && ent->mins[2] <= sl->origin[2] + sl->cullradius)
+                       if (surf->visframe == r_framecount)
                        {
-                               Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
-                               R_DrawBrushModelShadowVolume (ent, relativelightorigin, sl->cullradius, true);
+                               temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0];
+                               temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1];
+                               temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2];
+                               if (DotProduct(temp, temp) < lightradius2)
+                               {
+                                       f = PlaneDiff(relativelightorigin, surf->plane);
+                                       if (surf->flags & SURF_PLANEBACK)
+                                               f = -f;
+                                       if (f >= -0.1 && f < lightradius)
+                                       {
+                                               t = surf->texinfo->texture->currentframe;
+                                               if (t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
+                                               {
+                                                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                                                       {
+                                                               R_Mesh_ResizeCheck(mesh->numverts);
+                                                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                                                               R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL);
+                                                               R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL);
+                                                       }
+                                               }
+                                       }
+                               }
                        }
                }
        }
-       for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
-       {
-               if (ent->maxs[0] >= rd->origin[0] - rd->cullradius
-                && ent->mins[0] <= rd->origin[0] + rd->cullradius
-                && ent->maxs[1] >= rd->origin[1] - rd->cullradius
-                && ent->mins[1] <= rd->origin[1] + rd->cullradius
-                && ent->maxs[2] >= rd->origin[2] - rd->cullradius
-                && ent->mins[2] <= rd->origin[2] + rd->cullradius)
-               {
-                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                       R_DrawBrushModelShadowVolume (ent, relativelightorigin, rd->cullradius, true);
-               }
-       }
 }
-*/
 
 static void gl_surf_start(void)
 {