]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
r_nearclip cvar
[xonotic/darkplaces.git] / gl_rmain.c
index d1291faa51a0e1b00773313dd0ea6a5b2fceec74..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,44 +67,51 @@ matrix4x4_t r_view_matrix;
 //
 refdef_t r_refdef;
 
-cvar_t r_showtris = {0, "r_showtris", "0"};
-cvar_t r_shownormals = {0, "r_shownormals", "0"};
-cvar_t r_drawentities = {0, "r_drawentities","1"};
-cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
-cvar_t r_speeds = {0, "r_speeds","0"};
-cvar_t r_fullbright = {0, "r_fullbright","0"};
-cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
-cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
-cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
-cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
-
-cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
-cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
-cvar_t gl_fogred = {0, "gl_fogred","0.3"};
-cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
-cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
-cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
-cvar_t gl_fogend = {0, "gl_fogend","0"};
-
-cvar_t r_textureunits = {0, "r_textureunits", "32"};
-
-cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
-cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
-cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
-
-cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
-cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5"};
-cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4"};
-cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
-cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2"};
-
-cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
-
-cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
-
-cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
-
-cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
+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"};
+cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
+cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
+cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
+cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
+cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
+cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
+cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
+cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
+cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
+cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
+cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
+cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
+cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
+
+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)"};
+cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
+cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
+cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
+cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
+cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
+
+cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
+
+cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
+cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
+cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
+
+cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
+cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
+cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
+cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
+cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
+
+cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
+
+cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
+
+cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
+
+cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
 
 rtexturepool_t *r_main_texturepool;
 rtexture_t *r_bloom_texture_screen;
@@ -444,11 +449,18 @@ 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);
+       Cvar_RegisterVariable(&r_showlighting);
+       Cvar_RegisterVariable(&r_showshadowvolumes);
+       Cvar_RegisterVariable(&r_showcollisionbrushes);
+       Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
+       Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
+       Cvar_RegisterVariable(&r_showdisabledepthtest);
        Cvar_RegisterVariable(&r_drawentities);
        Cvar_RegisterVariable(&r_drawviewmodel);
        Cvar_RegisterVariable(&r_speeds);
@@ -460,7 +472,6 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_lerpsprites);
        Cvar_RegisterVariable(&r_lerpmodels);
        Cvar_RegisterVariable(&r_waterscroll);
-       Cvar_RegisterVariable(&r_drawcollisionbrushes);
        Cvar_RegisterVariable(&r_bloom);
        Cvar_RegisterVariable(&r_bloom_intensity);
        Cvar_RegisterVariable(&r_bloom_blur);
@@ -470,7 +481,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&developer_texturelogging);
        Cvar_RegisterVariable(&gl_lightmaps);
        Cvar_RegisterVariable(&r_test);
-       if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
+       if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
                Cvar_SetValue("r_fullbrights", 0);
        R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
 }
@@ -730,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;
@@ -791,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]);
@@ -824,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]);
 }
 
@@ -850,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;
@@ -1079,8 +1090,61 @@ void R_RenderView(void)
        R_ClearScreen();
        R_Textures_Frame();
        R_UpdateFog();
-       R_TimeReport("setup");
+       if (r_timereport_active)
+               R_TimeReport("setup");
+
+       qglDepthFunc(GL_LEQUAL);
+       qglPolygonOffset(0, 0);
+       qglEnable(GL_POLYGON_OFFSET_FILL);
+
+       R_RenderScene();
+
+       qglPolygonOffset(0, 0);
+       qglDisable(GL_POLYGON_OFFSET_FILL);
+
+       R_BlendView();
+       if (r_timereport_active)
+               R_TimeReport("blendview");
+
+       GL_Scissor(0, 0, vid.width, vid.height);
+       GL_ScissorTest(false);
+}
+
+//[515]: csqc
+void CSQC_R_ClearScreen (void)
+{
+       if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
+               return; //Host_Error ("R_RenderView: NULL worldmodel");
+
+       r_view_width = bound(0, r_refdef.width, vid.width);
+       r_view_height = bound(0, r_refdef.height, vid.height);
+       r_view_depth = 1;
+       r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
+       r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
+       r_view_z = 0;
+       r_view_matrix = r_refdef.viewentitymatrix;
+       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+       r_rtworld = r_shadow_realtime_world.integer;
+       r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
+       r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
+       r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
+       r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+
+       // GL is weird because it's bottom to top, r_view_y is top to bottom
+       qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
+       GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
+       GL_ScissorTest(true);
+       GL_DepthMask(true);
+       R_ClearScreen();
+       R_Textures_Frame();
+       R_UpdateFog();
+       if (r_timereport_active)
+               R_TimeReport("setup");
+}
 
+//[515]: csqc
+void CSQC_R_RenderScene (void)
+{
        qglDepthFunc(GL_LEQUAL);
        qglPolygonOffset(0, 0);
        qglEnable(GL_POLYGON_OFFSET_FILL);
@@ -1091,15 +1155,19 @@ void R_RenderView(void)
        qglDisable(GL_POLYGON_OFFSET_FILL);
 
        R_BlendView();
-       R_TimeReport("blendview");
+       if (r_timereport_active)
+               R_TimeReport("blendview");
 
        GL_Scissor(0, 0, vid.width, vid.height);
        GL_ScissorTest(false);
 }
 
 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 ();
@@ -1108,15 +1176,15 @@ void R_RenderScene(void)
 
        R_MeshQueue_BeginScene();
 
-       GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
-
        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);
 
@@ -1125,85 +1193,134 @@ void R_RenderScene(void)
        R_SkyStartFrame();
 
        R_WorldVisibility();
-       R_TimeReport("worldvis");
+       if (r_timereport_active)
+               R_TimeReport("worldvis");
 
        R_MarkEntities();
-       R_TimeReport("markentity");
+       if (r_timereport_active)
+               R_TimeReport("markentity");
 
        R_Shadow_UpdateWorldLightSelection();
 
-       // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
-               S_ExtraUpdate ();
-
-       GL_ShowTrisColor(0.025, 0.025, 0, 1);
-       if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
+       for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
        {
-               r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
-               R_TimeReport("worldsky");
-       }
+               if (r_showtrispass)
+               {
+                       rmeshstate_t m;
+                       r_showtrispass = 0;
+                       GL_BlendFunc(GL_ONE, GL_ONE);
+                       GL_DepthTest(!r_showdisabledepthtest.integer);
+                       GL_DepthMask(GL_FALSE);
+                       memset(&m, 0, sizeof(m));
+                       R_Mesh_State(&m);
+                       //qglEnable(GL_LINE_SMOOTH);
+                       qglEnable(GL_POLYGON_OFFSET_LINE);
+                       qglPolygonOffset(0, r_showtris_polygonoffset.value);
+                       r_showtrispass = 1;
+               }
 
-       if (R_DrawBrushModelsSky())
-               R_TimeReport("bmodelsky");
+               if (cl.csqc_vidvars.drawworld)
+               {
+                       // don't let sound skip if going slow
+                       if (r_refdef.extraupdate)
+                               S_ExtraUpdate ();
 
-       GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
-       if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
-       {
-               r_refdef.worldmodel->Draw(r_refdef.worldentity);
-               R_TimeReport("world");
-       }
+                       if (r_showtrispass)
+                               GL_ShowTrisColor(0.025, 0.025, 0, 1);
+                       if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
+                       {
+                               r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
+                               if (r_timereport_active)
+                                       R_TimeReport("worldsky");
+                       }
 
-       // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
-               S_ExtraUpdate ();
+                       if (R_DrawBrushModelsSky() && r_timereport_active)
+                               R_TimeReport("bmodelsky");
+
+                       if (r_showtrispass)
+                               GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
+                       if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
+                       {
+                               r_refdef.worldmodel->Draw(r_refdef.worldentity);
+                               if (r_timereport_active)
+                                       R_TimeReport("world");
+                       }
+               }
 
-       GL_ShowTrisColor(0, 0.015, 0, 1);
+               // don't let sound skip if going slow
+               if (r_refdef.extraupdate)
+                       S_ExtraUpdate ();
 
-       R_DrawModels();
-       R_TimeReport("models");
+               if (r_showtrispass)
+                       GL_ShowTrisColor(0, 0.015, 0, 1);
 
-       // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
-               S_ExtraUpdate ();
+               R_DrawModels();
+               if (r_timereport_active)
+                       R_TimeReport("models");
 
-       GL_ShowTrisColor(0, 0, 0.033, 1);
-       R_ShadowVolumeLighting(false);
-       R_TimeReport("rtlights");
+               // don't let sound skip if going slow
+               if (r_refdef.extraupdate)
+                       S_ExtraUpdate ();
 
-       // don't let sound skip if going slow
-       if (r_refdef.extraupdate)
-               S_ExtraUpdate ();
+               if (r_showtrispass)
+                       GL_ShowTrisColor(0, 0, 0.033, 1);
+               R_ShadowVolumeLighting(false);
+               if (r_timereport_active)
+                       R_TimeReport("rtlights");
 
-       GL_ShowTrisColor(0.1, 0, 0, 1);
+               // don't let sound skip if going slow
+               if (r_refdef.extraupdate)
+                       S_ExtraUpdate ();
 
-       R_DrawLightningBeams();
-       R_TimeReport("lightning");
+               if (r_showtrispass)
+                       GL_ShowTrisColor(0.1, 0, 0, 1);
 
-       R_DrawParticles();
-       R_TimeReport("particles");
+               if (cl.csqc_vidvars.drawworld)
+               {
+                       R_DrawLightningBeams();
+                       if (r_timereport_active)
+                               R_TimeReport("lightning");
 
-       R_DrawExplosions();
-       R_TimeReport("explosions");
+                       R_DrawParticles();
+                       if (r_timereport_active)
+                               R_TimeReport("particles");
 
-       R_MeshQueue_RenderTransparent();
-       R_TimeReport("drawtrans");
+                       R_DrawExplosions();
+                       if (r_timereport_active)
+                               R_TimeReport("explosions");
+               }
 
-       R_DrawCoronas();
-       R_TimeReport("coronas");
+               R_MeshQueue_RenderTransparent();
+               if (r_timereport_active)
+                       R_TimeReport("drawtrans");
 
-       R_DrawWorldCrosshair();
-       R_TimeReport("crosshair");
+               if (cl.csqc_vidvars.drawworld)
+               {
+                       R_DrawCoronas();
+                       if (r_timereport_active)
+                               R_TimeReport("coronas");
+               }
+               if(cl.csqc_vidvars.drawcrosshair)
+               {
+                       R_DrawWorldCrosshair();
+                       if (r_timereport_active)
+                               R_TimeReport("crosshair");
+               }
 
-       R_MeshQueue_Render();
-       R_MeshQueue_EndScene();
+               VM_AddPolygonsToMeshQueue();
 
-       if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
-       {
-               R_ShadowVolumeLighting(true);
-               R_TimeReport("visiblevolume");
+               R_MeshQueue_Render();
+
+               if (r_showtrispass)
+               {
+                       //qglDisable(GL_LINE_SMOOTH);
+                       qglDisable(GL_POLYGON_OFFSET_LINE);
+               }
        }
 
-       GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
+       r_showtrispass = 0;
+
+       R_MeshQueue_EndScene();
 
        // don't let sound skip if going slow
        if (r_refdef.extraupdate)
@@ -1219,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];
@@ -1281,9 +1398,8 @@ float nomodelcolor4f[6*4] =
        0.5f, 0.0f, 0.0f, 1.0f
 };
 
-void R_DrawNoModelCallback(const void *calldata1, int calldata2)
+void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
 {
-       const entity_render_t *ent = (entity_render_t *)calldata1;
        int i;
        float f1, f2, *c;
        float color4f[6*4];
@@ -1339,7 +1455,7 @@ void R_DrawNoModelCallback(const void *calldata1, int calldata2)
 void R_DrawNoModel(entity_render_t *ent)
 {
        //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
-               R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
+               R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
        //else
        //      R_DrawNoModelCallback(ent, 0);
 }
@@ -1385,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);
@@ -1477,7 +1593,7 @@ void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *plane
                {
                        if (planenum2 == planenum)
                                continue;
-                       PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints);
+                       PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
                        w = !w;
                }
                if (tempnumpoints < 3)
@@ -1487,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++;
@@ -1507,7 +1623,6 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
 {
        // FIXME: identify models using a better check than ent->model->brush.shadowmesh
        //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
-       float currentalpha;
 
        {
                texture_t *texture = t;
@@ -1530,31 +1645,31 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
        }
 
        t->currentmaterialflags = t->basematerialflags;
-       currentalpha = ent->alpha;
+       t->currentalpha = ent->alpha;
        if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
-               currentalpha *= r_wateralpha.value;
+               t->currentalpha *= r_wateralpha.value;
        if (!(ent->flags & RENDER_LIGHT))
                t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
        if (ent->effects & EF_ADDITIVE)
                t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
-       else if (currentalpha < 1)
+       else if (t->currentalpha < 1)
                t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
        if (ent->effects & EF_NODEPTHTEST)
                t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
        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
                {
@@ -1583,14 +1698,15 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                                int layerflags = 0;
                                if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
                                        layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
-                               currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
+                               currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
                                if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
                                {
-                                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
-                                       if (ent->colormap >= 0 && t->skin.pants)
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2], currentalpha);
-                                       if (ent->colormap >= 0 && t->skin.shirt)
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2], currentalpha);
+                                       // fullbright is not affected by r_lightmapintensity
+                                       R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
+                                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
+                                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
                                }
                                else
                                {
@@ -1601,32 +1717,30 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                                        // applied to the color
                                        if (ent->model->type == mod_brushq3)
                                                colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
-                                       // transparent and fullbright are not affected by r_lightmapintensity
-                                       if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
-                                               colorscale *= r_lightmapintensity;
+                                       colorscale *= r_lightmapintensity;
                                        if (r_textureunits.integer >= 2 && gl_combine.integer)
-                                               R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha);
+                                               R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
                                        else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
-                                               R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, currentalpha);
+                                               R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, t->currentalpha);
                                        else
-                                               R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha);
+                                               R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
                                        if (r_ambient.value >= (1.0f/64.0f))
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
-                                       if (ent->colormap >= 0 && t->skin.pants)
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
+                                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
                                        {
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * colorscale, ent->colormap_pantscolor[1] * colorscale, ent->colormap_pantscolor[2] * colorscale, currentalpha);
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2]  * ent->colormod[2] * colorscale, t->currentalpha);
                                                if (r_ambient.value >= (1.0f/64.0f))
-                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
+                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
                                        }
-                                       if (ent->colormap >= 0 && t->skin.shirt)
+                                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
                                        {
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * colorscale, ent->colormap_shirtcolor[1] * colorscale, ent->colormap_shirtcolor[2] * colorscale, currentalpha);
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
                                                if (r_ambient.value >= (1.0f/64.0f))
-                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
+                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
                                        }
                                }
                                if (t->skin.glow != NULL)
-                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
+                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
                                if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
                                {
                                        // if this is opaque use alpha blend which will darken the earlier
@@ -1640,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], 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);
                                }
                        }
                }
@@ -1661,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);
@@ -1742,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
@@ -1767,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;
@@ -1790,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)
@@ -1868,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)
@@ -1876,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;
@@ -1883,7 +1988,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
        // FIXME: identify models using a better check than ent->model->brush.shadowmesh
        lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
        GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
-       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+       if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
                qglDisable(GL_CULL_FACE);
        if (texture->currentnumlayers)
        {
@@ -1913,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:
@@ -1948,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);
@@ -1964,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:
@@ -1997,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);
+                                               RSurf_DrawLightmap(ent, texture, 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);
-                                       }
-                                       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));
@@ -2031,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:
@@ -2046,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:
@@ -2067,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:
@@ -2088,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);
@@ -2100,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:
@@ -2120,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);
                                }
                        }
                }
@@ -2132,7 +2241,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                {
                        int j, k;
                        float v[3];
-                       GL_DepthTest(true);
+                       GL_DepthTest(!r_showdisabledepthtest.integer);
                        GL_DepthMask(texture->currentlayers->depthmask);
                        GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
                        memset(&m, 0, sizeof(m));
@@ -2140,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++)
@@ -2177,14 +2279,13 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        }
                }
        }
-       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+       if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
                qglEnable(GL_CULL_FACE);
 }
 
-static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
+static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
 {
-       const entity_render_t *ent = (entity_render_t *)calldata1;
-       const msurface_t *surface = ent->model->data_surfaces + calldata2;
+       const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
        vec3_t modelorg;
        texture_t *texture;
 
@@ -2215,7 +2316,7 @@ void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int tex
                                tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
                                tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
                                Matrix4x4_Transform(&ent->matrix, tempcenter, center);
-                               R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
+                               R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
                        }
                }
        }
@@ -2281,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;
@@ -2312,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;