]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
initial support for user clipping plane in dpsoftrast
authoreihrul <eihrul@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 4 Apr 2011 14:31:32 +0000 (14:31 +0000)
committereihrul <eihrul@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 4 Apr 2011 14:31:32 +0000 (14:31 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11016 d7cf8633-e32d-0410-b094-e92efae38249

dpsoftrast.c
dpsoftrast.h
gl_backend.c
gl_rmain.c

index 70f3f3e4e974ded2f005eb4cf437bff94119d000..a784374e8773c55d8392d952875a2602a67ef024 100644 (file)
@@ -235,6 +235,7 @@ typedef ATOMIC(struct DPSOFTRAST_State_Thread_s
        int scissor[4];
        float depthrange[2];
        float polygonoffset[2];
+       ALIGN(float clipplane[4]);
 
        int shader_mode;
        int shader_permutation;
@@ -1435,6 +1436,25 @@ void DPSOFTRAST_Uniform1i(DPSOFTRAST_UNIFORM index, int i0)
        dpsoftrast.uniform1i[command->index] = i0;
 }
 
+DEFCOMMAND(24, ClipPlane, float clipplane[4];)
+static void DPSOFTRAST_Interpret_ClipPlane(DPSOFTRAST_State_Thread *thread, DPSOFTRAST_Command_ClipPlane *command)
+{
+       memcpy(thread->clipplane, command->clipplane, 4*sizeof(float));
+}
+void DPSOFTRAST_ClipPlane(float x, float y, float z, float w)
+{
+       DPSOFTRAST_Command_ClipPlane *command = DPSOFTRAST_ALLOCATECOMMAND(ClipPlane);
+       x /= dpsoftrast.fb_viewportscale[1];
+       y /= dpsoftrast.fb_viewportscale[2];
+       z /= dpsoftrast.fb_viewportscale[3];
+       w /= dpsoftrast.fb_viewportscale[0];
+       w -= dpsoftrast.fb_viewportcenter[1]*x + dpsoftrast.fb_viewportcenter[2]*y + dpsoftrast.fb_viewportcenter[3]*z + dpsoftrast.fb_viewportcenter[0]*w; 
+       command->clipplane[0] = x;
+       command->clipplane[1] = y;
+       command->clipplane[2] = z;
+       command->clipplane[3] = w;
+}
+
 #ifdef SSE_POSSIBLE
 static void DPSOFTRAST_Load4fTo4f(float *dst, const unsigned char *src, int size, int stride)
 {
@@ -4527,7 +4547,7 @@ void DPSOFTRAST_PixelShader_Refraction(DPSOFTRAST_State_Thread *thread, const DP
 
                // "    vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
                iw = 1.0f / (ModelViewProjectionPositiondata[3] + ModelViewProjectionPositionslope[3]*x); // / z
-        
+               
                // "    vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
                SafeScreenTexCoord[0] = (ModelViewProjectionPositiondata[0] + ModelViewProjectionPositionslope[0]*x) * iw * ScreenScaleRefractReflect[0] + ScreenCenterRefractReflect[0]; // * z (disappears)
                SafeScreenTexCoord[1] = (ModelViewProjectionPositiondata[1] + ModelViewProjectionPositionslope[1]*x) * iw * ScreenScaleRefractReflect[1] + ScreenCenterRefractReflect[1]; // * z (disappears)
@@ -4788,6 +4808,8 @@ static void DPSOFTRAST_Interpret_Draw(DPSOFTRAST_State_Thread *thread, DPSOFTRAS
        int numpoints;
        int clipcase;
        float clipdist[4];
+       float clip0origin, clip0slope;
+       int clip0dir;
        __m128 triangleedge1, triangleedge2, trianglenormal;
        __m128 clipfrac[3];
        __m128 screen[4];
@@ -5012,6 +5034,43 @@ static void DPSOFTRAST_Interpret_Draw(DPSOFTRAST_State_Thread *thread, DPSOFTRAS
                        _mm_store_ss(&triangle->w[0], attribxslope);
                        _mm_store_ss(&triangle->w[1], attribyslope);
                        _mm_store_ss(&triangle->w[2], attriborigin);
+                       
+                       clip0origin = 0;
+                       clip0slope = 0;
+                       clip0dir = 0;
+                       if(thread->clipplane[0] || thread->clipplane[1] || thread->clipplane[2])
+                       {
+                               float cliporigin, clipxslope, clipyslope;
+                               attriborigin = _mm_shuffle_ps(screen[1], screen[1], _MM_SHUFFLE(2, 2, 2, 2));
+                               attribedge1 = _mm_sub_ss(_mm_shuffle_ps(screen[0], screen[0], _MM_SHUFFLE(2, 2, 2, 2)), attriborigin);
+                               attribedge2 = _mm_sub_ss(_mm_shuffle_ps(screen[2], screen[2], _MM_SHUFFLE(2, 2, 2, 2)), attriborigin);
+                               attribxslope = _mm_sub_ss(_mm_mul_ss(attribuxslope, attribedge1), _mm_mul_ss(attribvxslope, attribedge2));
+                               attribyslope = _mm_sub_ss(_mm_mul_ss(attribvyslope, attribedge2), _mm_mul_ss(attribuyslope, attribedge1));
+                               attriborigin = _mm_sub_ss(attriborigin, _mm_add_ss(_mm_mul_ss(attribxslope, x1), _mm_mul_ss(attribyslope, y1)));
+                               cliporigin = _mm_cvtss_f32(attriborigin)*thread->clipplane[2] + thread->clipplane[3];
+                               clipxslope = thread->clipplane[0] + _mm_cvtss_f32(attribxslope)*thread->clipplane[2];
+                               clipyslope = thread->clipplane[1] + _mm_cvtss_f32(attribyslope)*thread->clipplane[2];
+                               if(clipxslope != 0)
+                               {
+                                       clip0origin = -cliporigin/clipxslope;
+                                       clip0slope = -clipyslope/clipxslope;
+                                       clip0dir = clipxslope > 0 ? 1 : -1;
+                               }
+                               else if(clipyslope > 0)
+                               {
+                                       clip0origin = dpsoftrast.fb_width*floor(cliporigin/clipyslope);
+                                       clip0slope = dpsoftrast.fb_width;
+                                       clip0dir = -1;
+                               }
+                               else if(clipyslope < 0)
+                               {
+                                       clip0origin = dpsoftrast.fb_width*ceil(cliporigin/clipyslope);
+                                       clip0slope = -dpsoftrast.fb_width;
+                                       clip0dir = -1;
+                               }
+                               else if(clip0origin < 0) continue;
+                       }
+
                        mipedgescale = _mm_setzero_ps();
                        for (j = 0;j < DPSOFTRAST_ARRAY_TOTAL; j++)
                        {
@@ -5073,6 +5132,7 @@ static void DPSOFTRAST_Interpret_Draw(DPSOFTRAST_State_Thread *thread, DPSOFTRAS
                        int yccmask = _mm_movemask_epi8(ycc);
                        int edge0p, edge0n, edge1p, edge1n;
                        int nexty;
+                       float clip0;
                        if (numpoints == 4)
                        {
                                switch(yccmask)
@@ -5126,9 +5186,10 @@ static void DPSOFTRAST_Interpret_Draw(DPSOFTRAST_State_Thread *thread, DPSOFTRAS
                                xcoords = _mm_shuffle_ps(xcoords, xcoords, _MM_SHUFFLE(1, 0, 3, 2));
                                xslope = _mm_shuffle_ps(xslope, xslope, _MM_SHUFFLE(1, 0, 3, 2));
                        }
-                       for(; y <= nexty; y++, xcoords = _mm_add_ps(xcoords, xslope))
+                       clip0 = clip0origin + (y+0.5f)*clip0slope;
+                       for(; y <= nexty; y++, xcoords = _mm_add_ps(xcoords, xslope), clip0 += clip0slope)
                        {
-                               int startx, endx, offset;
+                               int startx, endx, clipx = minx, offset;
                                startx = _mm_cvtss_si32(xcoords);
                                endx = _mm_cvtss_si32(_mm_movehl_ps(xcoords, xcoords));
                                if (startx < minx) 
@@ -5138,13 +5199,32 @@ static void DPSOFTRAST_Interpret_Draw(DPSOFTRAST_State_Thread *thread, DPSOFTRAS
                                }
                                if (endx > maxx) endx = maxx;
                                if (startx >= endx) continue;
+
+                               if (clip0dir)
+                               {
+                                       if (clip0dir > 0)
+                                       {
+                                               if (startx < clip0) 
+                                               {
+                                                       if(endx <= clip0) continue;
+                                                       clipx = max((int)clip0, minx);
+                                                       startx += (clipx-startx)&~(DPSOFTRAST_DRAW_MAXSPANLENGTH-1); 
+                                               }
+                                       }
+                                       else if (endx > clip0) 
+                                       {
+                                               if(startx >= clip0) continue;
+                                               endx = (int)clip0;
+                                       }
+                               }
+                                               
                                for (offset = startx; offset < endx;offset += DPSOFTRAST_DRAW_MAXSPANLENGTH)
                                {
                                        DPSOFTRAST_State_Span *span = &thread->spans[thread->numspans];
                                        span->triangle = thread->numtriangles;
                                        span->x = offset;
                                        span->y = y;
-                                       span->startx = max(minx - offset, 0);
+                                       span->startx = max(clipx - offset, 0);
                                        span->endx = min(endx - offset, DPSOFTRAST_DRAW_MAXSPANLENGTH);
                                        if (span->startx >= span->endx)
                                                continue; 
@@ -5334,6 +5414,7 @@ static void DPSOFTRAST_Draw_InterpretCommands(DPSOFTRAST_State_Thread *thread, i
                INTERPCOMMAND(UniformMatrix4f)
                INTERPCOMMAND(Uniform1i)
                INTERPCOMMAND(SetRenderTargets)
+               INTERPCOMMAND(ClipPlane)
 
                case DPSOFTRAST_OPCODE_Draw:
                        DPSOFTRAST_Interpret_Draw(thread, (DPSOFTRAST_Command_Draw *)command);
@@ -5496,6 +5577,10 @@ int DPSOFTRAST_Init(int width, int height, int numthreads, int interlace, unsign
                thread->depthrange[1] = 1;
                thread->polygonoffset[0] = 0;
                thread->polygonoffset[1] = 0;
+               thread->clipplane[0] = 0;
+               thread->clipplane[1] = 0;
+               thread->clipplane[2] = 0;
+               thread->clipplane[3] = 1;
        
                DPSOFTRAST_RecalcThread(thread);
        
index 8ebb98d6a11a7a8318503a6718c6a8d1e5331c2a..6b7a706710b34905d4458caa04c4f5efd2974637 100644 (file)
@@ -56,6 +56,7 @@ void DPSOFTRAST_ColorMask(int r, int g, int b, int a);
 void DPSOFTRAST_DepthTest(int enable);
 void DPSOFTRAST_ScissorTest(int enable);
 void DPSOFTRAST_Scissor(float x, float y, float width, float height);
+void DPSOFTRAST_ClipPlane(float x, float y, float z, float w);
 
 void DPSOFTRAST_BlendFunc(int smodulate, int dmodulate);
 void DPSOFTRAST_BlendSubtract(int enable);
index 7bc929e9b60d5864a8ffbd84759cb4f8c69db2d2..bb1d6b16abbaab385f2a4b104e7032b34ec5eb4c 100644 (file)
@@ -730,7 +730,7 @@ static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m
 
        VectorSet(normal, normalx, normaly, normalz);
        Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
-       VectorScale(normal, dist, v3);
+       VectorScale(normal, -dist, v3);
        Matrix4x4_Transform(&v->viewmatrix, v3, v4);
        // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
        clipPlane[3] = -DotProduct(v4, clipPlane);
index 4be0e918f9cf17e38e70b3a1b69e5c214666a675..7f998d21a7db8d087192f88cf27bf53144a91d7e 100644 (file)
@@ -5158,8 +5158,8 @@ void R_SetupView(qboolean allowwaterclippingplane)
                plane[0] = r_refdef.view.clipplane.normal[0];
                plane[1] = r_refdef.view.clipplane.normal[1];
                plane[2] = r_refdef.view.clipplane.normal[2];
-               plane[3] = dist;
-               customclipplane = plane;
+               plane[3] = -dist;
+               if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
        }
 
        R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
@@ -5171,6 +5171,16 @@ void R_SetupView(qboolean allowwaterclippingplane)
                R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
        R_Mesh_SetMainRenderTargets();
        R_SetViewport(&r_refdef.view.viewport);
+       if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
+       {
+               matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
+               float screenplane[4];
+               Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
+               Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
+               Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
+               Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
+               DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
+       }
 }
 
 void R_EntityMatrix(const matrix4x4_t *matrix)
@@ -5665,6 +5675,7 @@ static void R_Water_ProcessPlanes(void)
                }
 
        }
+       DPSOFTRAST_ClipPlane(0, 0, 0, 1);
        r_waterstate.renderingscene = false;
        r_refdef.view = originalview;
        R_ResetViewRendering3D();