From: havoc Date: Thu, 30 Sep 2004 16:38:54 +0000 (+0000) Subject: sped up nexuiz rtlights benchmark by 4% by optimizing box cull on models to skip... X-Git-Tag: xonotic-v0.1.0preview~5545 X-Git-Url: http://de.git.xonotic.org/?a=commitdiff_plain;h=ebb137a0e6716b4f4818ae825480b44978854d4d;p=xonotic%2Fdarkplaces.git sped up nexuiz rtlights benchmark by 4% by optimizing box cull on models to skip triangle box cull when surface box is entirely inside light box restructured R_Shadow_ConstructShadowVolume loops a bit to make for less stalls, this seems to have only netted a 0.5% speed gain or so git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4566 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/gl_models.c b/gl_models.c index f2d8b3a7..c5f20054 100644 --- a/gl_models.c +++ b/gl_models.c @@ -190,11 +190,21 @@ void R_Model_Alias_Draw(entity_render_t *ent) void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius) { int meshnum; + vec3_t lightmins, lightmaxs; aliasmesh_t *mesh; aliasskin_t *skin; float projectdistance, *vertex3f; if (!(ent->flags & RENDER_SHADOW)) return; + lightmins[0] = relativelightorigin[0] - lightradius; + lightmins[1] = relativelightorigin[1] - lightradius; + lightmins[2] = relativelightorigin[2] - lightradius; + lightmaxs[0] = relativelightorigin[0] + lightradius; + lightmaxs[1] = relativelightorigin[1] + lightradius; + lightmaxs[2] = relativelightorigin[2] + lightradius; + // check the box in modelspace, it was already checked in worldspace + if (!BoxesOverlap(ent->model->normalmins, ent->model->normalmaxs, lightmins, lightmaxs)) + return; projectdistance = lightradius + ent->model->radius;// - sqrt(DotProduct(relativelightorigin, relativelightorigin)); if (projectdistance > 0.1) { @@ -211,7 +221,10 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor vertex3f = varray_vertex3f; Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, mesh, vertex3f); } - R_Shadow_VolumeFromSphere(mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, projectdistance, lightradius); + // identify lit faces within the bounding box + R_Shadow_PrepareShadowMark(mesh->num_triangles); + R_Shadow_MarkVolumeFromBox(0, mesh->num_triangles, vertex3f, mesh->data_element3i, relativelightorigin, lightmins, lightmaxs, ent->model->normalmins, ent->model->normalmaxs); + R_Shadow_VolumeFromList(mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist); } } } diff --git a/gl_rsurf.c b/gl_rsurf.c index 5c9bfd92..e055c6da 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1835,9 +1835,7 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, model_t *model = ent->model; vec3_t lightmins, lightmaxs; msurface_t *surface; - int surfacelistindex, j, t; - const int *e; - const float *v[3]; + int surfacelistindex; if (r_drawcollisionbrushes.integer < 2) { lightmins[0] = relativelightorigin[0] - lightradius; @@ -1851,14 +1849,7 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { surface = model->brushq1.surfaces + surfacelist[surfacelistindex]; - for (j = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < surface->mesh.num_triangles;j++, t++, e += 3) - { - v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; - v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; - v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; - if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = t; - } + R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->mesh.num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->poly_mins, surface->poly_maxs); } R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist); } @@ -2469,9 +2460,7 @@ void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, model_t *model = ent->model; vec3_t lightmins, lightmaxs; q3msurface_t *surface; - int surfacelistindex, j, t; - const int *e; - const float *v[3]; + int surfacelistindex; if (r_drawcollisionbrushes.integer < 2) { lightmins[0] = relativelightorigin[0] - lightradius; @@ -2486,17 +2475,8 @@ void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, { surface = model->brushq3.data_faces + surfacelist[surfacelistindex]; // FIXME: check some manner of face->rendermode here? - if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && surface->num_triangles && !surface->texture->skin.fog) - { - for (j = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < surface->num_triangles;j++, t++, e += 3) - { - v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3; - v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3; - v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3; - if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = t; - } - } + if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && surface->num_triangles && !(surface->texture->surfaceparms & Q3SURFACEPARM_TRANS)) + R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs); } R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist); } diff --git a/r_shadow.c b/r_shadow.c index 79023e78..4a9fadc7 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -525,11 +525,14 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int * memset(vertexremap, 0, maxvertexupdate * sizeof(int)); } + for (i = 0;i < numshadowmarktris;i++) + shadowmark[shadowmarktris[i]] = shadowmarkcount; + for (i = 0;i < numshadowmarktris;i++) { t = shadowmarktris[i]; - shadowmark[t] = shadowmarkcount; e = inelement3i + t * 3; + n = inneighbor3i + t * 3; // make sure the vertices are created for (j = 0;j < 3;j++) { @@ -554,13 +557,6 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int * outelement3i[5] = vertexremap[e[0]] + 1; outelement3i += 6; tris += 2; - } - - for (i = 0;i < numshadowmarktris;i++) - { - t = shadowmarktris[i]; - e = inelement3i + t * 3; - n = inneighbor3i + t * 3; // output the sides (facing outward from this triangle) if (shadowmark[n[0]] != shadowmarkcount) { @@ -624,39 +620,41 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, R_Shadow_RenderVolume(outverts, tris, varray_vertex3f2, shadowelements); } -void R_Shadow_VolumeFromBox(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, const vec3_t mins, const vec3_t maxs) +void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, vec3_t lightmins, vec3_t lightmaxs, vec3_t surfacemins, vec3_t surfacemaxs) { - int i; + int j, t, tend; + const int *e; const float *v[3]; - - // check which triangles are facing the , and then output - // triangle elements and vertices... by clever use of elements we - // can construct the whole shadow from the unprojected vertices and - // the projected vertices - - // identify lit faces within the bounding box - R_Shadow_PrepareShadowMark(numtris); - for (i = 0;i < numtris;i++) + if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs)) + return; + tend = firsttriangle + numtris; + if (surfacemins[0] >= lightmins[0] && surfacemaxs[0] <= lightmaxs[0] + && surfacemins[1] >= lightmins[1] && surfacemaxs[1] <= lightmaxs[1] + && surfacemins[2] >= lightmins[2] && surfacemaxs[2] <= lightmaxs[2]) { - v[0] = invertex3f + elements[i*3+0] * 3; - v[1] = invertex3f + elements[i*3+1] * 3; - v[2] = invertex3f + elements[i*3+2] * 3; - if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]) && maxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && mins[0] < max(v[0][0], max(v[1][0], v[2][0])) && maxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && mins[1] < max(v[0][1], max(v[1][1], v[2][1])) && maxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && mins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = i; + // surface box entirely inside light box, no box cull + for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3) + if (PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3)) + shadowmarklist[numshadowmark++] = t; + } + else + { + // surface box not entirely inside light box, cull each triangle + for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3) + { + v[0] = invertex3f + e[0] * 3; + v[1] = invertex3f + e[1] * 3; + v[2] = invertex3f + e[2] * 3; + if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]) + && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) + && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) + && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) + && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) + && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) + && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) + shadowmarklist[numshadowmark++] = t; + } } - R_Shadow_VolumeFromList(numverts, numtris, invertex3f, elements, neighbors, projectorigin, projectdistance, numshadowmark, shadowmarklist); -} - -void R_Shadow_VolumeFromSphere(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, float radius) -{ - vec3_t mins, maxs; - mins[0] = projectorigin[0] - radius; - mins[1] = projectorigin[1] - radius; - mins[2] = projectorigin[2] - radius; - maxs[0] = projectorigin[0] + radius; - maxs[1] = projectorigin[1] + radius; - maxs[2] = projectorigin[2] + radius; - R_Shadow_VolumeFromBox(numverts, numtris, invertex3f, elements, neighbors, projectorigin, projectdistance, mins, maxs); } void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *vertex3f, const int *element3i) diff --git a/r_shadow.h b/r_shadow.h index ea8601af..29fd65b8 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -33,8 +33,7 @@ extern mempool_t *r_shadow_mempool; void R_Shadow_Init(void); void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, int nummarktris, const int *marktris); -void R_Shadow_VolumeFromBox(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, const vec3_t mins, const vec3_t maxs); -void R_Shadow_VolumeFromSphere(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, float radius); +void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, vec3_t lightmins, vec3_t lightmaxs, vec3_t surfacemins, vec3_t surfacemaxs); #define LIGHTING_DIFFUSE 1 #define LIGHTING_SPECULAR 2 void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements, const float *vertices, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, const float *lightcolor, const matrix4x4_t *matrix_worldtolight, const matrix4x4_t *matrix_worldtoattenuationxyz, const matrix4x4_t *matrix_worldtoattenuationz, rtexture_t *basetexture, rtexture_t *bumptexture, rtexture_t *glosstexture, rtexture_t *lightcubemap, int lightingflags);