added TEXF_CLAMP flag for textures
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 13 Oct 2002 22:13:57 +0000 (22:13 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 13 Oct 2002 22:13:57 +0000 (22:13 +0000)
r_shadows 3 mode is under heavy construction
changed pvsframecount stuff to be part of the model structure
new function Mod_BuildTextureVectorsAndNormals added
changed/improved how animating textures work
surface texture chains are now permanent for the lifetime of the model, and are specific to each submodel
surface textures now have a rendertype field which is updated every time R_PrepareSurfaces is called, values are SURFRENDER_ADD, SURFRENDER_ALPHA, or SURFRENDER_OPAQUE
added SHADERSTAGE_BASELIGHTING
added surfaceneighbors system (currently disabled because it increases load time greatly)
surface meshs are now allocated by a single function to simplify things
more heavy construction on static shadow volumes (which aren't working correctly)
VectorNormalize, VectorNormalize2, and VectorNormalizeDouble macros no longer produce infinite vectors if given null vectors
corrected names of dot3 enums
reduced duplicate code in texture manager with some new arrays for gl texture type enums
added GL_SetupView_Mode_PerspectiveInfiniteFarClip based on code from tenebrae
texture state management now has combinergb and combinealpha for each texture unit
aliasvert array went away
aliasvert_svectors, aliasvert_tvectors, and aliasvert_normals added (note: padded to 4 floats)
aliasvertnorm replaced with aliasvert_normals (adjusted code to use 4 float padding)
new r_light_* cvars allow tweaking of r_shadows 3 lighting system
R_DrawShadowSphere now works correctly
fixed fakeshadows appearing ontop of transparent stuff
got rid of unused RSurfShader_Wall_Fullbright

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2522 d7cf8633-e32d-0410-b094-e92efae38249

19 files changed:
gl_backend.c
gl_backend.h
gl_models.c
gl_rmain.c
gl_rsurf.c
gl_textures.c
glquake.h
mathlib.h
model_alias.c
model_brush.c
model_brush.h
model_shared.c
model_shared.h
model_sprite.c
r_light.c
r_shadow.c
r_shadow.h
r_textures.h
render.h

index 7de9f38..65b2c4a 100644 (file)
@@ -221,7 +221,7 @@ void GL_SetupView_Orientation_FromEntity (vec3_t origin, vec3_t angles)
        memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
 }
 
-void GL_SetupView_Mode_Perspective (double aspect, double fovx, double fovy, double zNear, double zFar)
+void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, double zFar)
 {
        double xmax, ymax;
 
@@ -240,6 +240,39 @@ void GL_SetupView_Mode_Perspective (double aspect, double fovx, double fovy, dou
        GL_SetupView_Orientation_Identity();
 }
 
+void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, double zNear)
+{
+       double nudge, m[16];
+
+       if (!r_render.integer)
+               return;
+
+       // set up viewpoint
+       qglMatrixMode(GL_PROJECTION);CHECKGLERROR
+       qglLoadIdentity ();CHECKGLERROR
+       // set view pyramid
+       nudge = 1.0 - 1.0 / (1<<23);
+       m[ 0] = 1.0 / tan(fovx * M_PI / 360.0);
+       m[ 1] = 0;
+       m[ 2] = 0;
+       m[ 3] = 0;
+       m[ 4] = 0;
+       m[ 5] = 1.0 / tan(fovy * M_PI / 360.0);
+       m[ 6] = 0;
+       m[ 7] = 0;
+       m[ 8] = 0;
+       m[ 9] = 0;
+       m[10] = -1 * nudge;
+       m[11] = -1 * nudge;
+       m[12] = 0;
+       m[13] = 0;
+       m[14] = -2 * zNear * nudge;
+       m[15] = 0;
+       qglLoadMatrixd(m);
+       qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
+       GL_SetupView_Orientation_Identity();
+}
+
 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
 {
        if (!r_render.integer)
@@ -258,6 +291,7 @@ typedef struct gltextureunit_s
        unsigned int t1d, t2d, t3d, tcubemap;
        unsigned int arrayenabled;
        float rgbscale;
+       int combinergb, combinealpha;
        // FIXME: add more combine stuff
 }
 gltextureunit_t;
@@ -292,6 +326,8 @@ void GL_SetupTextureState(void)
                unit->t3d = 0;
                unit->tcubemap = 0;
                unit->rgbscale = 1;
+               unit->combinergb = GL_MODULATE;
+               unit->combinealpha = GL_MODULATE;
                unit->arrayenabled = false;
                qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
                if (gl_texture3d)
@@ -444,7 +480,7 @@ void GL_ConvertColorsFloatToByte(int numverts)
        }
 }
 
-void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, int *index)
+void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, const int *index)
 {
        int arraylocked = false;
        c_meshs++;
@@ -461,9 +497,9 @@ void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, int *index
                arraylocked = true;
        }
        if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
-               qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, (GLuint *) index);
+               qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, (const GLuint *) index);
        else
-               qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, (GLuint *) index);
+               qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, (const GLuint *) index);
        CHECKGLERROR
        if (arraylocked)
        {
@@ -485,7 +521,7 @@ void _R_Mesh_ResizeCheck(int numverts)
 }
 
 // renders the mesh
-void R_Mesh_Draw(int numverts, int numtriangles, int *elements)
+void R_Mesh_Draw(int numverts, int numtriangles, const int *elements)
 {
        BACKENDACTIVECHECK
 
@@ -599,7 +635,7 @@ void R_Mesh_MainState(const rmeshstate_t *m)
 
 void R_Mesh_TextureState(const rmeshstate_t *m)
 {
-       int i;
+       int i, combinergb, combinealpha;
        float rgbscale;
        gltextureunit_t *unit;
 
@@ -644,6 +680,32 @@ void R_Mesh_TextureState(const rmeshstate_t *m)
                                        qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
                                }
                        }
+                       combinergb = m->texcombinergb[i];
+                       combinealpha = m->texcombinealpha[i];
+                       if (!combinergb)
+                               combinergb = GL_MODULATE;
+                       if (!combinealpha)
+                               combinealpha = GL_MODULATE;
+                       if (unit->combinergb != combinergb)
+                       {
+                               unit->combinergb = combinergb;
+                               if (gl_combine.integer)
+                               {
+                                       qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
+                               }
+                               else
+                               {
+                                       qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
+                               }
+                       }
+                       if (unit->combinealpha != combinealpha)
+                       {
+                               unit->combinealpha = combinealpha;
+                               if (gl_combine.integer)
+                               {
+                                       qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
+                               }
+                       }
                        if (unit->t1d != m->tex1d[i])
                        {
                                if (m->tex1d[i])
index a8f904c..5875754 100644 (file)
@@ -7,12 +7,13 @@
 #define POLYGONELEMENTS_MAXPOINTS 258
 extern int polygonelements[768];
 
-void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, int *index);
+void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, const int *index);
 
 void GL_SetupView_ViewPort (int x, int y, int width, int height);
 void GL_SetupView_Orientation_Identity (void);
 void GL_SetupView_Orientation_FromEntity (vec3_t origin, vec3_t angles);
-void GL_SetupView_Mode_Perspective (double aspect, double fovx, double fovy, double zNear, double zFar);
+void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, double zFar);
+void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, double zNear);
 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar);
 void GL_UseColorArray(void);
 void GL_Color(float cr, float cg, float cb, float ca);
@@ -34,6 +35,8 @@ typedef struct
        int tex3d[MAX_TEXTUREUNITS];
        int texcubemap[MAX_TEXTUREUNITS];
        int texrgbscale[MAX_TEXTUREUNITS]; // used only if COMBINE is present
+       int texcombinergb[MAX_TEXTUREUNITS]; // works with or without combine for some operations
+       int texcombinealpha[MAX_TEXTUREUNITS]; // does nothing without combine
 }
 rmeshstate_t;
 
@@ -72,7 +75,7 @@ void R_Mesh_TextureState(const rmeshstate_t *m);
 void _R_Mesh_ResizeCheck(int numverts);
 
 // renders the mesh in the varray_* buffers
-void R_Mesh_Draw(int numverts, int numtriangles, int *elements);
+void R_Mesh_Draw(int numverts, int numtriangles, const int *elements);
 
 // saves a section of the rendered frame to a .tga file
 qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height);
index c55f9c3..c5c4c71 100644 (file)
@@ -10,13 +10,13 @@ typedef struct
 
 // LordHavoc: vertex arrays
 
-float *aliasvertbuf;
 float *aliasvertcolorbuf;
-float *aliasvert; // this may point at aliasvertbuf or at vertex arrays in the mesh backend
 float *aliasvertcolor; // this may point at aliasvertcolorbuf or at vertex arrays in the mesh backend
+float *aliasvert_svectors;
+float *aliasvert_tvectors;
+float *aliasvert_normals;
 
 float *aliasvertcolor2;
-float *aliasvertnorm;
 int *aliasvertusage;
 zymbonematrix *zymbonepose;
 
@@ -26,9 +26,10 @@ void gl_models_start(void)
 {
        // allocate vertex processing arrays
        gl_models_mempool = Mem_AllocPool("GL_Models");
-       aliasvert = aliasvertbuf = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
        aliasvertcolor = aliasvertcolorbuf = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
-       aliasvertnorm = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][3]));
+       aliasvert_svectors = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
+       aliasvert_tvectors = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
+       aliasvert_normals = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
        aliasvertcolor2 = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
        zymbonepose = Mem_Alloc(gl_models_mempool, sizeof(zymbonematrix[256]));
        aliasvertusage = Mem_Alloc(gl_models_mempool, sizeof(int[MD2MAX_VERTS]));
@@ -87,7 +88,7 @@ void R_AliasLerpVerts(int vertcount, float *vertices, float *normals,
                                        avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3 + n4[1] * lerp4;
                                        avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3 + n4[2] * lerp4;
                                        av += 4;
-                                       avn += 3;
+                                       avn += 4;
                                        verts1++;verts2++;verts3++;verts4++;
                                }
                        }
@@ -109,7 +110,7 @@ void R_AliasLerpVerts(int vertcount, float *vertices, float *normals,
                                        avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3;
                                        avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3;
                                        av += 4;
-                                       avn += 3;
+                                       avn += 4;
                                        verts1++;verts2++;verts3++;
                                }
                        }
@@ -131,7 +132,7 @@ void R_AliasLerpVerts(int vertcount, float *vertices, float *normals,
                                avn[1] = n1[1] * lerp1 + n2[1] * lerp2;
                                avn[2] = n1[2] * lerp1 + n2[2] * lerp2;
                                av += 4;
-                               avn += 3;
+                               avn += 4;
                                verts1++;verts2++;
                        }
                }
@@ -155,7 +156,7 @@ void R_AliasLerpVerts(int vertcount, float *vertices, float *normals,
                                avn[1] = n1[1] * lerp1;
                                avn[2] = n1[2] * lerp1;
                                av += 4;
-                               avn += 3;
+                               avn += 4;
                                verts1++;
                        }
                }
@@ -169,7 +170,7 @@ void R_AliasLerpVerts(int vertcount, float *vertices, float *normals,
                                av[2] = verts1->v[2] * scale1[2] + translate[2];
                                VectorCopy(m_bytenormals[verts1->lightnormalindex], avn);
                                av += 4;
-                               avn += 3;
+                               avn += 4;
                                verts1++;
                        }
                }
@@ -265,7 +266,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2)
                blendfunc2 = GL_ZERO;
        }
 
-       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
        memcpy(varray_texcoord[0], model->mdlmd2data_texcoords, model->numverts * sizeof(float[4]));
        if (!skinframe->base && !skinframe->pants && !skinframe->shirt && !skinframe->glow)
        {
@@ -287,7 +288,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2)
                        varray_texcoord[0][i + 0] *= 8.0f;
                        varray_texcoord[0][i + 1] *= 8.0f;
                }
-               R_LightModel(ent, model->numverts, varray_vertex, aliasvertnorm, varray_color, colorscale, colorscale, colorscale, false);
+               R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, colorscale, colorscale, colorscale, false);
                GL_UseColorArray();
                R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                return;
@@ -331,7 +332,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2)
                else
                {
                        GL_UseColorArray();
-                       R_LightModel(ent, model->numverts, varray_vertex, aliasvertnorm, varray_color, colorscale * ifog, colorscale * ifog, colorscale * ifog, false);
+                       R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, colorscale * ifog, colorscale * ifog, colorscale * ifog, false);
                }
                R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                c_alias_polys += model->numtris;
@@ -362,7 +363,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2)
                                else
                                {
                                        GL_UseColorArray();
-                                       R_LightModel(ent, model->numverts, varray_vertex, aliasvertnorm, varray_color, pantscolor[0] * colorscale * ifog, pantscolor[1] * colorscale * ifog, pantscolor[2] * colorscale * ifog, false);
+                                       R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, pantscolor[0] * colorscale * ifog, pantscolor[1] * colorscale * ifog, pantscolor[2] * colorscale * ifog, false);
                                }
                                R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                                c_alias_polys += model->numtris;
@@ -391,7 +392,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2)
                                else
                                {
                                        GL_UseColorArray();
-                                       R_LightModel(ent, model->numverts, varray_vertex, aliasvertnorm, varray_color, shirtcolor[0] * colorscale * ifog, shirtcolor[1] * colorscale * ifog, shirtcolor[2] * colorscale * ifog, false);
+                                       R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, shirtcolor[0] * colorscale * ifog, shirtcolor[1] * colorscale * ifog, shirtcolor[2] * colorscale * ifog, false);
                                }
                                R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                                c_alias_polys += model->numtris;
@@ -475,14 +476,14 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
                                {
                                        model = ent->model;
                                        R_Mesh_ResizeCheck(model->numverts * 2);
-                                       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+                                       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
                                        Matrix4x4_Transform(&ent->inversematrix, sl->origin, temp);
                                        GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
                                        R_Shadow_Volume(model->numverts, model->numtris, varray_vertex, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, sl->cullradius + model->radius - sqrt(f), true);
                                        GL_UseColorArray();
                                        lightscale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f);
                                        VectorScale(sl->light, lightscale, lightcolor);
-                                       R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvertnorm, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor);
+                                       R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvert_normals, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor);
                                        R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                                }
                        }
@@ -497,12 +498,12 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
                                {
                                        model = ent->model;
                                        R_Mesh_ResizeCheck(model->numverts * 2);
-                                       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+                                       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
                                        Matrix4x4_Transform(&ent->inversematrix, rd->origin, temp);
                                        GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
                                        R_Shadow_Volume(model->numverts, model->numtris, varray_vertex, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, rd->cullradius + model->radius - sqrt(f), true);
                                        GL_UseColorArray();
-                                       R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvertnorm, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light);
+                                       R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvert_normals, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light);
                                        R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                                }
                        }
@@ -531,7 +532,7 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
        R_Mesh_State(&m);
 
        c_alias_polys += model->numtris;
-       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
 
        // put a light direction in the entity's coordinate space
        Matrix4x4_Transform3x3(&ent->inversematrix, lightdirection, projection);
@@ -558,10 +559,12 @@ void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
        R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
 }
 
-void R_Model_Alias_DrawDepth(entity_render_t *ent)
+void R_Model_Alias_DrawBaseLighting(entity_render_t *ent)
 {
+       R_Mesh_Matrix(&ent->matrix);
+       GL_Color(0, 0, 0, 1);
        R_Mesh_ResizeCheck(ent->model->numverts);
-       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
        R_Mesh_Draw(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices);
 }
 
@@ -571,24 +574,22 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor
        projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
        if (projectdistance > 0.1)
        {
+               R_Mesh_Matrix(&ent->matrix);
                R_Mesh_ResizeCheck(ent->model->numverts * 2);
-               R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+               R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
                R_Shadow_Volume(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_indices, ent->model->mdlmd2data_triangleneighbors, relativelightorigin, lightradius, projectdistance, visiblevolume);
        }
 }
 
-void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
 {
+       skinframe_t *skinframe;
+       R_Mesh_Matrix(&ent->matrix);
+       skinframe = R_FetchSkinFrame(ent);
        R_Mesh_ResizeCheck(ent->model->numverts);
-       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
-       R_Shadow_Light(ent->model->numverts, aliasvertnorm, relativelightorigin, lightradius, lightdistbias, lightsubtract, lightcolor);
-       GL_UseColorArray();
-       R_Mesh_Draw(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices);
-}
-
-void R_Model_Alias_DrawOntoLight(entity_render_t *ent)
-{
-       // FIXME
+       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
+       Mod_BuildTextureVectorsAndNormals(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_texcoords, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals);
+       R_Shadow_RenderLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, skinframe->base, r_notexture, NULL, NULL);
 }
 
 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
@@ -919,10 +920,10 @@ void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
        R_Mesh_State(&mstate);
        ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones);
        ZymoticTransformVerts(numverts, varray_vertex, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
-       ZymoticCalcNormals(numverts, varray_vertex, aliasvertnorm, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
+       ZymoticCalcNormals(numverts, varray_vertex, aliasvert_normals, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
        memcpy(varray_texcoord[0], ent->model->zymdata_texcoords, ent->model->zymnum_verts * sizeof(float[4]));
        GL_UseColorArray();
-       R_LightModel(ent, numverts, varray_vertex, aliasvertnorm, varray_color, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
+       R_LightModel(ent, numverts, varray_vertex, aliasvert_normals, varray_color, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
        R_Mesh_Draw(numverts, numtriangles, elements);
        c_alias_polys += numtriangles;
 
index 6ad76ed..4a8d46f 100644 (file)
@@ -522,7 +522,7 @@ void R_DrawViewModel (void)
 }
 
 void R_DrawNoModel(entity_render_t *ent);
-void R_DrawModels (void)
+void R_DrawModels (int baselighting)
 {
        int i;
        entity_render_t *ent;
@@ -538,7 +538,12 @@ void R_DrawModels (void)
                {
                        if (ent->model)
                        {
-                               if (ent->model->Draw)
+                               if (baselighting && ent->model->DrawBaseLighting != NULL)
+                               {
+                                       if (ent->model->DrawBaseLighting)
+                                               ent->model->DrawBaseLighting(ent);
+                               }
+                               else if (ent->model->Draw)
                                        ent->model->Draw(ent);
                        }
                        else
@@ -630,7 +635,6 @@ void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float l
 #endif
                        {
                                Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
-                               R_Mesh_Matrix(&ent->matrix);
                                ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius, visiblevolume);
                        }
                        }
@@ -662,6 +666,8 @@ void R_DrawShadowVolumes (void)
        {
                if (d_lightstylevalue[sl->style] <= 0)
                        continue;
+               if (r_light_debuglight.integer >= 0 && lnum != r_light_debuglight.integer)
+                       continue;
                /*
                mins[0] = sl->origin[0] - sl->cullradius;
                maxs[0] = sl->origin[0] + sl->cullradius;
@@ -691,7 +697,6 @@ void R_DrawShadowVolumes (void)
                if (ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2])
                {
                        Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
-                       R_Mesh_Matrix(&ent->matrix);
                        ent->model->DrawShadowVolume (ent, relativelightorigin, sl->cullradius, true);
                }
                */
@@ -714,7 +719,6 @@ void R_DrawShadowVolumes (void)
                                if (ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2])
                                {
                                        Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
-                                       R_Mesh_Matrix(&ent->matrix);
                                        ent->model->DrawShadowVolume (ent, relativelightorigin, sl->cullradius, true);
                                }
                                */
@@ -745,7 +749,6 @@ void R_DrawShadowVolumes (void)
                if (ent != rd->ent && ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2])
                {
                        Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                       R_Mesh_Matrix(&ent->matrix);
                        ent->model->DrawShadowVolume (ent, relativelightorigin, rd->cullradius, true);
                }
                */
@@ -761,7 +764,6 @@ void R_DrawShadowVolumes (void)
                                if (ent != rd->ent && ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2])
                                {
                                        Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                                       R_Mesh_Matrix(&ent->matrix);
                                        ent->model->DrawShadowVolume (ent, relativelightorigin, rd->cullradius, true);
                                }
                                */
@@ -779,11 +781,11 @@ void R_CreateShadowSphere(void)
        vec3_t angles, angles2, angles3, angles4;
        float verts[12];
        shadowsphere = Mod_ShadowMesh_Begin(zonemempool);
-       for (i = 0;i < SHADOWSPHERE_SEGMENTS;i++)
+       for (i = 0;i < SHADOWSPHERE_SEGMENTS / 2;i++)
        {
                for (j = 0;j < SHADOWSPHERE_SEGMENTS;j++)
                {
-                       angles[0] = i * 360.0f / SHADOWSPHERE_SEGMENTS;
+                       angles[0] = (i * 360.0f / SHADOWSPHERE_SEGMENTS) + 90.0f;
                        angles[1] = j * 360.0f / SHADOWSPHERE_SEGMENTS;
                        angles[2] = 0;
                        VectorCopy(angles, angles2);
@@ -797,43 +799,48 @@ void R_CreateShadowSphere(void)
                        AngleVectorsFLU(angles2, verts + 9, NULL, NULL);
                        AngleVectorsFLU(angles3, verts + 6, NULL, NULL);
                        AngleVectorsFLU(angles4, verts + 3, NULL, NULL);
-                       VectorScale(&verts[0], 64.0f, &verts[0]);
-                       VectorScale(&verts[3], 64.0f, &verts[3]);
-                       VectorScale(&verts[6], 64.0f, &verts[6]);
-                       VectorScale(&verts[9], 64.0f, &verts[9]);
+                       VectorScale(&verts[0], 1.0f, &verts[0]);
+                       VectorScale(&verts[3], 1.0f, &verts[3]);
+                       VectorScale(&verts[6], 1.0f, &verts[6]);
+                       VectorScale(&verts[9], 1.0f, &verts[9]);
                        Mod_ShadowMesh_AddPolygon(zonemempool, shadowsphere, 4, verts);
+                       /*
                        AngleVectorsFLU(angles, verts, NULL, NULL);
                        AngleVectorsFLU(angles2, verts + 3, NULL, NULL);
                        AngleVectorsFLU(angles3, verts + 6, NULL, NULL);
                        AngleVectorsFLU(angles4, verts + 9, NULL, NULL);
-                       VectorScale(&verts[0], 128.0f, &verts[0]);
-                       VectorScale(&verts[3], 128.0f, &verts[3]);
-                       VectorScale(&verts[6], 128.0f, &verts[6]);
-                       VectorScale(&verts[9], 128.0f, &verts[9]);
+                       VectorScale(&verts[0], -4.0f, &verts[0]);
+                       VectorScale(&verts[3], -4.0f, &verts[3]);
+                       VectorScale(&verts[6], -4.0f, &verts[6]);
+                       VectorScale(&verts[9], -4.0f, &verts[9]);
                        Mod_ShadowMesh_AddPolygon(zonemempool, shadowsphere, 4, verts);
+                       */
                }
        }
        shadowsphere = Mod_ShadowMesh_Finish(zonemempool, shadowsphere);
 }
 
 
-void R_DrawShadowSphere(vec3_t origin, float radius, int visiblevolume)
+void R_DrawShadowSphere(vec3_t origin, float cullradius, float lightradius, int visiblevolume)
 {
-       int i;
-       float *v;
        shadowmesh_t *mesh;
-       //matrix4x4_t matrix;
+       matrix4x4_t matrix;
        if (!shadowsphere)
                R_CreateShadowSphere();
-       //Matrix4x4_CreateTranslate(&matrix, origin[0], origin[1], origin[2]);
-       //Matrix4x4_ConcatScale(&matrix, radius);
-       //R_Mesh_Matrix(&matrix);
-       R_Mesh_Matrix(&r_identitymatrix);
+       Matrix4x4_CreateScale(&matrix, lightradius);
+       Matrix4x4_ConcatTranslate(&matrix, origin[0], origin[1], origin[2]);
+       R_Mesh_Matrix(&matrix);
+       for (mesh = shadowsphere;mesh;mesh = mesh->next)
+       {
+               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+               R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume);
+       }
+       Matrix4x4_CreateScale(&matrix, -cullradius);
+       Matrix4x4_ConcatTranslate(&matrix, origin[0], origin[1], origin[2]);
+       R_Mesh_Matrix(&matrix);
        for (mesh = shadowsphere;mesh;mesh = mesh->next)
        {
                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-               for (i = 0, v = varray_vertex;i < mesh->numverts;i++, v += 4)
-                       VectorMA(origin, radius, v, v);
                R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume);
        }
 }
@@ -844,46 +851,19 @@ void R_ShadowVolumeLighting (void)
        entity_render_t *ent;
        int lnum;
        float f;
-       vec3_t mins, maxs, relativelightorigin, lightcolor;
+       vec3_t mins, maxs, relativelightorigin, relativeeyeorigin, lightcolor;
        mlight_t *sl;
        rdlight_t *rd;
 
-       R_Shadow_Stage_Depth();
-       ent = &cl_entities[0].render;
-       if (ent->model && ent->model->DrawDepth)
-       {
-               R_Mesh_Matrix(&ent->matrix);
-               ent->model->DrawDepth(ent);
-       }
-       if (r_drawentities.integer)
-       {
-               for (i = 0;i < r_refdef.numentities;i++)
-               {
-                       ent = r_refdef.entities[i];
-                       if (ent->visframe == r_framecount && ent->model && ent->model->DrawDepth)
-                       {
-                               R_Mesh_Matrix(&ent->matrix);
-                               ent->model->DrawDepth(ent);
-                       }
-               }
-       }
-
+       R_Shadow_Stage_Begin();
        for (lnum = 0, sl = cl.worldmodel->lights;lnum < cl.worldmodel->numlights;lnum++, sl++)
        {
                if (d_lightstylevalue[sl->style] <= 0)
                        continue;
+               if (r_light_debuglight.integer >= 0 && lnum != r_light_debuglight.integer)
+                       continue;
                VectorCopy(sl->mins, mins);
                VectorCopy(sl->maxs, maxs);
-               /*
-               mins[0] = sl->origin[0] - sl->cullradius;
-               maxs[0] = sl->origin[0] + sl->cullradius;
-               mins[1] = sl->origin[1] - sl->cullradius;
-               maxs[1] = sl->origin[1] + sl->cullradius;
-               mins[2] = sl->origin[2] - sl->cullradius;
-               maxs[2] = sl->origin[2] + sl->cullradius;
-               if (R_CullBox(mins, maxs))
-                       continue;
-               */
                if (R_CullBox(mins, maxs))
                        continue;
 
@@ -891,7 +871,7 @@ void R_ShadowVolumeLighting (void)
                VectorScale(sl->light, f, lightcolor);
 
                R_Shadow_Stage_ShadowVolumes();
-               R_DrawShadowSphere(sl->origin, 1.0f/*sl->cullradius - 16*/, false);
+               R_DrawShadowSphere(sl->origin, sl->cullradius, sl->lightradius * 2, false);
                if (sl->shadowvolume && r_staticworldlights.integer)
                        R_DrawWorldLightShadowVolume(sl, false);
                else
@@ -901,12 +881,14 @@ void R_ShadowVolumeLighting (void)
                        for (i = 0;i < r_refdef.numentities;i++)
                        {
                                ent = r_refdef.entities[i];
+                               /*
                                if (ent->maxs[0] >= mins[0]
                                 && ent->mins[0] <= maxs[0]
                                 && ent->maxs[1] >= mins[1]
                                 && ent->mins[1] <= maxs[1]
                                 && ent->maxs[2] >= mins[2]
                                 && ent->mins[2] <= maxs[2])
+                               */
                                        R_TestAndDrawShadowVolume(r_refdef.entities[i], sl->origin, sl->cullradius, false);
                        }
                }
@@ -916,8 +898,8 @@ void R_ShadowVolumeLighting (void)
                if (ent->model && ent->model->DrawLight)
                {
                        Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
-                       R_Mesh_Matrix(&ent->matrix);
-                       ent->model->DrawLight(ent, relativelightorigin, sl->cullradius, sl->distbias, sl->subtract, lightcolor);
+                       Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, sl->lightradius, sl->distbias, sl->subtract, lightcolor);
                }
                if (r_drawentities.integer)
                {
@@ -925,16 +907,17 @@ void R_ShadowVolumeLighting (void)
                        {
                                ent = r_refdef.entities[i];
                                if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
+                               /*
                                 && ent->maxs[0] >= mins[0]
                                 && ent->mins[0] <= maxs[0]
                                 && ent->maxs[1] >= mins[1]
                                 && ent->mins[1] <= maxs[1]
                                 && ent->maxs[2] >= mins[2]
-                                && ent->mins[2] <= maxs[2])
+                                && ent->mins[2] <= maxs[2]*/)
                                {
                                        Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
-                                       R_Mesh_Matrix(&ent->matrix);
-                                       ent->model->DrawLight(ent, relativelightorigin, sl->cullradius, sl->distbias, sl->subtract, lightcolor);
+                                       Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+                                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, sl->lightradius, sl->distbias, sl->subtract, lightcolor);
                                }
                        }
                }
@@ -957,13 +940,15 @@ void R_ShadowVolumeLighting (void)
                        for (i = 0;i < r_refdef.numentities;i++)
                        {
                                ent = r_refdef.entities[i];
+                               /*
                                if (ent->maxs[0] >= mins[0]
                                 && ent->mins[0] <= maxs[0]
                                 && ent->maxs[1] >= mins[1]
                                 && ent->mins[1] <= maxs[1]
                                 && ent->maxs[2] >= mins[2]
                                 && ent->mins[2] <= maxs[2])
-                               R_TestAndDrawShadowVolume(ent, rd->origin, rd->cullradius, false);
+                               */
+                                       R_TestAndDrawShadowVolume(ent, rd->origin, rd->cullradius, false);
                        }
                }
 
@@ -972,8 +957,8 @@ void R_ShadowVolumeLighting (void)
                if (ent->model && ent->model->DrawLight)
                {
                        Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                       R_Mesh_Matrix(&ent->matrix);
-                       ent->model->DrawLight(ent, relativelightorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
+                       Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
                }
                if (r_drawentities.integer)
                {
@@ -981,41 +966,22 @@ void R_ShadowVolumeLighting (void)
                        {
                                ent = r_refdef.entities[i];
                                if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
+                               /*
                                 && ent->maxs[0] >= mins[0]
                                 && ent->mins[0] <= maxs[0]
                                 && ent->maxs[1] >= mins[1]
                                 && ent->mins[1] <= maxs[1]
                                 && ent->maxs[2] >= mins[2]
-                                && ent->mins[2] <= maxs[2])
+                                && ent->mins[2] <= maxs[2]*/)
                                {
                                        Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                                       R_Mesh_Matrix(&ent->matrix);
-                                       ent->model->DrawLight(ent, relativelightorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
+                                       Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+                                       ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
                                }
                        }
                }
        }
 
-       R_Shadow_Stage_Textures();
-       ent = &cl_entities[0].render;
-       if (ent->model && ent->model->DrawOntoLight)
-       {
-               R_Mesh_Matrix(&ent->matrix);
-               ent->model->DrawOntoLight(ent);
-       }
-       if (r_drawentities.integer)
-       {
-               for (i = 0;i < r_refdef.numentities;i++)
-               {
-                       ent = r_refdef.entities[i];
-                       if (ent->visframe == r_framecount && ent->model && ent->model->DrawOntoLight)
-                       {
-                               R_Mesh_Matrix(&ent->matrix);
-                               ent->model->DrawOntoLight(ent);
-                       }
-               }
-       }
-
        R_Shadow_Stage_End();
 }
 
@@ -1133,7 +1099,8 @@ void R_RenderView (void)
        R_TimeReport("markentity");
 
        GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
-       GL_SetupView_Mode_Perspective((double) r_refdef.height / r_refdef.width, r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
+       //GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
+       GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
        GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
        qglDepthFunc(GL_LEQUAL);
 
@@ -1142,24 +1109,24 @@ void R_RenderView (void)
 
        if (r_shadows.integer == 3)
        {
-               if (!gl_stencil)
+               if (!gl_texturecubemap)
                {
-                       Con_Printf("Stencil not enabled, turning off r_shadows 3\n");
+                       Con_Printf("Cubemap texture support not detected, turning off r_shadows 3\n");
                        Cvar_SetValueQuick(&r_shadows, 0);
                }
-               else if (!gl_texture3d)
+               else if (!gl_dot3arb)
                {
-                       Con_Printf("3D texture support not detected, turning off r_shadows 3\n");
+                       Con_Printf("Bumpmapping support not detected, turning off r_shadows 3\n");
                        Cvar_SetValueQuick(&r_shadows, 0);
                }
-               else if (!gl_texturecubemap)
+               else if (!gl_stencil)
                {
-                       Con_Printf("Cubemap texture support not detected, turning off r_shadows 3\n");
+                       Con_Printf("Stencil not enabled, turning off r_shadows 3, please type vid_stencil 1;vid_restart and try again\n");
                        Cvar_SetValueQuick(&r_shadows, 0);
                }
-               else if (!gl_dot3arb)
+               else if (!gl_combine.integer)
                {
-                       Con_Printf("Bumpmapping support not detected, turning off r_shadows 3\n");
+                       Con_Printf("Combine disabled, please turn on gl_combine, turning off r_shadows 3\n");
                        Cvar_SetValueQuick(&r_shadows, 0);
                }
        }
@@ -1168,16 +1135,22 @@ void R_RenderView (void)
                R_TimeReport("bmodelsky");
 
        // must occur early because it can draw sky
-       R_DrawWorld(world);
+       R_DrawWorld(world, r_shadows.integer == 3);
        R_TimeReport("world");
 
        // don't let sound skip if going slow
        if (!intimerefresh && !r_speeds.integer)
                S_ExtraUpdate ();
 
-       R_DrawModels();
+       R_DrawModels(r_shadows.integer == 3);
        R_TimeReport("models");
 
+       if (r_shadows.integer == 1)
+       {
+               R_DrawFakeShadows();
+               R_TimeReport("fakeshadows");
+       }
+
        if (r_shadows.integer == 3)
                R_ShadowVolumeLighting();
 
@@ -1201,11 +1174,6 @@ void R_RenderView (void)
 
        R_MeshQueue_Render();
        R_MeshQueue_EndScene();
-       if (r_shadows.integer == 1)
-       {
-               R_DrawFakeShadows();
-               R_TimeReport("fakeshadows");
-       }
        if (r_shadows.integer == 2)
        {
                R_DrawShadowVolumes();
index 749e223..aa5c405 100644 (file)
@@ -40,11 +40,6 @@ cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"};
 
 static int dlightdivtable[32768];
 
-// variables used by R_PVSUpdate
-int r_pvsframecount = 0;
-mleaf_t *r_pvsviewleaf = NULL;
-int r_pvsviewleafnovis = 0;
-
 static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
 {
        int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract, k;
@@ -752,7 +747,7 @@ static int RSurf_LightCheck(const matrix4x4_t *matrix, const int *dlightbits, co
        return false;
 }
 
-static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -789,14 +784,17 @@ static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture
        }
        m.depthwrite = true;
        R_Mesh_State(&m);
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+               if (surf->visframe == r_framecount)
                {
-                       R_Mesh_ResizeCheck(mesh->numverts);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, 1);
-                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, 1);
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
        qglColorMask(1,1,1,1);
@@ -877,21 +875,25 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        }
 }
 
-static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        vec3_t center;
        if ((r_wateralpha.value < 1 && !(texture->flags & SURF_DRAWNOALPHA)) || ent->effects & EF_ADDITIVE || texture->fogtexture)
        {
-               for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+               for (surf = firstsurf;surf;surf = surf->texturechain)
                {
-                       Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
-                       R_MeshQueue_AddTransparent(center, RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
+                       if (surf->visframe == r_framecount)
+                       {
+                               Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+                               R_MeshQueue_AddTransparent(center, RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
+                       }
                }
        }
        else
-               for (surf = texture->surfacechain;surf;surf = surf->texturechain)
-                       RSurfShader_Water_Callback(ent, surf - ent->model->surfaces);
+               for (surf = firstsurf;surf;surf = surf->texturechain)
+                       if (surf->visframe == r_framecount)
+                               RSurfShader_Water_Callback(ent, surf - ent->model->surfaces);
 }
 
 static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const msurface_t *surf)
@@ -945,41 +947,6 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m
        }
 }
 
-static void RSurfShader_Wall_Pass_BaseFullbright(const entity_render_t *ent, const msurface_t *surf)
-{
-       const surfmesh_t *mesh;
-       rmeshstate_t m;
-       float modelorg[3];
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
-       memset(&m, 0, sizeof(m));
-       if (ent->effects & EF_ADDITIVE)
-       {
-               m.blendfunc1 = GL_SRC_ALPHA;
-               m.blendfunc2 = GL_ONE;
-       }
-       else if (surf->currenttexture->fogtexture != NULL || ent->alpha < 1)
-       {
-               m.blendfunc1 = GL_SRC_ALPHA;
-               m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
-       }
-       else
-       {
-               m.blendfunc1 = GL_ONE;
-               m.blendfunc2 = GL_ZERO;
-       }
-       m.tex[0] = R_GetTexture(surf->currenttexture->texture);
-       R_Mesh_State(&m);
-       GL_UseColorArray();
-       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
-       {
-               R_Mesh_ResizeCheck(mesh->numverts);
-               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-               memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-               RSurf_FoggedColors(varray_vertex, varray_color, 1, 1, 1, ent->alpha, r_colorscale, mesh->numverts, modelorg);
-               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
-       }
-}
-
 static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurface_t *surf)
 {
        const surfmesh_t *mesh;
@@ -1025,7 +992,7 @@ static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1036,7 +1003,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render
        m.blendfunc1 = GL_ONE;
        m.blendfunc2 = GL_ZERO;
        m.tex[0] = R_GetTexture(texture->texture);
-       m.tex[1] = R_GetTexture(texture->surfacechain->lightmaptexture);
+       m.tex[1] = R_GetTexture(firstsurf->lightmaptexture);
        m.tex[2] = R_GetTexture(texture->detailtexture);
        m.texrgbscale[0] = 1;
        m.texrgbscale[1] = 4;
@@ -1044,27 +1011,30 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render
        R_Mesh_State(&m);
        cl = (float) (1 << r_lightmapscalebit) * r_colorscale;
        GL_Color(cl, cl, cl, 1);
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
-               if (m.tex[1] != lightmaptexturenum)
+               if (surf->visframe == r_framecount)
                {
-                       m.tex[1] = lightmaptexturenum;
-                       R_Mesh_State(&m);
-               }
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
-               {
-                       R_Mesh_ResizeCheck(mesh->numverts);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[1], mesh->uvw, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[2], mesh->abc, mesh->numverts * sizeof(float[4]));
-                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
+                       if (m.tex[1] != lightmaptexturenum)
+                       {
+                               m.tex[1] = lightmaptexturenum;
+                               R_Mesh_State(&m);
+                       }
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[1], mesh->uvw, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[2], mesh->abc, mesh->numverts * sizeof(float[4]));
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1074,31 +1044,34 @@ static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent
        m.blendfunc1 = GL_ONE;
        m.blendfunc2 = GL_ZERO;
        m.tex[0] = R_GetTexture(texture->texture);
-       m.tex[1] = R_GetTexture(texture->surfacechain->lightmaptexture);
+       m.tex[1] = R_GetTexture(firstsurf->lightmaptexture);
        if (gl_combine.integer)
                m.texrgbscale[1] = 4;
        R_Mesh_State(&m);
        GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
-               if (m.tex[1] != lightmaptexturenum)
+               if (surf->visframe == r_framecount)
                {
-                       m.tex[1] = lightmaptexturenum;
-                       R_Mesh_State(&m);
-               }
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
-               {
-                       R_Mesh_ResizeCheck(mesh->numverts);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[1], mesh->uvw, mesh->numverts * sizeof(float[4]));
-                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
+                       if (m.tex[1] != lightmaptexturenum)
+                       {
+                               m.tex[1] = lightmaptexturenum;
+                               R_Mesh_State(&m);
+                       }
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[1], mesh->uvw, mesh->numverts * sizeof(float[4]));
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1109,19 +1082,22 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent,
        m.tex[0] = R_GetTexture(texture->texture);
        R_Mesh_State(&m);
        GL_Color(1, 1, 1, 1);
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+               if (surf->visframe == r_framecount)
                {
-                       R_Mesh_ResizeCheck(mesh->numverts);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1130,30 +1106,33 @@ static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent,
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_ZERO;
        m.blendfunc2 = GL_SRC_COLOR;
-       m.tex[0] = R_GetTexture(texture->surfacechain->lightmaptexture);
+       m.tex[0] = R_GetTexture(firstsurf->lightmaptexture);
        if (gl_combine.integer)
                m.texrgbscale[0] = 4;
        R_Mesh_State(&m);
        GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
-               if (m.tex[0] != lightmaptexturenum)
-               {
-                       m.tex[0] = lightmaptexturenum;
-                       R_Mesh_State(&m);
-               }
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+               if (surf->visframe == r_framecount)
                {
-                       R_Mesh_ResizeCheck(mesh->numverts);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[0], mesh->uvw, mesh->numverts * sizeof(float[4]));
-                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
+                       if (m.tex[0] != lightmaptexturenum)
+                       {
+                               m.tex[0] = lightmaptexturenum;
+                               R_Mesh_State(&m);
+                       }
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[0], mesh->uvw, mesh->numverts * sizeof(float[4]));
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1172,9 +1151,9 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const
        }
        R_Mesh_State(&m);
        GL_UseColorArray();
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               if (surf->dlightframe == r_framecount)
+               if (surf->visframe == r_framecount && surf->dlightframe == r_framecount)
                {
                        for (mesh = surf->mesh;mesh;mesh = mesh->chain)
                        {
@@ -1193,7 +1172,7 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1205,21 +1184,24 @@ static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const te
        m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
        R_Mesh_State(&m);
        GL_UseColorArray();
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+               if (surf->visframe == r_framecount)
                {
-                       R_Mesh_ResizeCheck(mesh->numverts);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       if (m.tex[0])
-                               memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-                       RSurf_FogPassColors(varray_vertex, varray_color, fogcolor[0], fogcolor[1], fogcolor[2], 1, r_colorscale, mesh->numverts, modelorg);
-                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               if (m.tex[0])
+                                       memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+                               RSurf_FogPassColors(varray_vertex, varray_color, fogcolor[0], fogcolor[1], fogcolor[2], 1, r_colorscale, mesh->numverts, modelorg);
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1230,19 +1212,22 @@ static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, c
        m.tex[0] = R_GetTexture(texture->detailtexture);
        R_Mesh_State(&m);
        GL_Color(1, 1, 1, 1);
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+               if (surf->visframe == r_framecount)
                {
-                       R_Mesh_ResizeCheck(mesh->numverts);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[0], mesh->abc, mesh->numverts * sizeof(float[4]));
-                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[0], mesh->abc, mesh->numverts * sizeof(float[4]));
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1253,53 +1238,48 @@ static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const t
        m.tex[0] = R_GetTexture(texture->glowtexture);
        R_Mesh_State(&m);
        GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+               if (surf->visframe == r_framecount)
                {
-                       R_Mesh_ResizeCheck(mesh->numverts);
-                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                       memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
-                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
 }
 
-static void RSurfShader_Wall_Fullbright_Callback(const void *calldata1, int calldata2)
-{
-       const entity_render_t *ent = calldata1;
-       const msurface_t *surf = ent->model->surfaces + calldata2;
-       R_Mesh_Matrix(&ent->matrix);
-       RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
-       if (surf->currenttexture->glowtexture)
-               RSurfShader_Wall_Pass_Glow(ent, surf);
-       if (fogenabled)
-               RSurfShader_Wall_Pass_Fog(ent, surf);
-}
-
-static void RSurfShader_Wall_Fullbright(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
-       vec3_t center;
-       if (ent->effects & EF_ADDITIVE || ent->alpha < 1 || texture->fogtexture != NULL)
+       const surfmesh_t *mesh;
+       rmeshstate_t m;
+       memset(&m, 0, sizeof(m));
+       m.blendfunc1 = GL_SRC_ALPHA;
+       m.blendfunc2 = GL_ZERO;
+       m.tex[0] = R_GetTexture(texture->glowtexture);
+       R_Mesh_State(&m);
+       if (m.tex[0])
+               GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
+       else
+               GL_Color(0, 0, 0, 1);
+       for (surf = firstsurf;surf;surf = surf->texturechain)
        {
-               for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+               if (surf->visframe == r_framecount)
                {
-                       Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
-                       R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Fullbright_Callback, ent, surf - ent->model->surfaces);
+                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                       {
+                               R_Mesh_ResizeCheck(mesh->numverts);
+                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                               memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                       }
                }
        }
-       else
-       {
-               for (surf = texture->surfacechain;surf;surf = surf->texturechain)
-                       RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
-               if (texture->glowtexture)
-                       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
-                               RSurfShader_Wall_Pass_Glow(ent, surf);
-               if (fogenabled)
-                       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
-                               RSurfShader_Wall_Pass_Fog(ent, surf);
-       }
 }
 
 static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata2)
@@ -1314,30 +1294,36 @@ static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata
                RSurfShader_Wall_Pass_Fog(ent, surf);
 }
 
-static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
 {
        const msurface_t *surf;
        vec3_t center;
-       if (ent->effects & EF_ADDITIVE || ent->alpha < 1 || texture->fogtexture != NULL)
+       if (texture->rendertype != SURFRENDER_OPAQUE)
        {
                // transparent vertex shaded from lightmap
-               for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+               for (surf = firstsurf;surf;surf = surf->texturechain)
                {
-                       Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
-                       R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+                       if (surf->visframe == r_framecount)
+                       {
+                               Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+                               R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+                       }
                }
        }
        else if (r_vertexsurfaces.integer)
        {
                // opaque vertex shaded from lightmap
-               for (surf = texture->surfacechain;surf;surf = surf->texturechain)
-                       RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+               for (surf = firstsurf;surf;surf = surf->texturechain)
+                       if (surf->visframe == r_framecount)
+                               RSurfShader_Wall_Pass_BaseVertex(ent, surf);
                if (texture->glowtexture)
-                       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
-                               RSurfShader_Wall_Pass_Glow(ent, surf);
+                       for (surf = firstsurf;surf;surf = surf->texturechain)
+                               if (surf->visframe == r_framecount)
+                                       RSurfShader_Wall_Pass_Glow(ent, surf);
                if (fogenabled)
-                       for (surf = texture->surfacechain;surf;surf = surf->texturechain)
-                               RSurfShader_Wall_Pass_Fog(ent, surf);
+                       for (surf = firstsurf;surf;surf = surf->texturechain)
+                               if (surf->visframe == r_framecount)
+                                       RSurfShader_Wall_Pass_Fog(ent, surf);
        }
        else
        {
@@ -1345,75 +1331,122 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_
                if (r_textureunits.integer >= 2)
                {
                        if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer)
-                               RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture);
+                               RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, firstsurf);
                        else
                        {
-                               RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture);
+                               RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, firstsurf);
                                if (r_detailtextures.integer)
-                                       RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture);
+                                       RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
                        }
                }
                else
                {
-                       RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture);
-                       RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture);
+                       RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, firstsurf);
+                       RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, firstsurf);
                        if (r_detailtextures.integer)
-                               RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture);
+                               RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
                }
                if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT))
-                       RSurfShader_OpaqueWall_Pass_Light(ent, texture);
+                       RSurfShader_OpaqueWall_Pass_Light(ent, texture, firstsurf);
                if (texture->glowtexture)
-                       RSurfShader_OpaqueWall_Pass_Glow(ent, texture);
+                       RSurfShader_OpaqueWall_Pass_Glow(ent, texture, firstsurf);
                if (fogenabled)
-                       RSurfShader_OpaqueWall_Pass_Fog(ent, texture);
+                       RSurfShader_OpaqueWall_Pass_Fog(ent, texture, firstsurf);
        }
 }
 
-Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap}, SHADERFLAGS_NEEDLIGHTMAP};
-Cshader_t Cshader_wall_fullbright = {{NULL, RSurfShader_Wall_Fullbright}, 0};
-Cshader_t Cshader_water = {{NULL, RSurfShader_Water}, 0};
-Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL}, 0};
+static void RSurfShader_Wall_Lightmap_BaseLighting(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+{
+       const msurface_t *surf;
+       if (cl.worldmodel->numlights)
+               RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, firstsurf);
+       else if (r_vertexsurfaces.integer)
+       {
+               // opaque vertex shaded from lightmap
+               for (surf = firstsurf;surf;surf = surf->texturechain)
+                       if (surf->visframe == r_framecount)
+                               RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+               if (texture->glowtexture)
+                       for (surf = firstsurf;surf;surf = surf->texturechain)
+                               if (surf->visframe == r_framecount)
+                                       RSurfShader_Wall_Pass_Glow(ent, surf);
+       }
+       else
+       {
+               // opaque lightmapped
+               if (r_textureunits.integer >= 2)
+               {
+                       if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer)
+                               RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, firstsurf);
+                       else
+                       {
+                               RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, firstsurf);
+                               if (r_detailtextures.integer)
+                                       RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
+                       }
+               }
+               else
+               {
+                       RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, firstsurf);
+                       RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, firstsurf);
+                       if (r_detailtextures.integer)
+                               RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
+               }
+               if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT))
+                       RSurfShader_OpaqueWall_Pass_Light(ent, texture, firstsurf);
+               if (texture->glowtexture)
+                       RSurfShader_OpaqueWall_Pass_Glow(ent, texture, firstsurf);
+       }
+}
 
-int Cshader_count = 4;
-Cshader_t *Cshaders[4] =
+Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap, RSurfShader_Wall_Lightmap_BaseLighting}, SHADERFLAGS_NEEDLIGHTMAP};
+Cshader_t Cshader_water = {{NULL, RSurfShader_Water, NULL}, 0};
+Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL, NULL}, 0};
+
+int Cshader_count = 3;
+Cshader_t *Cshaders[3] =
 {
        &Cshader_wall_lightmap,
-       &Cshader_wall_fullbright,
        &Cshader_water,
        &Cshader_sky
 };
 
-void R_DrawSurfaces(entity_render_t *ent, int sky, int normal)
+void R_PrepareSurfaces(entity_render_t *ent)
 {
-       int i, alttextures, texframe, framecount, numtextures, numsurfaces, *surfacevisframes;
-       texture_t *t, *textures;
+       int i, texframe, numsurfaces, *surfacevisframes;
        model_t *model;
        msurface_t *surf, *surfaces;
+       texture_t *t;
        vec3_t modelorg;
 
        if (!ent->model)
                return;
 
-       // mark the surfaces touched by dynamic lights
-       if (normal && r_dynamic.integer)
-               R_MarkLights(ent);
-
-       R_Mesh_Matrix(&ent->matrix);
-
        model = ent->model;
-       alttextures = ent->frame != 0;
-       texframe = (int)(cl.time * 5.0f);
-
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
-
-       numtextures = model->numtextures;
-       textures = model->textures;
        numsurfaces = model->nummodelsurfaces;
        surfaces = model->surfaces + model->firstmodelsurface;
        surfacevisframes = model->surfacevisframes + model->firstmodelsurface;
 
-       for (i = 0;i < numtextures;i++)
-               textures[i].surfacechain = NULL;
+       texframe = (int)(cl.time * 5.0f);
+       for (i = 0;i < model->numtextures;i++)
+       {
+               t = model->textures + i;
+               if (ent->effects & EF_ADDITIVE)
+                       t->rendertype = SURFRENDER_ADD;
+               else if (ent->alpha < 1 || t->flags & SURF_WATERALPHA || t->fogtexture != NULL)
+                       t->rendertype = SURFRENDER_ALPHA;
+               else
+                       t->rendertype = SURFRENDER_OPAQUE;
+               if (t->animated)
+               {
+                       t->currentframe[0] = t->anim_frames[0][(t->anim_total[0] >= 2) ? (texframe % t->anim_total[0]) : 0];
+                       t->currentframe[1] = t->anim_frames[1][(t->anim_total[1] >= 2) ? (texframe % t->anim_total[1]) : 0];
+               }
+       }
+
+       if (r_dynamic.integer)
+               R_MarkLights(ent);
 
        for (i = 0, surf = surfaces;i < numsurfaces;i++, surf++)
        {
@@ -1435,30 +1468,19 @@ void R_DrawSurfaces(entity_render_t *ent, int sky, int normal)
 #endif
                        {
                                c_faces++;
-                               t = surf->texinfo->texture;
-                               if (t->animated)
-                               {
-                                       framecount = t->anim_total[alttextures];
-                                       if (framecount >= 2)
-                                               t = t->anim_frames[alttextures][texframe % framecount];
-                                       else
-                                               t = t->anim_frames[alttextures][0];
-                               }
-                               surf->currenttexture = t;
-                               surf->texturechain = t->surfacechain;
-                               t->surfacechain = surf;
+                               surf->visframe = r_framecount;
                                if (!r_vertexsurfaces.integer && surf->lightmaptexture != NULL)
                                {
                                        if (surf->cached_dlight
-                                       || surf->cached_ambient != r_ambient.value
-                                       || surf->cached_lightmapscalebit != r_lightmapscalebit)
+                                        || surf->cached_ambient != r_ambient.value
+                                        || surf->cached_lightmapscalebit != r_lightmapscalebit)
                                                R_BuildLightMap(ent, surf, false); // base lighting changed
                                        else if (r_dynamic.integer)
                                        {
                                                if  (surf->styles[0] != 255 && (d_lightstylevalue[surf->styles[0]] != surf->cached_light[0]
-                                               || (surf->styles[1] != 255 && (d_lightstylevalue[surf->styles[1]] != surf->cached_light[1]
-                                               || (surf->styles[2] != 255 && (d_lightstylevalue[surf->styles[2]] != surf->cached_light[2]
-                                               || (surf->styles[3] != 255 && (d_lightstylevalue[surf->styles[3]] != surf->cached_light[3]))))))))
+                                                || (surf->styles[1] != 255 && (d_lightstylevalue[surf->styles[1]] != surf->cached_light[1]
+                                                || (surf->styles[2] != 255 && (d_lightstylevalue[surf->styles[2]] != surf->cached_light[2]
+                                                || (surf->styles[3] != 255 && (d_lightstylevalue[surf->styles[3]] != surf->cached_light[3]))))))))
                                                        R_BuildLightMap(ent, surf, false); // base lighting changed
                                                else if (surf->dlightframe == r_framecount && r_dlightmap.integer)
                                                        R_BuildLightMap(ent, surf, true); // only dlights
@@ -1467,16 +1489,16 @@ void R_DrawSurfaces(entity_render_t *ent, int sky, int normal)
                        }
                }
        }
+}
 
-       if (sky)
-               for (i = 0, t = textures;i < numtextures;i++, t++)
-                       if (t->surfacechain && t->shader->shaderfunc[SHADERSTAGE_SKY])
-                               t->shader->shaderfunc[SHADERSTAGE_SKY](ent, t);
-
-       if (normal)
-               for (i = 0, t = textures;i < numtextures;i++, t++)
-                       if (t->surfacechain && t->shader->shaderfunc[SHADERSTAGE_NORMAL])
-                               t->shader->shaderfunc[SHADERSTAGE_NORMAL](ent, t);
+void R_DrawSurfaces(entity_render_t *ent, int type)
+{
+       int i;
+       texture_t *t;
+       R_Mesh_Matrix(&ent->matrix);
+       for (i = 0, t = ent->model->textures;i < ent->model->numtextures;i++, t++)
+               if (t->shader->shaderfunc[type] && ent->model->texturesurfacechains[i])
+                       t->shader->shaderfunc[type](ent, t, ent->model->texturesurfacechains[i]);
 }
 
 static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
@@ -1519,7 +1541,7 @@ static void R_DrawPortals(entity_render_t *ent)
 
        for (portal = ent->model->portals, endportal = portal + ent->model->numportals;portal < endportal;portal++)
        {
-               if (portal->here->pvsframe == r_pvsframecount || portal->past->pvsframe == r_pvsframecount)
+               if (portal->here->pvsframe == ent->model->pvsframecount || portal->past->pvsframe == ent->model->pvsframecount)
                {
                        if (portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
                        {
@@ -1535,7 +1557,7 @@ static void R_DrawPortals(entity_render_t *ent)
        }
 }
 
-void R_DrawBrushModel(entity_render_t *ent, int sky, int normal)
+void R_PrepareBrushModel(entity_render_t *ent)
 {
        int i, numsurfaces, *surfacevisframes, *surfacepvsframes;
        msurface_t *surf;
@@ -1563,7 +1585,7 @@ void R_DrawBrushModel(entity_render_t *ent, int sky, int normal)
                        if ((surf->flags & SURF_PLANEBACK))
                        {
                                surfacevisframes[i] = r_framecount;
-                               surfacepvsframes[i] = r_pvsframecount;
+                               surfacepvsframes[i] = model->pvsframecount;
                        }
                }
                else
@@ -1571,16 +1593,16 @@ void R_DrawBrushModel(entity_render_t *ent, int sky, int normal)
                        if (!(surf->flags & SURF_PLANEBACK))
                        {
                                surfacevisframes[i] = r_framecount;
-                               surfacepvsframes[i] = r_pvsframecount;
+                               surfacepvsframes[i] = model->pvsframecount;
                        }
                }
 #else
                surfacevisframes[i] = r_framecount;
-               surfacepvsframes[i] = r_pvsframecount;
+               surfacepvsframes[i] = model->pvsframecount;
 #endif
                surf->dlightframe = -1;
        }
-       R_DrawSurfaces(ent, sky, normal);
+       R_PrepareSurfaces(ent);
 }
 
 void R_SurfaceWorldNode (entity_render_t *ent)
@@ -1599,7 +1621,7 @@ void R_SurfaceWorldNode (entity_render_t *ent)
 
        for (i = 0, surf = surfaces;i < numsurfaces;i++, surf++)
        {
-               if (surfacepvsframes[i] == r_pvsframecount)
+               if (surfacepvsframes[i] == model->pvsframecount)
                {
 #if WORLDNODECULLBACKFACES
                        if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
@@ -1666,7 +1688,7 @@ loc0:
                {
                        leaf->worldnodeframe = r_framecount;
                        // FIXME: R_NotCulledBox is absolute, should be done relative
-                       if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
+                       if (leaf->pvsframe == ent->model->pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
                        {
                                p->visframe = r_framecount;
                                pstack[portalstack++] = p;
@@ -1744,7 +1766,7 @@ static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
                                {
                                        leaf->worldnodeframe = r_framecount;
                                        // FIXME: R_NotCulledBox is absolute, should be done relative
-                                       if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
+                                       if (leaf->pvsframe == ent->model->pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
                                                leafstack[leafstackpos++] = leaf;
                                }
                        }
@@ -1754,40 +1776,41 @@ static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
                R_DrawPortals(ent);
 }
 
-void R_PVSUpdate (mleaf_t *viewleaf)
+void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf)
 {
        int i, j, l, c, bits, *surfacepvsframes, *mark;
        mleaf_t *leaf;
        qbyte *vis;
+       model_t *model;
 
-       if (r_pvsviewleaf == viewleaf && r_pvsviewleafnovis == r_novis.integer)
-               return;
-
-       r_pvsframecount++;
-       r_pvsviewleaf = viewleaf;
-       r_pvsviewleafnovis = r_novis.integer;
-
-       if (viewleaf)
+       model = ent->model;
+       if (model && (model->pvsviewleaf != viewleaf || model->pvsviewleafnovis != r_novis.integer))
        {
-               surfacepvsframes = cl.worldmodel->surfacepvsframes;
-               vis = Mod_LeafPVS (viewleaf, cl.worldmodel);
-               for (j = 0;j < cl.worldmodel->numleafs;j += 8)
+               model->pvsframecount++;
+               model->pvsviewleaf = viewleaf;
+               model->pvsviewleafnovis = r_novis.integer;
+               if (viewleaf)
                {
-                       bits = *vis++;
-                       if (bits)
+                       surfacepvsframes = model->surfacepvsframes;
+                       vis = Mod_LeafPVS (viewleaf, model);
+                       for (j = 0;j < model->numleafs;j += 8)
                        {
-                               l = cl.worldmodel->numleafs - j;
-                               if (l > 8)
-                                       l = 8;
-                               for (i = 0;i < l;i++)
+                               bits = *vis++;
+                               if (bits)
                                {
-                                       if (bits & (1 << i))
+                                       l = model->numleafs - j;
+                                       if (l > 8)
+                                               l = 8;
+                                       for (i = 0;i < l;i++)
                                        {
-                                               leaf = &cl.worldmodel->leafs[j + i + 1];
-                                               leaf->pvsframe = r_pvsframecount;
-                                               // mark surfaces bounding this leaf as visible
-                                               for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
-                                                       surfacepvsframes[*mark++] = r_pvsframecount;
+                                               if (bits & (1 << i))
+                                               {
+                                                       leaf = &model->leafs[j + i + 1];
+                                                       leaf->pvsframe = model->pvsframecount;
+                                                       // mark surfaces bounding this leaf as visible
+                                                       for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
+                                                               surfacepvsframes[*mark++] = model->pvsframecount;
+                                               }
                                        }
                                }
                        }
@@ -1800,33 +1823,52 @@ void R_PVSUpdate (mleaf_t *viewleaf)
 R_DrawWorld
 =============
 */
-void R_DrawWorld (entity_render_t *ent)
+void R_DrawWorld (entity_render_t *ent, int baselighting)
 {
+       vec3_t modelorg;
        mleaf_t *viewleaf;
-       viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
-       R_PVSUpdate(viewleaf);
+
+       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       viewleaf = Mod_PointInLeaf (modelorg, ent->model);
+       R_PVSUpdate(ent, viewleaf);
+
        if (!viewleaf)
                return;
+
        if (r_surfaceworldnode.integer || viewleaf->contents == CONTENTS_SOLID)
                R_SurfaceWorldNode (ent);
        else
                R_PortalWorldNode (ent, viewleaf);
-       R_DrawSurfaces(ent, true, true);
+       R_PrepareSurfaces(ent);
+       R_DrawSurfaces(ent, SHADERSTAGE_SKY);
+       if (baselighting)
+               R_DrawSurfaces(ent, SHADERSTAGE_BASELIGHTING);
+       else
+               R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
 }
 
 void R_Model_Brush_DrawSky (entity_render_t *ent)
 {
-       R_DrawBrushModel(ent, true, false);
+       if (ent != &cl_entities[0].render)
+               R_PrepareBrushModel(ent);
+       R_DrawSurfaces(ent, SHADERSTAGE_SKY);
 }
 
 void R_Model_Brush_Draw (entity_render_t *ent)
 {
        c_bmodels++;
-       R_DrawBrushModel(ent, false, true);
+       if (ent != &cl_entities[0].render)
+               R_PrepareBrushModel(ent);
+       R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
 }
 
-void R_Model_Brush_DrawDepth (entity_render_t *ent)
+void R_Model_Brush_DrawBaseLighting (entity_render_t *ent)
 {
+       c_bmodels++;
+       if (ent != &cl_entities[0].render)
+               R_PrepareBrushModel(ent);
+       R_DrawSurfaces(ent, SHADERSTAGE_BASELIGHTING);
+       /*
        shadowmesh_t *mesh;
        if (!cl.worldmodel->numlights)
                GL_Color(0.3, 0.3, 0.3, 1);
@@ -1838,17 +1880,19 @@ void R_Model_Brush_DrawDepth (entity_render_t *ent)
        }
        if (!cl.worldmodel->numlights)
                GL_Color(0, 0, 0, 1);
+       */
 }
 
 void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
 {
-#if 0
+#if 1
        float projectdistance, temp[3];
        shadowmesh_t *mesh;
        VectorSubtract(relativelightorigin, ent->model->shadowmesh_center, temp);
        projectdistance = lightradius + ent->model->shadowmesh_radius - sqrt(DotProduct(temp, temp));
        if (projectdistance >= 0.1)
        {
+               R_Mesh_Matrix(&ent->matrix);
                for (mesh = ent->model->shadowmesh;mesh;mesh = mesh->next)
                {
                        R_Mesh_ResizeCheck(mesh->numverts * 2);
@@ -1861,10 +1905,11 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto
        msurface_t *surf;
        float projectdistance, f, temp[3], lightradius2;
        surfmesh_t *mesh;
+       R_Mesh_Matrix(&ent->matrix);
        lightradius2 = lightradius * lightradius;
        for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
        {
-               if (surf->flags & SURF_SHADOWCAST)
+               if (surf->rendertype == SURFRENDER_OPAQUE && surf->flags & SURF_SHADOWCAST)
                {
                        f = PlaneDiff(relativelightorigin, surf->plane);
                        if (surf->flags & SURF_PLANEBACK)
@@ -1889,36 +1934,38 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto
 #endif
 }
 
-void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
 {
-       int i;
+       int tnum;
        msurface_t *surf;
+       texture_t *t;
        float f, lightradius2;
        surfmesh_t *mesh;
-       vec3_t modelorg;
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       R_Mesh_Matrix(&ent->matrix);
+       if (ent != &cl_entities[0].render)
+               R_PrepareBrushModel(ent);
        lightradius2 = lightradius * lightradius;
-       GL_UseColorArray();
-       for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
+       for (tnum = 0;tnum < ent->model->numtextures;tnum++)
        {
-               if (surf->flags & SURF_SHADOWLIGHT)
+               t = ent->model->textures + tnum;
+               if (ent->model->texturesurfacechains[tnum] && t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
                {
-                       f = PlaneDiff(relativelightorigin, surf->plane);
-                       if (surf->flags & SURF_PLANEBACK)
-                               f = -f;
-                       if (f >= -0.1 && f < lightradius)
+                       t = t->currentframe[ent->frame != 0];
+                       for (surf = ent->model->texturesurfacechains[tnum];surf;surf = surf->texturechain)
                        {
-                               f = PlaneDiff(modelorg, surf->plane);
-                               if (surf->flags & SURF_PLANEBACK)
-                                       f = -f;
-                               if (f > 0)
+                               if (surf->visframe == r_framecount)
                                {
-                                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                                       f = PlaneDiff(relativelightorigin, surf->plane);
+                                       if (surf->flags & SURF_PLANEBACK)
+                                               f = -f;
+                                       if (f >= -0.1 && f < lightradius)
                                        {
-                                               R_Mesh_ResizeCheck(mesh->numverts);
-                                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                               R_Shadow_Light(mesh->numverts, mesh->normals, relativelightorigin, lightradius, lightdistbias, lightsubtract, lightcolor);
-                                               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                                               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                                               {
+                                                       R_Mesh_ResizeCheck(mesh->numverts);
+                                                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                                                       R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->texture, r_notexture, NULL, NULL);
+                                               }
                                        }
                                }
                        }
@@ -1926,12 +1973,6 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, f
        }
 }
 
-void R_Model_Brush_DrawOntoLight(entity_render_t *ent)
-{
-       // FIXME
-       c_bmodels++;
-}
-
 /*
 extern cvar_t r_shadows;
 void R_DrawBrushModelFakeShadow (entity_render_t *ent)
@@ -2009,10 +2050,6 @@ static void gl_surf_shutdown(void)
 
 static void gl_surf_newmap(void)
 {
-       // reset pvs visibility variables so it will update on first frame
-       r_pvsframecount = 1;
-       r_pvsviewleaf = NULL;
-       r_pvsviewleafnovis = false;
 }
 
 void GL_Surf_Init(void)
index b2629ba..aa421f9 100644 (file)
@@ -52,6 +52,8 @@ static textypeinfo_t textype_rgba_alpha     = {TEXTYPE_RGBA    , 4, 4, GL_RGBA,
 #define GLTEXTURETYPE_3D 2
 #define GLTEXTURETYPE_CUBEMAP 3
 
+static int gltexturetypeenums[4] = {GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB};
+static int gltexturetypedimensions[4] = {1, 2, 3, 2};
 static int cubemapside[6] =
 {
        GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
@@ -541,32 +543,39 @@ void R_MakeResizeBufferBigger(int size)
        }
 }
 
+static void GL_SetupTextureParameters(int flags, int texturetype)
+{
+       int textureenum = gltexturetypeenums[texturetype];
+       int wrapmode = (flags & TEXF_CLAMP) ? GL_CLAMP : GL_REPEAT;
+
+       CHECKGLERROR
+
+       qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);
+       if (gltexturetypedimensions[texturetype] >= 2)
+               qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);
+       if (gltexturetypedimensions[texturetype] >= 3)
+               qglTexParameteri(textureenum, GL_TEXTURE_WRAP_R, wrapmode);
+
+       if (flags & TEXF_MIPMAP)
+               qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+       else
+               qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
+       qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
+
+       CHECKGLERROR
+}
+
 static void R_Upload(gltexture_t *glt, qbyte *data)
 {
        int i, mip, width, height, depth, internalformat;
        qbyte *prevbuffer;
        prevbuffer = data;
 
+       CHECKGLERROR
+
        glt->texnum = glt->image->texnum;
-       switch(glt->image->texturetype)
-       {
-       case GLTEXTURETYPE_1D:
-               qglBindTexture(GL_TEXTURE_1D, glt->image->texnum);
-               CHECKGLERROR
-               break;
-       case GLTEXTURETYPE_2D:
-               qglBindTexture(GL_TEXTURE_2D, glt->image->texnum);
-               CHECKGLERROR
-               break;
-       case GLTEXTURETYPE_3D:
-               qglBindTexture(GL_TEXTURE_3D, glt->image->texnum);
-               CHECKGLERROR
-               break;
-       case GLTEXTURETYPE_CUBEMAP:
-               qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, glt->image->texnum);
-               CHECKGLERROR
-               break;
-       }
+       qglBindTexture(gltexturetypeenums[glt->image->texturetype], glt->image->texnum);
+       CHECKGLERROR
        glt->flags &= ~GLTEXF_UPLOAD;
        gl_backend_rebindtextures = true;
 
@@ -583,31 +592,20 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                        case GLTEXTURETYPE_1D:
                                qglTexImage1D(GL_TEXTURE_1D, 0, glt->image->glinternalformat, glt->image->width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, resizebuffer);
                                CHECKGLERROR
-                               qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
-                               CHECKGLERROR
-                               qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                               CHECKGLERROR
                                break;
                        case GLTEXTURETYPE_2D:
                                qglTexImage2D(GL_TEXTURE_2D, 0, glt->image->glinternalformat, glt->image->width, glt->image->height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, resizebuffer);
                                CHECKGLERROR
-                               qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
-                               CHECKGLERROR
-                               qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                               CHECKGLERROR
                                break;
                        case GLTEXTURETYPE_3D:
                                qglTexImage3D(GL_TEXTURE_3D, 0, glt->image->glinternalformat, glt->image->width, glt->image->height, glt->image->depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, resizebuffer);
                                CHECKGLERROR
-                               qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
-                               CHECKGLERROR
-                               qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                               CHECKGLERROR
                                break;
                        default:
                                Host_Error("R_Upload: fragment texture of type other than 1D, 2D, or 3D\n");
                                break;
                        }
+                       GL_SetupTextureParameters(glt->image->flags, glt->image->texturetype);
                }
 
                if (prevbuffer == NULL)
@@ -708,17 +706,6 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                                qglTexImage1D(GL_TEXTURE_1D, mip++, internalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                                CHECKGLERROR
                        }
-                       qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
-                       CHECKGLERROR
-                       qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                       CHECKGLERROR
-               }
-               else
-               {
-                       qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
-                       CHECKGLERROR
-                       qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                       CHECKGLERROR
                }
                break;
        case GLTEXTURETYPE_2D:
@@ -733,17 +720,6 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                                qglTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                                CHECKGLERROR
                        }
-                       qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
-                       CHECKGLERROR
-                       qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                       CHECKGLERROR
-               }
-               else
-               {
-                       qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
-                       CHECKGLERROR
-                       qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                       CHECKGLERROR
                }
                break;
        case GLTEXTURETYPE_3D:
@@ -758,17 +734,6 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                                qglTexImage3D(GL_TEXTURE_3D, mip++, internalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                                CHECKGLERROR
                        }
-                       qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
-                       CHECKGLERROR
-                       qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                       CHECKGLERROR
-               }
-               else
-               {
-                       qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
-                       CHECKGLERROR
-                       qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                       CHECKGLERROR
                }
                break;
        case GLTEXTURETYPE_CUBEMAP:
@@ -790,21 +755,11 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                                        qglTexImage2D(cubemapside[i], mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                                        CHECKGLERROR
                                }
-                               qglTexParameteri(cubemapside[i], GL_TEXTURE_MIN_FILTER, gl_filter_min);
-                               CHECKGLERROR
-                               qglTexParameteri(cubemapside[i], GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                               CHECKGLERROR
-                       }
-                       else
-                       {
-                               qglTexParameteri(cubemapside[i], GL_TEXTURE_MIN_FILTER, gl_filter_mag);
-                               CHECKGLERROR
-                               qglTexParameteri(cubemapside[i], GL_TEXTURE_MAG_FILTER, gl_filter_mag);
-                               CHECKGLERROR
                        }
                }
                break;
        }
+       GL_SetupTextureParameters(glt->image->flags, glt->image->texturetype);
 }
 
 static void R_FindImageForTexture(gltexture_t *glt)
@@ -834,9 +789,11 @@ static void R_FindImageForTexture(gltexture_t *glt)
                                continue;
                        if (image->texturetype != glt->texturetype)
                                continue;
+                       if ((image->flags ^ glt->flags) & (TEXF_MIPMAP | TEXF_ALPHA | TEXF_CLAMP))
+                               continue;
                        if (image->glformat != texinfo->glformat || image->glinternalformat != texinfo->glinternalformat)
                                continue;
-                       if (glt->width > image->width || glt->height > image->height)
+                       if (glt->width > image->width || glt->height > image->height || glt->depth > image->depth)
                                continue;
 
                        // got a fragments texture, find a place in it if we can
@@ -878,10 +835,10 @@ static void R_FindImageForTexture(gltexture_t *glt)
                // make sure the created image is big enough for the fragment
                for (image->width = block_size;image->width < glt->width;image->width <<= 1);
                image->height = 1;
-               if (glt->texturetype != GLTEXTURETYPE_1D)
+               if (gltexturetypedimensions[glt->texturetype] >= 2)
                        for (image->height = block_size;image->height < glt->height;image->height <<= 1);
                image->depth = 1;
-               if (glt->texturetype == GLTEXTURETYPE_3D)
+               if (gltexturetypedimensions[glt->texturetype] >= 3)
                        for (image->depth = block_size;image->depth < glt->depth;image->depth <<= 1);
                image->blockallocation = Mem_Alloc(texturemempool, image->width * sizeof(short));
                memset(image->blockallocation, 0, image->width * sizeof(short));
@@ -918,7 +875,7 @@ static void R_FindImageForTexture(gltexture_t *glt)
        image->texturetype = glt->texturetype;
        image->glinternalformat = texinfo->glinternalformat;
        image->glformat = texinfo->glformat;
-       image->flags = (glt->flags & (TEXF_MIPMAP | TEXF_ALPHA)) | GLTEXF_UPLOAD;
+       image->flags = (glt->flags & (TEXF_MIPMAP | TEXF_ALPHA | TEXF_CLAMP)) | GLTEXF_UPLOAD;
        image->bytesperpixel = texinfo->internalbytesperpixel;
        image->sides = image->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
        // get a texture number to use
index 48c1e60..182e43e 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -323,8 +323,8 @@ extern int gl_texturecubemap;
 
 extern int gl_dot3arb;
 #ifndef GL_DOT3_RGB_ARB
-#define DOT3_RGB_ARB                           0x86AE
-#define DOT3_RGBA_ARB                          0x86AF
+#define GL_DOT3_RGB_ARB                                0x86AE
+#define GL_DOT3_RGBA_ARB                               0x86AF
 #endif
 
 /*
index cffbbbc..8cb2e75 100644 (file)
--- a/mathlib.h
+++ b/mathlib.h
@@ -63,9 +63,9 @@ extern vec3_t vec3_origin;
 #define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
 #define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
 #define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
-#define VectorNormalize(v) {float ilength = 1.0f / (float) sqrt(DotProduct(v,v));v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
-#define VectorNormalize2(v,dest) {float ilength = 1.0f / (float) sqrt(DotProduct(v,v));dest[0] = v[0] * ilength;dest[1] = v[1] * ilength;dest[2] = v[2] * ilength;}
-#define VectorNormalizeDouble(v) {double ilength = 1.0 / (float) sqrt(DotProduct(v,v));v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
+#define VectorNormalize(v) {float ilength = (float) sqrt(DotProduct(v,v));if (ilength) ilength = 1.0f / ilength;v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
+#define VectorNormalize2(v,dest) {float ilength = (float) sqrt(DotProduct(v,v));if (ilength) ilength = 1.0f / ilength;dest[0] = v[0] * ilength;dest[1] = v[1] * ilength;dest[2] = v[2] * ilength;}
+#define VectorNormalizeDouble(v) {double ilength = sqrt(DotProduct(v,v));if (ilength) ilength = 1.0 / ilength;v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
 #define VectorDistance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))
 #define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
 #define VectorLength(a) sqrt(DotProduct(a, a))
index d25a153..9b62402 100644 (file)
@@ -250,10 +250,9 @@ static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, qbyte *skintem
 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", loadmodel->name, VALUE, MIN, MAX);
 extern void R_Model_Alias_Draw(entity_render_t *ent);
 extern void R_Model_Alias_DrawFakeShadow(entity_render_t *ent);
-extern void R_Model_Alias_DrawDepth(entity_render_t *ent);
+extern void R_Model_Alias_DrawBaseLighting(entity_render_t *ent);
 extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
-extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
-extern void R_Model_Alias_DrawOntoLight(entity_render_t *ent);
+extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
 void Mod_LoadAliasModel (model_t *mod, void *buffer)
 {
        int                                             i, j, version, numverts, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins;
@@ -289,10 +288,9 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        loadmodel->DrawSky = NULL;
        loadmodel->Draw = R_Model_Alias_Draw;
        loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
-       loadmodel->DrawDepth = R_Model_Alias_DrawDepth;
+       loadmodel->DrawBaseLighting = R_Model_Alias_DrawBaseLighting;
        loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
        loadmodel->DrawLight = R_Model_Alias_DrawLight;
-       loadmodel->DrawOntoLight = R_Model_Alias_DrawOntoLight;
 
        loadmodel->numskins = LittleLong(pinmodel->numskins);
        BOUNDI(loadmodel->numskins,0,256);
@@ -616,10 +614,9 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        loadmodel->DrawSky = NULL;
        loadmodel->Draw = R_Model_Alias_Draw;
        loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
-       loadmodel->DrawDepth = R_Model_Alias_DrawDepth;
+       loadmodel->DrawBaseLighting = R_Model_Alias_DrawBaseLighting;
        loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
        loadmodel->DrawLight = R_Model_Alias_DrawLight;
-       loadmodel->DrawOntoLight = R_Model_Alias_DrawOntoLight;
 
        if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > MD2MAX_TRIANGLES)
                Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
@@ -806,23 +803,12 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris);
 }
 
-static void zymswapintblock(int *m, int size)
-{
-       size /= 4;
-       while(size--)
-       {
-               *m = BigLong(*m);
-               m++;
-       }
-}
-
 extern void R_Model_Zymotic_DrawSky(entity_render_t *ent);
 extern void R_Model_Zymotic_Draw(entity_render_t *ent);
 extern void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent);
-extern void R_Model_Zymotic_DrawDepth(entity_render_t *ent);
+extern void R_Model_Zymotic_DrawBaseLighting(entity_render_t *ent);
 extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
-extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
-extern void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent);
+extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
 void Mod_LoadZymoticModel(model_t *mod, void *buffer)
 {
        zymtype1header_t *pinmodel, *pheader;
@@ -840,10 +826,9 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer)
        loadmodel->DrawSky = NULL;
        loadmodel->Draw = R_Model_Zymotic_Draw;
        loadmodel->DrawFakeShadow = NULL;//R_Model_Zymotic_DrawFakeShadow;
-       loadmodel->DrawDepth = NULL;//R_Model_Zymotic_DrawDepth;
+       loadmodel->DrawBaseLighting = NULL;//R_Model_Zymotic_DrawBaseLighting;
        loadmodel->DrawShadowVolume = NULL;//R_Model_Zymotic_DrawShadowVolume;
        loadmodel->DrawLight = NULL;//R_Model_Zymotic_DrawLight;
-       loadmodel->DrawOntoLight = NULL;//R_Model_Zymotic_DrawOntoLight;
 
        // byteswap header
        pheader = pinmodel;
index a499fd4..d5fe31f 100644 (file)
@@ -416,6 +416,8 @@ static void Mod_LoadTextures (lump_t *l)
                         || !strncmp(tx->name,"*teleport",9)
                         || !strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture
                                tx->flags |= SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA;
+                       else
+                               tx->flags |= SURF_WATERALPHA;
                        tx->shader = &Cshader_water;
                }
                else if (tx->name[0] == 's' && tx->name[1] == 'k' && tx->name[2] == 'y')
@@ -432,6 +434,9 @@ static void Mod_LoadTextures (lump_t *l)
                }
 
                tx->detailtexture = detailtextures[i % NUM_DETAILTEXTURES];
+               // start out with no animation
+               tx->currentframe[0] = tx;
+               tx->currentframe[1] = tx;
        }
 
        // sequence the animations
@@ -1115,6 +1120,37 @@ void Mod_ShadowBrush_AddPolygon(mempool_t *mempool, svbrush_t *brush, int numver
        memcpy(poly->verts, verts, numverts * sizeof(float[3]));
 }
 
+void Mod_ShadowBrush_AddPolygonI(mempool_t *mempool, svbrush_t *brush, int numverts, float *verts)
+{
+       int i;
+       float normal[3], dist, dir0[3], dir1[3], *v0, *v1, *v2;
+       svpolygon_t *poly;
+       for (i = 0, v0 = verts + (numverts - 2) * 3, v1 = verts + (numverts - 1) * 3, v2 = verts;i < numverts;i++, v0 = v1, v1 = v2, v2 += 3)
+       {
+               VectorSubtract(v0, v1, dir0);
+               VectorSubtract(v2, v1, dir1);
+               CrossProduct(dir0, dir1, normal);
+               if (DotProduct(normal, normal) >= 0.1)
+                       break;
+       }
+       if (i == numverts)
+               return;
+       VectorNormalize(normal);
+       dist = DotProduct(verts, normal);
+       VectorNegate(normal, normal);
+       dist = -dist;
+
+       poly = Mem_Alloc(mempool, sizeof(svpolygon_t) + numverts * sizeof(float[3]));
+       poly->numverts = numverts;
+       poly->verts = (float *)(poly + 1);
+       VectorCopy(normal, poly->normal);
+       poly->dist = dist;
+       poly->next = brush->polygons;
+       brush->polygons = poly;
+       for (i = 0, v0 = verts + (numverts - 1) * 3, v1 = poly->verts;i < numverts;i++, v0 -= 3, v1 += 3)
+               VectorCopy(v0, v1);
+}
+
 void Mod_ShadowBrush_EndBrush(svworld_t *world, svbrush_t *brush)
 {
        int i;
@@ -1190,7 +1226,7 @@ void Mod_ProcessLightList(void)
                e->cullradius2 = DotProduct(e->light, e->light) / (e->falloff * e->falloff * 8192.0f * 8192.0f);// + 4096.0f;
                if (e->cullradius2 > 4096.0f * 4096.0f)
                        e->cullradius2 = 4096.0f * 4096.0f;
-               e->cullradius = sqrt(e->cullradius2);
+               e->cullradius = e->lightradius = sqrt(e->cullradius2);
                leaf = Mod_PointInLeaf(e->origin, loadmodel);
                if (leaf->compressed_vis)
                        pvs = Mod_DecompressVis (leaf->compressed_vis, loadmodel);
@@ -1229,6 +1265,7 @@ void Mod_ProcessLightList(void)
                                if (loadmodel->surfacevisframes[j] == -2)
                                        e->surfaces[e->numsurfaces++] = loadmodel->surfaces + j;
                }
+#if 1
                {
                // find bounding box and sphere of lit surfaces
                // (these will be used for creating a shape to clip the light)
@@ -1253,25 +1290,37 @@ void Mod_ProcessLightList(void)
                                        radius2 = dist;
                        }
                }
-               /*
                if (e->cullradius2 > radius2)
                {
                        e->cullradius2 = radius2;
                        e->cullradius = sqrt(e->cullradius2);
                }
-               */
                }
+#endif
+#if 1
+               e->mins[0] = e->origin[0] - e->cullradius;
+               e->maxs[0] = e->origin[0] + e->cullradius;
+               e->mins[1] = e->origin[1] - e->cullradius;
+               e->maxs[1] = e->origin[1] + e->cullradius;
+               e->mins[2] = e->origin[2] - e->cullradius;
+               e->maxs[2] = e->origin[2] + e->cullradius;
+#endif
 #if 1
                // clip shadow volumes against eachother to remove unnecessary
                // polygons (and sections of polygons)
                {
-                       vec3_t temp, outermins, outermaxs, innermins, innermaxs;
+                       vec3_t temp;
+                       //vec3_t polymins, polymaxs;
                        int maxverts = 4;
                        float *verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
                        float f, *v0, *v1, projectdistance;
                        svworld_t *svworld;
                        svbrush_t *svbrush;
 
+                       svworld = Mod_ShadowBrush_NewWorld(loadmodel->mempool);
+#if 0
+                       {
+                       vec3_t outermins, outermaxs, innermins, innermaxs;
                        innermins[0] = e->mins[0] - 1;
                        innermins[1] = e->mins[1] - 1;
                        innermins[2] = e->mins[2] - 1;
@@ -1284,57 +1333,6 @@ void Mod_ProcessLightList(void)
                        outermaxs[0] = loadmodel->normalmaxs[0] + 1;
                        outermaxs[1] = loadmodel->normalmaxs[1] + 1;
                        outermaxs[2] = loadmodel->normalmaxs[2] + 1;
-                       svworld = Mod_ShadowBrush_NewWorld(loadmodel->mempool);
-                       for (j = 0, surf = loadmodel->surfaces + loadmodel->firstmodelsurface;j < loadmodel->nummodelsurfaces;j++, surf++)
-                       {
-                               if (!(surf->flags & SURF_SHADOWCAST))
-                                       continue;
-                               f = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
-                               if (surf->flags & SURF_PLANEBACK)
-                                       f = -f;
-                               projectdistance = e->cullradius + f;
-                               if (projectdistance < 0.1 || projectdistance > e->cullradius)
-                                       continue;
-                               VectorSubtract(e->origin, surf->poly_center, temp);
-                               if (DotProduct(temp, temp) > (surf->poly_radius2 + e->cullradius2))
-                                       continue;
-                               if (maxverts < surf->poly_numverts)
-                               {
-                                       maxverts = surf->poly_numverts;
-                                       if (verts)
-                                               Mem_Free(verts);
-                                       verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
-                               }
-                               svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
-                               // copy the original polygon, reversed, for the front cap of the volume
-                               for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
-                                       VectorCopy(v0, v1);
-                               Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
-                               // project the original polygon, for the back cap of the volume
-                               for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
-                               {
-                                       VectorSubtract(v0, e->origin, temp);
-                                       VectorNormalize(temp);
-                                       VectorMA(v0, projectdistance, temp, v1);
-                               }
-                               Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
-                               // project the shadow volume sides
-                               for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;k++, v0 = v1, v1 += 3)
-                               {
-                                       VectorCopy(v0, &verts[0]);
-                                       VectorCopy(v1, &verts[3]);
-                                       VectorCopy(v1, &verts[6]);
-                                       VectorCopy(v0, &verts[9]);
-                                       VectorSubtract(&verts[6], e->origin, temp);
-                                       VectorNormalize(temp);
-                                       VectorMA(&verts[6], projectdistance, temp, &verts[6]);
-                                       VectorSubtract(&verts[9], e->origin, temp);
-                                       VectorNormalize(temp);
-                                       VectorMA(&verts[9], projectdistance, temp, &verts[9]);
-                                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
-                               }
-                               Mod_ShadowBrush_EndBrush(svworld, svbrush);
-                       }
                        // add bounding box around the whole shadow volume set,
                        // facing inward to limit light area, with an outer bounding box
                        // facing outward (this is needed by the shadow rendering method)
@@ -1416,6 +1414,113 @@ void Mod_ProcessLightList(void)
                        verts[ 9] = outermins[0];verts[10] = outermins[1];verts[11] = outermins[2];
                        Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
                        Mod_ShadowBrush_EndBrush(svworld, svbrush);
+                       }
+#endif
+#define SHADOWCASTFRONT 1
+#if SHADOWCASTFRONT
+                       for (j = 0;j < e->numsurfaces;j++)
+                       {
+                               surf = e->surfaces[j];
+#else
+                       for (j = 0, surf = loadmodel->surfaces + loadmodel->firstmodelsurface;j < loadmodel->nummodelsurfaces;j++, surf++)
+                       {
+#endif
+                               if (!(surf->flags & SURF_CLIPSOLID))
+                                       continue;
+                               f = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
+                               if (surf->flags & SURF_PLANEBACK)
+                                       f = -f;
+#if SHADOWCASTFRONT
+                               projectdistance = e->cullradius - f;
+#else
+                               projectdistance = e->cullradius + f;
+#endif
+                               if (projectdistance < 0.1 || projectdistance > e->cullradius)
+                                       continue;
+                               VectorSubtract(e->origin, surf->poly_center, temp);
+                               if (DotProduct(temp, temp) > (surf->poly_radius2 + e->cullradius2))
+                                       continue;
+                               /*
+                               VectorCopy(surf->poly_verts, polymins);
+                               VectorCopy(surf->poly_verts, polymaxs);
+                               for (k = 0, v0 = surf->poly_verts;k < surf->poly_numverts;k++, v0 += 3)
+                               {
+                                       if (polymins[0] > v0[0]) polymins[0] = v0[0];if (polymaxs[0] < v0[0]) polymaxs[0] = v0[0];
+                                       if (polymins[1] > v0[1]) polymins[1] = v0[1];if (polymaxs[1] < v0[1]) polymaxs[1] = v0[1];
+                                       if (polymins[2] > v0[2]) polymins[2] = v0[2];if (polymaxs[2] < v0[2]) polymaxs[2] = v0[2];
+                               }
+                               if (polymins[0] > e->maxs[0] || polymaxs[0] < e->mins[0]
+                                || polymins[1] > e->maxs[1] || polymaxs[1] < e->mins[1]
+                                || polymins[2] > e->maxs[2] || polymaxs[2] < e->mins[2])
+                                       continue;
+                               */
+                               if (maxverts < surf->poly_numverts)
+                               {
+                                       maxverts = surf->poly_numverts;
+                                       if (verts)
+                                               Mem_Free(verts);
+                                       verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
+                               }
+                               svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
+#if SHADOWCASTFRONT
+                               // copy the original polygon, for the front cap of the volume
+                               for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
+                                       VectorCopy(v0, v1);
+                               Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
+                               // project the original polygon, reversed, for the back cap of the volume
+                               for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
+                               {
+                                       VectorSubtract(v0, e->origin, temp);
+                                       VectorNormalize(temp);
+                                       VectorMA(v0, projectdistance, temp, v1);
+                               }
+                               Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
+                               // project the shadow volume sides
+                               for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;k++, v0 = v1, v1 += 3)
+                               {
+                                       VectorCopy(v1, &verts[0]);
+                                       VectorCopy(v0, &verts[3]);
+                                       VectorCopy(v0, &verts[6]);
+                                       VectorCopy(v1, &verts[9]);
+                                       VectorSubtract(&verts[6], e->origin, temp);
+                                       VectorNormalize(temp);
+                                       VectorMA(&verts[6], projectdistance, temp, &verts[6]);
+                                       VectorSubtract(&verts[9], e->origin, temp);
+                                       VectorNormalize(temp);
+                                       VectorMA(&verts[9], projectdistance, temp, &verts[9]);
+                                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                               }
+#else
+                               // copy the original polygon, reversed, for the front cap of the volume
+                               for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
+                                       VectorCopy(v0, v1);
+                               Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
+                               // project the original polygon, for the back cap of the volume
+                               for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
+                               {
+                                       VectorSubtract(v0, e->origin, temp);
+                                       VectorNormalize(temp);
+                                       VectorMA(v0, projectdistance, temp, v1);
+                               }
+                               Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
+                               // project the shadow volume sides
+                               for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;k++, v0 = v1, v1 += 3)
+                               {
+                                       VectorCopy(v0, &verts[0]);
+                                       VectorCopy(v1, &verts[3]);
+                                       VectorCopy(v1, &verts[6]);
+                                       VectorCopy(v0, &verts[9]);
+                                       VectorSubtract(&verts[6], e->origin, temp);
+                                       VectorNormalize(temp);
+                                       VectorMA(&verts[6], projectdistance, temp, &verts[6]);
+                                       VectorSubtract(&verts[9], e->origin, temp);
+                                       VectorNormalize(temp);
+                                       VectorMA(&verts[9], projectdistance, temp, &verts[9]);
+                                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                               }
+#endif
+                               Mod_ShadowBrush_EndBrush(svworld, svbrush);
+                       }
                        // clip away hidden polygons
                        Mod_ShadowBrush_ProcessWorld(loadmodel->mempool, svworld);
                        // build the triangle mesh
@@ -2055,6 +2160,25 @@ void Mod_GenerateWarpMesh (msurface_t *surf)
 }
 #endif
 
+surfmesh_t *Mod_AllocSurfMesh(int numverts, int numtriangles)
+{
+       surfmesh_t *mesh;
+       mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + numtriangles * sizeof(int[6]) + numverts * (4 + 4 + 4 + 4 + 4 + 4 + 4 + 1) * sizeof(float));
+       mesh->numverts = numverts;
+       mesh->numtriangles = numtriangles;
+       mesh->verts = (float *)(mesh + 1);
+       mesh->str = mesh->verts + mesh->numverts * 4;
+       mesh->uvw = mesh->str + mesh->numverts * 4;
+       mesh->abc = mesh->uvw + mesh->numverts * 4;
+       mesh->svectors = (float *)(mesh->abc + mesh->numverts * 4);
+       mesh->tvectors = mesh->svectors + mesh->numverts * 4;
+       mesh->normals = mesh->tvectors + mesh->numverts * 4;
+       mesh->lightmapoffsets = (int *)(mesh->normals + mesh->numverts * 4);
+       mesh->index = mesh->lightmapoffsets + mesh->numverts;
+       mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
+       return mesh;
+}
+
 void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
 {
        int i, iu, iv, *index, smax, tmax;
@@ -2091,17 +2215,7 @@ void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
                vscale = (vscale - vbase) * 16.0 / ((surf->extents[1] & ~15) + 16);
        }
 
-       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[6]) + surf->poly_numverts * (4 + 4 + 4 + 4 + 1 + 3) * sizeof(float));
-       mesh->numverts = surf->poly_numverts;
-       mesh->numtriangles = surf->poly_numverts - 2;
-       mesh->verts = (float *)(mesh + 1);
-       mesh->str = mesh->verts + mesh->numverts * 4;
-       mesh->uvw = mesh->str + mesh->numverts * 4;
-       mesh->abc = mesh->uvw + mesh->numverts * 4;
-       mesh->lightmapoffsets = (int *)(mesh->abc + mesh->numverts * 4);
-       mesh->index = mesh->lightmapoffsets + mesh->numverts;
-       mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
-       mesh->normals = (float *)(mesh->triangleneighbors + mesh->numtriangles * 3);
+       surf->mesh = mesh = Mod_AllocSurfMesh(surf->poly_numverts, surf->poly_numverts - 2);
 
        index = mesh->index;
        for (i = 0;i < mesh->numtriangles;i++)
@@ -2139,10 +2253,8 @@ void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
                mesh->abc[i * 4 + 0] = s * (1.0f / 16.0f);
                mesh->abc[i * 4 + 1] = t * (1.0f / 16.0f);
                mesh->lightmapoffsets[i] = ((iv * (smax+1) + iu) * 3);
-               mesh->normals[i * 3 + 0] = normal[0];
-               mesh->normals[i * 3 + 1] = normal[1];
-               mesh->normals[i * 3 + 2] = normal[2];
        }
+       Mod_BuildTextureVectorsAndNormals(mesh->numverts, mesh->numtriangles, mesh->verts, mesh->str, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals);
 }
 
 void Mod_GenerateVertexMesh (msurface_t *surf)
@@ -2154,15 +2266,7 @@ void Mod_GenerateVertexMesh (msurface_t *surf)
        surf->lightmaptexturestride = 0;
        surf->lightmaptexture = NULL;
 
-       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[6]) + surf->poly_numverts * (4 + 4 + 4 + 3) * sizeof(float));
-       mesh->numverts = surf->poly_numverts;
-       mesh->numtriangles = surf->poly_numverts - 2;
-       mesh->verts = (float *)(mesh + 1);
-       mesh->str = mesh->verts + mesh->numverts * 4;
-       mesh->abc = mesh->str + mesh->numverts * 4;
-       mesh->index = (int *)(mesh->abc + mesh->numverts * 4);
-       mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
-       mesh->normals = (float *)(mesh->triangleneighbors + mesh->numtriangles * 3);
+       surf->mesh = mesh = Mod_AllocSurfMesh(surf->poly_numverts, surf->poly_numverts - 2);
 
        index = mesh->index;
        for (i = 0;i < mesh->numtriangles;i++)
@@ -2185,12 +2289,12 @@ void Mod_GenerateVertexMesh (msurface_t *surf)
                mesh->verts[i * 4 + 2] = in[2];
                mesh->str[i * 4 + 0] = s / surf->texinfo->texture->width;
                mesh->str[i * 4 + 1] = t / surf->texinfo->texture->height;
+               mesh->uvw[i * 4 + 0] = 0;
+               mesh->uvw[i * 4 + 1] = 0;
                mesh->abc[i * 4 + 0] = s * (1.0f / 16.0f);
                mesh->abc[i * 4 + 1] = t * (1.0f / 16.0f);
-               mesh->normals[i * 3 + 0] = normal[0];
-               mesh->normals[i * 3 + 1] = normal[1];
-               mesh->normals[i * 3 + 2] = normal[2];
        }
+       Mod_BuildTextureVectorsAndNormals(mesh->numverts, mesh->numtriangles, mesh->verts, mesh->str, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals);
 }
 
 void Mod_GenerateSurfacePolygon (msurface_t *surf)
@@ -3309,6 +3413,40 @@ static void Mod_MakePortals(void)
        Mod_FinalizePortals();
 }
 
+static void Mod_BuildSurfaceNeighbors (msurface_t *surfaces, int numsurfaces, mempool_t *mempool)
+{
+       #if 0
+       int surfnum, vertnum, snum, vnum;
+       msurface_t *surf, *s;
+       float *v0, *v1, *v2, *v3;
+       for (surf = surfaces, surfnum = 0;surfnum < numsurfaces;surf++, surfnum++)
+       {
+               surf->neighborsurfaces = Mem_Alloc(mempool, surf->poly_numverts * sizeof(msurface_t *));
+               for (vertnum = 0;vertnum < surf->poly_numverts;vertnum++)
+               {
+                       v0 = surf->poly_verts + ((vertnum + 1) % surf->poly_numverts) * 3;
+                       v1 = surf->poly_verts + vertnum * 3;
+                       surf->neighborsurfaces[vertnum] = NULL;
+                       for (s = surfaces, snum = 0;snum < numsurfaces;s++, snum++)
+                       {
+                               if (s == surf)
+                                       continue;
+                               for (vnum = 0, v2 = s->poly_verts + (s->poly_numverts - 1) * 3, v3 = s->poly_verts;vnum < s->poly_numverts;vnum++, v2 = v3, v3 += 3)
+                               {
+                                       if (v0[0] == v2[0] && v0[1] == v2[1] && v0[2] == v2[2] && v1[0] == v3[0] && v1[1] == v3[1] && v1[2] == v3[2])
+                                       {
+                                               surf->neighborsurfaces[vertnum] = s;
+                                               break;
+                                       }
+                               }
+                               if (vnum < s->poly_numverts)
+                                       break;
+                       }
+               }
+       }
+       #endif
+}
+
 /*
 =================
 Mod_LoadBrushModel
@@ -3317,10 +3455,9 @@ Mod_LoadBrushModel
 extern void R_Model_Brush_DrawSky(entity_render_t *ent);
 extern void R_Model_Brush_Draw(entity_render_t *ent);
 //extern void R_Model_Brush_DrawFakeShadow(entity_render_t *ent);
-extern void R_Model_Brush_DrawDepth(entity_render_t *ent);
+extern void R_Model_Brush_DrawBaseLighting(entity_render_t *ent);
 extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
-extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
-extern void R_Model_Brush_DrawOntoLight(entity_render_t *ent);
+extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
 void Mod_LoadBrushModel (model_t *mod, void *buffer)
 {
        int                     i, j;
@@ -3413,10 +3550,10 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                mod->DrawSky = NULL;
                mod->Draw = R_Model_Brush_Draw;
                mod->DrawFakeShadow = NULL;
-               mod->DrawDepth = R_Model_Brush_DrawDepth;
+               mod->DrawBaseLighting = R_Model_Brush_DrawBaseLighting;
                mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume;
                mod->DrawLight = R_Model_Brush_DrawLight;
-               mod->DrawOntoLight = R_Model_Brush_DrawOntoLight;
+               mod->texturesurfacechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t *));
                if (mod->nummodelsurfaces)
                {
                        // LordHavoc: calculate bmodel bounding box rather than trusting what it says
@@ -3425,6 +3562,10 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                                // we only need to have a drawsky function if it is used (usually only on world model)
                                if (surf->texinfo->texture->shader == &Cshader_sky)
                                        mod->DrawSky = R_Model_Brush_DrawSky;
+                               // link into texture chain
+                               surf->texturechain = mod->texturesurfacechains[surf->texinfo->texture - mod->textures];
+                               mod->texturesurfacechains[surf->texinfo->texture - mod->textures] = surf;
+                               // calculate bounding shapes
                                for (k = 0;k < surf->numedges;k++)
                                {
                                        l = mod->surfedges[k + surf->firstedge];
@@ -3478,6 +3619,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                        mod->radius2 = 0;
                        mod->shadowmesh = NULL;
                }
+               Mod_BuildSurfaceNeighbors(mod->surfaces + mod->firstmodelsurface, mod->nummodelsurfaces, originalloadmodel->mempool);
 
                mod->numleafs = bm->visleafs;
 
index e928269..c2eed62 100644 (file)
@@ -57,22 +57,39 @@ mplane_t;
 
 #define SHADERSTAGE_SKY 0
 #define SHADERSTAGE_NORMAL 1
-#define SHADERSTAGE_COUNT 2
+#define SHADERSTAGE_BASELIGHTING 2
+#define SHADERSTAGE_COUNT 3
 
 #define SHADERFLAGS_NEEDLIGHTMAP 1
 
+#define SURF_PLANEBACK 2
+#define SURF_DRAWSKY 4
+#define SURF_DRAWTURB 0x10
+#define SURF_LIGHTMAP 0x20
+#define SURF_DRAWNOALPHA 0x100
+#define SURF_DRAWFULLBRIGHT 0x200
+#define SURF_LIGHTBOTHSIDES 0x400
+#define SURF_CLIPSOLID 0x800 // this polygon can obscure other polygons
+#define SURF_SHADOWCAST 0x1000 // this polygon can cast stencil shadows
+#define SURF_SHADOWLIGHT 0x2000 // this polygon can be lit by stencil shadowing
+#define SURF_WATERALPHA 0x4000 // this polygon's alpha is modulated by r_wateralpha
+
+#define SURFRENDER_OPAQUE 0
+#define SURFRENDER_ALPHA 1
+#define SURFRENDER_ADD 2
+
 struct entity_render_s;
 struct texture_s;
+struct msurface_s;
 // change this stuff when real shaders are added
 typedef struct Cshader_s
 {
-       void (*shaderfunc[SHADERSTAGE_COUNT])(const struct entity_render_s *ent, const struct texture_s *texture);
+       void (*shaderfunc[SHADERSTAGE_COUNT])(const struct entity_render_s *ent, const struct texture_s *texture, const struct msurface_s *firstsurf);
        int flags;
 }
 Cshader_t;
 
 extern Cshader_t Cshader_wall_lightmap;
-extern Cshader_t Cshader_wall_fullbright;
 extern Cshader_t Cshader_water;
 extern Cshader_t Cshader_sky;
 
@@ -85,6 +102,9 @@ typedef struct texture_s
        // SURF_ flags
        unsigned int flags;
 
+       // type of rendering (SURFRENDER_ value)
+       int rendertype;
+
        // base texture without fullbrights, never NULL
        rtexture_t *texture;
        // fullbrights texture, NULL if no fullbrights used
@@ -97,9 +117,6 @@ typedef struct texture_s
        // shader to use for this texture
        Cshader_t *shader;
 
-       // list of surfaces to render using this texture
-       struct msurface_s *surfacechain;
-
        // total frames in sequence and alternate sequence
        int anim_total[2];
        // direct pointers to each of the frames in the sequences
@@ -108,21 +125,12 @@ typedef struct texture_s
        // set if animated or there is an alternate frame set
        // (this is an optimization in the renderer)
        int animated;
+       // the current texture frames in animation
+       // (index with entity frame != 0)
+       struct texture_s *currentframe[2];
 }
 texture_t;
 
-
-#define SURF_PLANEBACK 2
-#define SURF_DRAWSKY 4
-#define SURF_DRAWTURB 0x10
-#define SURF_LIGHTMAP 0x20
-#define SURF_DRAWNOALPHA 0x100
-#define SURF_DRAWFULLBRIGHT 0x200
-#define SURF_LIGHTBOTHSIDES 0x400
-#define SURF_CLIPSOLID 0x800 // this polygon can obscure other polygons
-#define SURF_SHADOWCAST 0x1000 // this polygon can cast stencil shadows
-#define SURF_SHADOWLIGHT 0x2000 // this polygon can be lit by stencil shadowing
-
 typedef struct
 {
        unsigned short v[2];
@@ -145,6 +153,8 @@ typedef struct surfmesh_s
        int numverts;
        int numtriangles;
        float *verts;
+       float *svectors;
+       float *tvectors;
        float *normals;
        int *lightmapoffsets;
        float *str;
@@ -159,8 +169,8 @@ typedef struct msurface_s
 {
        // surface number, to avoid having to do a divide to find the number of a surface from it's address
        int number;
-       // should be drawn if visframe == r_framecount (set by WorldNode functions)
-       //int visframe;
+       // should be drawn if visframe == r_framecount (set by PrepareSurfaces)
+       int visframe;
        // should be drawn if onscreen and not a backface (used for setting visframe)
        //int pvsframe;
        // chain of surfaces marked visible by pvs
@@ -207,6 +217,9 @@ typedef struct msurface_s
        // bounding sphere radius (around poly_center)
        float poly_radius, poly_radius2;
 
+       // neighboring surfaces (one per poly_numverts)
+       struct msurface_s **neighborsurfaces;
+
        // these are regenerated every frame
        // lighting info
        int dlightframe;
@@ -331,7 +344,9 @@ typedef struct mlight_s
        float distbias;
        // light style controlling this light
        int style;
-       // maximum extent of the light for various purposes
+       // maximum extent of the light for shading purposes
+       float lightradius;
+       // maximum extent of the light for culling purposes
        float cullradius;
        float cullradius2;
        // surfaces this shines on
index 93d2524..8c7342a 100644 (file)
@@ -383,7 +383,7 @@ static void Mod_Flush (void)
        Mod_LoadModels();
 }
 
-int Mod_FindTriangleWithEdge(int *elements, int numtriangles, int start, int end)
+int Mod_FindTriangleWithEdge(const int *elements, int numtriangles, int start, int end)
 {
        int i;
        for (i = 0;i < numtriangles;i++, elements += 3)
@@ -398,9 +398,10 @@ int Mod_FindTriangleWithEdge(int *elements, int numtriangles, int start, int end
        return -1;
 }
 
-void Mod_BuildTriangleNeighbors(int *neighbors, int *elements, int numtriangles)
+void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtriangles)
 {
-       int i, *e, *n;
+       int i, *n;
+       const int *e;
        for (i = 0, e = elements, n = neighbors;i < numtriangles;i++, e += 3, n += 3)
        {
                n[0] = Mod_FindTriangleWithEdge(elements, numtriangles, e[1], e[0]);
@@ -409,6 +410,76 @@ void Mod_BuildTriangleNeighbors(int *neighbors, int *elements, int numtriangles)
        }
 }
 
+void Mod_BuildTextureVectorsAndNormals(int numverts, int numtriangles, const float *vertex, const float *texcoord, const int *elements, float *svectors, float *tvectors, float *normals)
+{
+       int i, tnum, voffset;
+       float vert[3][4], vec[3][4], sdir[3], tdir[3], normal[3], f, *v;
+       const int *e;
+       // clear the vectors
+       memset(svectors, 0, numverts * sizeof(float[4]));
+       memset(tvectors, 0, numverts * sizeof(float[4]));
+       memset(normals, 0, numverts * sizeof(float[4]));
+       // process each vertex of each triangle and accumulate the results
+       for (tnum = 0, e = elements;tnum < numtriangles;tnum++, e += 3)
+       {
+               // calculate texture matrix for triangle
+               voffset = e[0] * 4;
+               vert[0][0] = vertex[voffset+0];
+               vert[0][1] = vertex[voffset+1];
+               vert[0][2] = vertex[voffset+2];
+               vert[0][3] = texcoord[voffset];
+               voffset = e[1] * 4;
+               vert[1][0] = vertex[voffset+0];
+               vert[1][1] = vertex[voffset+1];
+               vert[1][2] = vertex[voffset+2];
+               vert[1][3] = texcoord[voffset];
+               voffset = e[2] * 4;
+               vert[2][0] = vertex[voffset+0];
+               vert[2][1] = vertex[voffset+1];
+               vert[2][2] = vertex[voffset+2];
+               vert[2][3] = texcoord[voffset];
+               VectorSubtract(vert[1], vert[0], vec[0]);
+               VectorSubtract(vert[2], vert[0], vec[1]);
+               CrossProduct(vec[0], vec[1], normal);
+               if (DotProduct(normal, normal) >= 0.001)
+               {
+                       VectorNormalize(normal);
+                       sdir[0] = (vert[1][3] - vert[0][3]) * (vert[2][0] - vert[0][0]) - (vert[2][3] - vert[0][3]) * (vert[1][0] - vert[0][0]);
+                       sdir[1] = (vert[1][3] - vert[0][3]) * (vert[2][1] - vert[0][1]) - (vert[2][3] - vert[0][3]) * (vert[1][1] - vert[0][1]);
+                       sdir[2] = (vert[1][3] - vert[0][3]) * (vert[2][2] - vert[0][2]) - (vert[2][3] - vert[0][3]) * (vert[1][2] - vert[0][2]);
+                       VectorNormalize(sdir);
+                       f = -DotProduct(sdir, normal);
+                       VectorMA(sdir, f, normal, sdir);
+                       VectorNormalize(sdir);
+                       CrossProduct(sdir, normal, tdir);
+                       // this is probably not necessary
+                       VectorNormalize(tdir);
+                       // accumulate matrix onto verts used by triangle
+                       for (i = 0;i < 3;i++)
+                       {
+                               voffset = e[i] * 4;
+                               svectors[voffset    ] += sdir[0];
+                               svectors[voffset + 1] += sdir[1];
+                               svectors[voffset + 2] += sdir[2];
+                               tvectors[voffset    ] += tdir[0];
+                               tvectors[voffset + 1] += tdir[1];
+                               tvectors[voffset + 2] += tdir[2];
+                               normals[voffset    ] += normal[0];
+                               normals[voffset + 1] += normal[1];
+                               normals[voffset + 2] += normal[2];
+                       }
+               }
+       }
+       // now we could divide the vectors by the number of averaged values on
+       // each vertex...  but instead normalize them
+       for (i = 0, v = svectors;i < numverts;i++, v += 4)
+               VectorNormalize(v);
+       for (i = 0, v = tvectors;i < numverts;i++, v += 4)
+               VectorNormalize(v);
+       for (i = 0, v = normals;i < numverts;i++, v += 4)
+               VectorNormalize(v);
+}
+
 shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts)
 {
        shadowmesh_t *mesh;
@@ -460,7 +531,7 @@ void Mod_ShadowMesh_AddPolygon(mempool_t *mempool, shadowmesh_t *mesh, int numve
        while (numverts + mesh->numverts > mesh->maxverts || (numverts - 2) + mesh->numtriangles > mesh->maxtriangles)
        {
                if (mesh->next == NULL)
-                       mesh->next = Mod_ShadowMesh_Alloc(mempool, max(1000, numverts));
+                       mesh->next = Mod_ShadowMesh_Alloc(mempool, max(4096, numverts));
                mesh = mesh->next;
        }
        i1 = Mod_ShadowMesh_AddVertex(mesh, verts);
@@ -479,7 +550,7 @@ void Mod_ShadowMesh_AddPolygon(mempool_t *mempool, shadowmesh_t *mesh, int numve
 
 shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool)
 {
-       return Mod_ShadowMesh_Alloc(mempool, 1000);
+       return Mod_ShadowMesh_Alloc(mempool, 4096);
 }
 
 shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh)
index 7690623..0523fb3 100644 (file)
@@ -174,6 +174,8 @@ typedef struct model_s
        int                             numtextures;
        texture_t               *textures;
 
+       msurface_t              **texturesurfacechains;
+
        qbyte                   *visdata;
        qbyte                   *lightdata;
        char                    *entities;
@@ -192,6 +194,11 @@ typedef struct model_s
        vec3_t                  shadowmesh_mins, shadowmesh_maxs, shadowmesh_center;
        float                   shadowmesh_radius;
 
+       // pvs visibility marking
+       mleaf_t                 *pvsviewleaf;
+       int                             pvsviewleafnovis;
+       int                             pvsframecount;
+
        // skin animation info
        animscene_t             *skinscenes; // [numskins]
        // skin frame info
@@ -236,13 +243,12 @@ typedef struct model_s
        void(*DrawFakeShadow)(struct entity_render_s *ent);
 
        // functions used only in shadow volume rendering mode
-       void(*DrawDepth)(struct entity_render_s *ent);
+       // draw the base lighting for the model (glowing areas, etc)
+       void(*DrawBaseLighting)(struct entity_render_s *ent);
        // draw a shadow volume for the model based on light source
        void(*DrawShadowVolume)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
        // draw the lighting on a model (through stencil)
-       void(*DrawLight)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor);
-       // draw the model with lighting already in framebuffer
-       void(*DrawOntoLight)(struct entity_render_s *ent);
+       void(*DrawLight)(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor);
 
        // memory pool for allocations
        mempool_t               *mempool;
@@ -279,8 +285,9 @@ void Mod_LoadModels(void);
 extern model_t *loadmodel;
 extern char loadname[32];      // for hunk tags
 
-int Mod_FindTriangleWithEdge(int *elements, int numtriangles, int start, int end);
-void Mod_BuildTriangleNeighbors(int *neighbors, int *elements, int numtriangles);
+int Mod_FindTriangleWithEdge(const int *elements, int numtriangles, int start, int end);
+void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtriangles);
+void Mod_BuildTextureVectorsAndNormals(int numverts, int numtriangles, const float *vertex, const float *texcoord, const int *elements, float *svectors, float *tvectors, float *normals);
 
 shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts);
 shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh);
index 4f4e791..0d96a24 100644 (file)
@@ -248,10 +248,9 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer)
        loadmodel->DrawSky = NULL;
        loadmodel->Draw = R_Model_Sprite_Draw;
        loadmodel->DrawFakeShadow = NULL;
-       loadmodel->DrawDepth = NULL;
+       loadmodel->DrawBaseLighting = NULL;
        loadmodel->DrawShadowVolume = NULL;
        loadmodel->DrawLight = NULL;
-       loadmodel->DrawOntoLight = NULL;
 
        version = LittleLong(((dsprite_t *)buffer)->version);
        if (version == SPRITE_VERSION || SPRITE32_VERSION)
index 1d5c2cb..b33418c 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -205,7 +205,6 @@ DYNAMIC LIGHTS
 R_MarkLights
 =============
 */
-extern int r_pvsframecount;
 static void R_OldMarkLights (entity_render_t *ent, vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node)
 {
        float ndist, maxdist;
@@ -242,7 +241,7 @@ loc0:
        surf = ent->model->surfaces + node->firstsurface;
        for (i = 0;i < node->numsurfaces;i++, surf++)
        {
-               if (surfacepvsframes[surf->number] != r_pvsframecount)
+               if (surfacepvsframes[surf->number] != ent->model->pvsframecount)
                        continue;
                dist = ndist;
                if (surf->flags & SURF_PLANEBACK)
@@ -382,7 +381,7 @@ static void R_VisMarkLights (entity_render_t *ent, rdlight_t *rd, int bit, int b
                                                        if (surf->lightframe == lightframe)
                                                                continue;
                                                        surf->lightframe = lightframe;
-                                                       if (surfacepvsframes[surf->number] != r_pvsframecount)
+                                                       if (surfacepvsframes[surf->number] != model->pvsframecount)
                                                                continue;
                                                        dist = PlaneDiff(lightorigin, surf->plane);
                                                        if (surf->flags & SURF_PLANEBACK)
@@ -867,7 +866,7 @@ void R_LightModel(const entity_render_t *ent, int numverts, float *vertices, flo
                        avc[3] = a;
                        avc += 4;
                        av += 4;
-                       avn += 3;
+                       avn += 4;
                }
        }
        else
index 07fcb21..eca072c 100644 (file)
@@ -10,14 +10,21 @@ int maxtrianglefacinglight;
 qbyte *trianglefacinglight;
 
 rtexturepool_t *r_shadow_texturepool;
-rtexture_t *r_shadow_attenuationtexture;
+rtexture_t *r_shadow_normalsattenuationtexture;
+rtexture_t *r_shadow_normalscubetexture;
+rtexture_t *r_shadow_attenuation2dtexture;
+rtexture_t *r_shadow_blankbumptexture;
 
 cvar_t r_shadow1 = {0, "r_shadow1", "16"};
-cvar_t r_shadow2 = {0, "r_shadow2", "4"};
+cvar_t r_shadow2 = {0, "r_shadow2", "2"};
 cvar_t r_shadow3 = {0, "r_shadow3", "65536"};
 cvar_t r_shadow4 = {0, "r_shadow4", "1"};
 cvar_t r_shadow5 = {0, "r_shadow5", "0"};
 cvar_t r_shadow6 = {0, "r_shadow6", "1"};
+cvar_t r_light_realtime = {0, "r_light_realtime", "0"};
+cvar_t r_light_quality = {0, "r_light_quality", "1"};
+cvar_t r_light_gloss = {0, "r_light_gloss", "0"};
+cvar_t r_light_debuglight = {0, "r_light_debuglight", "-1"};
 
 void r_shadow_start(void)
 {
@@ -27,13 +34,19 @@ void r_shadow_start(void)
        shadowelements = NULL;
        maxtrianglefacinglight = 0;
        trianglefacinglight = NULL;
-       r_shadow_attenuationtexture = NULL;
+       r_shadow_normalsattenuationtexture = NULL;
+       r_shadow_normalscubetexture = NULL;
+       r_shadow_attenuation2dtexture = NULL;
+       r_shadow_blankbumptexture = NULL;
        r_shadow_texturepool = NULL;
 }
 
 void r_shadow_shutdown(void)
 {
-       r_shadow_attenuationtexture = NULL;
+       r_shadow_normalsattenuationtexture = NULL;
+       r_shadow_normalscubetexture = NULL;
+       r_shadow_attenuation2dtexture = NULL;
+       r_shadow_blankbumptexture = NULL;
        R_FreeTexturePool(&r_shadow_texturepool);
        maxshadowelements = 0;
        shadowelements = NULL;
@@ -54,6 +67,10 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow4);
        Cvar_RegisterVariable(&r_shadow5);
        Cvar_RegisterVariable(&r_shadow6);
+       Cvar_RegisterVariable(&r_light_realtime);
+       Cvar_RegisterVariable(&r_light_quality);
+       Cvar_RegisterVariable(&r_light_gloss);
+       Cvar_RegisterVariable(&r_light_debuglight);
        R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
 }
 
@@ -109,13 +126,18 @@ void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, in
        // the unprojected vertices and these projected vertices
        for (i = 0, v0 = vertex, v1 = vertex + numverts * 4;i < numverts;i++, v0 += 4, v1 += 4)
        {
+#if 1
+               v1[0] = v0[0] + 50.0f * (v0[0] - relativelightorigin[0]);
+               v1[1] = v0[1] + 50.0f * (v0[1] - relativelightorigin[1]);
+               v1[2] = v0[2] + 50.0f * (v0[2] - relativelightorigin[2]);
+#elif 0
                VectorSubtract(v0, relativelightorigin, temp);
-#if 0
                f = lightradius / sqrt(DotProduct(temp,temp));
                if (f < 1)
                        f = 1;
                VectorMA(relativelightorigin, f, temp, v1);
 #else
+               VectorSubtract(v0, relativelightorigin, temp);
                f = projectdistance / sqrt(DotProduct(temp,temp));
                VectorMA(v0, f, temp, v1);
 #endif
@@ -132,7 +154,7 @@ void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, in
                // of the comparison use it, therefore they are both multiplied the
                // same amount...  furthermore the subtract can be done on the
                // vectors, saving a little bit of math in the dotproducts
-#if 1
+#if 0
                // fast version
                // subtracts v1 from v0 and v2, combined into a crossproduct,
                // combined with a dotproduct of the light location relative to the
@@ -165,7 +187,10 @@ void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, in
                // I.E. flat, so all points give the same answer)
                // the normal is not normalized because it is used on both sides of
                // the comparison, so it's magnitude does not matter
-               trianglefacinglight[i] = DotProduct(relativelightorigin, temp) >= DotProduct(v0, temp);
+               //trianglefacinglight[i] = DotProduct(relativelightorigin, temp) >= DotProduct(v0, temp);
+               f = DotProduct(relativelightorigin, temp) - DotProduct(v0, temp);
+               trianglefacinglight[i] = f > 0 && f < lightradius * sqrt(DotProduct(temp, temp));
+               }
 #endif
        }
 
@@ -193,7 +218,7 @@ void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, in
                        out[5] = e[2] + numverts;
                        out += 6;
                        tris += 2;
-#else
+#else if 1
                        // rear cap
                        out[0] = e[0] + numverts;
                        out[1] = e[1] + numverts;
@@ -245,9 +270,9 @@ void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visible
        // draw the volume
        if (visiblevolume)
        {
-               qglDisable(GL_CULL_FACE);
+               //qglDisable(GL_CULL_FACE);
                R_Mesh_Draw(numverts, numtris, elements);
-               qglEnable(GL_CULL_FACE);
+               //qglEnable(GL_CULL_FACE);
        }
        else
        {
@@ -263,43 +288,147 @@ void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visible
 }
 
 float r_shadow_atten1, r_shadow_atten2, r_shadow_atten5;
-static void R_Shadow_MakeTextures(void)
+#define ATTEN3DSIZE 64
+static void R_Shadow_Make3DTextures(void)
 {
        int x, y, z, d;
-       float v[3];
-       qbyte data[32][32][32][4];
+       float v[3], intensity, ilen, length;
+       qbyte data[ATTEN3DSIZE][ATTEN3DSIZE][ATTEN3DSIZE][4];
+       if (r_light_quality.integer != 1 || !gl_texture3d)
+               return;
+       for (z = 0;z < ATTEN3DSIZE;z++)
+       {
+               for (y = 0;y < ATTEN3DSIZE;y++)
+               {
+                       for (x = 0;x < ATTEN3DSIZE;x++)
+                       {
+                               v[0] = (x + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f;
+                               v[1] = (y + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f;
+                               v[2] = (z + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f;
+                               length = sqrt(DotProduct(v, v));
+                               if (DotProduct(v, v) < 1)
+                                       intensity = (((r_shadow_atten1 / (length*length + r_shadow_atten5)) - (r_shadow_atten1 * r_shadow_atten2))) / 256.0f;
+                               else
+                                       intensity = 0;
+                               ilen = 127.0f * bound(0, intensity, 1) / length;
+                               data[z][y][x][0] = 128.0f + ilen * v[0];
+                               data[z][y][x][1] = 128.0f + ilen * v[1];
+                               data[z][y][x][2] = 128.0f + ilen * v[2];
+                               data[z][y][x][3] = 255;
+                       }
+               }
+       }
+       r_shadow_normalsattenuationtexture = R_LoadTexture3D(r_shadow_texturepool, "normalsattenuation", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+}
+
+static void R_Shadow_MakeTextures(void)
+{
+       int x, y, z, d, side;
+       float v[3], s, t, intensity;
+       qbyte data[6][128][128][4];
        R_FreeTexturePool(&r_shadow_texturepool);
        r_shadow_texturepool = R_AllocTexturePool();
        r_shadow_atten1 = r_shadow1.value;
        r_shadow_atten2 = r_shadow2.value;
        r_shadow_atten5 = r_shadow5.value;
-       for (z = 0;z < 32;z++)
+       for (y = 0;y < 128;y++)
        {
-               for (y = 0;y < 32;y++)
+               for (x = 0;x < 128;x++)
                {
-                       for (x = 0;x < 32;x++)
+                       data[0][y][x][0] = 128;
+                       data[0][y][x][1] = 128;
+                       data[0][y][x][2] = 255;
+                       data[0][y][x][3] = 255;
+               }
+       }
+       r_shadow_blankbumptexture = R_LoadTexture(r_shadow_texturepool, "blankbump", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE);
+       for (side = 0;side < 6;side++)
+       {
+               for (y = 0;y < 128;y++)
+               {
+                       for (x = 0;x < 128;x++)
                        {
-                               v[0] = (x / 32.0f) - 0.5f;
-                               v[1] = (y / 32.0f) - 0.5f;
-                               v[2] = (z / 32.0f) - 0.5f;
-                               d = (int) (((r_shadow_atten1 / (DotProduct(v, v)+r_shadow_atten5)) - (r_shadow_atten1 * r_shadow_atten2)));
-                               d = bound(0, d, 255);
-                               data[z][y][x][0] = data[z][y][x][1] = data[z][y][x][2] = data[z][y][x][3] = d;
+                               s = (x + 0.5f) * (2.0f / 128.0f) - 1.0f;
+                               t = (y + 0.5f) * (2.0f / 128.0f) - 1.0f;
+                               switch(side)
+                               {
+                               case 0:
+                                       v[0] = 1;
+                                       v[1] = -t;
+                                       v[2] = -s;
+                                       break;
+                               case 1:
+                                       v[0] = -1;
+                                       v[1] = -t;
+                                       v[2] = s;
+                                       break;
+                               case 2:
+                                       v[0] = s;
+                                       v[1] = 1;
+                                       v[2] = t;
+                                       break;
+                               case 3:
+                                       v[0] = s;
+                                       v[1] = -1;
+                                       v[2] = -t;
+                                       break;
+                               case 4:
+                                       v[0] = s;
+                                       v[1] = -t;
+                                       v[2] = 1;
+                                       break;
+                               case 5:
+                                       v[0] = -s;
+                                       v[1] = -t;
+                                       v[2] = -1;
+                                       break;
+                               }
+                               intensity = 127.0f / sqrt(DotProduct(v, v));
+                               data[side][y][x][0] = 128.0f + intensity * v[0];
+                               data[side][y][x][1] = 128.0f + intensity * v[1];
+                               data[side][y][x][2] = 128.0f + intensity * v[2];
+                               data[side][y][x][3] = 255;
                        }
                }
        }
-       r_shadow_attenuationtexture = R_LoadTexture3D(r_shadow_texturepool, "attenuation", 32, 32, 32, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_ALPHA);
-       qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-       qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-       qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
+       r_shadow_normalscubetexture = R_LoadTextureCubeMap(r_shadow_texturepool, "normalscube", 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+       for (y = 0;y < 128;y++)
+       {
+               for (x = 0;x < 128;x++)
+               {
+                       v[0] = (x + 0.5f) * (2.0f / 128.0f) - 1.0f;
+                       v[1] = (y + 0.5f) * (2.0f / 128.0f) - 1.0f;
+                       v[2] = 0;
+                       if (DotProduct(v, v) < 1)
+                               intensity = (((r_shadow_atten1 / (DotProduct(v, v)+r_shadow_atten5)) - (r_shadow_atten1 * r_shadow_atten2))) / 256.0f;
+                       else
+                               intensity = 0;
+                       d = bound(0, intensity, 255) / sqrt(DotProduct(v, v));
+                       data[0][y][x][0] = d;
+                       data[0][y][x][1] = d;
+                       data[0][y][x][2] = d;
+                       data[0][y][x][3] = 255;
+               }
+       }
+       r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+       R_Shadow_Make3DTextures();
 }
 
-void R_Shadow_Stage_Depth(void)
+void R_Shadow_Stage_Begin(void)
 {
        rmeshstate_t m;
 
+       if (r_light_quality.integer == 1 && !gl_texture3d)
+       {
+               Con_Printf("3D texture support not detected, falling back on slower 2D + 1D + normalization lighting\n");
+               Cvar_SetValueQuick(&r_light_quality, 0);
+       }
        //cl.worldmodel->numlights = min(cl.worldmodel->numlights, 1);
-       if (!r_shadow_attenuationtexture || r_shadow1.value != r_shadow_atten1 || r_shadow2.value != r_shadow_atten2 || r_shadow5.value != r_shadow_atten5)
+       if (!r_shadow_attenuation2dtexture
+        || (r_light_quality.integer == 1 && !r_shadow_normalsattenuationtexture)
+        || r_shadow1.value != r_shadow_atten1
+        || r_shadow2.value != r_shadow_atten2
+        || r_shadow5.value != r_shadow_atten5)
                R_Shadow_MakeTextures();
 
        memset(&m, 0, sizeof(m));
@@ -330,9 +459,9 @@ void R_Shadow_Stage_Light(void)
 {
        rmeshstate_t m;
        memset(&m, 0, sizeof(m));
-       if (r_shadow6.integer)
-               m.tex3d[0] = R_GetTexture(r_shadow_attenuationtexture);
        R_Mesh_TextureState(&m);
+       qglActiveTexture(GL_TEXTURE0_ARB);
+
        qglEnable(GL_BLEND);
        qglBlendFunc(GL_ONE, GL_ONE);
        GL_Color(1, 1, 1, 1);
@@ -346,101 +475,173 @@ void R_Shadow_Stage_Light(void)
        qglStencilFunc(GL_EQUAL, 0, 0xFF);
 }
 
-void R_Shadow_Stage_Textures(void)
+void R_Shadow_Stage_End(void)
 {
        rmeshstate_t m;
        // attempt to restore state to what Mesh_State thinks it is
        qglDisable(GL_BLEND);
        qglBlendFunc(GL_ONE, GL_ZERO);
        qglDepthMask(1);
-
-       // now change to a more useful state
-       memset(&m, 0, sizeof(m));
-       m.blendfunc1 = GL_DST_COLOR;
-       m.blendfunc2 = GL_SRC_COLOR;
-       R_Mesh_State(&m);
-
-       // now hack some more
-       GL_Color(1, 1, 1, 1);
-       qglColorMask(1, 1, 1, 1);
-       qglDepthFunc(GL_EQUAL);
-       qglEnable(GL_STENCIL_TEST);
-       qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-       // only draw in lit areas
-       qglStencilFunc(GL_EQUAL, 0, 0xFF);
-}
-
-void R_Shadow_Stage_End(void)
-{
-       rmeshstate_t m;
+       // now restore the rest of the state to normal
        GL_Color(1, 1, 1, 1);
        qglColorMask(1, 1, 1, 1);
        qglDepthFunc(GL_LEQUAL);
        qglDisable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        qglStencilFunc(GL_ALWAYS, 0, 0xFF);
+}
 
-       // now change to a more useful state
-       memset(&m, 0, sizeof(m));
-       m.blendfunc1 = GL_ONE;
-       m.blendfunc2 = GL_ZERO;
-       R_Mesh_State(&m);
+void R_Shadow_GenTexCoords_Attenuation2D(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const vec3_t relativelightorigin, float lightradius)
+{
+       int i;
+       float lightvec[3], iradius;
+       iradius = 0.5f / lightradius;
+       for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, out += 4)
+       {
+               VectorSubtract(vertex, relativelightorigin, lightvec);
+               out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius;
+               out[1] = 0.5f + DotProduct(tvectors, lightvec) * iradius;
+       }
+}
+
+void R_Shadow_GenTexCoords_Attenuation1D(float *out, int numverts, const float *vertex, const float *normals, const vec3_t relativelightorigin, float lightradius)
+{
+       int i;
+       float lightvec[3], iradius;
+       iradius = 0.5f / lightradius;
+       for (i = 0;i < numverts;i++, vertex += 4, normals += 4, out += 4)
+       {
+               VectorSubtract(vertex, relativelightorigin, lightvec);
+               out[0] = 0.5f + DotProduct(normals, lightvec) * iradius;
+               out[1] = 0.5f;
+       }
+}
+
+void R_Shadow_GenTexCoords_Diffuse_Attenuation3D(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, float lightradius)
+{
+       int i;
+       float lightvec[3], iradius;
+       iradius = 0.5f / lightradius;
+       for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
+       {
+               VectorSubtract(vertex, relativelightorigin, lightvec);
+               out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius;
+               out[1] = 0.5f + DotProduct(tvectors, lightvec) * iradius;
+               out[2] = 0.5f + DotProduct(normals, lightvec) * iradius;
+       }
+}
+
+void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, float lightradius)
+{
+       int i;
+       float lightdir[3], iradius;
+       iradius = 0.5f / lightradius;
+       for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
+       {
+               VectorSubtract(vertex, relativelightorigin, lightdir);
+               // the cubemap normalizes this for us
+               out[0] = DotProduct(svectors, lightdir);
+               out[1] = DotProduct(tvectors, lightdir);
+               out[2] = DotProduct(normals, lightdir);
+       }
+}
+
+void R_Shadow_GenTexCoords_Specular_Attenuation3D(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin, float lightradius)
+{
+       int i;
+       float lightdir[3], eyedir[3], halfdir[3], lightdirlen, ilen, iradius;
+       iradius = 0.5f / lightradius;
+       for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
+       {
+               VectorSubtract(vertex, relativelightorigin, lightdir);
+               // this is used later to make the attenuation correct
+               lightdirlen = sqrt(DotProduct(lightdir, lightdir)) * iradius;
+               VectorNormalizeFast(lightdir);
+               VectorSubtract(vertex, relativeeyeorigin, eyedir);
+               VectorNormalizeFast(eyedir);
+               VectorAdd(lightdir, eyedir, halfdir);
+               VectorNormalizeFast(halfdir);
+               out[0] = 0.5f + DotProduct(svectors, halfdir) * lightdirlen;
+               out[1] = 0.5f + DotProduct(tvectors, halfdir) * lightdirlen;
+               out[2] = 0.5f + DotProduct(normals, halfdir) * lightdirlen;
+       }
+}
+
+void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin, float lightradius)
+{
+       int i;
+       float lightdir[3], eyedir[3], halfdir[3], lightdirlen, ilen, iradius;
+       iradius = 0.5f / lightradius;
+       for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
+       {
+               VectorSubtract(vertex, relativelightorigin, lightdir);
+               VectorNormalizeFast(lightdir);
+               VectorSubtract(vertex, relativeeyeorigin, eyedir);
+               VectorNormalizeFast(eyedir);
+               VectorAdd(lightdir, eyedir, halfdir);
+               // the cubemap normalizes this for us
+               out[0] = DotProduct(svectors, halfdir);
+               out[1] = DotProduct(tvectors, halfdir);
+               out[2] = DotProduct(normals, halfdir);
+       }
+}
+
+void R_Shadow_GenTexCoords_LightCubeMap(float *out, int numverts, const float *vertex, const vec3_t relativelightorigin)
+{
+       int i;
+       for (i = 0;i < numverts;i++, vertex += 4, out += 4)
+               VectorSubtract(vertex, relativelightorigin, out);
 }
 
-void R_Shadow_Light(int numverts, float *normals, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, rtexture_t *basetexture, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap)
 {
-       if (!r_shadow6.integer)
+       float f;
+       rmeshstate_t m;
+       memset(&m, 0, sizeof(m));
+       if (!bumptexture)
+               bumptexture = r_shadow_blankbumptexture;
+       f = 1.0f / r_shadow3.value;
+       if (r_light_quality.integer == 1)
        {
-               int i;
-               float *n, *v, *c, f, dist, temp[3], light[3], lightradius2;
-               VectorCopy(lightcolor, light);
-               lightradius2 = lightradius * lightradius;
-               for (i = 0, v = varray_vertex, c = varray_color, n = normals;i < numverts;i++, v += 4, c += 4, n += 3)
+               // 4 texture 3D path, two pass
+               GL_Color(1,1,1,1);
+               //lightcolor[0] * f, lightcolor[1] * f, lightcolor[2] * f, 1);
+               memcpy(varray_texcoord[0], texcoords, numverts * sizeof(float[4]));
+               memcpy(varray_texcoord[2], texcoords, numverts * sizeof(float[4]));
+               if (r_light_gloss.integer != 2)
                {
-                       VectorSubtract(relativelightorigin, v, temp);
-                       c[0] = 0;
-                       c[1] = 0;
-                       c[2] = 0;
-                       c[3] = 1;
-                       f = DotProduct(n, temp);
-                       if (f > 0)
-                       {
-                               dist = DotProduct(temp, temp);
-                               if (dist < lightradius2)
-                               {
-                                       f = ((1.0f / (dist + lightdistbias)) - lightsubtract) * (f / sqrt(dist));
-                                       c[0] = f * light[0];
-                                       c[1] = f * light[1];
-                                       c[2] = f * light[2];
-                               }
-                       }
+                       m.tex[0] = R_GetTexture(bumptexture);
+                       m.tex3d[1] = R_GetTexture(r_shadow_normalsattenuationtexture);
+                       m.tex[2] = R_GetTexture(basetexture);
+                       m.texcubemap[3] = R_GetTexture(lightcubemap);
+                       m.texcombinergb[0] = GL_REPLACE;
+                       m.texcombinergb[1] = GL_DOT3_RGB_ARB;
+                       m.texcombinergb[2] = GL_MODULATE;
+                       m.texcombinergb[3] = GL_MODULATE;
+                       R_Mesh_TextureState(&m);
+                       R_Shadow_GenTexCoords_Diffuse_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, lightradius);
+                       if (m.texcubemap[3])
+                               R_Shadow_GenTexCoords_LightCubeMap(varray_texcoord[3], numverts, varray_vertex, relativelightorigin);
+                       R_Mesh_Draw(numverts, numtriangles, elements);
+               }
+               if (r_light_gloss.integer && glosstexture)
+               {
+                       m.tex[0] = R_GetTexture(bumptexture);
+                       m.tex3d[1] = R_GetTexture(r_shadow_normalsattenuationtexture);
+                       m.tex[2] = R_GetTexture(glosstexture);
+                       m.texcubemap[3] = R_GetTexture(lightcubemap);
+                       m.texcombinergb[0] = GL_REPLACE;
+                       m.texcombinergb[1] = GL_DOT3_RGB_ARB;
+                       m.texcombinergb[2] = GL_MODULATE;
+                       m.texcombinergb[3] = GL_MODULATE;
+                       R_Mesh_TextureState(&m);
+                       R_Shadow_GenTexCoords_Specular_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, relativeeyeorigin, lightradius);
+                       R_Mesh_Draw(numverts, numtriangles, elements);
                }
        }
        else
        {
-               int i;
-               float *n, *v, *c, *t, f, temp[3], light[3], iradius, attentexbase[3];
-               VectorScale(lightcolor, (1.0f / r_shadow3.value), light);
-               iradius = 0.5f / lightradius;
-               attentexbase[0] = 0.5f;
-               attentexbase[1] = 0.5f;
-               attentexbase[2] = 0.5f;
-               for (i = 0, v = varray_vertex, c = varray_color, n = normals, t = varray_texcoord[0];i < numverts;i++, v += 4, c += 4, n += 3, t += 4)
-               {
-                       VectorSubtract(v, relativelightorigin, temp);
-                       VectorMA(attentexbase, iradius, temp, t);
-                       c[0] = 0;
-                       c[1] = 0;
-                       c[2] = 0;
-                       c[3] = 1;
-                       f = DotProduct(n, temp);
-                       if (f < 0)
-                       {
-                               f /= -sqrt(DotProduct(temp, temp));
-                               c[0] = f * light[0];
-                               c[1] = f * light[1];
-                               c[2] = f * light[2];
-                       }
-               }
+               //R_Mesh_TextureState(&m);
        }
 }
+
index cbd35c6..e2dedad 100644 (file)
@@ -2,17 +2,20 @@
 #ifndef R_SHADOW_H
 #define R_SHADOW_H
 
+extern cvar_t r_light_realtime;
+extern cvar_t r_light_quality;
+extern cvar_t r_light_gloss;
+extern cvar_t r_light_debuglight;
+
 void R_Shadow_Init(void);
 void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance, int visiblevolume);
-void R_Shadow_Light(int numverts, float *normals, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor);
-void R_Shadow_RenderLightThroughStencil(int numverts, int numtris, int *elements, vec3_t relativelightorigin, float *normals);
+void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, rtexture_t *basetexture, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap);
 void R_Shadow_ClearStencil(void);
 
 void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visiblevolume);
-void R_Shadow_Stage_Depth(void);
+void R_Shadow_Stage_Begin(void);
 void R_Shadow_Stage_ShadowVolumes(void);
 void R_Shadow_Stage_Light(void);
-void R_Shadow_Stage_Textures(void);
 void R_Shadow_Stage_End(void);
 
 #endif
index 4f4eaa5..48f6220 100644 (file)
 // allocated as a fragment in a larger texture, mipmap is not allowed with
 // this, mostly used for lightmaps
 #define TEXF_FRAGMENT 0x00000010
+// indicates texture coordinates should be clamped rather than wrapping
+#define TEXF_CLAMP 0x00000020
 // used for checking if textures mismatch
-#define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_FRAGMENT)
+#define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_FRAGMENT | TEXF_CLAMP)
 
 // 8bit quake paletted
 #define TEXTYPE_QPALETTE 1
index bb73ebd..fdeb233 100644 (file)
--- a/render.h
+++ b/render.h
@@ -108,7 +108,7 @@ void R_InitSky (qbyte *src, int bytesperpixel); // called at level load
 
 void R_NewMap (void);
 
-void R_DrawWorld(entity_render_t *ent);
+void R_DrawWorld(entity_render_t *ent, int baselighting);
 void R_DrawParticles(void);
 void R_DrawExplosions(void);