From 6d6bb0a8d9e2cb7ad6e156584304b4fd621eac3e Mon Sep 17 00:00:00 2001 From: havoc Date: Mon, 30 Sep 2002 18:01:08 +0000 Subject: [PATCH] optimized trianglefacing calculation, per Vic's recommendation (yes it's all one statement now) shadow functions now take a vertex array pointer, to make them more broadly useful (in precomputation perhaps?) beginning work on a precomputed shadow volumes system for static lights git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2486 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_models.c | 8 +++---- gl_rsurf.c | 2 +- model_brush.c | 7 ++++++ model_brush.h | 11 ++++++++++ r_shadow.c | 61 +++++++++++++++++++++++++++++++++++++++------------ r_shadow.h | 4 ++-- 6 files changed, 72 insertions(+), 21 deletions(-) diff --git a/gl_models.c b/gl_models.c index 4d5a876f..4cc5f9fd 100644 --- a/gl_models.c +++ b/gl_models.c @@ -513,11 +513,11 @@ void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent) 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); + 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, aliasvertnorm, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor); + R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvertnorm, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor); R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); } } @@ -535,9 +535,9 @@ void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent) 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); - R_Shadow_Volume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, rd->cullradius + model->radius - sqrt(f), true); + 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, aliasvertnorm, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light); + R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvertnorm, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light); R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices); } } diff --git a/gl_rsurf.c b/gl_rsurf.c index 9448717d..37e048cc 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1856,7 +1856,7 @@ void R_DrawBrushModelShadowVolumes (entity_render_t *ent, vec3_t relativelightor { 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); + R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->index, mesh->triangleneighbors, relativelightorigin, projectdistance, visiblevolume); } } } diff --git a/model_brush.c b/model_brush.c index 51fc0c79..28347fc6 100644 --- a/model_brush.c +++ b/model_brush.c @@ -710,6 +710,13 @@ void Mod_ProcessLightList(void) e->surfaces[e->numsurfaces++] = loadmodel->surfaces + loadmodel->firstmodelsurface + j; } } + // construct shadow volumes for each light + /* + for (i = 0, e = loadmodel->lights;i < loadmodel->numlights;i++, e++) + { + FIXME FINISH THIS CODE! + } + */ } diff --git a/model_brush.h b/model_brush.h index f109b1d9..8424b538 100644 --- a/model_brush.h +++ b/model_brush.h @@ -301,6 +301,15 @@ typedef struct mportal_s } mportal_t; +typedef struct mlightshadowvolumemesh_s +{ + struct mlightshadowvolumemesh_s *next; + int numverts; + int numtris; + float *vertex; +} +mlightshadowvolumemesh_t; + typedef struct mlight_s { // location of light @@ -325,6 +334,8 @@ typedef struct mlight_s // surfaces this shines on int numsurfaces; msurface_t **surfaces; + // precomputed shadow volume meshs + mlightshadowvolumemesh_t *shadowvolumemeshs; // used only for loading calculations, number of leafs this shines on //int numleafs; } diff --git a/r_shadow.c b/r_shadow.c index c33d04f0..aebace17 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -36,10 +36,10 @@ void R_Shadow_Init(void) R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap); } -void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume) +void R_Shadow_Volume(int numverts, int numtris, float *vertex, 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; + float *v0, *v1, *v2, temp[3], f; // terminology: // // frontface: @@ -57,8 +57,8 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v // description: // draws the shadow volumes of the model. // requirements: -// vertex loations must already be in varray_vertex before use. -// varray_vertex must have capacity for numverts * 2. +// vertex loations must already be in vertex before use. +// vertex must have capacity for numverts * 2. // make sure trianglefacinglight is big enough for this volume if (maxtrianglefacinglight < numtris) @@ -81,7 +81,7 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v // make projected vertices // by clever use of elements we'll construct the whole shadow from // the unprojected vertices and these projected vertices - for (i = 0, v0 = varray_vertex, v1 = varray_vertex + numverts * 4;i < numverts;i++, v0 += 4, v1 += 4) + for (i = 0, v0 = vertex, v1 = vertex + numverts * 4;i < numverts;i++, v0 += 4, v1 += 4) { VectorSubtract(v0, relativelightorigin, temp); f = projectdistance / sqrt(DotProduct(temp,temp)); @@ -91,17 +91,50 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v // check which triangles are facing the light for (i = 0, e = elements;i < numtris;i++, e += 3) { - // calculate surface plane - v0 = varray_vertex + e[0] * 4; - v1 = varray_vertex + e[1] * 4; - v2 = varray_vertex + e[2] * 4; + // calculate triangle facing flag + v0 = vertex + e[0] * 4; + v1 = vertex + e[1] * 4; + v2 = vertex + e[2] * 4; + // we do not need to normalize the surface normal because both sides + // 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 + // fast version + // subtracts v1 from v0 and v2, combined into a crossproduct, + // combined with a dotproduct of the light location relative to the + // first point of the triangle (any point works, since the triangle + // is obviously flat), and finally a comparison to determine if the + // light is infront of the triangle (the goal of this statement) + trianglefacinglight[i] = + (relativelightorigin[0] - v0[0]) * ((v0[1] - v1[1]) * (v2[2] - v1[2]) - (v0[2] - v1[2]) * (v2[1] - v1[1])) + + (relativelightorigin[1] - v0[1]) * ((v0[2] - v1[2]) * (v2[0] - v1[0]) - (v0[0] - v1[0]) * (v2[2] - v1[2])) + + (relativelightorigin[2] - v0[2]) * ((v0[0] - v1[0]) * (v2[1] - v1[1]) - (v0[1] - v1[1]) * (v2[0] - v1[0])) > 0; +#else + // readable version + { + float dir0[3], dir1[3], + + // calculate two mostly perpendicular edge directions VectorSubtract(v0, v1, dir0); VectorSubtract(v2, v1, dir1); + + // we have two edge directions, we can calculate a third vector from + // them, which is the direction of the surface normal (it's magnitude + // is not 1 however) CrossProduct(dir0, dir1, temp); - // we do not need to normalize the surface normal because both sides - // of the comparison use it, therefore they are both multiplied the - // same amount... + + // this is entirely unnecessary, but kept for clarity + //VectorNormalize(temp); + + // compare distance of light along normal, with distance of any point + // of the triangle along the same normal (the triangle is planar, + // 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); + } +#endif } // output triangle elements @@ -189,12 +222,12 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v } } -void R_Shadow_VertexLight(int numverts, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor) +void R_Shadow_VertexLight(int numverts, float *vertex, 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) + for (i = 0, v = vertex, c = varray_color, n = normals;i < numverts;i++, v += 4, c += 4, n += 3) { VectorSubtract(relativelightorigin, v, temp); c[0] = 0; diff --git a/r_shadow.h b/r_shadow.h index 470d96d7..cef3d81b 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -3,8 +3,8 @@ #define R_SHADOW_H void R_Shadow_Init(void); -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_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume); +void R_Shadow_VertexLight(int numverts, float *vertex, 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); -- 2.39.2