From: havoc Date: Mon, 17 Dec 2007 06:24:19 +0000 (+0000) Subject: redesigned box clipping code in R_Shadow_ScissorForBBox, now clips edges X-Git-Tag: xonotic-v0.1.0preview~2679 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=d9ccb9ee0da7badb6844ef189084e0dd3af2bc5a;p=xonotic%2Fdarkplaces.git redesigned box clipping code in R_Shadow_ScissorForBBox, now clips edges against the nearplane rather than doing brush building (too slow) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7812 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/r_shadow.c b/r_shadow.c index c520ac57..ebcb4601 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -1193,14 +1193,41 @@ void R_Shadow_RenderMode_End(void) r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE; } +int bboxedges[12][2] = +{ + // top + {0, 1}, // +X + {0, 2}, // +Y + {1, 3}, // Y, +X + {2, 3}, // X, +Y + // bottom + {4, 5}, // +X + {4, 6}, // +Y + {5, 7}, // Y, +X + {6, 7}, // X, +Y + // verticals + {0, 4}, // +Z + {1, 5}, // X, +Z + {2, 6}, // Y, +Z + {3, 7}, // XY, +Z +}; + qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) { int i, ix1, iy1, ix2, iy2; float x1, y1, x2, y2; vec4_t v, v2; - rmesh_t mesh; - mplane_t planes[11]; - float vertex3f[256*3]; + float vertex[20][3]; + int j, k; + vec4_t plane4f; + int numvertices; + float corner[8][4]; + float dist[8]; + int sign[8]; + float f; + + if (!r_shadow_scissor.integer) + return false; // if view is inside the light box, just say yes it's visible if (BoxesOverlap(r_view.origin, r_view.origin, mins, maxs)) @@ -1209,40 +1236,52 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) return false; } - // create a temporary brush describing the area the light can affect in worldspace - VectorNegate(r_view.frustum[0].normal, planes[ 0].normal);planes[ 0].dist = -r_view.frustum[0].dist; - VectorNegate(r_view.frustum[1].normal, planes[ 1].normal);planes[ 1].dist = -r_view.frustum[1].dist; - VectorNegate(r_view.frustum[2].normal, planes[ 2].normal);planes[ 2].dist = -r_view.frustum[2].dist; - VectorNegate(r_view.frustum[3].normal, planes[ 3].normal);planes[ 3].dist = -r_view.frustum[3].dist; - VectorNegate(r_view.frustum[4].normal, planes[ 4].normal);planes[ 4].dist = -r_view.frustum[4].dist; - VectorSet (planes[ 5].normal, 1, 0, 0); planes[ 5].dist = maxs[0]; - VectorSet (planes[ 6].normal, -1, 0, 0); planes[ 6].dist = -mins[0]; - VectorSet (planes[ 7].normal, 0, 1, 0); planes[ 7].dist = maxs[1]; - VectorSet (planes[ 8].normal, 0, -1, 0); planes[ 8].dist = -mins[1]; - VectorSet (planes[ 9].normal, 0, 0, 1); planes[ 9].dist = maxs[2]; - VectorSet (planes[10].normal, 0, 0, -1); planes[10].dist = -mins[2]; - - // turn the brush into a mesh - memset(&mesh, 0, sizeof(rmesh_t)); - mesh.maxvertices = 256; - mesh.vertex3f = vertex3f; - mesh.epsilon2 = (1.0f / (32.0f * 32.0f)); - R_Mesh_AddBrushMeshFromPlanes(&mesh, 11, planes); - - // if that mesh is empty, the light is not visible at all - if (!mesh.numvertices) - return true; + x1 = y1 = x2 = y2 = 0; - if (!r_shadow_scissor.integer) - return false; + // transform all corners that are infront of the nearclip plane + VectorNegate(r_view.frustum[4].normal, plane4f); + plane4f[3] = r_view.frustum[4].dist; + numvertices = 0; + for (i = 0;i < 8;i++) + { + Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1); + dist[i] = DotProduct4(corner[i], plane4f); + sign[i] = dist[i] > 0; + if (!sign[i]) + { + VectorCopy(corner[i], vertex[numvertices]); + numvertices++; + } + } + // if some points are behind the nearclip, add clipped edge points to make + // sure that the scissor boundary is complete + if (numvertices > 0 && numvertices < 8) + { + // add clipped edge points + for (i = 0;i < 12;i++) + { + j = bboxedges[i][0]; + k = bboxedges[i][1]; + if (sign[j] != sign[k]) + { + f = dist[j] / (dist[j] - dist[k]); + VectorLerp(corner[j], f, corner[k], vertex[numvertices]); + numvertices++; + } + } + } + + // if we have no points to check, the light is behind the view plane + if (!numvertices) + return true; - // if that mesh is not empty, check what area of the screen it covers + // if we have some points to transform, check what screen area is covered x1 = y1 = x2 = y2 = 0; v[3] = 1.0f; - //Con_Printf("%i vertices to transform...\n", mesh.numvertices); - for (i = 0;i < mesh.numvertices;i++) + //Con_Printf("%i vertices to transform...\n", numvertices); + for (i = 0;i < numvertices;i++) { - VectorCopy(mesh.vertex3f + i * 3, v); + VectorCopy(vertex[i], v); GL_TransformToScreen(v, v2); //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); if (i)