]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
r_nearclip cvar
[xonotic/darkplaces.git] / gl_rmain.c
index 3e6c5d6859628e40097000f404f3567ee3baf52e..2f262bc0fc0bab6877a5b6a8bb2e81797c03d834 100644 (file)
@@ -28,8 +28,6 @@ int r_framecount;
 
 mplane_t frustum[5];
 
-matrix4x4_t r_identitymatrix;
-
 renderstats_t renderstats;
 
 // true during envmap command capture
@@ -69,6 +67,7 @@ matrix4x4_t r_view_matrix;
 //
 refdef_t r_refdef;
 
+cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
@@ -450,9 +449,9 @@ void gl_main_newmap(void)
 
 void GL_Main_Init(void)
 {
-       Matrix4x4_CreateIdentity(&r_identitymatrix);
 // FIXME: move this to client?
        FOG_registercvars();
+       Cvar_RegisterVariable(&r_nearclip);
        Cvar_RegisterVariable(&r_showtris);
        Cvar_RegisterVariable(&r_showtris_polygonoffset);
        Cvar_RegisterVariable(&r_shownormals);
@@ -742,7 +741,7 @@ static void R_SetFrustum(void)
 #endif
 
 #if 0
-       zNear = 1.0;
+       zNear = r_nearclip.value;
        nudge = 1.0 - 1.0 / (1<<23);
        frustum[4].normal[0] = 0 - 0;
        frustum[4].normal[1] = 0 - 0;
@@ -803,7 +802,7 @@ static void R_SetFrustum(void)
        frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
        frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
        frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
-       frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
+       frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
        PlaneClassify(&frustum[0]);
        PlaneClassify(&frustum[1]);
        PlaneClassify(&frustum[2]);
@@ -836,7 +835,7 @@ static void R_SetFrustum(void)
 
        // nearclip plane
        //VectorCopy(r_viewforward, frustum[4].normal);
-       //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
+       //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
        //PlaneClassify(&frustum[4]);
 }
 
@@ -862,7 +861,7 @@ static void R_BlendView(void)
        GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
        GL_DepthMask(true);
        GL_DepthTest(false);
-       R_Mesh_Matrix(&r_identitymatrix);
+       R_Mesh_Matrix(&identitymatrix);
        // vertex coordinates for a quad that covers the screen exactly
        varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
        varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
@@ -1167,6 +1166,8 @@ extern void R_DrawLightningBeams (void);
 extern void VM_AddPolygonsToMeshQueue (void);
 void R_RenderScene(void)
 {
+       float nearclip;
+
        // don't let sound skip if going slow
        if (r_refdef.extraupdate)
                S_ExtraUpdate ();
@@ -1178,10 +1179,12 @@ void R_RenderScene(void)
        R_SetFrustum();
 
        r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
+       nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
+
        if (r_rtworldshadows || r_rtdlightshadows)
-               GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
+               GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
        else
-               GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
+               GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
 
        GL_SetupView_Orientation_FromEntity(&r_view_matrix);
 
@@ -1333,7 +1336,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        GL_DepthMask(false);
        GL_DepthTest(true);
-       R_Mesh_Matrix(&r_identitymatrix);
+       R_Mesh_Matrix(&identitymatrix);
 
        vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
        vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
@@ -1498,7 +1501,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_
                fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
        ifog = 1 - fog;
 
-       R_Mesh_Matrix(&r_identitymatrix);
+       R_Mesh_Matrix(&identitymatrix);
        GL_BlendFunc(blendfunc1, blendfunc2);
        GL_DepthMask(false);
        GL_DepthTest(!depthdisable);
@@ -1600,7 +1603,7 @@ void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *plane
        }
 }
 
-void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, matrix4x4_t *matrix, float r, float g, float b, float a)
+static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
 {
        texturelayer_t *layer;
        layer = t->currentlayers + t->currentnumlayers++;
@@ -1656,17 +1659,17 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
        if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
                t->currenttexmatrix = r_waterscrollmatrix;
        else
-               t->currenttexmatrix = r_identitymatrix;
+               t->currenttexmatrix = identitymatrix;
        t->currentnumlayers = 0;
        if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
        {
                if (gl_lightmaps.integer)
-                       R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
+                       R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
                else if (t->currentmaterialflags & MATERIALFLAG_SKY)
                {
                        // transparent sky would be ridiculous
                        if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
-                               R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
+                               R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
                }
                else
                {
@@ -1751,7 +1754,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                                        // were darkened by fog already, and we should not add fog color
                                        // (because the background was not darkened, there is no fog color
                                        // that was lost behind it).
-                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
+                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
                                }
                        }
                }
@@ -1772,72 +1775,44 @@ float *rsurface_tvector3f;
 float *rsurface_normal3f;
 float *rsurface_lightmapcolor4f;
 
-void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
+void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
 {
-       int i, j;
-       float center[3], forward[3], right[3], up[3], v[4][3];
-       matrix4x4_t matrix1, imatrix1;
        if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
        {
                rsurface_vertex3f = varray_vertex3f;
-               rsurface_svector3f = NULL;
-               rsurface_tvector3f = NULL;
-               rsurface_normal3f = NULL;
                Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
-       }
-       else
-       {
-               rsurface_vertex3f = surface->groupmesh->data_vertex3f;
-               rsurface_svector3f = surface->groupmesh->data_svector3f;
-               rsurface_tvector3f = surface->groupmesh->data_tvector3f;
-               rsurface_normal3f = surface->groupmesh->data_normal3f;
-       }
-       if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
-       {
-               if (!rsurface_svector3f)
+               if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
                {
                        rsurface_svector3f = varray_svector3f;
                        rsurface_tvector3f = varray_tvector3f;
                        rsurface_normal3f = varray_normal3f;
                        Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
                }
-               // a single autosprite surface can contain multiple sprites...
-               VectorClear(forward);
-               VectorClear(right);
-               VectorSet(up, 0, 0, 1);
-               for (j = 0;j < surface->num_vertices - 3;j += 4)
+               else
                {
-                       VectorClear(center);
-                       for (i = 0;i < 4;i++)
-                               VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
-                       VectorScale(center, 0.25f, center);
-                       // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
-                       Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
-                       Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
-                       for (i = 0;i < 4;i++)
-                               Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
-                       forward[0] = modelorg[0] - center[0];
-                       forward[1] = modelorg[1] - center[1];
-                       VectorNormalize(forward);
-                       right[0] = forward[1];
-                       right[1] = -forward[0];
-                       for (i = 0;i < 4;i++)
-                               VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
+                       rsurface_svector3f = NULL;
+                       rsurface_tvector3f = NULL;
+                       if (generatenormals)
+                       {
+                               rsurface_normal3f = varray_normal3f;
+                               Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
+                       }
+                       else
+                               rsurface_normal3f = NULL;
                }
-               rsurface_vertex3f = varray_vertex3f;
-               rsurface_svector3f = NULL;
-               rsurface_tvector3f = NULL;
-               rsurface_normal3f = NULL;
        }
-       else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
+       else
        {
-               if (!rsurface_svector3f)
-               {
-                       rsurface_svector3f = varray_svector3f;
-                       rsurface_tvector3f = varray_tvector3f;
-                       rsurface_normal3f = varray_normal3f;
-                       Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
-               }
+               rsurface_vertex3f = surface->groupmesh->data_vertex3f;
+               rsurface_svector3f = surface->groupmesh->data_svector3f;
+               rsurface_tvector3f = surface->groupmesh->data_tvector3f;
+               rsurface_normal3f = surface->groupmesh->data_normal3f;
+       }
+       if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+       {
+               int i, j;
+               float center[3], forward[3], right[3], up[3], v[4][3];
+               matrix4x4_t matrix1, imatrix1;
                Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
                Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
                Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
@@ -1853,22 +1828,35 @@ void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture
                        Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
                        for (i = 0;i < 4;i++)
                                Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
+                       if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
+                       {
+                               forward[0] = modelorg[0] - center[0];
+                               forward[1] = modelorg[1] - center[1];
+                               forward[2] = 0;
+                               VectorNormalize(forward);
+                               right[0] = forward[1];
+                               right[1] = -forward[0];
+                               right[2] = 0;
+                               VectorSet(up, 0, 0, 1);
+                       }
                        for (i = 0;i < 4;i++)
                                VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
                }
                rsurface_vertex3f = varray_vertex3f;
-               rsurface_svector3f = NULL;
-               rsurface_tvector3f = NULL;
-               rsurface_normal3f = NULL;
+               rsurface_svector3f = varray_svector3f;
+               rsurface_tvector3f = varray_tvector3f;
+               rsurface_normal3f = varray_normal3f;
+               Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
        }
        R_Mesh_VertexPointer(rsurface_vertex3f);
 }
 
-void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
 {
        int i;
        float f;
        float *v, *c, *c2;
+       RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode == 2, false);
        if (lightmode >= 2)
        {
                // model lighting
@@ -1878,11 +1866,6 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface
                if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
                {
                        rsurface_lightmapcolor4f = varray_color4f;
-                       if (rsurface_normal3f == NULL)
-                       {
-                               rsurface_normal3f = varray_normal3f;
-                               Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
-                       }
                        R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
                        r = 1;
                        g = 1;
@@ -1901,13 +1884,13 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface
        }
        else if (lightmode >= 1)
        {
-               if (surface->lightmapinfo)
+               if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
                {
                        for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
                        {
-                               const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
-                               if (lm)
+                               if (surface->lightmapinfo->samples)
                                {
+                                       const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
                                        float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
                                        VectorScale(lm, scale, c);
                                        if (surface->lightmapinfo->styles[1] != 255)
@@ -1979,6 +1962,16 @@ void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface
        }
        R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
        GL_Color(r, g, b, a);
+       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+       GL_LockArrays(0, 0);
+}
+
+static void RSurf_Draw(const msurface_t *surface)
+{
+       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+       GL_LockArrays(0, 0);
 }
 
 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
@@ -1987,6 +1980,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
        int lightmode;
        const msurface_t *surface;
        qboolean applycolor;
+       qboolean applyfog;
        rmeshstate_t m;
        if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
                return;
@@ -2024,6 +2018,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        layercolor[3] = layer->color[3];
                        GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
                        applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
+                       applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
                        switch (layer->type)
                        {
                        case TEXTURELAYERTYPE_SKY:
@@ -2059,10 +2054,8 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                        for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                        {
                                                surface = texturesurfacelist[texturesurfaceindex];
-                                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
-                                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                               GL_LockArrays(0, 0);
+                                               RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
+                                               RSurf_Draw(surface);
                                        }
                                        if (skyrendermasked)
                                                GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
@@ -2075,30 +2068,35 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                m.texrgbscale[1] = layertexrgbscale;
                                m.pointer_color = varray_color4f;
                                R_Mesh_State(&m);
-                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                               if (lightmode == 2)
                                {
-                                       surface = texturesurfacelist[texturesurfaceindex];
-                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
-                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
-                                       R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
-                                       if (lightmode == 2)
+                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                        {
+                                               surface = texturesurfacelist[texturesurfaceindex];
+                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
+                                               R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
                                                R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                               RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
-                                       }
-                                       else if (surface->lightmaptexture)
-                                       {
-                                               R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
-                                               RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
+                                               RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
                                        }
-                                       else
+                               }
+                               else
+                               {
+                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                        {
-                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                               RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
+                                               surface = texturesurfacelist[texturesurfaceindex];
+                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
+                                               R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
+                                               if (surface->lightmaptexture)
+                                               {
+                                                       R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
+                                                       RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
+                                               }
+                                               else
+                                               {
+                                                       R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+                                                       RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
+                                               }
                                        }
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
                                }
                                break;
                        case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
@@ -2108,29 +2106,33 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                m.pointer_color = varray_color4f;
                                m.texrgbscale[0] = layertexrgbscale;
                                R_Mesh_State(&m);
-                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                               if (lightmode == 2)
                                {
-                                       surface = texturesurfacelist[texturesurfaceindex];
-                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
-                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
-                                       if (lightmode == 2)
+                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                        {
+                                               surface = texturesurfacelist[texturesurfaceindex];
+                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
                                                R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                               RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
-                                       }
-                                       else if (surface->lightmaptexture)
-                                       {
-                                               R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
-                                               R_Mesh_ColorPointer(NULL);
+                                               RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
                                        }
-                                       else
+                               }
+                               else
+                               {
+                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                        {
-                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                               RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
+                                               surface = texturesurfacelist[texturesurfaceindex];
+                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
+                                               if (surface->lightmaptexture)
+                                               {
+                                                       R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
+                                                       RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
+                                               }
+                                               else
+                                               {
+                                                       R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+                                                       RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
+                                               }
                                        }
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
                                }
                                GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
                                memset(&m, 0, sizeof(m));
@@ -2142,12 +2144,8 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
                                        surface = texturesurfacelist[texturesurfaceindex];
-                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
                                        R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                       RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
+                                       RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
                                }
                                break;
                        case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
@@ -2157,15 +2155,23 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                m.texrgbscale[0] = layertexrgbscale;
                                m.pointer_color = varray_color4f;
                                R_Mesh_State(&m);
-                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                               if (lightmode == 2)
                                {
-                                       surface = texturesurfacelist[texturesurfaceindex];
-                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
-                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                       RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
+                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                                       {
+                                               surface = texturesurfacelist[texturesurfaceindex];
+                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                                               RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
+                                       }
+                               }
+                               else
+                               {
+                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                                       {
+                                               surface = texturesurfacelist[texturesurfaceindex];
+                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                                               RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
+                                       }
                                }
                                break;
                        case TEXTURELAYERTYPE_TEXTURE:
@@ -2178,12 +2184,8 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
                                        surface = texturesurfacelist[texturesurfaceindex];
-                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
                                        R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                       RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
+                                       RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
                                }
                                break;
                        case TEXTURELAYERTYPE_FOG:
@@ -2199,7 +2201,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                        int i;
                                        float f, *v, *c;
                                        surface = texturesurfacelist[texturesurfaceindex];
-                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
                                        if (layer->texture)
                                                R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
                                        R_Mesh_ColorPointer(varray_color4f);
@@ -2211,9 +2213,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                                c[2] = layercolor[2];
                                                c[3] = f * layercolor[3];
                                        }
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
+                                       RSurf_Draw(surface);
                                }
                                break;
                        default:
@@ -2231,11 +2231,9 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
                                        surface = texturesurfacelist[texturesurfaceindex];
-                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
                                        for (scale = 1;scale < layertexrgbscale;scale <<= 1)
-                                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
+                                               RSurf_Draw(surface);
                                }
                        }
                }
@@ -2251,14 +2249,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                        {
                                surface = texturesurfacelist[texturesurfaceindex];
-                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
-                               if (!rsurface_svector3f)
-                               {
-                                       rsurface_svector3f = varray_svector3f;
-                                       rsurface_tvector3f = varray_tvector3f;
-                                       rsurface_normal3f = varray_normal3f;
-                                       Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
-                               }
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
                                GL_Color(1, 0, 0, 1);
                                qglBegin(GL_LINES);
                                for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
@@ -2391,7 +2382,7 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
                        if (f && surface->num_triangles)
                        {
                                // if lightmap parameters changed, rebuild lightmap texture
-                               if (surface->cached_dlight && surface->lightmapinfo->samples)
+                               if (surface->cached_dlight)
                                        R_BuildLightMap(ent, surface);
                                // add face to draw list
                                surfacelist[numsurfacelist++] = surface;
@@ -2422,7 +2413,7 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
                        if (f && surface->num_triangles)
                        {
                                // if lightmap parameters changed, rebuild lightmap texture
-                               if (surface->cached_dlight && surface->lightmapinfo->samples)
+                               if (surface->cached_dlight)
                                        R_BuildLightMap(ent, surface);
                                // add face to draw list
                                surfacelist[numsurfacelist++] = surface;