]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
fixed bug that was causing prediction to fail periodically in singleplayer games...
[xonotic/darkplaces.git] / gl_rmain.c
index 095a5f9cdcfc3e3d0caaeabc1ecebc048109860b..361012e3f02ac04b445383fc56e2fb9569f427b9 100644 (file)
@@ -1122,7 +1122,7 @@ void GL_Main_Init(void)
 {
        r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
 
-       Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
+       Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
        FOG_registercvars(); // FIXME: move this fog stuff to client?
        Cvar_RegisterVariable(&r_nearclip);
        Cvar_RegisterVariable(&r_showsurfaces);
@@ -2350,7 +2350,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight
                GL_DepthMask(true);
        }
        GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
-       GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+       GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
        R_Mesh_VertexPointer(nomodelvertex3f);
        if (r_refdef.fogenabled)
        {
@@ -2653,8 +2653,8 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
        else if (t->currentalpha < 1)
                t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
-       if (ent->flags & RENDER_NOCULLFACE)
-               t->currentmaterialflags |= MATERIALFLAG_NOSHADOW;
+       if (ent->effects & EF_DOUBLESIDED)
+               t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
        if (ent->effects & EF_NODEPTHTEST)
                t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
        if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
@@ -2851,17 +2851,36 @@ void RSurf_CleanUp(void)
        rsurface_texture = NULL;
 }
 
-void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
+void RSurf_ActiveWorldEntity(void)
+{
+       RSurf_CleanUp();
+       rsurface_entity = r_refdef.worldentity;
+       rsurface_model = r_refdef.worldmodel;
+       if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
+               R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
+       R_Mesh_Matrix(&identitymatrix);
+       VectorCopy(r_view.origin, rsurface_modelorg);
+       rsurface_modelvertex3f  = rsurface_model->surfmesh.data_vertex3f;
+       rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
+       rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
+       rsurface_modelnormal3f  = rsurface_model->surfmesh.data_normal3f;
+       rsurface_generatedvertex = false;
+       rsurface_vertex3f  = rsurface_modelvertex3f;
+       rsurface_svector3f = rsurface_modelsvector3f;
+       rsurface_tvector3f = rsurface_modeltvector3f;
+       rsurface_normal3f  = rsurface_modelnormal3f;
+}
+
+void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
 {
        RSurf_CleanUp();
-       Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
        rsurface_entity = ent;
        rsurface_model = ent->model;
        if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
                R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
        R_Mesh_Matrix(&ent->matrix);
        Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
-       if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
+       if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
        {
                if (wanttangents)
                {
@@ -3393,7 +3412,7 @@ static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t
 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
 {
        GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
-       GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+       GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
        if (rsurface_mode != RSURFMODE_SHOWSURFACES)
        {
                rsurface_mode = RSURFMODE_SHOWSURFACES;
@@ -3427,7 +3446,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **te
                R_Mesh_Matrix(&rsurface_entity->matrix);
        }
        GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
-       GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+       GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
        GL_DepthMask(true);
        // LordHavoc: HalfLife maps have freaky skypolys so don't use
        // skymasking on them, and Quake3 never did sky masking (unlike
@@ -3762,7 +3781,7 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur
        else if (rsurface_texture->currentnumlayers)
        {
                GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
-               GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+               GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
                GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
                GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
                GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
@@ -3791,10 +3810,12 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
        // if the model is static it doesn't matter what value we give for
        // wantnormals and wanttangents, so this logic uses only rules applicable
        // to a model, knowing that they are meaningless otherwise
-       if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
-               RSurf_ActiveEntity(ent, false, false);
+       if (ent == r_refdef.worldentity)
+               RSurf_ActiveWorldEntity();
+       else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
+               RSurf_ActiveModelEntity(ent, false, false);
        else
-               RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
+               RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
 
        for (i = 0;i < numsurfaces;i = j)
        {
@@ -3821,7 +3842,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
        RSurf_CleanUp();
 }
 
-void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist)
+void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
 {
        int i, j;
        vec3_t tempcenter, center;
@@ -3837,6 +3858,13 @@ void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist)
                texture = surfacelist[i]->texture;
                rsurface_texture = texture->currentframe;
                rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
+               if (!(rsurface_texture->currentmaterialflags & flagsmask))
+               {
+                       // if this texture is not the kind we want, skip ahead to the next one
+                       for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
+                               ;
+                       continue;
+               }
                if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
                {
                        // transparent surfaces get pushed off into the transparent queue
@@ -3849,38 +3877,136 @@ void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist)
                }
                else
                {
-                       // simply scan ahead until we find a different texture
-                       for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++);
+                       // simply scan ahead until we find a different texture or lightmap state
+                       for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
+                               ;
                        // render the range of surfaces
                        R_DrawTextureSurfaceList(j - i, surfacelist + i);
                }
        }
 }
 
-extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
-void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
+void R_DrawCollisionBrushes(entity_render_t *ent)
 {
-       int i, j, k, l, endj, f, flagsmask;
-       int counttriangles = 0;
-       msurface_t *surface, *endsurface, **surfacechain;
-       texture_t *t;
+       int i;
        q3mbrush_t *brush;
+       msurface_t *surface;
        model_t *model = ent->model;
+       if (!model->brush.num_brushes)
+               return;
+       CHECKGLERROR
+       R_Mesh_ColorPointer(NULL);
+       R_Mesh_ResetTextureState();
+       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+       GL_DepthMask(false);
+       GL_DepthTest(!r_showdisabledepthtest.integer);
+       qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
+       for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
+               if (brush->colbrushf && brush->colbrushf->numtriangles)
+                       R_DrawCollisionBrush(brush->colbrushf);
+       for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+               if (surface->num_collisiontriangles)
+                       R_DrawCollisionSurface(ent, surface);
+       qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+}
+
+void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
+{
+       int i, j, k, l;
        const int *elements;
+       msurface_t *surface;
+       model_t *model = ent->model;
+       vec3_t v;
+       CHECKGLERROR
+       GL_DepthTest(!r_showdisabledepthtest.integer);
+       GL_DepthMask(true);
+       GL_BlendFunc(GL_ONE, GL_ZERO);
+       R_Mesh_ColorPointer(NULL);
+       R_Mesh_ResetTextureState();
+       for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+       {
+               if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
+                       continue;
+               rsurface_texture = surface->texture->currentframe;
+               if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
+               {
+                       RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
+                       if (drawtris)
+                       {
+                               if (!rsurface_texture->currentlayers->depthmask)
+                                       GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
+                               else if (ent == r_refdef.worldentity)
+                                       GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
+                               else
+                                       GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
+                               elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
+                               CHECKGLERROR
+                               qglBegin(GL_LINES);
+                               for (k = 0;k < surface->num_triangles;k++, elements += 3)
+                               {
+                                       qglArrayElement(elements[0]);qglArrayElement(elements[1]);
+                                       qglArrayElement(elements[1]);qglArrayElement(elements[2]);
+                                       qglArrayElement(elements[2]);qglArrayElement(elements[0]);
+                               }
+                               qglEnd();
+                               CHECKGLERROR
+                       }
+                       if (drawnormals)
+                       {
+                               GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
+                               qglBegin(GL_LINES);
+                               for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+                               {
+                                       VectorCopy(rsurface_vertex3f + l * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                                       VectorMA(v, 8, rsurface_svector3f + l * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                               }
+                               qglEnd();
+                               CHECKGLERROR
+                               GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
+                               qglBegin(GL_LINES);
+                               for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+                               {
+                                       VectorCopy(rsurface_vertex3f + l * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                                       VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                               }
+                               qglEnd();
+                               CHECKGLERROR
+                               GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
+                               qglBegin(GL_LINES);
+                               for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+                               {
+                                       VectorCopy(rsurface_vertex3f + l * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                                       VectorMA(v, 8, rsurface_normal3f + l * 3, v);
+                                       qglVertex3f(v[0], v[1], v[2]);
+                               }
+                               qglEnd();
+                               CHECKGLERROR
+                       }
+               }
+       }
+       rsurface_texture = NULL;
+}
+
+extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
+void R_DrawWorldSurfaces(qboolean skysurfaces)
+{
+       int i, j, endj, f, flagsmask;
+       int counttriangles = 0;
+       msurface_t *surface, **surfacechain;
+       texture_t *t;
+       model_t *model = r_refdef.worldmodel;
        const int maxsurfacelist = 1024;
        int numsurfacelist = 0;
        msurface_t *surfacelist[1024];
-       vec3_t v;
        if (model == NULL)
                return;
 
-       // if the model is static it doesn't matter what value we give for
-       // wantnormals and wanttangents, so this logic uses only rules applicable
-       // to a model, knowing that they are meaningless otherwise
-       if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
-               RSurf_ActiveEntity(ent, false, false);
-       else
-               RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
+       RSurf_ActiveWorldEntity();
 
        // update light styles
        if (!skysurfaces && model->brushq1.light_styleupdatechains)
@@ -3897,166 +4023,127 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
                }
        }
 
-       R_UpdateAllTextureInfo(ent);
+       R_UpdateAllTextureInfo(r_refdef.worldentity);
        flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
        f = 0;
        t = NULL;
        rsurface_uselightmaptexture = false;
        rsurface_texture = NULL;
        numsurfacelist = 0;
-       if (ent == r_refdef.worldentity)
+       j = model->firstmodelsurface;
+       endj = j + model->nummodelsurfaces;
+       while (j < endj)
        {
-               j = model->firstmodelsurface;
-               endj = j + model->nummodelsurfaces;
-               while (j < endj)
-               {
-                       // quickly skip over non-visible surfaces
-                       for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
-                               ;
-                       // quickly iterate over visible surfaces
-                       for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
-                       {
-                               // process this surface
-                               surface = model->data_surfaces + j;
-                               // if this surface fits the criteria, add it to the list
-                               if (surface->texture->basematerialflags & flagsmask && surface->num_triangles)
-                               {
-                                       // if lightmap parameters changed, rebuild lightmap texture
-                                       if (surface->cached_dlight)
-                                               R_BuildLightMap(ent, surface);
-                                       // add face to draw list
-                                       surfacelist[numsurfacelist++] = surface;
-                                       counttriangles += surface->num_triangles;
-                                       if (numsurfacelist >= maxsurfacelist)
-                                       {
-                                               R_QueueSurfaceList(numsurfacelist, surfacelist);
-                                               numsurfacelist = 0;
-                                       }
-                               }
-                       }
-               }
-       }
-       else
-       {
-               surface = model->data_surfaces + model->firstmodelsurface;
-               endsurface = surface + model->nummodelsurfaces;
-               for (;surface < endsurface;surface++)
+               // quickly skip over non-visible surfaces
+               for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
+                       ;
+               // quickly iterate over visible surfaces
+               for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
                {
+                       // process this surface
+                       surface = model->data_surfaces + j;
                        // if this surface fits the criteria, add it to the list
-                       if (surface->texture->basematerialflags & flagsmask && surface->num_triangles)
+                       if (surface->num_triangles)
                        {
                                // if lightmap parameters changed, rebuild lightmap texture
                                if (surface->cached_dlight)
-                                       R_BuildLightMap(ent, surface);
+                                       R_BuildLightMap(r_refdef.worldentity, surface);
                                // add face to draw list
                                surfacelist[numsurfacelist++] = surface;
                                counttriangles += surface->num_triangles;
                                if (numsurfacelist >= maxsurfacelist)
                                {
-                                       R_QueueSurfaceList(numsurfacelist, surfacelist);
+                                       R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
                                        numsurfacelist = 0;
                                }
                        }
                }
        }
        if (numsurfacelist)
-               R_QueueSurfaceList(numsurfacelist, surfacelist);
+               R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
        r_refdef.stats.entities_triangles += counttriangles;
        RSurf_CleanUp();
 
-       if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
+       if (r_showcollisionbrushes.integer && !skysurfaces)
+               R_DrawCollisionBrushes(r_refdef.worldentity);
+
+       if (r_showtris.integer || r_shownormals.integer)
+               R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
+}
+
+void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
+{
+       int i, f, flagsmask;
+       int counttriangles = 0;
+       msurface_t *surface, *endsurface, **surfacechain;
+       texture_t *t;
+       model_t *model = ent->model;
+       const int maxsurfacelist = 1024;
+       int numsurfacelist = 0;
+       msurface_t *surfacelist[1024];
+       if (model == NULL)
+               return;
+
+       // if the model is static it doesn't matter what value we give for
+       // wantnormals and wanttangents, so this logic uses only rules applicable
+       // to a model, knowing that they are meaningless otherwise
+       if (ent == r_refdef.worldentity)
+               RSurf_ActiveWorldEntity();
+       else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
+               RSurf_ActiveModelEntity(ent, false, false);
+       else
+               RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
+
+       // update light styles
+       if (!skysurfaces && model->brushq1.light_styleupdatechains)
        {
-               CHECKGLERROR
-               R_Mesh_Matrix(&ent->matrix);
-               R_Mesh_ColorPointer(NULL);
-               R_Mesh_ResetTextureState();
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               GL_DepthMask(false);
-               GL_DepthTest(!r_showdisabledepthtest.integer);
-               qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
-               for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
-                       if (brush->colbrushf && brush->colbrushf->numtriangles)
-                               R_DrawCollisionBrush(brush->colbrushf);
-               for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
-                       if (surface->num_collisiontriangles)
-                               R_DrawCollisionSurface(ent, surface);
-               qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+               for (i = 0;i < model->brushq1.light_styles;i++)
+               {
+                       if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
+                       {
+                               model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
+                               if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
+                                       for (;(surface = *surfacechain);surfacechain++)
+                                               surface->cached_dlight = true;
+                       }
+               }
        }
 
-       if (r_showtris.integer || r_shownormals.integer)
+       R_UpdateAllTextureInfo(ent);
+       flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
+       f = 0;
+       t = NULL;
+       rsurface_uselightmaptexture = false;
+       rsurface_texture = NULL;
+       numsurfacelist = 0;
+       surface = model->data_surfaces + model->firstmodelsurface;
+       endsurface = surface + model->nummodelsurfaces;
+       for (;surface < endsurface;surface++)
        {
-               CHECKGLERROR
-               GL_DepthTest(!r_showdisabledepthtest.integer);
-               GL_DepthMask(true);
-               GL_BlendFunc(GL_ONE, GL_ZERO);
-               R_Mesh_ColorPointer(NULL);
-               R_Mesh_ResetTextureState();
-               for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+               // if this surface fits the criteria, add it to the list
+               if (surface->num_triangles)
                {
-                       if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
-                               continue;
-                       rsurface_texture = surface->texture->currentframe;
-                       if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
+                       // if lightmap parameters changed, rebuild lightmap texture
+                       if (surface->cached_dlight)
+                               R_BuildLightMap(ent, surface);
+                       // add face to draw list
+                       surfacelist[numsurfacelist++] = surface;
+                       counttriangles += surface->num_triangles;
+                       if (numsurfacelist >= maxsurfacelist)
                        {
-                               RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
-                               if (r_showtris.integer)
-                               {
-                                       if (!rsurface_texture->currentlayers->depthmask)
-                                               GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
-                                       else if (ent == r_refdef.worldentity)
-                                               GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
-                                       else
-                                               GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
-                                       elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
-                                       CHECKGLERROR
-                                       qglBegin(GL_LINES);
-                                       for (k = 0;k < surface->num_triangles;k++, elements += 3)
-                                       {
-                                               qglArrayElement(elements[0]);qglArrayElement(elements[1]);
-                                               qglArrayElement(elements[1]);qglArrayElement(elements[2]);
-                                               qglArrayElement(elements[2]);qglArrayElement(elements[0]);
-                                       }
-                                       qglEnd();
-                                       CHECKGLERROR
-                               }
-                               if (r_shownormals.integer)
-                               {
-                                       GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
-                                       qglBegin(GL_LINES);
-                                       for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
-                                       {
-                                               VectorCopy(rsurface_vertex3f + l * 3, v);
-                                               qglVertex3f(v[0], v[1], v[2]);
-                                               VectorMA(v, 8, rsurface_svector3f + l * 3, v);
-                                               qglVertex3f(v[0], v[1], v[2]);
-                                       }
-                                       qglEnd();
-                                       CHECKGLERROR
-                                       GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
-                                       qglBegin(GL_LINES);
-                                       for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
-                                       {
-                                               VectorCopy(rsurface_vertex3f + l * 3, v);
-                                               qglVertex3f(v[0], v[1], v[2]);
-                                               VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
-                                               qglVertex3f(v[0], v[1], v[2]);
-                                       }
-                                       qglEnd();
-                                       CHECKGLERROR
-                                       GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
-                                       qglBegin(GL_LINES);
-                                       for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
-                                       {
-                                               VectorCopy(rsurface_vertex3f + l * 3, v);
-                                               qglVertex3f(v[0], v[1], v[2]);
-                                               VectorMA(v, 8, rsurface_normal3f + l * 3, v);
-                                               qglVertex3f(v[0], v[1], v[2]);
-                                       }
-                                       qglEnd();
-                                       CHECKGLERROR
-                               }
+                               R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
+                               numsurfacelist = 0;
                        }
                }
-               rsurface_texture = NULL;
        }
+       if (numsurfacelist)
+               R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
+       r_refdef.stats.entities_triangles += counttriangles;
+       RSurf_CleanUp();
+
+       if (r_showcollisionbrushes.integer && !skysurfaces)
+               R_DrawCollisionBrushes(ent);
+
+       if (r_showtris.integer || r_shownormals.integer)
+               R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);
 }