]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
bmodel shadow volumes
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 30 Sep 2002 14:55:28 +0000 (14:55 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 30 Sep 2002 14:55:28 +0000 (14:55 +0000)
static lights (in maps with .lights files) now cast shadow volumes (this combined with the above makes dpdm1 and dpdm2 unplayably slow - need to do precomputed world shadow volumes)
(note: like the previous shadow volume commits, this is still just visible volumes when you use r_shadows 2, purely experimental still)

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

13 files changed:
gl_backend.c
gl_backend.h
gl_draw.c
gl_models.c
gl_rmain.c
gl_rsurf.c
glquake.h
model_brush.c
model_brush.h
r_shadow.c
r_shadow.h
r_sky.c
vid_shared.c

index 160881413e71506bc8b9d555c492ba643eb2e08a..2ec09f0bc95c0d97e1866405a9bba87fe4ce67c9 100644 (file)
@@ -583,26 +583,6 @@ void R_Mesh_Finish(void)
        qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
 }
 
-void GL_DepthFunc(int value)
-{
-       if (!r_render.integer)
-               return;
-
-       qglDepthFunc (value);
-       CHECKGLERROR
-}
-
-void GL_ClearDepth(void)
-{
-       BACKENDACTIVECHECK
-
-       if (!r_render.integer)
-               return;
-
-       qglClear(GL_DEPTH_BUFFER_BIT);
-       CHECKGLERROR
-}
-
 void R_Mesh_Matrix(const matrix4x4_t *matrix)
 {
        if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
index cd4b85cb454d0bb5db33ef2d5a2389ef72d13f7e..6a652013a17ba65ec2061767eb7cd137c3d19f74 100644 (file)
@@ -16,8 +16,6 @@ void GL_SetupView_Mode_Perspective (double aspect, double fovx, double fovy, dou
 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);
-void GL_DepthFunc(int value);
-void GL_ClearDepth(void);
 
 extern cvar_t gl_lockarrays;
 
index 598d9026ca22c068addb1d97eb8a0bee7e2f8bd3..717f0b8983874b90ff0cb43cb08c519e2714737d 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -397,7 +397,7 @@ void R_DrawQueue(void)
        }
        GL_SetupView_ViewPort(vid.realx, vid.realy, vid.realwidth, vid.realheight);
        GL_SetupView_Mode_Ortho(0, 0, vid.conwidth, vid.conheight, -10, 100);
-       GL_DepthFunc(GL_LEQUAL);
+       qglDepthFunc(GL_LEQUAL);
        R_Mesh_Start();
        R_Mesh_Matrix(&r_identitymatrix);
 
index c56ee35a333336f69756958f5c8e8ab226b058b6..4d5a876f82b293c75dcab11e9ddae36ecdf07e4b 100644 (file)
@@ -488,30 +488,57 @@ void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent)
        rmeshstate_t m;
        model_t *model;
        float *v, planenormal[3], planedist, dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
+       mlight_t *sl;
+       rdlight_t *rd;
 
        if (r_shadows.integer > 1)
        {
-               float f;
+               float f, lightscale, lightcolor[3];
                vec3_t temp;
-               for (i = 0;i < r_numdlights;i++)
+               memset(&m, 0, sizeof(m));
+               m.blendfunc1 = GL_ONE;
+               m.blendfunc2 = GL_ONE;
+               R_Mesh_State(&m);
+               R_Mesh_Matrix(&ent->matrix);
+               for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++)
+               {
+                       if (d_lightstylevalue[sl->style] > 0)
+                       {
+                               VectorSubtract(ent->origin, sl->origin, temp);
+                               f = DotProduct(temp,temp);
+                               if (f < (ent->model->radius2 + sl->cullradius2))
+                               {
+                                       model = ent->model;
+                                       R_Mesh_ResizeCheck(model->numverts * 2);
+                                       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+                                       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, 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, aliasvertnorm, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor);
+                                       R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
+                               }
+                       }
+               }
+               for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
                {
-                       if (ent != r_dlight[i].ent)
+                       if (ent != rd->ent)
                        {
-                               VectorSubtract(ent->origin, r_dlight[i].origin, temp);
+                               VectorSubtract(ent->origin, rd->origin, temp);
                                f = DotProduct(temp,temp);
-                               if (f < (ent->model->radius2 + r_dlight[i].cullradius2))
+                               if (f < (ent->model->radius2 + rd->cullradius2))
                                {
                                        model = ent->model;
                                        R_Mesh_ResizeCheck(model->numverts * 2);
-                                       memset(&m, 0, sizeof(m));
-                                       m.blendfunc1 = GL_ONE;
-                                       m.blendfunc2 = GL_ONE;
-                                       R_Mesh_State(&m);
-                                       R_Mesh_Matrix(&ent->matrix);
                                        R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+                                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, temp);
                                        GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
-                                       Matrix4x4_Transform(&ent->inversematrix, r_dlight[i].origin, temp);
-                                       R_ShadowVolume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, r_dlight[i].cullradius + model->radius - sqrt(f), true);
+                                       R_Shadow_Volume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, rd->cullradius + model->radius - sqrt(f), true);
+                                       GL_UseColorArray();
+                                       R_Shadow_VertexLight(model->numverts, aliasvertnorm, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light);
+                                       R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                                }
                        }
                }
index dc4bd184a547fffa3f28c2f26f66a039244a390c..184af30762a74bfc542b9030c7d46d5521a99612 100644 (file)
@@ -544,7 +544,7 @@ void R_DrawModels (void)
        }
 }
 
-void R_DrawModelFakeShadows (void)
+void R_DrawFakeShadows (void)
 {
        int i;
        entity_render_t *ent;
@@ -552,6 +552,9 @@ void R_DrawModelFakeShadows (void)
        if (!r_drawentities.integer)
                return;
 
+       ent = &cl_entities[0].render;
+       if (ent->model && ent->model->DrawFakeShadow)
+               ent->model->DrawFakeShadow(ent);
        for (i = 0;i < r_refdef.numentities;i++)
        {
                ent = r_refdef.entities[i];
@@ -676,7 +679,7 @@ void R_RenderView (void)
        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_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
-       GL_DepthFunc(GL_LEQUAL);
+       qglDepthFunc(GL_LEQUAL);
        
        R_Mesh_Start();
        R_MeshQueue_BeginScene();
@@ -692,12 +695,6 @@ void R_RenderView (void)
        if (!intimerefresh && !r_speeds.integer)
                S_ExtraUpdate ();
 
-       if (r_shadows.integer)
-       {
-               R_DrawModelFakeShadows();
-               R_TimeReport("fakeshadows");
-       }
-
        R_DrawModels();
        R_TimeReport("models");
 
@@ -721,6 +718,11 @@ void R_RenderView (void)
 
        R_MeshQueue_Render();
        R_MeshQueue_EndScene();
+       if (r_shadows.integer)
+       {
+               R_DrawFakeShadows();
+               R_TimeReport("fakeshadows");
+       }
        R_Mesh_Finish();
        R_TimeReport("meshfinish");
 }
index 314429c0f92a7dd49c9897baf9e6064b1c293852..9448717d8f77e6d51a6954f6f6d71c89f51ce466 100644 (file)
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // r_surf.c: surface-related refresh code
 
 #include "quakedef.h"
+#include "r_shadow.h"
 
 #define MAX_LIGHTMAP_SIZE 256
 
@@ -774,6 +775,9 @@ static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture
        memset(&m, 0, sizeof(m));
        if (skyrendermasked)
        {
+               qglColorMask(0,0,0,0);
+               // just to make sure that braindead drivers don't draw anything
+               // despite that colormask...
                m.blendfunc1 = GL_ZERO;
                m.blendfunc2 = GL_ONE;
        }
@@ -795,6 +799,7 @@ static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture
                        R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
                }
        }
+       qglColorMask(1,1,1,1);
 }
 
 static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
@@ -1825,6 +1830,87 @@ void R_DrawBrushModelNormal (entity_render_t *ent)
        R_DrawBrushModel(ent, false, true);
 }
 
+void R_DrawBrushModelShadowVolumes (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
+{
+       int i, numsurfaces;
+       msurface_t *surf;
+       float projectdistance, f, temp[3], lightradius2;
+       surfmesh_t *mesh;
+       numsurfaces = ent->model->nummodelsurfaces;
+       lightradius2 = lightradius * lightradius;
+       for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < numsurfaces;i++, surf++)
+       {
+               VectorSubtract(relativelightorigin, surf->poly_center, temp);
+               if (DotProduct(temp, temp) < (surf->poly_radius2 + lightradius2))
+               {
+                       f = PlaneDiff(relativelightorigin, surf->plane);
+                       if (surf->flags & SURF_PLANEBACK)
+                               f = -f;
+                       // draw shadows only for backfaces
+                       if (f < 0)
+                       {
+                               projectdistance = lightradius + f;
+                               if (projectdistance > 0)
+                               {
+                                       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                                       {
+                                               R_Mesh_ResizeCheck(mesh->numverts * 2);
+                                               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                                               R_Shadow_Volume(mesh->numverts, mesh->numtriangles, mesh->index, mesh->triangleneighbors, relativelightorigin, projectdistance, visiblevolume);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+extern cvar_t r_shadows;
+void R_DrawBrushModelFakeShadow (entity_render_t *ent)
+{
+       int i;
+       vec3_t relativelightorigin;
+       rmeshstate_t m;
+       mlight_t *sl;
+       rdlight_t *rd;
+
+       if (r_shadows.integer < 2)
+               return;
+
+       memset(&m, 0, sizeof(m));
+       m.blendfunc1 = GL_ONE;
+       m.blendfunc2 = GL_ONE;
+       R_Mesh_State(&m);
+       R_Mesh_Matrix(&ent->matrix);
+       GL_Color(0.0125 * r_colorscale, 0.025 * r_colorscale, 0.1 * r_colorscale, 1);
+       for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++)
+       {
+               if (d_lightstylevalue[sl->style] > 0
+                && ent->maxs[0] >= sl->origin[0] - sl->cullradius
+                && ent->mins[0] <= sl->origin[0] + sl->cullradius
+                && ent->maxs[1] >= sl->origin[1] - sl->cullradius
+                && ent->mins[1] <= sl->origin[1] + sl->cullradius
+                && ent->maxs[2] >= sl->origin[2] - sl->cullradius
+                && ent->mins[2] <= sl->origin[2] + sl->cullradius)
+               {
+                       Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
+                       R_DrawBrushModelShadowVolumes (ent, relativelightorigin, sl->cullradius, true);
+               }
+       }
+       for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
+       {
+               if (ent->maxs[0] >= rd->origin[0] - rd->cullradius
+                && ent->mins[0] <= rd->origin[0] + rd->cullradius
+                && ent->maxs[1] >= rd->origin[1] - rd->cullradius
+                && ent->mins[1] <= rd->origin[1] + rd->cullradius
+                && ent->maxs[2] >= rd->origin[2] - rd->cullradius
+                && ent->mins[2] <= rd->origin[2] + rd->cullradius)
+               {
+                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
+                       R_DrawBrushModelShadowVolumes (ent, relativelightorigin, rd->cullradius, true);
+               }
+       }
+}
+
 static void gl_surf_start(void)
 {
 }
index 18e75d9e471c7fb4f3cebdddd109c5ffcd7ef4fd..e2832595759be17e6791cf3066d37efd2f46bd84 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -195,6 +195,12 @@ typedef double GLclampd;
 #define GL_ACCUM_BUFFER_BIT                    0x00000200
 #define GL_STENCIL_BUFFER_BIT                  0x00000400
 #define GL_COLOR_BUFFER_BIT                    0x00004000
+
+#define GL_STENCIL_TEST                                0x0B90
+#define GL_KEEP                                        0x1E00
+#define GL_REPLACE                             0x1E01
+#define GL_INCR                                        0x1E02
+#define GL_DECR                                        0x1E03
 #endif
 
 // GL_ARB_multitexture
@@ -312,6 +318,7 @@ extern void (GLAPIENTRY *qglClearDepth)(GLclampd depth);
 extern void (GLAPIENTRY *qglDepthFunc)(GLenum func);
 extern void (GLAPIENTRY *qglDepthMask)(GLboolean flag);
 extern void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val);
+extern void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
 
 extern void (GLAPIENTRY *qglDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
 extern void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
index 51538971121534d932ea03e58090d99f046d8903..51fc0c79bd1baf936248f9d9cd6068fd193fb303 100644 (file)
@@ -662,6 +662,56 @@ void Mod_LoadLightList(void)
        }
 }
 
+void Mod_ProcessLightList(void)
+{
+       int i, j, k, *mark;
+       mlight_t *e;
+       msurface_t *surf;
+       float dist;
+       mleaf_t *l;
+       qbyte *pvs;
+       for (i = 0, e = loadmodel->lights;i < loadmodel->numlights;i++, e++)
+       {
+               e->cullradius2 = DotProduct(e->light, e->light) * (1.0f / (8192.0f * 8192.0f)) / (e->falloff * e->falloff) + 4096.0f;
+               if (e->cullradius2 > 4096.0f * 4096.0f)
+                       e->cullradius2 = 4096.0f * 4096.0f;
+               e->cullradius = sqrt(e->cullradius2);
+               l = Mod_PointInLeaf(e->origin, loadmodel);
+               if (l->compressed_vis)
+                       pvs = Mod_DecompressVis (l->compressed_vis, loadmodel);
+               else
+                       pvs = mod_novis;
+               for (j = 0, l = loadmodel->leafs + 1;j < loadmodel->numleafs - 1;j++)
+               {
+                       if (pvs[j >> 3] & (1 << (j & 7)))
+                       {
+                               for (k = 0, mark = l->firstmarksurface;k < l->nummarksurfaces;k++, mark++)
+                               {
+                                       surf = loadmodel->surfaces + *mark;
+                                       dist = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
+                                       if (surf->flags & SURF_PLANEBACK)
+                                               dist = -dist;
+                                       if (dist > 0 && dist < e->cullradius)
+                                               loadmodel->surfacevisframes[j] = i - 1000000;
+                               }
+                       }
+               }
+               e->numsurfaces = 0;
+               for (j = 0;j < loadmodel->nummodelsurfaces;j++)
+                       if (loadmodel->surfacevisframes[j] == i - 1000000)
+                               e->numsurfaces++;
+               e->surfaces = NULL;
+               if (e->numsurfaces > 0)
+               {
+                       e->surfaces = Mem_Alloc(loadmodel->mempool, sizeof(msurface_t *) * e->numsurfaces);
+                       e->numsurfaces = 0;
+                       for (j = 0;j < loadmodel->nummodelsurfaces;j++)
+                               if (loadmodel->surfacevisframes[j] == i - 1000000)
+                                       e->surfaces[e->numsurfaces++] = loadmodel->surfaces + loadmodel->firstmodelsurface + j;
+               }
+       }
+}
+
 
 /*
 =================
@@ -1111,8 +1161,8 @@ void Mod_GenerateWarpMesh (msurface_t *surf)
 
 void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
 {
-       int i, iu, iv, *index, smax, tmax;
-       float *in, s, t, u, v, ubase, vbase, uscale, vscale;
+       int i, iu, iv, *index, *n, smax, tmax;
+       float *in, s, t, u, v, ubase, vbase, uscale, vscale, normal[3];
        surfmesh_t *mesh;
 
        smax = surf->extents[0] >> 4;
@@ -1145,7 +1195,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[3]) + surf->poly_numverts * (4 + 2 + 2 + 2 + 1) * sizeof(float));
+       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[6]) + surf->poly_numverts * (4 + 2 + 2 + 2 + 1 + 3) * sizeof(float));
        mesh->numverts = surf->poly_numverts;
        mesh->numtriangles = surf->poly_numverts - 2;
        mesh->verts = (float *)(mesh + 1);
@@ -1154,15 +1204,24 @@ void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
        mesh->ab = mesh->uv + mesh->numverts * 2;
        mesh->lightmapoffsets = (int *)(mesh->ab + mesh->numverts * 2);
        mesh->index = mesh->lightmapoffsets + mesh->numverts;
+       mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
+       mesh->normals = (float *)(mesh->triangleneighbors + mesh->numtriangles * 3);
 
        index = mesh->index;
+       n = mesh->triangleneighbors;
        for (i = 0;i < mesh->numtriangles;i++)
        {
                *index++ = 0;
                *index++ = i + 1;
                *index++ = i + 2;
+               *n++ = i - 1;
+               *n++ = -1;
+               *n++ = i + 1;
        }
 
+       VectorCopy(surf->plane->normal, normal);
+       if (surf->flags & SURF_PLANEBACK)
+               VectorNegate(normal, normal);
        for (i = 0, in = surf->poly_verts;i < mesh->numverts;i++, in += 3)
        {
                s = DotProduct (in, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3];
@@ -1187,34 +1246,46 @@ void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
                mesh->ab[i * 2 + 0] = s * (1.0f / 16.0f);
                mesh->ab[i * 2 + 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];
        }
 }
 
 void Mod_GenerateVertexMesh (msurface_t *surf)
 {
-       int i, *index;
-       float *in, s, t;
+       int i, *index, *n;
+       float *in, s, t, normal[3];
        surfmesh_t *mesh;
 
        surf->lightmaptexturestride = 0;
        surf->lightmaptexture = NULL;
 
-       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * (4 + 2 + 2) * sizeof(float));
+       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[6]) + surf->poly_numverts * (4 + 2 + 2 + 3) * sizeof(float));
        mesh->numverts = surf->poly_numverts;
        mesh->numtriangles = surf->poly_numverts - 2;
        mesh->verts = (float *)(mesh + 1);
        mesh->st = mesh->verts + mesh->numverts * 4;
        mesh->ab = mesh->st + mesh->numverts * 2;
        mesh->index = (int *)(mesh->ab + mesh->numverts * 2);
+       mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
+       mesh->normals = (float *)(mesh->triangleneighbors + mesh->numtriangles * 3);
 
        index = mesh->index;
+       n = mesh->triangleneighbors;
        for (i = 0;i < mesh->numtriangles;i++)
        {
                *index++ = 0;
                *index++ = i + 1;
                *index++ = i + 2;
+               *n++ = -1;
+               *n++ = -1;
+               *n++ = i + 1;
        }
 
+       VectorCopy(surf->plane->normal, normal);
+       if (surf->flags & SURF_PLANEBACK)
+               VectorNegate(normal, normal);
        for (i = 0, in = surf->poly_verts;i < mesh->numverts;i++, in += 3)
        {
                s = (DotProduct (in, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
@@ -1226,13 +1297,16 @@ void Mod_GenerateVertexMesh (msurface_t *surf)
                mesh->st[i * 2 + 1] = t / surf->texinfo->texture->height;
                mesh->ab[i * 2 + 0] = s * (1.0f / 16.0f);
                mesh->ab[i * 2 + 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];
        }
 }
 
 void Mod_GenerateSurfacePolygon (msurface_t *surf)
 {
        int i, lindex;
-       float *vec, *vert, mins[3], maxs[3];
+       float *vec, *vert, mins[3], maxs[3], temp[3], dist;
 
        // convert edges back to a normal polygon
        surf->poly_numverts = surf->numedges;
@@ -1263,6 +1337,17 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf)
        surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f;
        surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f;
        surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f;
+       surf->poly_radius2 = 0;
+       vert = surf->poly_verts;
+       for (i = 0;i < surf->poly_numverts;i++)
+       {
+               VectorSubtract(vert, surf->poly_center, temp);
+               dist = DotProduct(temp, temp);
+               if (surf->poly_radius2 < dist)
+                       surf->poly_radius2 = dist;
+               vert += 3;
+       }
+       surf->poly_radius = sqrt(surf->poly_radius2);
 }
 
 /*
@@ -2339,6 +2424,7 @@ static void Mod_MakePortals(void)
 Mod_LoadBrushModel
 =================
 */
+extern void R_DrawBrushModelFakeShadow (entity_render_t *ent);
 void Mod_LoadBrushModel (model_t *mod, void *buffer)
 {
        int                     i, j;
@@ -2346,6 +2432,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
        dmodel_t        *bm;
        mempool_t       *mainmempool;
        char            *loadname;
+       model_t         *originalloadmodel;
 
        mod->type = mod_brush;
 
@@ -2398,6 +2485,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
        loadname = mod->name;
 
        Mod_LoadLightList ();
+       originalloadmodel = loadmodel;
 
 //
 // set up the submodels (FIXME: this is confusing)
@@ -2479,7 +2567,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                mod->numleafs = bm->visleafs;
 
                mod->Draw = R_DrawBrushModelNormal;
-               mod->DrawFakeShadow = NULL;
+               mod->DrawFakeShadow = R_DrawBrushModelFakeShadow;
 
                // LordHavoc: only register submodels if it is the world
                // (prevents bsp models from replacing world submodels)
@@ -2497,5 +2585,8 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                        mod = loadmodel;
                }
        }
+
+       loadmodel = originalloadmodel;
+       Mod_ProcessLightList ();
 }
 
index 80756e39dbe76a30782eb1ae9525f490bd6a032c..f109b1d94cd40872a432633b4b7a9db619ca0435 100644 (file)
@@ -143,11 +143,13 @@ typedef struct surfmesh_s
        int numverts;
        int numtriangles;
        float *verts;
+       float *normals;
        int *lightmapoffsets;
        float *st;
        float *uv;
        float *ab;
        int *index;
+       int *triangleneighbors;
 }
 surfmesh_t;
 
@@ -200,6 +202,8 @@ typedef struct msurface_s
        float *poly_verts;
        // bounding box for onscreen checks, and center for sorting
        vec3_t poly_mins, poly_maxs, poly_center;
+       // bounding sphere radius (around poly_center)
+       float poly_radius, poly_radius2;
 
        // these are regenerated every frame
        // lighting info
@@ -315,6 +319,12 @@ typedef struct mlight_s
        float distbias;
        // light style controlling this light
        int style;
+       // maximum extent of the light for various purposes
+       float cullradius;
+       float cullradius2;
+       // surfaces this shines on
+       int numsurfaces;
+       msurface_t **surfaces;
        // used only for loading calculations, number of leafs this shines on
        //int numleafs;
 }
index 153867fd031ddf0504d0dadf41f60ef342f51532..c33d04f09a1a449afe27f48dc7abcb84fb95ceeb 100644 (file)
@@ -36,7 +36,7 @@ void R_Shadow_Init(void)
        R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
 }
 
-void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume)
+void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume)
 {
        int i, *e, *n, *out, tris;
        float *v0, *v1, *v2, dir0[3], dir1[3], temp[3], f;
@@ -128,7 +128,7 @@ void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, ve
                        out += 6;
                        tris += 2;
                        // check the edges
-                       if (trianglefacinglight[n[0]])
+                       if (n[0] < 0 || trianglefacinglight[n[0]])
                        {
                                out[0] = e[0];
                                out[1] = e[1];
@@ -139,7 +139,7 @@ void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, ve
                                out += 6;
                                tris += 2;
                        }
-                       if (trianglefacinglight[n[1]])
+                       if (n[1] < 0 || trianglefacinglight[n[1]])
                        {
                                out[0] = e[1];
                                out[1] = e[2];
@@ -150,7 +150,7 @@ void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, ve
                                out += 6;
                                tris += 2;
                        }
-                       if (trianglefacinglight[n[2]])
+                       if (n[2] < 0 || trianglefacinglight[n[2]])
                        {
                                out[0] = e[2];
                                out[1] = e[0];
@@ -172,16 +172,64 @@ void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, ve
        }
        else
        {
-               qglCullFace(GL_FRONT);
-               //qglStencilFunc(
+               qglColorMask(0,0,0,0);
+               qglEnable(GL_STENCIL_TEST);
+               // increment stencil if backface is behind depthbuffer
+               qglCullFace(GL_BACK); // quake is backwards, this culls front faces
+               qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
+               R_Mesh_Draw(numverts * 2, tris, shadowelements);
+               // decrement stencil if frontface is infront of depthbuffer
+               qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
+               qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+               R_Mesh_Draw(numverts * 2, tris, shadowelements);
+               // restore to normal quake rendering
+               qglDisable(GL_STENCIL_TEST);
+               qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+               qglColorMask(1,1,1,1);
+       }
+}
+
+void R_Shadow_VertexLight(int numverts, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
+{
+       int i;
+       float *n, *v, *c, f, dist, temp[3];
+       // calculate vertex colors
+       for (i = 0, v = varray_vertex, c = varray_color, n = normals;i < numverts;i++, v += 4, c += 4, n += 3)
+       {
+               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 * lightcolor[0];
+                               c[1] = f * lightcolor[1];
+                               c[2] = f * lightcolor[2];
+                       }
+               }
        }
 }
 
-void R_Shadow_BeginScene(void)
+void R_Shadow_RenderLightThroughStencil(int numverts, int numtris, int *elements, vec3_t relativelightorigin, float *normals)
+{
+       // only draw light where this geometry was already rendered AND the
+       // stencil is 0 (non-zero means shadow)
+       qglDepthFunc(GL_EQUAL);
+       qglEnable(GL_STENCIL_TEST);
+       qglStencilFunc(GL_EQUAL, 0, 0xFF);
+       R_Mesh_Draw(numverts, numtris, elements);
+       qglDisable(GL_STENCIL_TEST);
+       qglDepthFunc(GL_LEQUAL);
+}
+
+void R_Shadow_ClearStencil(void)
 {
-       rmeshstate_t m;
-       memset(&m, 0, sizeof(m));
-       m.blendfunc1 = GL_ONE;
-       m.blendfunc2 = GL_ZERO;
-       R_Mesh_State(&m);
+       qglClearStencil(0);
+       qglClear(GL_STENCIL_BUFFER_BIT);
 }
index 42e80ba139caed1a14569fd0ea5b649c09cf1b4a..470d96d7d7288aace7e2504b505c6a4b7dff0e99 100644 (file)
@@ -3,6 +3,9 @@
 #define R_SHADOW_H
 
 void R_Shadow_Init(void);
-void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume);
+void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume);
+void R_Shadow_VertexLight(int numverts, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
+void R_Shadow_RenderLightThroughStencil(int numverts, int numtris, int *elements, vec3_t relativelightorigin, float *normals);
+void R_Shadow_ClearStencil(void);
 
 #endif
diff --git a/r_sky.c b/r_sky.c
index 9b237f908a3c19a186480a197cd06e1646185cb9..e73d3672bbacd77596d07ea68d885dcb4dac378f 100644 (file)
--- a/r_sky.c
+++ b/r_sky.c
@@ -305,7 +305,7 @@ void R_Sky(void)
                        // this modifies the depth buffer so we have to clear it afterward
                        //R_SkyRoom();
                        // clear the depthbuffer that was used while rendering the skyroom
-                       //R_Mesh_ClearDepth();
+                       //qglClear(GL_DEPTH_BUFFER_BIT);
                }
                */
        }
index 4ae9663a030b1385c818acb0807a83d4bd7da1bc..212118b7d528e6ed754db583ebed1f2509224fd0 100644 (file)
@@ -98,6 +98,7 @@ void (GLAPIENTRY *qglClearDepth)(GLclampd depth);
 void (GLAPIENTRY *qglDepthFunc)(GLenum func);
 void (GLAPIENTRY *qglDepthMask)(GLboolean flag);
 void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val);
+void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
 
 void (GLAPIENTRY *qglDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
 void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
@@ -224,6 +225,7 @@ static gl_extensionfunctionlist_t opengl110funcs[] =
        {"glDepthMask", (void **) &qglDepthMask},
        {"glDepthRange", (void **) &qglDepthRange},
        {"glDrawElements", (void **) &qglDrawElements},
+       {"glColorMask", (void **) &qglColorMask},
        {"glVertexPointer", (void **) &qglVertexPointer},
 //     {"glNormalPointer", (void **) &qglNormalPointer},
        {"glColorPointer", (void **) &qglColorPointer},