r_water_scissormode: 0 = none, 1 = glScissor, 2 = glScissor and frustum culling
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 13 Oct 2010 16:08:13 +0000 (16:08 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 13 Oct 2010 16:08:13 +0000 (16:08 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10520 d7cf8633-e32d-0410-b094-e92efae38249

gl_backend.c
gl_backend.h
gl_rmain.c
r_shadow.c
render.h

index 78e0082..9423cc7 100644 (file)
@@ -524,6 +524,156 @@ void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t
        out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
 }
 
+static 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_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
+{
+       int i, ix1, iy1, ix2, iy2;
+       float x1, y1, x2, y2;
+       vec4_t v, v2;
+       float vertex[20][3];
+       int j, k;
+       vec4_t plane4f;
+       int numvertices;
+       float corner[8][4];
+       float dist[8];
+       int sign[8];
+       float f;
+
+       scissor[0] = r_refdef.view.viewport.x;
+       scissor[1] = r_refdef.view.viewport.y;
+       scissor[2] = r_refdef.view.viewport.width;
+       scissor[3] = r_refdef.view.viewport.height;
+
+       // if view is inside the box, just say yes it's visible
+       if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
+               return false;
+
+       x1 = y1 = x2 = y2 = 0;
+
+       // transform all corners that are infront of the nearclip plane
+       VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
+       plane4f[3] = r_refdef.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, it is behind the view plane
+       if (!numvertices)
+               return true;
+
+       // 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", numvertices);
+       for (i = 0;i < numvertices;i++)
+       {
+               VectorCopy(vertex[i], v);
+               R_Viewport_TransformToScreen(&r_refdef.view.viewport, 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)
+               {
+                       if (x1 > v2[0]) x1 = v2[0];
+                       if (x2 < v2[0]) x2 = v2[0];
+                       if (y1 > v2[1]) y1 = v2[1];
+                       if (y2 < v2[1]) y2 = v2[1];
+               }
+               else
+               {
+                       x1 = x2 = v2[0];
+                       y1 = y2 = v2[1];
+               }
+       }
+
+       // now convert the scissor rectangle to integer screen coordinates
+       ix1 = (int)(x1 - 1.0f);
+       //iy1 = vid.height - (int)(y2 - 1.0f);
+       //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
+       iy1 = (int)(y1 - 1.0f);
+       ix2 = (int)(x2 + 1.0f);
+       //iy2 = vid.height - (int)(y1 + 1.0f);
+       //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
+       iy2 = (int)(y2 + 1.0f);
+       //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
+
+       // clamp it to the screen
+       if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
+       if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
+       if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
+       if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
+
+       // if it is inside out, it's not visible
+       if (ix2 <= ix1 || iy2 <= iy1)
+               return true;
+
+       // the light area is visible, set up the scissor rectangle
+       scissor[0] = ix1;
+       scissor[1] = iy1;
+       scissor[2] = ix2 - ix1;
+       scissor[3] = iy2 - iy1;
+
+       // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
+       switch(vid.renderpath)
+       {
+       case RENDERPATH_D3D9:
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+               scissor[1] = vid.height - scissor[1] - scissor[3];
+               break;
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
+               break;
+       }
+
+       return false;
+}
+
+
 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
 {
        float q[4];
index aff9f40..596b4bf 100644 (file)
@@ -20,6 +20,7 @@ extern int quadelement3i[QUADELEMENTS_MAXQUADS*6];
 extern unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
 
 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out);
+qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor);
 void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float x1, float y1, float x2, float y2, float zNear, float zFar, const float *nearplane);
 void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float zNear, float zFar, const float *nearplane);
 void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float zNear, const float *nearplane);
index 8d60afd..7b251da 100644 (file)
@@ -154,6 +154,7 @@ cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1",
 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
+cvar_t r_water_scissormode = {CVAR_SAVE, "r_water_scissormode", "2", "scissor (1) and cull (2) water renders"};
 
 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
@@ -7285,6 +7286,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_water_clippingplanebias);
        Cvar_RegisterVariable(&r_water_refractdistort);
        Cvar_RegisterVariable(&r_water_reflectdistort);
+       Cvar_RegisterVariable(&r_water_scissormode);
        Cvar_RegisterVariable(&r_lerpsprites);
        Cvar_RegisterVariable(&r_lerpmodels);
        Cvar_RegisterVariable(&r_lerplightstyles);
@@ -8006,12 +8008,28 @@ static void R_DrawModelsAddWaterPlanes(void)
        }
 }
 
-static void R_View_SetFrustum(void)
+static void R_View_SetFrustum(const int *scissor)
 {
        int i;
-       double slopex, slopey;
+       double fpx, fnx, fpy, fny;
        vec3_t forward, left, up, origin;
 
+       if(scissor)
+       {
+               // flipped x coordinates (because x points left here)
+               fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
+               fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
+
+               // non-flipped y coordinates
+               fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
+               fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
+       }
+       else
+       {
+               fnx = fny = -1;
+               fpx = fpy = +1;
+       }
+
        // we can't trust r_refdef.view.forward and friends in reflected scenes
        Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
 
@@ -8079,13 +8097,17 @@ static void R_View_SetFrustum(void)
 
        if (r_refdef.view.useperspective)
        {
-               slopex = 1.0 / r_refdef.view.frustum_x;
-               slopey = 1.0 / r_refdef.view.frustum_y;
-               VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
-               VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
-               VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
-               VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
-               VectorCopy(forward, r_refdef.view.frustum[4].normal);
+               // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
+               VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
+               VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
+               VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
+               VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
+
+               // then the normals from the corners relative to origin
+               CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
+               CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
+               CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
+               CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
 
                // Leaving those out was a mistake, those were in the old code, and they
                // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
@@ -8095,11 +8117,14 @@ static void R_View_SetFrustum(void)
                VectorNormalize(r_refdef.view.frustum[2].normal);
                VectorNormalize(r_refdef.view.frustum[3].normal);
 
-               // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
-               VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
+               // make the corners absolute
+               VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
+               VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
+               VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
+               VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
+
+               // one more normal
+               VectorCopy(forward, r_refdef.view.frustum[4].normal);
 
                r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
                r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
@@ -8161,10 +8186,19 @@ static void R_View_SetFrustum(void)
        //PlaneClassify(&frustum[4]);
 }
 
+void R_View_UpdateWithScissor(const int *myscissor)
+{
+       R_Main_ResizeViewCache();
+       R_View_SetFrustum(myscissor);
+       R_View_WorldVisibility(r_refdef.view.useclipplane);
+       R_View_UpdateEntityVisible();
+       R_View_UpdateEntityLighting();
+}
+
 void R_View_Update(void)
 {
        R_Main_ResizeViewCache();
-       R_View_SetFrustum();
+       R_View_SetFrustum(NULL);
        R_View_WorldVisibility(r_refdef.view.useclipplane);
        R_View_UpdateEntityVisible();
        R_View_UpdateEntityLighting();
@@ -8479,6 +8513,18 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno)
                p->materialflags = 0;
                p->pvsvalid = false;
                p->camera_entity = t->camera_entity;
+               VectorCopy(surface->mins, p->mins);
+               VectorCopy(surface->maxs, p->maxs);
+       }
+       else
+       {
+               // merge mins/maxs
+               p->mins[0] = min(p->mins[0], surface->mins[0]);
+               p->mins[1] = min(p->mins[1], surface->mins[1]);
+               p->mins[2] = min(p->mins[2], surface->mins[2]);
+               p->maxs[0] = min(p->maxs[0], surface->maxs[0]);
+               p->maxs[1] = min(p->maxs[1], surface->maxs[1]);
+               p->maxs[2] = min(p->maxs[2], surface->maxs[2]);
        }
        // merge this surface's materialflags into the waterplane
        p->materialflags |= t->currentmaterialflags;
@@ -8497,6 +8543,7 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno)
 
 static void R_Water_ProcessPlanes(void)
 {
+       int myscissor[4];
        r_refdef_view_t originalview;
        r_refdef_view_t myview;
        int planeindex;
@@ -8545,11 +8592,19 @@ static void R_Water_ProcessPlanes(void)
                if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
                {
                        r_refdef.view = myview;
+                       if(r_water_scissormode.integer)
+                       {
+                               R_SetupView(true);
+                               if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
+                                       continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
+                       }
+
                        // render reflected scene and copy into texture
                        Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
                        // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
                        Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
                        r_refdef.view.clipplane = p->plane;
+
                        // reverse the cullface settings for this render
                        r_refdef.view.cullface_front = GL_FRONT;
                        r_refdef.view.cullface_back = GL_BACK;
@@ -8564,7 +8619,12 @@ static void R_Water_ProcessPlanes(void)
 
                        R_ResetViewRendering3D();
                        R_ClearScreen(r_refdef.fogenabled);
-                       R_View_Update();
+                       if(r_water_scissormode.integer >= 2)
+                               R_View_UpdateWithScissor(myscissor);
+                       else
+                               R_View_Update();
+                       if(r_water_scissormode.integer)
+                               GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
                        R_RenderScene();
 
                        R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
@@ -8574,8 +8634,15 @@ static void R_Water_ProcessPlanes(void)
                // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
                if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
                {
-                       r_waterstate.renderingrefraction = true;
                        r_refdef.view = myview;
+                       if(r_water_scissormode.integer)
+                       {
+                               R_SetupView(true);
+                               if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
+                                       continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
+                       }
+
+                       r_waterstate.renderingrefraction = true;
 
                        r_refdef.view.clipplane = p->plane;
                        VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
@@ -8598,7 +8665,12 @@ static void R_Water_ProcessPlanes(void)
 
                        R_ResetViewRendering3D();
                        R_ClearScreen(r_refdef.fogenabled);
-                       R_View_Update();
+                       if(r_water_scissormode.integer >= 2)
+                               R_View_UpdateWithScissor(myscissor);
+                       else
+                               R_View_Update();
+                       if(r_water_scissormode.integer)
+                               GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
                        R_RenderScene();
 
                        R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
@@ -8623,6 +8695,9 @@ static void R_Water_ProcessPlanes(void)
                                CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
                        }
 
+                       // note: all of the view is used for displaying... so
+                       // there is no use in scissoring
+
                        // reverse the cullface settings for this render
                        r_refdef.view.cullface_front = GL_FRONT;
                        r_refdef.view.cullface_back = GL_BACK;
@@ -9472,6 +9547,7 @@ void R_RenderView(void)
 
        GL_Scissor(0, 0, vid.width, vid.height);
        GL_ScissorTest(false);
+
        CHECKGLERROR
 }
 
@@ -9723,6 +9799,27 @@ void R_RenderScene(void)
                        R_TimeReport("coronas");
        }
 
+#if 0
+       {
+               GL_DepthTest(false);
+               qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+               GL_Color(1, 1, 1, 1);
+               qglBegin(GL_POLYGON);
+               qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
+               qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
+               qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
+               qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
+               qglEnd();
+               qglBegin(GL_POLYGON);
+               qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
+               qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
+               qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
+               qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
+               qglEnd();
+               qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+       }
+#endif
+
        // don't let sound skip if going slow
        if (r_refdef.scene.extraupdate)
                S_ExtraUpdate ();
index bceb235..fe060e0 100644 (file)
@@ -2265,157 +2265,28 @@ 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;
-       float vertex[20][3];
-       int j, k;
-       vec4_t plane4f;
-       int numvertices;
-       float corner[8][4];
-       float dist[8];
-       int sign[8];
-       float f;
-
-       r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
-       r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
-       r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
-       r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
-
        if (!r_shadow_scissor.integer)
-               return false;
-
-       // if view is inside the light box, just say yes it's visible
-       if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
-               return false;
-
-       x1 = y1 = x2 = y2 = 0;
-
-       // transform all corners that are infront of the nearclip plane
-       VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
-       plane4f[3] = r_refdef.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 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", numvertices);
-       for (i = 0;i < numvertices;i++)
-       {
-               VectorCopy(vertex[i], v);
-               R_Viewport_TransformToScreen(&r_refdef.view.viewport, 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)
-               {
-                       if (x1 > v2[0]) x1 = v2[0];
-                       if (x2 < v2[0]) x2 = v2[0];
-                       if (y1 > v2[1]) y1 = v2[1];
-                       if (y2 < v2[1]) y2 = v2[1];
-               }
-               else
-               {
-                       x1 = x2 = v2[0];
-                       y1 = y2 = v2[1];
-               }
+               r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
+               r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
+               r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
+               r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
+               return false;
        }
 
-       // now convert the scissor rectangle to integer screen coordinates
-       ix1 = (int)(x1 - 1.0f);
-       //iy1 = vid.height - (int)(y2 - 1.0f);
-       //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
-       iy1 = (int)(y1 - 1.0f);
-       ix2 = (int)(x2 + 1.0f);
-       //iy2 = vid.height - (int)(y1 + 1.0f);
-       //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
-       iy2 = (int)(y2 + 1.0f);
-       //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
-
-       // clamp it to the screen
-       if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
-       if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
-       if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
-       if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
-
-       // if it is inside out, it's not visible
-       if (ix2 <= ix1 || iy2 <= iy1)
-               return true;
-
-       // the light area is visible, set up the scissor rectangle
-       r_shadow_lightscissor[0] = ix1;
-       r_shadow_lightscissor[1] = iy1;
-       r_shadow_lightscissor[2] = ix2 - ix1;
-       r_shadow_lightscissor[3] = iy2 - iy1;
-
-       // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
-       switch(vid.renderpath)
+       if(R_ScissorForBBox(mins, maxs, r_shadow_lightscissor))
        {
-       case RENDERPATH_D3D9:
-       case RENDERPATH_D3D10:
-       case RENDERPATH_D3D11:
-               r_shadow_lightscissor[1] = vid.height - r_shadow_lightscissor[1] - r_shadow_lightscissor[3];
-               break;
-       case RENDERPATH_GL11:
-       case RENDERPATH_GL13:
-       case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
-               break;
+               if(r_shadow_lightscissor[0] != r_refdef.view.viewport.x
+               || r_shadow_lightscissor[1] != r_refdef.view.viewport.y
+               || r_shadow_lightscissor[2] != r_refdef.view.viewport.width
+               || r_shadow_lightscissor[3] != r_refdef.view.viewport.height)
+                       r_refdef.stats.lights_scissored++;
+               return false;
        }
-
-       r_refdef.stats.lights_scissored++;
-       return false;
+       else
+               return true; // invisible
 }
 
 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, const float *diffusecolor, const float *ambientcolor)
index 7a5f846..6115f5b 100644 (file)
--- a/render.h
+++ b/render.h
@@ -531,6 +531,7 @@ typedef struct r_waterstate_waterplane_s
        unsigned char pvsbits[(MAX_MAP_LEAFS+7)>>3]; // FIXME: buffer overflow on huge maps
        qboolean pvsvalid;
        int camera_entity;
+       vec3_t mins, maxs;
 }
 r_waterstate_waterplane_t;