From 8ca84375827e16c963229b584b0dd64595a780f2 Mon Sep 17 00:00:00 2001 From: havoc Date: Mon, 4 Nov 2002 01:09:33 +0000 Subject: [PATCH] now clears stencil to 128 instead of 0, this avoids problems with arbitrary incr/decr orders stencil shadows are now always erased by glClear, never by drawing again, removes r_shadow_erasebydrawing cvar shadow volumes now have a nudge away from the surface that cast them, this is controlled by the r_shadow_shadownudge cvar (default 1 unit), avoids rare z fighting issues shadow volume projection distance is now not infinite for alias model volumes, because they are more well-behaved than the world shadows... msurface_t poly_radius and poly_radius2 removed now validates elements in more parts of loading (hoped this would reveal a model shadow bug, but it didn't) Mod_ShadowMesh_AddVertex now uses a hash table search to speed up static shadow volume building (unfortunately this doesn't seem to be the real speed problem) removed ALLOCMESHINPIECES option from Mod_ShadowMesh code removed non-PRECOMPUTEDSHADOWVOLUMES option from static shadow volume creation removed some unused variables git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2597 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_backend.c | 5 +- gl_rmain.c | 54 --------------- gl_rsurf.c | 24 ++++--- model_alias.c | 2 + model_brush.c | 22 ++---- model_brush.h | 2 - model_shared.c | 57 ++++++---------- model_shared.h | 10 +++ r_shadow.c | 180 +++++++++---------------------------------------- r_shadow.h | 3 - 10 files changed, 90 insertions(+), 269 deletions(-) diff --git a/gl_backend.c b/gl_backend.c index 8125cb75..a6648711 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -882,7 +882,10 @@ void R_ClearScreen(void) qglClearDepth(1);CHECKGLERROR if (gl_stencil) { - qglClearStencil(0);CHECKGLERROR + // LordHavoc: we use a stencil centered around 128 instead of 0, + // to avoid clamping interfering with strange shadow volume + // drawing orders + qglClearStencil(128);CHECKGLERROR } // clear the screen qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));CHECKGLERROR diff --git a/gl_rmain.c b/gl_rmain.c index fcc9f671..2fe41e5e 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -939,27 +939,6 @@ void R_ShadowVolumeLighting (int visiblevolumes) } } } - - if (R_Shadow_Stage_EraseShadowVolumes()) - { - ent = &cl_entities[0].render; - if (wl->shadowvolume && r_staticworldlights.integer) - R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl); - else - R_TestAndDrawShadowVolume(ent, wl->origin, cullradius / ent->scale, lightradius / ent->scale, clipmins, clipmaxs); - if (r_drawentities.integer) - { - for (i = 0;i < r_refdef.numentities;i++) - { - ent = r_refdef.entities[i]; - if (ent->maxs[0] >= wl->mins[0] && ent->mins[0] <= wl->maxs[0] - && ent->maxs[1] >= wl->mins[1] && ent->mins[1] <= wl->maxs[1] - && ent->maxs[2] >= wl->mins[2] && ent->mins[2] <= wl->maxs[2] - && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1) - R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius / ent->scale, lightradius / ent->scale, clipmins, clipmaxs); - } - } - } } } /* @@ -1023,24 +1002,6 @@ void R_ShadowVolumeLighting (int visiblevolumes) } } } - - R_Shadow_Stage_EraseShadowVolumes(); - if (sl->shadowvolume && r_staticworldlights.integer) - R_DrawWorldLightShadowVolume(&cl_entities[0].render.matrix, sl->shadowvolume); - else - R_TestAndDrawShadowVolume(&cl_entities[0].render, sl->origin, cullradius, lightradius); - if (r_drawentities.integer) - { - for (i = 0;i < r_refdef.numentities;i++) - { - ent = r_refdef.entities[i]; - if (ent->maxs[0] >= sl->mins[0] && ent->mins[0] <= sl->maxs[0] - && ent->maxs[1] >= sl->mins[1] && ent->mins[1] <= sl->maxs[1] - && ent->maxs[2] >= sl->mins[2] && ent->mins[2] <= sl->maxs[2] - && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1) - R_TestAndDrawShadowVolume(r_refdef.entities[i], sl->origin, cullradius, lightradius); - } - } } } */ @@ -1100,21 +1061,6 @@ void R_ShadowVolumeLighting (int visiblevolumes) } } } - - if (R_Shadow_Stage_EraseShadowVolumes()) - { - ent = &cl_entities[0].render; - R_TestAndDrawShadowVolume(ent, rd->origin, cullradius / ent->scale, lightradius / ent->scale, clipmins, clipmaxs); - if (r_drawentities.integer) - { - for (i = 0;i < r_refdef.numentities;i++) - { - ent = r_refdef.entities[i]; - if (ent != rd->ent && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1) - R_TestAndDrawShadowVolume(ent, rd->origin, cullradius / ent->scale, lightradius / ent->scale, clipmins, clipmaxs); - } - } - } } } diff --git a/gl_rsurf.c b/gl_rsurf.c index 7177b463..8bdb5db5 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1824,6 +1824,7 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto R_Mesh_Matrix(&ent->matrix); lightradius2 = lightradius * lightradius; R_UpdateTextureInfo(ent); + projectdistance = 1000000000.0f;//lightradius + ent->model->radius; for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++) { if (surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && surf->flags & SURF_SHADOWCAST) @@ -1831,12 +1832,13 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto f = PlaneDiff(relativelightorigin, surf->plane); if (surf->flags & SURF_PLANEBACK) f = -f; - // draw shadows only for frontfaces - projectdistance = lightradius - f; - if (projectdistance >= 0.1 && projectdistance < lightradius) + // draw shadows only for frontfaces and only if they are close + if (f >= 0.1 && f < lightradius) { - VectorSubtract(relativelightorigin, surf->poly_center, temp); - if (DotProduct(temp, temp) < lightradius2 - surf->poly_radius2) + temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0]; + temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1]; + temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2]; + if (DotProduct(temp, temp) < lightradius2) { for (mesh = surf->mesh;mesh;mesh = mesh->chain) { @@ -1893,8 +1895,10 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v // bmodel, cull crudely to view and light for (surfnum = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;surfnum < ent->model->nummodelsurfaces;surfnum++, surf++) { - VectorSubtract(relativelightorigin, surf->poly_center, temp); - if (DotProduct(temp, temp) < lightradius2 - surf->poly_radius2) + temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0]; + temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1]; + temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2]; + if (DotProduct(temp, temp) < lightradius2) { f = PlaneDiff(relativelightorigin, surf->plane); if (surf->flags & SURF_PLANEBACK) @@ -1929,8 +1933,10 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v { if (surf->visframe == r_framecount) { - VectorSubtract(relativelightorigin, surf->poly_center, temp); - if (DotProduct(temp, temp) < lightradius2 - surf->poly_radius2) + temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0]; + temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1]; + temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2]; + if (DotProduct(temp, temp) < lightradius2) { f = PlaneDiff(relativelightorigin, surf->plane); if (surf->flags & SURF_PLANEBACK) diff --git a/model_alias.c b/model_alias.c index 24829cfa..2d42510e 100644 --- a/model_alias.c +++ b/model_alias.c @@ -495,6 +495,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) loadmodel->radius2 = modelradius * modelradius; loadmodel->mdlmd2data_triangleneighbors = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3])); + Mod_ValidateElements(loadmodel->mdlmd2data_indices, loadmodel->numtris, loadmodel->numverts, __FILE__, __LINE__); Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris); } @@ -757,6 +758,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) loadmodel->radius2 = modelradius * modelradius; loadmodel->mdlmd2data_triangleneighbors = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3])); + Mod_ValidateElements(loadmodel->mdlmd2data_indices, loadmodel->numtris, loadmodel->numverts, __FILE__, __LINE__); Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris); } diff --git a/model_brush.c b/model_brush.c index f62506f5..c003fb2c 100644 --- a/model_brush.c +++ b/model_brush.c @@ -783,8 +783,10 @@ void Mod_ProcessLightList(void) dist = -dist; if (dist > 0 && dist < e->cullradius) { - VectorSubtract(e->origin, surf->poly_center, temp); - if (DotProduct(temp, temp) < e->cullradius2 - surf->poly_radius2) + temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0]; + temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1]; + temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2]; + if (DotProduct(temp, temp) < lightradius2) loadmodel->surfacevisframes[*mark] = -2; } } @@ -1587,7 +1589,7 @@ void Mod_GenerateVertexMesh (msurface_t *surf) void Mod_GenerateSurfacePolygon (msurface_t *surf) { int i, lindex; - float *vec, *vert, mins[3], maxs[3], temp[3], dist; + float *vec, *vert, mins[3], maxs[3]; // convert edges back to a normal polygon surf->poly_numverts = surf->numedges; @@ -1606,29 +1608,17 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf) VectorCopy(vert, mins); VectorCopy(vert, maxs); vert += 3; - for (i = 1;i < surf->poly_numverts;i++) + for (i = 1;i < surf->poly_numverts;i++, vert += 3) { if (mins[0] > vert[0]) mins[0] = vert[0];if (maxs[0] < vert[0]) maxs[0] = vert[0]; if (mins[1] > vert[1]) mins[1] = vert[1];if (maxs[1] < vert[1]) maxs[1] = vert[1]; if (mins[2] > vert[2]) mins[2] = vert[2];if (maxs[2] < vert[2]) maxs[2] = vert[2]; - vert += 3; } VectorCopy(mins, surf->poly_mins); VectorCopy(maxs, surf->poly_maxs); 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); } /* diff --git a/model_brush.h b/model_brush.h index fb4c30a6..120679b1 100644 --- a/model_brush.h +++ b/model_brush.h @@ -216,8 +216,6 @@ 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; // neighboring surfaces (one per poly_numverts) struct msurface_s **neighborsurfaces; diff --git a/model_shared.c b/model_shared.c index 2ab19e64..4c75ef00 100644 --- a/model_shared.c +++ b/model_shared.c @@ -523,47 +523,28 @@ void Mod_BuildTextureVectorsAndNormals(int numverts, int numtriangles, const flo shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts) { shadowmesh_t *mesh; -#define ALLOCMESHINPIECES 0 -#if ALLOCMESHINPIECES - mesh = Mem_Alloc(mempool, sizeof(shadowmesh_t)); -#else - mesh = Mem_Alloc(mempool, sizeof(shadowmesh_t) + maxverts * sizeof(float[4]) + maxverts * sizeof(int[3]) + maxverts * sizeof(int[3])); -#endif + mesh = Mem_Alloc(mempool, sizeof(shadowmesh_t) + maxverts * sizeof(float[4]) + maxverts * sizeof(int[3]) + maxverts * sizeof(int[3]) + SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *) + maxverts * sizeof(shadowmeshvertexhash_t)); mesh->maxverts = maxverts; mesh->maxtriangles = maxverts; mesh->numverts = 0; mesh->numtriangles = 0; -#if ALLOCMESHINPIECES - mesh->verts = Mem_Alloc(mempool, maxverts * sizeof(float[4])); - mesh->elements = Mem_Alloc(mempool, maxverts * sizeof(int[3])); - mesh->neighbors = Mem_Alloc(mempool, maxverts * sizeof(int[3])); -#else mesh->verts = (float *)(mesh + 1); mesh->elements = (int *)(mesh->verts + mesh->maxverts * 4); mesh->neighbors = (int *)(mesh->elements + mesh->maxtriangles * 3); -#endif + mesh->vertexhashtable = (shadowmeshvertexhash_t **)(mesh->neighbors + mesh->maxtriangles * 3); + mesh->vertexhashentries = (shadowmeshvertexhash_t *)(mesh->vertexhashtable + SHADOWMESHVERTEXHASH); return mesh; } shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh) { shadowmesh_t *newmesh; -#if ALLOCMESHINPIECES - newmesh = Mem_Alloc(mempool, sizeof(shadowmesh_t)); -#else newmesh = Mem_Alloc(mempool, sizeof(shadowmesh_t) + oldmesh->numverts * sizeof(float[4]) + oldmesh->numtriangles * sizeof(int[3]) + oldmesh->numtriangles * sizeof(int[3])); -#endif newmesh->maxverts = newmesh->numverts = oldmesh->numverts; newmesh->maxtriangles = newmesh->numtriangles = oldmesh->numtriangles; -#if ALLOCMESHINPIECES - newmesh->verts = Mem_Alloc(mempool, newmesh->maxverts * sizeof(float[4])); - newmesh->elements = Mem_Alloc(mempool, newmesh->numtriangles * sizeof(int[3])); - newmesh->neighbors = Mem_Alloc(mempool, newmesh->numtriangles * sizeof(int[3])); -#else newmesh->verts = (float *)(newmesh + 1); newmesh->elements = (int *)(newmesh->verts + newmesh->maxverts * 4); newmesh->neighbors = (int *)(newmesh->elements + newmesh->maxtriangles * 3); -#endif memcpy(newmesh->verts, oldmesh->verts, newmesh->numverts * sizeof(float[4])); memcpy(newmesh->elements, oldmesh->elements, newmesh->numtriangles * sizeof(int[3])); memcpy(newmesh->neighbors, oldmesh->neighbors, newmesh->numtriangles * sizeof(int[3])); @@ -572,17 +553,24 @@ shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh) int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, float *v) { - int j; - float *m, temp[3]; - for (j = 0, m = mesh->verts;j < mesh->numverts;j++, m += 4) + int hashindex; + float *m; + shadowmeshvertexhash_t *hash; + // this uses prime numbers intentionally + hashindex = (int) (v[0] * 3 + v[1] * 5 + v[2] * 7) % SHADOWMESHVERTEXHASH; + for (hash = mesh->vertexhashtable[hashindex];hash;hash = hash->next) { - VectorSubtract(v, m, temp); - if (DotProduct(temp, temp) < 0.1) - return j; + m = mesh->verts + (hash - mesh->vertexhashentries) * 4; + if (m[0] == v[0] && m[1] == v[1] && m[2] == v[2]) + return hash - mesh->vertexhashentries; } - mesh->numverts++; + hash = mesh->vertexhashentries + mesh->numverts; + hash->next = mesh->vertexhashtable[hashindex]; + mesh->vertexhashtable[hashindex] = hash; + m = mesh->verts + (hash - mesh->vertexhashentries) * 4; VectorCopy(v, m); - return j; + mesh->numverts++; + return mesh->numverts - 1; } void Mod_ShadowMesh_AddTriangle(mempool_t *mempool, shadowmesh_t *mesh, float *vert0, float *vert1, float *vert2) @@ -658,6 +646,7 @@ shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh) //Con_Printf("mesh\n"); //for (i = 0;i < newmesh->numtriangles;i++) // Con_Printf("tri %d %d %d\n", newmesh->elements[i * 3 + 0], newmesh->elements[i * 3 + 1], newmesh->elements[i * 3 + 2]); + Mod_ValidateElements(newmesh->elements, newmesh->numtriangles, newmesh->numverts, __FILE__, __LINE__); Mod_BuildTriangleNeighbors(newmesh->neighbors, newmesh->elements, newmesh->numtriangles); } Mem_Free(mesh); @@ -665,7 +654,10 @@ shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh) #else shadowmesh_t *mesh; for (mesh = firstmesh;mesh;mesh = mesh->next) + { + Mod_ValidateElements(mesh->elements, mesh->numtriangles, mesh->numverts, __FILE__, __LINE__); Mod_BuildTriangleNeighbors(mesh->neighbors, mesh->elements, mesh->numtriangles); + } #endif return firstmesh; } @@ -723,11 +715,6 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh) for (;mesh;mesh = nextmesh) { nextmesh = mesh->next; -#if ALLOCMESHINPIECES - Mem_Free(mesh->verts); - Mem_Free(mesh->elements); - Mem_Free(mesh->neighbors); -#endif Mem_Free(mesh); } } diff --git a/model_shared.h b/model_shared.h index cebb49d9..83d981fd 100644 --- a/model_shared.h +++ b/model_shared.h @@ -60,6 +60,13 @@ skinframe_t; #define MAX_SKINS 256 +#define SHADOWMESHVERTEXHASH 1024 +typedef struct shadowmeshvertexhash_s +{ + struct shadowmeshvertexhash_s *next; +} +shadowmeshvertexhash_t; + typedef struct shadowmesh_s { struct shadowmesh_s *next; @@ -68,6 +75,9 @@ typedef struct shadowmesh_s float *verts; int *elements; int *neighbors; + // these are NULL after Mod_ShadowMesh_Finish is performed, only used + // while building meshes + shadowmeshvertexhash_t **vertexhashtable, *vertexhashentries; } shadowmesh_t; diff --git a/r_shadow.c b/r_shadow.c index 54ce7584..449e2a47 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -33,12 +33,12 @@ rtexture_t *r_shadow_blankwhitetexture; cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "2"}; cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1"}; cvar_t r_shadow_realtime = {0, "r_shadow_realtime", "0"}; -cvar_t r_shadow_erasebydrawing = {0, "r_shadow_erasebydrawing", "0"}; cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "0"}; cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"}; cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"}; cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"}; cvar_t r_shadow_bumpscale = {0, "r_shadow_bumpscale", "4"}; +cvar_t r_shadow_shadownudge = {0, "r_shadow_shadownudge", "1"}; void R_Shadow_ClearWorldLights(void); void R_Shadow_SaveWorldLights(void); @@ -97,33 +97,25 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_texture3d); Cvar_RegisterVariable(&r_shadow_gloss); Cvar_RegisterVariable(&r_shadow_debuglight); - Cvar_RegisterVariable(&r_shadow_erasebydrawing); Cvar_RegisterVariable(&r_shadow_scissor); Cvar_RegisterVariable(&r_shadow_bumpscale); + Cvar_RegisterVariable(&r_shadow_shadownudge); R_Shadow_EditLights_Init(); R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap); } -void R_Shadow_ProjectVertices(const float *in, float *out, int numverts, const float *relativelightorigin, float projectdistance) +void R_Shadow_ProjectVertices(float *verts, int numverts, const float *relativelightorigin, float projectdistance) { int i; + float *in, *out, diff[4]; + in = verts; + out = verts + numverts * 4; for (i = 0;i < numverts;i++, in += 4, out += 4) { -#if 1 - out[0] = in[0] + 1000000.0f * (in[0] - relativelightorigin[0]); - out[1] = in[1] + 1000000.0f * (in[1] - relativelightorigin[1]); - out[2] = in[2] + 1000000.0f * (in[2] - relativelightorigin[2]); -#elif 0 - VectorSubtract(in, relativelightorigin, temp); - f = lightradius / sqrt(DotProduct(temp,temp)); - if (f < 1) - f = 1; - VectorMA(relativelightorigin, f, temp, out); -#else - VectorSubtract(in, relativelightorigin, temp); - f = projectdistance / sqrt(DotProduct(temp,temp)); - VectorMA(in, f, temp, out); -#endif + VectorSubtract(in, relativelightorigin, diff); + VectorNormalizeFast(diff); + VectorMA(in, projectdistance, diff, out); + VectorMA(in, r_shadow_shadownudge.value, diff, in); } } @@ -304,13 +296,13 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v if (maxshadowelements < numtris * 24) R_Shadow_ResizeShadowElements(numtris); + // check which triangles are facing the light + R_Shadow_MakeTriangleShadowFlags(elements, varray_vertex, numtris, trianglefacinglight, relativelightorigin, lightradius); + // generate projected vertices // by clever use of elements we'll construct the whole shadow from // the unprojected vertices and these projected vertices - R_Shadow_ProjectVertices(varray_vertex, varray_vertex + numverts * 4, numverts, relativelightorigin, projectdistance); - - // check which triangles are facing the light - R_Shadow_MakeTriangleShadowFlags(elements, varray_vertex, numtris, trianglefacinglight, relativelightorigin, lightradius); + R_Shadow_ProjectVertices(varray_vertex, numverts, relativelightorigin, projectdistance); // output triangle elements tris = R_Shadow_BuildShadowVolumeTriangles(elements, neighbors, numtris, numverts, trianglefacinglight, shadowelements); @@ -541,12 +533,11 @@ void R_Shadow_Stage_ShadowVolumes(void) qglDepthFunc(GL_LESS); qglEnable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - qglStencilFunc(GL_ALWAYS, 0, 0xFF); + qglStencilFunc(GL_ALWAYS, 128, 0xFF); qglEnable(GL_CULL_FACE); qglEnable(GL_DEPTH_TEST); r_shadowstage = SHADOWSTAGE_STENCIL; - if (!r_shadow_erasebydrawing.integer) - qglClear(GL_STENCIL_BUFFER_BIT); + qglClear(GL_STENCIL_BUFFER_BIT); } void R_Shadow_Stage_Light(void) @@ -565,37 +556,13 @@ void R_Shadow_Stage_Light(void) qglEnable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // only draw light where this geometry was already rendered AND the - // stencil is 0 (non-zero means shadow) - qglStencilFunc(GL_EQUAL, 0, 0xFF); + // stencil is 128 (values other than this mean shadow) + qglStencilFunc(GL_EQUAL, 128, 0xFF); qglEnable(GL_CULL_FACE); qglEnable(GL_DEPTH_TEST); r_shadowstage = SHADOWSTAGE_LIGHT; } -int R_Shadow_Stage_EraseShadowVolumes(void) -{ - if (r_shadow_erasebydrawing.integer) - { - rmeshstate_t m; - memset(&m, 0, sizeof(m)); - R_Mesh_TextureState(&m); - GL_Color(1, 1, 1, 1); - qglColorMask(0, 0, 0, 0); - qglDisable(GL_BLEND); - qglDepthMask(0); - qglDepthFunc(GL_LESS); - qglEnable(GL_STENCIL_TEST); - qglStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); - qglStencilFunc(GL_ALWAYS, 0, 0xFF); - qglDisable(GL_CULL_FACE); - qglDisable(GL_DEPTH_TEST); - r_shadowstage = SHADOWSTAGE_ERASESTENCIL; - return true; - } - else - return false; -} - void R_Shadow_Stage_End(void) { rmeshstate_t m; @@ -610,7 +577,7 @@ void R_Shadow_Stage_End(void) qglDepthFunc(GL_LEQUAL); qglDisable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - qglStencilFunc(GL_ALWAYS, 0, 0xFF); + qglStencilFunc(GL_ALWAYS, 128, 0xFF); qglEnable(GL_CULL_FACE); qglEnable(GL_DEPTH_TEST); // force mesh state to reset by using various combinations of features @@ -1076,22 +1043,10 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen } } -#define PRECOMPUTEDSHADOWVOLUMES 1 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light) { -#if PRECOMPUTEDSHADOWVOLUMES R_Mesh_Matrix(matrix); R_Shadow_RenderShadowMeshVolume(light->shadowvolume); -#else - shadowmesh_t *mesh; - R_Mesh_Matrix(matrix); - for (mesh = light->shadowvolume;mesh;mesh = mesh->next) - { - R_Mesh_ResizeCheck(mesh->numverts * 2); - memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->elements, mesh->neighbors, light->origin, light->lightradius, light->lightradius); - } -#endif } cvar_t r_editlights = {0, "r_editlights", "0"}; @@ -1106,13 +1061,15 @@ vec3_t r_editlights_cursorlocation; static int castshadowcount = 1; void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style, const char *cubemapname) { - int i, j, k, l, maxverts, *mark; - float *verts, *v, *v0, *v1, f, projectdistance, temp[3], temp2[3], temp3[3], radius2; + int i, j, k, l, maxverts, *mark, tris; + float *verts, *v, f, temp[3], radius2; + //float projectdistance, *v0, *v1, temp2[3], temp3[3]; worldlight_t *e; - shadowmesh_t *mesh; + shadowmesh_t *mesh, *castmesh; mleaf_t *leaf; msurface_t *surf; qbyte *pvs; + surfmesh_t *surfmesh; e = Mem_Alloc(r_shadow_mempool, sizeof(worldlight_t)); VectorCopy(origin, e->origin); @@ -1160,8 +1117,10 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style f = -f; if (f > 0 && f < e->lightradius) { - VectorSubtract(e->origin, surf->poly_center, temp); - if (DotProduct(temp, temp) - surf->poly_radius2 < e->lightradius * e->lightradius) + temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0]; + temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1]; + temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2]; + if (DotProduct(temp, temp) < e->lightradius * e->lightradius) surf->castshadow = castshadowcount; } } @@ -1236,17 +1195,6 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style } } e->shadowvolume = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768); -#if !PRECOMPUTEDSHADOWVOLUMES - // make a mesh to cast a shadow volume from - for (j = 0;j < e->numsurfaces;j++) - if (e->surfaces[j]->castshadow == castshadowcount) - Mod_ShadowMesh_AddPolygon(r_shadow_mempool, e->shadowvolume, e->surfaces[j]->poly_numverts, e->surfaces[j]->poly_verts); -#else -#if 1 - { - int tris; - shadowmesh_t *castmesh, *mesh; - surfmesh_t *surfmesh; // make a mesh to cast a shadow volume from castmesh = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768); for (j = 0;j < e->numsurfaces;j++) @@ -1273,7 +1221,7 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style // now that we have the buffers big enough, construct shadow volume mesh memcpy(verts, castmesh->verts, castmesh->numverts * sizeof(float[4])); - R_Shadow_ProjectVertices(verts, verts + castmesh->numverts * 4, castmesh->numverts, e->origin, e->lightradius); + R_Shadow_ProjectVertices(verts, castmesh->numverts, e->origin, 1000000.0f);//, e->lightradius); R_Shadow_MakeTriangleShadowFlags(castmesh->elements, verts, castmesh->numtriangles, trianglefacinglight, e->origin, e->lightradius); tris = R_Shadow_BuildShadowVolumeTriangles(castmesh->elements, castmesh->neighbors, castmesh->numtriangles, castmesh->numverts, trianglefacinglight, shadowelements); // add the constructed shadow volume mesh @@ -1281,72 +1229,6 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style } // we're done with castmesh now Mod_ShadowMesh_Free(castmesh); - } -#else - // make a shadow volume mesh - if (verts == NULL && maxverts > 0) - verts = Mem_Alloc(r_shadow_mempool, maxverts * sizeof(float[4])); - for (j = 0;j < e->numsurfaces;j++) - { - surf = e->surfaces[j]; - if (surf->castshadow != castshadowcount) - continue; - projectdistance = 1000000.0f;//e->lightradius; - // 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_ShadowMesh_AddPolygon(r_shadow_mempool, e->shadowvolume, 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_ShadowMesh_AddPolygon(r_shadow_mempool, e->shadowvolume, surf->poly_numverts, verts); - // project the shadow volume sides - for (l = surf->poly_numverts - 1, k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;l = k, k++, v0 = v1, v1 += 3) - { - if (surf->neighborsurfaces == NULL || surf->neighborsurfaces[l] == NULL || surf->neighborsurfaces[l]->castshadow != castshadowcount) - { - 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]); - -#if 0 - VectorSubtract(&verts[0], &verts[3], temp); - VectorSubtract(&verts[6], &verts[3], temp2); - CrossProduct(temp, temp2, temp3); - VectorNormalize(temp3); - if (DotProduct(surf->poly_center, temp3) > DotProduct(&verts[0], temp3)) - { - 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]); - Con_Printf("flipped shadow volume edge %8p %i\n", surf, l); - } -#endif - - Mod_ShadowMesh_AddPolygon(r_shadow_mempool, e->shadowvolume, 4, verts); - } - } - } -#endif -#endif e->shadowvolume = Mod_ShadowMesh_Finish(r_shadow_mempool, e->shadowvolume); for (l = 0, mesh = e->shadowvolume;mesh;mesh = mesh->next) l += mesh->numtriangles; @@ -1399,7 +1281,7 @@ void R_Shadow_FreeSelectedWorldLight(void) void R_Shadow_SelectLightInView(void) { - float bestrating, rating, temp[3], dist; + float bestrating, temp[3], dist; worldlight_t *best, *light; best = NULL; bestrating = 1e30; @@ -1498,7 +1380,7 @@ void R_Shadow_SaveWorldLights(void) void R_Shadow_LoadLightsFile(void) { int n, a, style; - char name[MAX_QPATH], cubemapname[MAX_QPATH], *lightsstring, *s, *t; + char name[MAX_QPATH], *lightsstring, *s, *t; float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias; COM_StripExtension(cl.worldmodel->name, name); strcat(name, ".lights"); diff --git a/r_shadow.h b/r_shadow.h index 9b119357..40eb5ab1 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -20,9 +20,6 @@ void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *mesh); void R_Shadow_Stage_Begin(void); void R_Shadow_Stage_ShadowVolumes(void); void R_Shadow_Stage_Light(void); -// returns true if shadow volumes should be drawn again to erase, -// otherwise clears stencil -int R_Shadow_Stage_EraseShadowVolumes(void); void R_Shadow_Stage_End(void); int R_Shadow_ScissorForBBoxAndSphere(const float *mins, const float *maxs, const float *origin, float radius); -- 2.39.2