int scissor[4];
float depthrange[2];
float polygonoffset[2];
+ ALIGN(float clipplane[4]);
int shader_mode;
int shader_permutation;
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)
{
// " 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)
int numpoints;
int clipcase;
float clipdist[4];
+ float clip0origin, clip0slope;
+ int clip0dir;
__m128 triangleedge1, triangleedge2, trianglenormal;
__m128 clipfrac[3];
__m128 screen[4];
_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++)
{
int yccmask = _mm_movemask_epi8(ycc);
int edge0p, edge0n, edge1p, edge1n;
int nexty;
+ float clip0;
if (numpoints == 4)
{
switch(yccmask)
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)
}
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;
INTERPCOMMAND(UniformMatrix4f)
INTERPCOMMAND(Uniform1i)
INTERPCOMMAND(SetRenderTargets)
+ INTERPCOMMAND(ClipPlane)
case DPSOFTRAST_OPCODE_Draw:
DPSOFTRAST_Interpret_Draw(thread, (DPSOFTRAST_Command_Draw *)command);
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);
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);
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)
}
}
+ DPSOFTRAST_ClipPlane(0, 0, 0, 1);
r_waterstate.renderingscene = false;
r_refdef.view = originalview;
R_ResetViewRendering3D();