]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
an attempt at optimizing msurface_t dlight_cache checks by moving them
[xonotic/darkplaces.git] / gl_rmain.c
index 44486d94e212f5815bd6b1c564c936a1e3df410c..2c65e85cc20b0feb2d7f489448c81eb80f2e891b 100644 (file)
@@ -33,7 +33,8 @@ rtexturepool_t *r_main_texturepool;
 //
 r_refdef_t r_refdef;
 
-cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
+cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
+cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
@@ -63,6 +64,7 @@ cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons
 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
+cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
 
 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
@@ -149,36 +151,7 @@ static struct r_bloomstate_s
 }
 r_bloomstate;
 
-typedef struct r_waterstate_waterplane_s
-{
-       rtexture_t *texture_refraction;
-       rtexture_t *texture_reflection;
-       mplane_t plane;
-       int materialflags; // combined flags of all water surfaces on this plane
-       unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
-       qboolean pvsvalid;
-}
-r_waterstate_waterplane_t;
-
-#define MAX_WATERPLANES 16
-
-static struct r_waterstate_s
-{
-       qboolean enabled;
-
-       qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
-
-       int waterwidth, waterheight;
-       int texturewidth, textureheight;
-
-       int maxwaterplanes; // same as MAX_WATERPLANES
-       int numwaterplanes;
-       r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
-
-       float screenscale[2];
-       float screencenter[2];
-}
-r_waterstate;
+r_waterstate_t r_waterstate;
 
 // shadow volume bsp struct with automatically growing nodes buffer
 svbsp_t r_svbsp;
@@ -269,7 +242,7 @@ float FogPoint_World(const vec3_t p)
 
 float FogPoint_Model(const vec3_t p)
 {
-       return FogForDistance(VectorDistance((p), rsurface.modelorg));
+       return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
 }
 
 static void R_BuildBlankTextures(void)
@@ -510,6 +483,7 @@ static const char *builtinshaderstring =
 "// uniform vec4 UserVec3;\n"
 "// uniform vec4 UserVec4;\n"
 "// uniform float ClientTime;\n"
+"// uniform vec2 PixelSize;\n"
 "void main(void)\n"
 "{\n"
 "      gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
@@ -574,7 +548,7 @@ static const char *builtinshaderstring =
 "      gl_FragColor += tex2;\n"
 "#  endif\n"
 "#  ifdef USEVERTEXTEXTUREBLEND\n"
-"      gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n"
+"      gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
 "#  endif\n"
 "}\n"
 "# endif\n"
@@ -606,15 +580,13 @@ static const char *builtinshaderstring =
 "\n"
 "#ifdef MODE_WATER\n"
 "varying vec4 ModelViewProjectionPosition;\n"
-"#else\n"
+"#endif\n"
 "#ifdef MODE_REFRACTION\n"
 "varying vec4 ModelViewProjectionPosition;\n"
-"#else\n"
+"#endif\n"
 "#ifdef USEREFLECTION\n"
 "varying vec4 ModelViewProjectionPosition;\n"
 "#endif\n"
-"#endif\n"
-"#endif\n"
 "\n"
 "\n"
 "\n"
@@ -1208,6 +1180,7 @@ typedef struct r_glsl_permutation_s
        int loc_UserVec3;
        int loc_UserVec4;
        int loc_ClientTime;
+       int loc_PixelSize;
 }
 r_glsl_permutation_t;
 
@@ -1317,6 +1290,7 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per
                // have to look them up every time we set them
                p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
                p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
+               p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
                p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
                p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
                p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
@@ -1366,6 +1340,7 @@ static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t per
                p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
                p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
                p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
+               p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
                // initialize the samplers to refer to the texture units we use
                if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
                if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
@@ -1711,7 +1686,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                }
                else
                {
-                       if (r_glsl_permutation->loc_AmbientScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
+                       if (r_glsl_permutation->loc_AmbientScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
                        if (r_glsl_permutation->loc_DiffuseScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
                        if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
                }
@@ -1761,7 +1736,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                else
                        qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
        }
-       if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
+       if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
        if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
        if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
        CHECKGLERROR
@@ -1918,6 +1893,9 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        if (basepixels == NULL)
                return NULL;
 
+       if (developer_loading.integer)
+               Con_Printf("loading skin \"%s\"\n", name);
+
        // we've got some pixels to store, so really allocate this new texture now
        if (!skinframe)
                skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
@@ -2038,6 +2016,9 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co
        if (!skindata)
                return NULL;
 
+       if (developer_loading.integer)
+               Con_Printf("loading 32bit skin \"%s\"\n", name);
+
        if (r_shadow_bumpscale_basetexture.value > 0)
        {
                temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
@@ -2094,6 +2075,9 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i
        if (!skindata)
                return NULL;
 
+       if (developer_loading.integer)
+               Con_Printf("loading quake skin \"%s\"\n", name);
+
        if (r_shadow_bumpscale_basetexture.value > 0)
        {
                temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
@@ -2248,6 +2232,7 @@ void GL_Main_Init(void)
                Cvar_RegisterVariable (&gl_skyclip);
        }
        Cvar_RegisterVariable(&r_depthfirst);
+       Cvar_RegisterVariable(&r_useinfinitefarclip);
        Cvar_RegisterVariable(&r_nearclip);
        Cvar_RegisterVariable(&r_showbboxes);
        Cvar_RegisterVariable(&r_showsurfaces);
@@ -2277,6 +2262,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
        Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
        Cvar_RegisterVariable(&r_fog_exp2);
+       Cvar_RegisterVariable(&r_drawfog);
        Cvar_RegisterVariable(&r_textureunits);
        Cvar_RegisterVariable(&r_glsl);
        Cvar_RegisterVariable(&r_glsl_contrastboost);
@@ -2362,6 +2348,22 @@ GL_Init
 extern char *ENGINE_EXTENSIONS;
 void GL_Init (void)
 {
+       gl_renderer = (const char *)qglGetString(GL_RENDERER);
+       gl_vendor = (const char *)qglGetString(GL_VENDOR);
+       gl_version = (const char *)qglGetString(GL_VERSION);
+       gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
+
+       if (!gl_extensions)
+               gl_extensions = "";
+       if (!gl_platformextensions)
+               gl_platformextensions = "";
+
+       Con_Printf("GL_VENDOR: %s\n", gl_vendor);
+       Con_Printf("GL_RENDERER: %s\n", gl_renderer);
+       Con_Printf("GL_VERSION: %s\n", gl_version);
+       Con_Printf("GL_EXTENSIONS: %s\n", gl_extensions);
+       Con_Printf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
+
        VID_CheckExtensions();
 
        // LordHavoc: report supported extensions
@@ -2484,11 +2486,14 @@ static void R_View_UpdateEntityVisible (void)
        if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
        {
                // worldmodel can check visibility
+               memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
                for (i = 0;i < r_refdef.scene.numentities;i++)
                {
                        ent = r_refdef.scene.entities[i];
-                       r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
-
+                       if (!(ent->flags & renderimask))
+                       if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
+                       if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
+                               r_refdef.viewcache.entityvisible[i] = true;
                }
                if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
                {
@@ -2781,7 +2786,7 @@ void R_SetupView(qboolean allowwaterclippingplane)
 {
        if (!r_refdef.view.useperspective)
                GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
-       else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
+       else if (gl_stencil && r_useinfinitefarclip.integer)
                GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
        else
                GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
@@ -2927,6 +2932,7 @@ static void R_Water_AddWaterPlane(msurface_t *surface)
        vec3_t vert[3];
        vec3_t normal;
        vec3_t center;
+       mplane_t plane;
        r_waterstate_waterplane_t *p;
        // just use the first triangle with a valid normal for any decisions
        VectorClear(normal);
@@ -2940,6 +2946,21 @@ static void R_Water_AddWaterPlane(msurface_t *surface)
                        break;
        }
 
+       VectorCopy(normal, plane.normal);
+       VectorNormalize(plane.normal);
+       plane.dist = DotProduct(vert[0], plane.normal);
+       PlaneClassify(&plane);
+       if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
+       {
+               // skip backfaces (except if nocullface is set)
+               if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
+                       return;
+               VectorNegate(plane.normal, plane.normal);
+               plane.dist *= -1;
+               PlaneClassify(&plane);
+       }
+
+
        // find a matching plane if there is one
        for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
                if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
@@ -2952,17 +2973,7 @@ static void R_Water_AddWaterPlane(msurface_t *surface)
        {
                // store the new plane
                r_waterstate.numwaterplanes++;
-               VectorCopy(normal, p->plane.normal);
-               VectorNormalize(p->plane.normal);
-               p->plane.dist = DotProduct(vert[0], p->plane.normal);
-               PlaneClassify(&p->plane);
-               // flip the plane if it does not face the viewer
-               if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
-               {
-                       VectorNegate(p->plane.normal, p->plane.normal);
-                       p->plane.dist *= -1;
-                       PlaneClassify(&p->plane);
-               }
+               p->plane = plane;
                // clear materialflags and pvs
                p->materialflags = 0;
                p->pvsvalid = false;
@@ -3187,7 +3198,7 @@ void R_Bloom_CopyBloomTexture(float colorscale)
        R_SetupGenericShader(true);
        R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
        R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
-       R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+       R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
        r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
 
        // we now have a bloom image in the framebuffer
@@ -3232,7 +3243,7 @@ void R_Bloom_MakeTexture(void)
                GL_Color(r, r, r, 1);
                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
                R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
 
                // copy the vertically blurred bloom view to a texture
@@ -3276,7 +3287,7 @@ void R_Bloom_MakeTexture(void)
                        //r = (dir ? 1.0f : brighten)/(range*2+1);
                        r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
                        GL_Color(r, r, r, 1);
-                       R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+                       R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                        r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
                        GL_BlendFunc(GL_ONE, GL_ONE);
                }
@@ -3296,7 +3307,7 @@ void R_Bloom_MakeTexture(void)
                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
                R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
                GL_Color(1, 1, 1, 1);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
 
                GL_BlendFunc(GL_ONE, GL_ONE);
@@ -3304,7 +3315,7 @@ void R_Bloom_MakeTexture(void)
                R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
                R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
                GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
                qglBlendEquationEXT(GL_FUNC_ADD_EXT);
 
@@ -3407,9 +3418,14 @@ static void R_BlendView(void)
                        qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
                if (r_glsl_permutation->loc_ClientTime >= 0)
                        qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
+               if (r_glsl_permutation->loc_PixelSize >= 0)
+                       qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
                if (r_glsl_permutation->loc_UserVec1 >= 0)
                {
                        float a=0, b=0, c=0, d=0;
+#if _MSC_VER >= 1400
+#define sscanf sscanf_s
+#endif
                        sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
                        qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
                }
@@ -3431,7 +3447,7 @@ static void R_BlendView(void)
                        sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
                        qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
                }
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
                return;
        }
@@ -3451,7 +3467,7 @@ static void R_BlendView(void)
                GL_BlendFunc(GL_ONE, GL_ONE);
                R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
                R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
        }
        else if (r_bloomstate.texture_bloom)
@@ -3480,14 +3496,14 @@ static void R_BlendView(void)
                else
                {
                        R_SetupGenericShader(true);
-                       R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+                       R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                        r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
                        // now blend on the bloom texture
                        GL_BlendFunc(GL_ONE, GL_ONE);
                        R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
                        R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
                }
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
        }
        if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
@@ -3499,7 +3515,7 @@ static void R_BlendView(void)
                R_SetupGenericShader(false);
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
        }
 }
 
@@ -3538,9 +3554,11 @@ void R_UpdateVariables(void)
 {
        R_Textures_Frame();
 
+       r_refdef.scene.ambient = r_ambient.value;
+
        r_refdef.farclip = 4096;
        if (r_refdef.scene.worldmodel)
-               r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
+               r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
        r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
 
        if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
@@ -3550,17 +3568,17 @@ void R_UpdateVariables(void)
        r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
        r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
 
-       r_refdef.rtworld = r_shadow_realtime_world.integer;
-       r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
-       r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
-       r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
-       r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+       r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
+       r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
+       r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
+       r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
+       r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
        if (r_showsurfaces.integer)
        {
-               r_refdef.rtworld = false;
-               r_refdef.rtworldshadows = false;
-               r_refdef.rtdlight = false;
-               r_refdef.rtdlightshadows = false;
+               r_refdef.scene.rtworld = false;
+               r_refdef.scene.rtworldshadows = false;
+               r_refdef.scene.rtdlight = false;
+               r_refdef.scene.rtdlightshadows = false;
                r_refdef.lightmapintensity = 0;
        }
 
@@ -3596,7 +3614,7 @@ void R_UpdateVariables(void)
 
        // R_UpdateFogColor(); // why? R_RenderScene does it anyway
 
-       if (r_refdef.fog_density)
+       if (r_refdef.fog_density && r_drawfog.integer)
        {
                r_refdef.fogenabled = true;
                // this is the point where the fog reaches 0.9986 alpha, which we
@@ -3692,7 +3710,24 @@ R_RenderView
 */
 void R_RenderView(void)
 {
-       if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
+       if (r_refdef.view.isoverlay)
+       {
+               // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
+               GL_Clear( GL_DEPTH_BUFFER_BIT );
+               R_TimeReport("depthclear");
+
+               r_refdef.view.showdebug = false;
+
+               r_waterstate.enabled = false;
+               r_waterstate.numwaterplanes = 0;
+
+               R_RenderScene(false);
+
+               CHECKGLERROR
+               return;
+       }
+
+       if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
                return; //Host_Error ("R_RenderView: NULL worldmodel");
 
        r_refdef.view.colorscale = r_hdr_scenebrightness.value;
@@ -3945,7 +3980,7 @@ void R_RenderScene(qboolean addwaterplanes)
        R_ResetViewRendering2D();
 }
 
-static const int bboxelements[36] =
+static const unsigned short bboxelements[36] =
 {
        5, 1, 3, 5, 3, 7,
        6, 2, 0, 6, 0, 4,
@@ -3990,7 +4025,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa
        R_Mesh_ColorPointer(color4f, 0, 0);
        R_Mesh_ResetTextureState();
        R_SetupGenericShader(false);
-       R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
+       R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
 }
 
 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
@@ -3998,10 +4033,16 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh
        int i;
        float color[4];
        prvm_edict_t *edict;
+       prvm_prog_t *prog_save = prog;
+
        // this function draws bounding boxes of server entities
        if (!sv.active)
                return;
+
+       GL_CullFace(GL_NONE);
        R_SetupGenericShader(false);
+
+       prog = 0;
        SV_VM_Begin();
        for (i = 0;i < numsurfaces;i++)
        {
@@ -4022,6 +4063,7 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh
                R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
        }
        SV_VM_End();
+       prog = prog_save;
 }
 
 static void R_DrawEntityBBoxes(void)
@@ -4029,22 +4071,32 @@ static void R_DrawEntityBBoxes(void)
        int i;
        prvm_edict_t *edict;
        vec3_t center;
+       prvm_prog_t *prog_save = prog;
+
        // this function draws bounding boxes of server entities
        if (!sv.active)
                return;
+
+       prog = 0;
        SV_VM_Begin();
        for (i = 0;i < prog->num_edicts;i++)
        {
                edict = PRVM_EDICT_NUM(i);
                if (edict->priv.server->free)
                        continue;
+               // exclude the following for now, as they don't live in world coordinate space and can't be solid:
+               if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
+                       continue;
+               if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
+                       continue;
                VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
                R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
        }
        SV_VM_End();
+       prog = prog_save;
 }
 
-int nomodelelements[24] =
+unsigned short nomodelelements[24] =
 {
        5, 2, 0,
        5, 1, 2,
@@ -4132,7 +4184,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight
        else
                R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
        R_Mesh_ResetTextureState();
-       R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
+       R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
 }
 
 void R_DrawNoModel(entity_render_t *ent)
@@ -4224,7 +4276,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_
        R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
        // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
        GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
-       R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+       R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
 
        if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
        {
@@ -4232,7 +4284,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_
                GL_BlendFunc(blendfunc1, GL_ONE);
                fog = 1 - fog;
                GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
        }
 }
 
@@ -4386,11 +4438,17 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
 {
        int i;
-       model_t *model = ent->model;
+       dp_model_t *model = ent->model;
        float f;
        float tcmat[12];
        q3shaderinfo_layer_tcmod_t *tcmod;
 
+       if (t->basematerialflags & MATERIALFLAG_NODRAW)
+       {
+               t->currentmaterialflags = MATERIALFLAG_NODRAW;
+               return;
+       }
+
        // switch to an alternate material if this is a q1bsp animated material
        {
                texture_t *texture = t;
@@ -4424,7 +4482,8 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
                {
                        strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
-                       Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
+                       if (developer_loading.integer)
+                               Con_Printf("loading skins/%s\n", r_qwskincache[i]);
                        r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0);
                }
                t->currentskinframe = r_qwskincache_skinframe[i];
@@ -4439,18 +4498,10 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
        t->currentmaterialflags = t->basematerialflags;
        t->currentalpha = ent->alpha;
        if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
-       {
                t->currentalpha *= r_wateralpha.value;
-               /*
-                * FIXME what is this supposed to do?
-               // if rendering refraction/reflection, disable transparency
-               if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
-                       t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
-               */
-       }
-       if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled)
+       if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
                t->currentalpha *= t->r_water_wateralpha;
-       if(!r_waterstate.enabled)
+       if(!r_waterstate.enabled || r_refdef.view.isoverlay)
                t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
        if (!(ent->flags & RENDER_LIGHT))
                t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
@@ -4483,7 +4534,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
 
        // there is no tcmod
-       if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
+       if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
                t->currenttexmatrix = r_waterscrollmatrix;
 
        for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
@@ -4493,7 +4544,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                {
                case Q3TCMOD_COUNT:
                case Q3TCMOD_NONE:
-                       if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
+                       if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
                                matrix = r_waterscrollmatrix;
                        else
                                matrix = identitymatrix;
@@ -4575,105 +4626,98 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                t->basetexture = r_texture_grey128;
                t->backgroundbasetexture = NULL;
                t->specularscale = 0;
-               t->currentmaterialflags &= ~(MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_WATERALPHA | MATERIALFLAG_WATER | MATERIALFLAG_SKY | MATERIALFLAG_ALPHATEST | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
-               t->currentmaterialflags |= MATERIALFLAG_WALL;
+               t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
        }
 
        Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
        VectorClear(t->dlightcolor);
        t->currentnumlayers = 0;
-       if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
+       if (t->currentmaterialflags & MATERIALFLAG_WALL)
        {
-               if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
+               int layerflags = 0;
+               int blendfunc1, blendfunc2, depthmask;
+               if (t->currentmaterialflags & MATERIALFLAG_ADD)
                {
-                       int blendfunc1, blendfunc2, depthmask;
-                       if (t->currentmaterialflags & MATERIALFLAG_ADD)
-                       {
-                               blendfunc1 = GL_SRC_ALPHA;
-                               blendfunc2 = GL_ONE;
-                       }
-                       else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
-                       {
-                               blendfunc1 = GL_SRC_ALPHA;
-                               blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
-                       }
-                       else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
-                       {
-                               blendfunc1 = t->customblendfunc[0];
-                               blendfunc2 = t->customblendfunc[1];
-                       }
-                       else
-                       {
-                               blendfunc1 = GL_ONE;
-                               blendfunc2 = GL_ZERO;
-                       }
-                       depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
-                       if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
+                       blendfunc1 = GL_SRC_ALPHA;
+                       blendfunc2 = GL_ONE;
+               }
+               else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
+               {
+                       blendfunc1 = GL_SRC_ALPHA;
+                       blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+               }
+               else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
+               {
+                       blendfunc1 = t->customblendfunc[0];
+                       blendfunc2 = t->customblendfunc[1];
+               }
+               else
+               {
+                       blendfunc1 = GL_ONE;
+                       blendfunc2 = GL_ZERO;
+               }
+               depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
+               if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
+                       layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
+               if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+               {
+                       // fullbright is not affected by r_refdef.lightmapintensity
+                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
+                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+               }
+               else
+               {
+                       vec3_t ambientcolor;
+                       float colorscale;
+                       // set the color tint used for lights affecting this surface
+                       VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
+                       colorscale = 2;
+                       // q3bsp has no lightmap updates, so the lightstylevalue that
+                       // would normally be baked into the lightmap must be
+                       // applied to the color
+                       // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
+                       if (ent->model->type == mod_brushq3)
+                               colorscale *= r_refdef.scene.rtlightstylevalue[0];
+                       colorscale *= r_refdef.lightmapintensity;
+                       VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
+                       VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
+                       // basic lit geometry
+                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
+                       // add pants/shirt if needed
+                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
+                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+                       // now add ambient passes if needed
+                       if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
                        {
-                               int layerflags = 0;
-                               if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
-                                       layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
-                               if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
-                               {
-                                       // fullbright is not affected by r_refdef.lightmapintensity
-                                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
-                                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
-                                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
-                               }
-                               else
-                               {
-                                       vec3_t ambientcolor;
-                                       float colorscale;
-                                       // set the color tint used for lights affecting this surface
-                                       VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
-                                       colorscale = 2;
-                                       // q3bsp has no lightmap updates, so the lightstylevalue that
-                                       // would normally be baked into the lightmap must be
-                                       // applied to the color
-                                       // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
-                                       if (ent->model->type == mod_brushq3)
-                                               colorscale *= r_refdef.scene.rtlightstylevalue[0];
-                                       colorscale *= r_refdef.lightmapintensity;
-                                       VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
-                                       VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
-                                       // basic lit geometry
-                                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
-                                       // add pants/shirt if needed
-                                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
-                                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
-                                       // now add ambient passes if needed
-                                       if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
-                                       {
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
-                                               if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
-                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
-                                               if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
-                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
-                                       }
-                               }
-                               if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
-                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
-                               if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
-                               {
-                                       // if this is opaque use alpha blend which will darken the earlier
-                                       // passes cheaply.
-                                       //
-                                       // if this is an alpha blended material, all the earlier passes
-                                       // were darkened by fog already, so we only need to add the fog
-                                       // color ontop through the fog mask texture
-                                       //
-                                       // if this is an additive blended material, all the earlier passes
-                                       // 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_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
-                               }
+                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
+                               if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
+                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
+                               if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
+                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
                        }
                }
+               if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
+                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
+               if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
+               {
+                       // if this is opaque use alpha blend which will darken the earlier
+                       // passes cheaply.
+                       //
+                       // if this is an alpha blended material, all the earlier passes
+                       // were darkened by fog already, so we only need to add the fog
+                       // color ontop through the fog mask texture
+                       //
+                       // if this is an additive blended material, all the earlier passes
+                       // 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_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
+               }
        }
 }
 
@@ -4711,7 +4755,7 @@ void R_Mesh_ResizeArrays(int newvertices)
 
 void RSurf_ActiveWorldEntity(void)
 {
-       model_t *model = r_refdef.scene.worldmodel;
+       dp_model_t *model = r_refdef.scene.worldmodel;
        if (rsurface.array_size < model->surfmesh.num_vertices)
                R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
        rsurface.matrix = identitymatrix;
@@ -4755,7 +4799,9 @@ void RSurf_ActiveWorldEntity(void)
        rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
        rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
        rsurface.modelelement3i = model->surfmesh.data_element3i;
-       rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
+       rsurface.modelelement3s = model->surfmesh.data_element3s;
+       rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
+       rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
        rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
        rsurface.modelnum_vertices = model->surfmesh.num_vertices;
        rsurface.modelnum_triangles = model->surfmesh.num_triangles;
@@ -4778,7 +4824,7 @@ void RSurf_ActiveWorldEntity(void)
 
 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
 {
-       model_t *model = ent->model;
+       dp_model_t *model = ent->model;
        if (rsurface.array_size < model->surfmesh.num_vertices)
                R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
        rsurface.matrix = ent->matrix;
@@ -4806,7 +4852,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
                rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
                rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
        }
-       if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
+       if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
        {
                if (wanttangents)
                {
@@ -4814,7 +4860,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
                        rsurface.modelsvector3f = rsurface.array_modelsvector3f;
                        rsurface.modeltvector3f = rsurface.array_modeltvector3f;
                        rsurface.modelnormal3f = rsurface.array_modelnormal3f;
-                       Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
+                       model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
                }
                else if (wantnormals)
                {
@@ -4822,7 +4868,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
                        rsurface.modelsvector3f = NULL;
                        rsurface.modeltvector3f = NULL;
                        rsurface.modelnormal3f = rsurface.array_modelnormal3f;
-                       Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
+                       model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
                }
                else
                {
@@ -4830,7 +4876,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
                        rsurface.modelsvector3f = NULL;
                        rsurface.modeltvector3f = NULL;
                        rsurface.modelnormal3f = NULL;
-                       Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
+                       model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
                }
                rsurface.modelvertex3f_bufferobject = 0;
                rsurface.modelvertex3f_bufferoffset = 0;
@@ -4868,7 +4914,9 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
        rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
        rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
        rsurface.modelelement3i = model->surfmesh.data_element3i;
-       rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
+       rsurface.modelelement3s = model->surfmesh.data_element3s;
+       rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
+       rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
        rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
        rsurface.modelnum_vertices = model->surfmesh.num_vertices;
        rsurface.modelnum_triangles = model->surfmesh.num_triangles;
@@ -5322,7 +5370,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel
        if (texturenumsurfaces == 1)
        {
                GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
        }
        else if (r_batchmode.integer == 2)
        {
@@ -5335,7 +5383,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel
                        j = i + 1;
                        if (surface->num_triangles > MAXBATCHTRIANGLES)
                        {
-                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                                continue;
                        }
                        memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
@@ -5354,7 +5402,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel
                        }
                        surface2 = texturesurfacelist[j-1];
                        numvertices = endvertex - firstvertex;
-                       R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
+                       R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
                }
        }
        else if (r_batchmode.integer == 1)
@@ -5369,7 +5417,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel
                        numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
                        numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
                        GL_LockArrays(surface->num_firstvertex, numvertices);
-                       R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+                       R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
        }
        else
@@ -5378,7 +5426,7 @@ void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacel
                {
                        surface = texturesurfacelist[i];
                        GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
        }
 }
@@ -5432,7 +5480,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int
                                R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
                }
                GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
        }
 }
 
@@ -5453,7 +5501,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa
                if (deluxemaptexunit >= 0)
                        R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
                GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
        }
        else if (r_batchmode.integer == 2)
        {
@@ -5469,7 +5517,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa
                        j = i + 1;
                        if (surface->num_triangles > MAXBATCHTRIANGLES)
                        {
-                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                                continue;
                        }
                        memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
@@ -5488,7 +5536,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa
                        }
                        surface2 = texturesurfacelist[j-1];
                        numvertices = endvertex - firstvertex;
-                       R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
+                       R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
                }
        }
        else if (r_batchmode.integer == 1)
@@ -5522,7 +5570,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa
                        numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
                        numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
                        GL_LockArrays(surface->num_firstvertex, numvertices);
-                       R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+                       R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
 #if 0
                Con_Printf("\n");
@@ -5537,7 +5585,7 @@ static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurfa
                        if (deluxemaptexunit >= 0)
                                R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
                        GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
        }
 }
@@ -5555,7 +5603,7 @@ static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **te
                        {
                                float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
                                GL_Color(f, f, f, 1);
-                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
+                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                        }
                }
        }
@@ -5567,7 +5615,7 @@ static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **te
                        int k = (int)(((size_t)surface) / sizeof(msurface_t));
                        GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
                        GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
+                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
                }
        }
 }
@@ -5670,7 +5718,7 @@ static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t
        int i;
        float *c;
        // TODO: optimize
-       if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
+       if (texturesurfacelist[0]->lightmapinfo)
        {
                // generate color arrays for the surfaces in this list
                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
@@ -5870,8 +5918,11 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **t
                R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
                R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
        }
-       R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
-       R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
+       if(rsurface.texture->colormapping)
+       {
+               R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
+               R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
+       }
        R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
        if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
                R_Mesh_ColorPointer(NULL, 0, 0);
@@ -6367,7 +6418,7 @@ float locboxvertex3f[6*4*3] =
        1,0,0, 0,0,0, 0,1,0, 1,1,0
 };
 
-int locboxelement3i[6*2*3] =
+unsigned short locboxelements[6*2*3] =
 {
         0, 1, 2, 0, 2, 3,
         4, 5, 6, 4, 6, 7,
@@ -6418,7 +6469,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in
                for (j = 0;j < 3;j++, i++)
                        vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
 
-       R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
+       R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
 }
 
 void R_DrawLocs(void)
@@ -6440,10 +6491,10 @@ void R_DrawDebugModel(entity_render_t *ent)
        const int *elements;
        q3mbrush_t *brush;
        msurface_t *surface;
-       model_t *model = ent->model;
+       dp_model_t *model = ent->model;
        vec3_t v;
 
-       flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
+       flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
 
        R_Mesh_ColorPointer(NULL, 0, 0);
        R_Mesh_ResetTextureState();
@@ -6462,7 +6513,7 @@ void R_DrawDebugModel(entity_render_t *ent)
                        {
                                R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
                                GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
-                               R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
+                               R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
                        }
                }
                for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
@@ -6471,7 +6522,7 @@ void R_DrawDebugModel(entity_render_t *ent)
                        {
                                R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
                                GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
-                               R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
+                               R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
                        }
                }
        }
@@ -6565,20 +6616,32 @@ void R_DrawDebugModel(entity_render_t *ent)
 }
 
 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
+int r_maxsurfacelist = 0;
+msurface_t **r_surfacelist = NULL;
 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
 {
        int i, j, endj, f, flagsmask;
-       msurface_t *surface;
        texture_t *t;
-       model_t *model = r_refdef.scene.worldmodel;
-       const int maxsurfacelist = 1024;
+       dp_model_t *model = r_refdef.scene.worldmodel;
+       msurface_t *surfaces;
+       unsigned char *update;
        int numsurfacelist = 0;
-       msurface_t *surfacelist[1024];
        if (model == NULL)
                return;
 
+       if (r_maxsurfacelist < model->num_surfaces)
+       {
+               r_maxsurfacelist = model->num_surfaces;
+               if (r_surfacelist)
+                       Mem_Free(r_surfacelist);
+               r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
+       }
+
        RSurf_ActiveWorldEntity();
 
+       surfaces = model->data_surfaces;
+       update = model->brushq1.lightmapupdateflags;
+
        // update light styles on this submodel
        if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
        {
@@ -6587,17 +6650,16 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
                {
                        if (style->value != r_refdef.scene.lightstylevalue[style->style])
                        {
-                               msurface_t *surfaces = model->data_surfaces;
                                int *list = style->surfacelist;
                                style->value = r_refdef.scene.lightstylevalue[style->style];
                                for (j = 0;j < style->numsurfaces;j++)
-                                       surfaces[list[j]].cached_dlight = true;
+                                       update[list[j]] = true;
                        }
                }
        }
 
        R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
-       flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
+       flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
 
        if (debug)
        {
@@ -6611,54 +6673,60 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
        rsurface.texture = NULL;
        rsurface.rtlight = NULL;
        numsurfacelist = 0;
+       // add visible surfaces to draw list
        j = model->firstmodelsurface;
        endj = j + model->nummodelsurfaces;
-       while (j < endj)
+       if (update)
        {
-               // quickly skip over non-visible surfaces
-               for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
-                       ;
-               // quickly iterate over visible surfaces
-               for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
+               for (;j < endj;j++)
                {
-                       // process this surface
-                       surface = model->data_surfaces + j;
-                       // if this surface fits the criteria, add it to the list
-                       if (surface->num_triangles)
+                       if (r_refdef.viewcache.world_surfacevisible[j])
                        {
-                               // if lightmap parameters changed, rebuild lightmap texture
-                               if (surface->cached_dlight)
-                                       R_BuildLightMap(r_refdef.scene.worldentity, surface);
-                               // add face to draw list
-                               surfacelist[numsurfacelist++] = surface;
-                               r_refdef.stats.world_triangles += surface->num_triangles;
-                               if (numsurfacelist >= maxsurfacelist)
-                               {
-                                       r_refdef.stats.world_surfaces += numsurfacelist;
-                                       R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
-                                       numsurfacelist = 0;
-                               }
+                               r_surfacelist[numsurfacelist++] = surfaces + j;
+                               // update lightmap if needed
+                               if (update[j])
+                                       R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
                        }
                }
        }
-       r_refdef.stats.world_surfaces += numsurfacelist;
-       if (numsurfacelist)
-               R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
+       else
+               for (;j < endj;j++)
+                       if (r_refdef.viewcache.world_surfacevisible[j])
+                               r_surfacelist[numsurfacelist++] = surfaces + j;
+       // don't do anything if there were no surfaces
+       if (!numsurfacelist)
+               return;
+       R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
        GL_AlphaTest(false);
+
+       // add to stats if desired
+       if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
+       {
+               r_refdef.stats.world_surfaces += numsurfacelist;
+               for (j = 0;j < numsurfacelist;j++)
+                       r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
+       }
 }
 
 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
 {
-       int i, j, f, flagsmask;
-       msurface_t *surface, *endsurface;
+       int i, j, endj, f, flagsmask;
        texture_t *t;
-       model_t *model = ent->model;
-       const int maxsurfacelist = 1024;
+       dp_model_t *model = ent->model;
+       msurface_t *surfaces;
+       unsigned char *update;
        int numsurfacelist = 0;
-       msurface_t *surfacelist[1024];
        if (model == NULL)
                return;
 
+       if (r_maxsurfacelist < model->num_surfaces)
+       {
+               r_maxsurfacelist = model->num_surfaces;
+               if (r_surfacelist)
+                       Mem_Free(r_surfacelist);
+               r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
+       }
+
        // 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
@@ -6669,6 +6737,9 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
        else
                RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
 
+       surfaces = model->data_surfaces;
+       update = model->brushq1.lightmapupdateflags;
+
        // update light styles
        if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
        {
@@ -6677,17 +6748,16 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                {
                        if (style->value != r_refdef.scene.lightstylevalue[style->style])
                        {
-                               msurface_t *surfaces = model->data_surfaces;
                                int *list = style->surfacelist;
                                style->value = r_refdef.scene.lightstylevalue[style->style];
                                for (j = 0;j < style->numsurfaces;j++)
-                                       surfaces[list[j]].cached_dlight = true;
+                                       update[list[j]] = true;
                        }
                }
        }
 
        R_UpdateAllTextureInfo(ent);
-       flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
+       flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
 
        if (debug)
        {
@@ -6701,29 +6771,28 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
        rsurface.texture = NULL;
        rsurface.rtlight = NULL;
        numsurfacelist = 0;
-       surface = model->data_surfaces + model->firstmodelsurface;
-       endsurface = surface + model->nummodelsurfaces;
-       for (;surface < endsurface;surface++)
+       // add visible surfaces to draw list
+       j = model->firstmodelsurface;
+       endj = j + model->nummodelsurfaces;
+       for (;j < endj;j++)
+               r_surfacelist[numsurfacelist++] = surfaces + j;
+       // don't do anything if there were no surfaces
+       if (!numsurfacelist)
+               return;
+       // update lightmaps if needed
+       if (update)
+               for (j = model->firstmodelsurface;j < endj;j++)
+                       if (update[j])
+                               R_BuildLightMap(ent, surfaces + j);
+       R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
+       GL_AlphaTest(false);
+
+       // add to stats if desired
+       if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
        {
-               // if this surface fits the criteria, add it to the list
-               if (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;
-                       r_refdef.stats.entities_triangles += surface->num_triangles;
-                       if (numsurfacelist >= maxsurfacelist)
-                       {
-                               r_refdef.stats.entities_surfaces += numsurfacelist;
-                               R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
-                               numsurfacelist = 0;
-                       }
-               }
+               r_refdef.stats.entities++;
+               r_refdef.stats.entities_surfaces += numsurfacelist;
+               for (j = 0;j < numsurfacelist;j++)
+                       r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
        }
-       r_refdef.stats.entities_surfaces += numsurfacelist;
-       if (numsurfacelist)
-               R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
-       GL_AlphaTest(false);
 }