mirror of
https://github.com/simple64/simple64.git
synced 2026-11-11 21:18:42 +01:00
update gliden64
This commit is contained in:
1 parent
2119ce5ae9
commit
ecfa52cb06
19 files changed
+809
-228
No files matched your search
@@ -46,6 +46,7 @@ void Config::resetToDefaults()
|
||||
generalEmulation.rdramImageDitheringMode = BufferDitheringMode::bdmBlueNoise;
|
||||
generalEmulation.enableHWLighting = 0;
|
||||
generalEmulation.enableCoverage = 0;
|
||||
generalEmulation.enableClipping = 1;
|
||||
generalEmulation.enableCustomSettings = 1;
|
||||
generalEmulation.enableShadersStorage = 1;
|
||||
generalEmulation.enableLegacyBlending = 0;
|
||||
|
||||
@@ -63,6 +63,7 @@ struct Config
|
||||
u32 enableLOD;
|
||||
u32 enableHWLighting;
|
||||
u32 enableCoverage;
|
||||
u32 enableClipping;
|
||||
u32 enableCustomSettings;
|
||||
u32 enableShadersStorage;
|
||||
u32 enableLegacyBlending;
|
||||
|
||||
@@ -24,34 +24,11 @@
|
||||
//****************************************************************
|
||||
|
||||
|
||||
#include <gSP.h>
|
||||
#include <assert.h>
|
||||
#include "gSP.h"
|
||||
#include "Combiner.h"
|
||||
#include "ClipPolygon.h"
|
||||
|
||||
float LeftClip = 0.0f;
|
||||
float RightClip = 320.0f;
|
||||
float TopClip = 240.0f;
|
||||
float BotClip = 0.0f;
|
||||
|
||||
inline int cliptestx(vertexclip * v)
|
||||
{
|
||||
int bits = 0;
|
||||
if(v->y < LeftClip)
|
||||
bits |= LEFT;
|
||||
if(v->y > RightClip)
|
||||
bits |= RIGHT;
|
||||
return bits;
|
||||
}
|
||||
|
||||
inline int cliptesty(vertexclip * v)
|
||||
{
|
||||
int bits = 0;
|
||||
if(v->y < BotClip)
|
||||
bits |= BOT;
|
||||
if(v->y > TopClip)
|
||||
bits |= TOP;
|
||||
return bits;
|
||||
}
|
||||
|
||||
/*
|
||||
* vbp is a pointer to a vertex array. The first 3 vertices in that
|
||||
* array is our source vertices. The rest of the array will be used
|
||||
@@ -61,46 +38,75 @@ inline int cliptesty(vertexclip * v)
|
||||
*
|
||||
* function returns the number of vertices in the resulting polygon
|
||||
*/
|
||||
|
||||
int ClipPolygon(vertexclip *** final, vertexclip * vbp, int numVertices)
|
||||
unsigned int clipInScreenSpace(vertexclip *** final, vertexclip * vbp, unsigned int numVertices)
|
||||
{
|
||||
LeftClip = gSP.viewport.x;
|
||||
RightClip = LeftClip + gSP.viewport.width;
|
||||
BotClip = gSP.viewport.y;
|
||||
TopClip = BotClip + gSP.viewport.height;
|
||||
int max, n, dsti;
|
||||
const float LeftClip = gSP.viewport.x;
|
||||
const float RightClip = LeftClip + gSP.viewport.width;
|
||||
const float BotClip = gSP.viewport.y;
|
||||
const float TopClip = BotClip + gSP.viewport.height;
|
||||
graphics::CombinerProgram * pCurrCmb = currentCombiner();
|
||||
const bool clipColor = pCurrCmb->usesShade();
|
||||
const bool clipTexCoords = pCurrCmb->usesTexture();
|
||||
|
||||
auto cliptestx = [LeftClip, RightClip](vertexclip * v)
|
||||
{
|
||||
int bits = 0;
|
||||
if (v->y < LeftClip)
|
||||
bits |= LEFT;
|
||||
if (v->y > RightClip)
|
||||
bits |= RIGHT;
|
||||
return bits;
|
||||
};
|
||||
|
||||
auto cliptesty = [BotClip, TopClip](vertexclip * v)
|
||||
{
|
||||
int bits = 0;
|
||||
if (v->y < BotClip)
|
||||
bits |= BOT;
|
||||
if (v->y > TopClip)
|
||||
bits |= TOP;
|
||||
return bits;
|
||||
};
|
||||
|
||||
auto clipVertex = [clipColor, clipTexCoords](vertexclip const* src1, vertexclip const* src2, vertexclip * dst, float a)
|
||||
{
|
||||
float ima = 1.0f - a;
|
||||
#define doClip(V) dst->V = src1->V*ima + src2->V*a
|
||||
doClip(x);
|
||||
doClip(y);
|
||||
doClip(z);
|
||||
#undef doClip
|
||||
};
|
||||
|
||||
static vertexclip * vp1[12], * vp2[12]; // vertex ptr buffers
|
||||
vertexclip ** src = vp1;
|
||||
vertexclip ** dst = vp2;
|
||||
vertexclip ** tmp;
|
||||
|
||||
for (n = 0; n < numVertices; n++)
|
||||
for (unsigned int n = 0; n < numVertices; n++)
|
||||
vp1[n] = vbp + n;
|
||||
vp1[n] = vbp + 0;
|
||||
vp1[numVertices] = vbp + 0;
|
||||
|
||||
vbp += numVertices; // Next free vertex
|
||||
|
||||
dsti = 0;
|
||||
max = numVertices;
|
||||
unsigned int dsti = 0;
|
||||
unsigned int max = numVertices;
|
||||
|
||||
// right clip
|
||||
|
||||
for (n = 0; n < max; n++) {
|
||||
for (unsigned int n = 0; n < max; n++) {
|
||||
vertexclip * src1 = src[n]; // current vertex
|
||||
vertexclip * src2 = src[n + 1]; // next vertex
|
||||
if ((src1->visible & RIGHT) == VISIBLE) {
|
||||
dst[dsti++] = src1; // add visible vertex to list
|
||||
if ((src2->visible & RIGHT) == VISIBLE)
|
||||
if ((src1->clip & RIGHT) == VISIBLE) {
|
||||
dst[dsti++] = src1; // add clip vertex to list
|
||||
if ((src2->clip & RIGHT) == VISIBLE)
|
||||
continue;
|
||||
} else if ((src2->visible & RIGHT) != VISIBLE)
|
||||
} else if ((src2->clip & RIGHT) != VISIBLE)
|
||||
continue;
|
||||
float a = (RightClip - src1->x) / (src2->x - src1->x);
|
||||
float ima = 1.0f - a;
|
||||
dst[dsti] = vbp++; // create new vertex
|
||||
dst[dsti]->y = src1->y*ima + src2->y*a;
|
||||
clipVertex(src1, src2, dst[dsti], a);
|
||||
dst[dsti]->x = RightClip;
|
||||
dst[dsti]->z = src1->z*ima + src2->z*a;
|
||||
dst[dsti]->visible = cliptesty(dst[dsti]);
|
||||
dst[dsti]->clip = cliptesty(dst[dsti]);
|
||||
dsti++;
|
||||
}
|
||||
dst[dsti] = dst[0];
|
||||
@@ -109,23 +115,20 @@ int ClipPolygon(vertexclip *** final, vertexclip * vbp, int numVertices)
|
||||
dsti = 0;
|
||||
|
||||
// left clip
|
||||
|
||||
for(n = 0; n < max; n++) {
|
||||
for(unsigned int n = 0; n < max; n++) {
|
||||
vertexclip * src1 = src[n]; // current vertex
|
||||
vertexclip * src2 = src[n+1]; // next vertex
|
||||
if((src1->visible & LEFT) == VISIBLE) {
|
||||
dst[dsti++] = src1; // add visible vertex to list
|
||||
if((src2->visible & LEFT) == VISIBLE)
|
||||
if((src1->clip & LEFT) == VISIBLE) {
|
||||
dst[dsti++] = src1; // add clip vertex to list
|
||||
if((src2->clip & LEFT) == VISIBLE)
|
||||
continue;
|
||||
} else if((src2->visible & LEFT) != VISIBLE)
|
||||
} else if((src2->clip & LEFT) != VISIBLE)
|
||||
continue;
|
||||
float a = (LeftClip - src1->x) / (src2->x - src1->x);
|
||||
float ima = 1.0f - a;
|
||||
dst[dsti] = vbp++; // create new vertex
|
||||
dst[dsti]->y = src1->y*ima + src2->y*a;
|
||||
clipVertex(src1, src2, dst[dsti], a);
|
||||
dst[dsti]->x = LeftClip;
|
||||
dst[dsti]->z = src1->z*ima + src2->z*a;
|
||||
dst[dsti]->visible = cliptesty(dst[dsti]);
|
||||
dst[dsti]->clip = cliptesty(dst[dsti]);
|
||||
dsti++;
|
||||
}
|
||||
dst[dsti] = dst[0];
|
||||
@@ -134,23 +137,20 @@ int ClipPolygon(vertexclip *** final, vertexclip * vbp, int numVertices)
|
||||
dsti = 0;
|
||||
|
||||
// top clip
|
||||
|
||||
for(n = 0; n < max; n++) {
|
||||
for(unsigned int n = 0; n < max; n++) {
|
||||
vertexclip * src1 = src[n]; // current vertex
|
||||
vertexclip * src2 = src[n+1]; // next vertex
|
||||
if((src1->visible & TOP) == VISIBLE) {
|
||||
dst[dsti++] = src1; // add visible vertex to list
|
||||
if((src2->visible & TOP) == VISIBLE)
|
||||
if((src1->clip & TOP) == VISIBLE) {
|
||||
dst[dsti++] = src1; // add clip vertex to list
|
||||
if((src2->clip & TOP) == VISIBLE)
|
||||
continue;
|
||||
} else if((src2->visible & TOP) != VISIBLE)
|
||||
} else if((src2->clip & TOP) != VISIBLE)
|
||||
continue;
|
||||
float a = (TopClip - src1->y) / (src2->y - src1->y);
|
||||
float ima = 1.0f - a;
|
||||
dst[dsti] = vbp++; // create new vertex
|
||||
dst[dsti]->x = src1->x*ima + src2->x*a;
|
||||
clipVertex(src1, src2, dst[dsti], a);
|
||||
dst[dsti]->y = TopClip;
|
||||
dst[dsti]->z = src1->z*ima + src2->z*a;
|
||||
dst[dsti]->visible = cliptestx(dst[dsti]);
|
||||
dst[dsti]->clip = cliptestx(dst[dsti]);
|
||||
dsti++;
|
||||
}
|
||||
dst[dsti] = dst[0];
|
||||
@@ -159,22 +159,19 @@ int ClipPolygon(vertexclip *** final, vertexclip * vbp, int numVertices)
|
||||
dsti = 0;
|
||||
|
||||
// bot clip
|
||||
|
||||
for(n = 0; n < max; n++) {
|
||||
for(unsigned int n = 0; n < max; n++) {
|
||||
vertexclip * src1 = src[n]; // current vertex
|
||||
vertexclip * src2 = src[n+1]; // next vertex
|
||||
if((src1->visible & BOT) == VISIBLE) {
|
||||
dst[dsti++] = src1; // add visible vertex to list
|
||||
if((src2->visible & BOT) == VISIBLE)
|
||||
if((src1->clip & BOT) == VISIBLE) {
|
||||
dst[dsti++] = src1; // add clip vertex to list
|
||||
if((src2->clip & BOT) == VISIBLE)
|
||||
continue;
|
||||
} else if((src2->visible & BOT) != VISIBLE)
|
||||
} else if((src2->clip & BOT) != VISIBLE)
|
||||
continue;
|
||||
float a = (BotClip - src1->y) / (src2->y - src1->y);
|
||||
float ima = 1.0f - a;
|
||||
dst[dsti] = vbp++; // create new vertex
|
||||
dst[dsti]->x = src1->x*ima + src2->x*a;
|
||||
clipVertex(src1, src2, dst[dsti], a);
|
||||
dst[dsti]->y = BotClip;
|
||||
dst[dsti]->z = src1->z*ima + src2->z*a;
|
||||
dsti++;
|
||||
}
|
||||
|
||||
@@ -182,3 +179,326 @@ int ClipPolygon(vertexclip *** final, vertexclip * vbp, int numVertices)
|
||||
|
||||
return dsti;
|
||||
}
|
||||
|
||||
unsigned int clipW(const SPVertex ** _vsrc, SPVertex * _vdst)
|
||||
{
|
||||
graphics::CombinerProgram * pCurrCmb = currentCombiner();
|
||||
const bool clipColor = pCurrCmb->usesShade();
|
||||
const bool clipTexCoords = pCurrCmb->usesTexture();
|
||||
|
||||
auto copyVertex = [](SPVertex & _dst, const SPVertex * _src)
|
||||
{
|
||||
_dst.x = _src->x;
|
||||
_dst.y = _src->y;
|
||||
_dst.z = _src->z;
|
||||
_dst.w = _src->w;
|
||||
_dst.modify = _src->modify;
|
||||
};
|
||||
|
||||
unsigned int dsti = 0;
|
||||
for (int n = 0; n < 3; ++n) {
|
||||
const SPVertex * src1 = _vsrc[n]; // current vertex
|
||||
const SPVertex * src2 = _vsrc[n + 1]; // next vertex
|
||||
if (src1->w >= 0.01f) {
|
||||
copyVertex(_vdst[dsti++], src1); // add visible vertex to list
|
||||
if (src2->w >= 0.01f)
|
||||
continue;
|
||||
} else if (src2->w < 0.01f)
|
||||
continue;
|
||||
float a = (-src1->w) / (src2->w - src1->w);
|
||||
float ima = 1.0f - a;
|
||||
// create new vertex
|
||||
_vdst[dsti].x = src1->x*ima + src2->x*a;
|
||||
_vdst[dsti].y = src1->y*ima + src2->y*a;
|
||||
_vdst[dsti].z = src1->z*ima + src2->z*a;
|
||||
_vdst[dsti].w = 0.01f;
|
||||
_vdst[dsti].modify = 0;
|
||||
dsti++;
|
||||
}
|
||||
return dsti;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// clipping using homogeneous coordinates
|
||||
// http://www.3dcpptutorials.sk/
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// c equals the x or y or z coordinate of a fragment
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// a fragment of an edge is in front of or lies on a negative clip plane: - w <= c
|
||||
//
|
||||
// a fragment of an edge is behind a negative clip plane: - w > c
|
||||
//
|
||||
// to find the intersection of an edge with a negative clip plane we need to find t for which: - w = c
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// w = w1 + (w2 - w1) * t
|
||||
// c = c1 + (c2 - c1) * t
|
||||
//
|
||||
// - w = c
|
||||
//
|
||||
// - (w1 + (w2 - w1) * t) = c1 + (c2 - c1) * t
|
||||
// - w1 - (w2 - w1) * t = c1 + (c2 - c1) * t
|
||||
// - (w2 - w1) * t = c1 + w1 + (c2 - c1) * t
|
||||
// - (c2 - c1) * t - (w2 - w1) * t = c1 + w1
|
||||
// (c2 - c1) * t + (w2 - w1) * t = - c1 - w1
|
||||
// (c2 - c1 + w2 - w1) * t = - c1 - w1
|
||||
// t = (- c1 - w1) / (c2 - c1 + w2 - w1)
|
||||
// t = (c1 + w1) / (- c2 + c1 - w2 + w1)
|
||||
// t = (c1 + w1) / (c1 - c2 + w1 - w2)
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// a fragment of an edge is in front of or lies on a positive clip plane: c <= w
|
||||
//
|
||||
// a fragment of an edge is behind a positive clip plane: c > w
|
||||
//
|
||||
// to find the intersection of an edge with a positive clip plane we need to find t for which: c = w
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// c = c1 + (c2 - c1) * t
|
||||
// w = w1 + (w2 - w1) * t
|
||||
//
|
||||
// c = w
|
||||
//
|
||||
// c1 + (c2 - c1) * t = w1 + (w2 - w1) * t
|
||||
// (c2 - c1) * t = w1 - c1 + (w2 - w1) * t
|
||||
// (c2 - c1) * t - (w2 - w1) * t = w1 - c1
|
||||
// ((c2 - c1) - (w2 - w1)) * t = w1 - c1
|
||||
// (c2 - c1 - w2 + w1) * t = w1 - c1
|
||||
// t = (w1 - c1) / (c2 - c1 - w2 + w1)
|
||||
// t = (- w1 + c1) / (- c2 + c1 + w2 - w1)
|
||||
// t = (c1 - w1) / (c1 - c2 - w1 + w2)
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
void clipInHomogeneousSpace(SPVertex * _pVertices, std::vector<SPVertex> & _vResult, int _clipPlane)
|
||||
{
|
||||
if (_clipPlane == 5 && GBI.isNoN()) {
|
||||
// Skip near plane clipping
|
||||
clipInHomogeneousSpace(_pVertices, _vResult, _clipPlane + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
graphics::CombinerProgram * pCurrCmb = currentCombiner();
|
||||
const bool usesColor = pCurrCmb->usesShade();
|
||||
const bool usesTexture = pCurrCmb->usesTexture();
|
||||
const float wScale = static_cast<float>(gSP.clipRatio);
|
||||
|
||||
auto clipVertex = [usesColor, usesTexture](SPVertex const* src, SPVertex * dst, float t)
|
||||
{
|
||||
#define doClip(V) dst->V += (src->V - dst->V) * t
|
||||
doClip(x);
|
||||
doClip(y);
|
||||
doClip(z);
|
||||
doClip(w);
|
||||
doClip(bc0);
|
||||
doClip(bc1);
|
||||
if (usesColor)
|
||||
{
|
||||
doClip(r);
|
||||
doClip(g);
|
||||
doClip(b);
|
||||
doClip(a);
|
||||
doClip(flat_r);
|
||||
doClip(flat_g);
|
||||
doClip(flat_b);
|
||||
doClip(flat_a);
|
||||
}
|
||||
if (usesTexture)
|
||||
{
|
||||
doClip(s);
|
||||
doClip(t);
|
||||
}
|
||||
dst->modify = src->modify & (MODIFY_ST | MODIFY_RGBA);
|
||||
dst->HWLight = src->HWLight;
|
||||
#undef doClip
|
||||
};
|
||||
|
||||
auto copyVertex = [usesColor, usesTexture](SPVertex const* src, SPVertex * dst)
|
||||
{
|
||||
#define doCopy(V) dst->V = src->V
|
||||
doCopy(x);
|
||||
doCopy(y);
|
||||
doCopy(z);
|
||||
doCopy(w);
|
||||
doCopy(bc0);
|
||||
doCopy(bc1);
|
||||
doCopy(a);
|
||||
doCopy(flat_a);
|
||||
if (usesColor)
|
||||
{
|
||||
doCopy(r);
|
||||
doCopy(g);
|
||||
doCopy(b);
|
||||
doCopy(flat_r);
|
||||
doCopy(flat_g);
|
||||
doCopy(flat_b);
|
||||
}
|
||||
if (usesTexture)
|
||||
{
|
||||
doCopy(s);
|
||||
doCopy(t);
|
||||
}
|
||||
doCopy(HWLight);
|
||||
dst->modify = src->modify & (MODIFY_ST | MODIFY_RGBA);
|
||||
#undef doCopy
|
||||
};
|
||||
|
||||
|
||||
if (_clipPlane >= 1 && _clipPlane <= 6) {
|
||||
unsigned int fifocp, fbcp, fbcpc = 0; // fragment in front of clip plane, fragment behind clip plane, fragments behind clip plane count
|
||||
|
||||
// visibility testing
|
||||
|
||||
SPVertex *pVertex = _pVertices;
|
||||
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
bool visible;
|
||||
|
||||
switch (_clipPlane) {
|
||||
case 1:
|
||||
visible = -pVertex->w * wScale <= pVertex->x;
|
||||
break;
|
||||
case 2:
|
||||
visible = pVertex->x <= pVertex->w * wScale;
|
||||
break;
|
||||
case 3:
|
||||
visible = -pVertex->w * wScale <= pVertex->y;
|
||||
break;
|
||||
case 4:
|
||||
visible = pVertex->y <= pVertex->w * wScale;
|
||||
break;
|
||||
case 5:
|
||||
visible = -pVertex->w * wScale <= pVertex->z;
|
||||
break;
|
||||
case 6:
|
||||
visible = pVertex->z <= pVertex->w * wScale;
|
||||
break;
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
fifocp = i;
|
||||
} else {
|
||||
fbcp = i;
|
||||
fbcpc++;
|
||||
}
|
||||
|
||||
pVertex++;
|
||||
}
|
||||
|
||||
// clipping
|
||||
|
||||
if (fbcpc == 3) {
|
||||
return;
|
||||
} else if (fbcpc == 2) {
|
||||
SPVertex *Vertex1 = _pVertices + (fifocp + 1) % 3;
|
||||
SPVertex *Vertex2 = _pVertices + (fifocp + 2) % 3;
|
||||
SPVertex *Vertex3 = _pVertices + fifocp;
|
||||
|
||||
float t1, t2;
|
||||
|
||||
switch (_clipPlane) {
|
||||
case 1:
|
||||
t1 = (Vertex1->x + Vertex1->w * wScale) / (Vertex1->x - Vertex3->x + Vertex1->w * wScale - Vertex3->w * wScale);
|
||||
t2 = (Vertex2->x + Vertex2->w * wScale) / (Vertex2->x - Vertex3->x + Vertex2->w * wScale - Vertex3->w * wScale);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
t1 = (Vertex1->x - Vertex1->w * wScale) / (Vertex1->x - Vertex3->x - Vertex1->w * wScale + Vertex3->w * wScale);
|
||||
t2 = (Vertex2->x - Vertex2->w * wScale) / (Vertex2->x - Vertex3->x - Vertex2->w * wScale + Vertex3->w * wScale);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
t1 = (Vertex1->y + Vertex1->w * wScale) / (Vertex1->y - Vertex3->y + Vertex1->w * wScale - Vertex3->w * wScale);
|
||||
t2 = (Vertex2->y + Vertex2->w * wScale) / (Vertex2->y - Vertex3->y + Vertex2->w * wScale - Vertex3->w * wScale);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
t1 = (Vertex1->y - Vertex1->w * wScale) / (Vertex1->y - Vertex3->y - Vertex1->w * wScale + Vertex3->w * wScale);
|
||||
t2 = (Vertex2->y - Vertex2->w * wScale) / (Vertex2->y - Vertex3->y - Vertex2->w * wScale + Vertex3->w * wScale);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
t1 = (Vertex1->z + Vertex1->w * wScale) / (Vertex1->z - Vertex3->z + Vertex1->w * wScale - Vertex3->w * wScale);
|
||||
t2 = (Vertex2->z + Vertex2->w * wScale) / (Vertex2->z - Vertex3->z + Vertex2->w * wScale - Vertex3->w * wScale);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
t1 = (Vertex1->z - Vertex1->w * wScale) / (Vertex1->z - Vertex3->z - Vertex1->w * wScale + Vertex3->w * wScale);
|
||||
t2 = (Vertex2->z - Vertex2->w * wScale) / (Vertex2->z - Vertex3->z - Vertex2->w * wScale + Vertex3->w * wScale);
|
||||
break;
|
||||
}
|
||||
|
||||
clipVertex(Vertex3, Vertex1, t1);
|
||||
clipVertex(Vertex3, Vertex2, t2);
|
||||
|
||||
clipInHomogeneousSpace(_pVertices, _vResult, _clipPlane + 1);
|
||||
} else if (fbcpc == 1) {
|
||||
unsigned int if1 = (fbcp + 1) % 3, if2 = (fbcp + 2) % 3;
|
||||
|
||||
SPVertex *Vertex1 = _pVertices + if1;
|
||||
SPVertex *Vertex2 = _pVertices + if2;
|
||||
SPVertex *Vertex3 = _pVertices + fbcp;
|
||||
|
||||
SPVertex NewVertices[3];
|
||||
|
||||
SPVertex *NewVertex1 = NewVertices + if1;
|
||||
SPVertex *NewVertex2 = NewVertices + if2;
|
||||
SPVertex *NewVertex3 = NewVertices + fbcp;
|
||||
|
||||
float t1, t2;
|
||||
|
||||
switch (_clipPlane) {
|
||||
case 1:
|
||||
t1 = (Vertex3->x + Vertex3->w * wScale) / (Vertex3->x - Vertex1->x + Vertex3->w * wScale - Vertex1->w * wScale);
|
||||
t2 = (Vertex3->x + Vertex3->w * wScale) / (Vertex3->x - Vertex2->x + Vertex3->w * wScale - Vertex2->w * wScale);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
t1 = (Vertex3->x - Vertex3->w * wScale) / (Vertex3->x - Vertex1->x - Vertex3->w * wScale + Vertex1->w * wScale);
|
||||
t2 = (Vertex3->x - Vertex3->w * wScale) / (Vertex3->x - Vertex2->x - Vertex3->w * wScale + Vertex2->w * wScale);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
t1 = (Vertex3->y + Vertex3->w * wScale) / (Vertex3->y - Vertex1->y + Vertex3->w * wScale - Vertex1->w * wScale);
|
||||
t2 = (Vertex3->y + Vertex3->w * wScale) / (Vertex3->y - Vertex2->y + Vertex3->w * wScale - Vertex2->w * wScale);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
t1 = (Vertex3->y - Vertex3->w * wScale) / (Vertex3->y - Vertex1->y - Vertex3->w * wScale + Vertex1->w * wScale);
|
||||
t2 = (Vertex3->y - Vertex3->w * wScale) / (Vertex3->y - Vertex2->y - Vertex3->w * wScale + Vertex2->w * wScale);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
t1 = (Vertex3->z + Vertex3->w * wScale) / (Vertex3->z - Vertex1->z + Vertex3->w * wScale - Vertex1->w * wScale);
|
||||
t2 = (Vertex3->z + Vertex3->w * wScale) / (Vertex3->z - Vertex2->z + Vertex3->w * wScale - Vertex2->w * wScale);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
t1 = (Vertex3->z - Vertex3->w * wScale) / (Vertex3->z - Vertex1->z - Vertex3->w * wScale + Vertex1->w * wScale);
|
||||
t2 = (Vertex3->z - Vertex3->w * wScale) / (Vertex3->z - Vertex2->z - Vertex3->w * wScale + Vertex2->w * wScale);
|
||||
break;
|
||||
}
|
||||
|
||||
copyVertex(Vertex3, NewVertex3);
|
||||
copyVertex(Vertex2, NewVertex2);
|
||||
clipVertex(Vertex1, Vertex3, t1);
|
||||
copyVertex(Vertex3, NewVertex1);
|
||||
clipVertex(NewVertex2, NewVertex3, t2);
|
||||
|
||||
clipInHomogeneousSpace(_pVertices, _vResult, _clipPlane + 1);
|
||||
clipInHomogeneousSpace(NewVertices, _vResult, _clipPlane + 1);
|
||||
} else if (fbcpc == 0) {
|
||||
clipInHomogeneousSpace(_pVertices, _vResult, _clipPlane + 1);
|
||||
}
|
||||
} else if (_clipPlane == 7) {
|
||||
for (int i = 0; i < 3; ++i)
|
||||
_vResult.push_back(_pVertices[i]);
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,12 @@
|
||||
#define TOP 4
|
||||
#define BOT 8
|
||||
|
||||
struct SPVertex;
|
||||
|
||||
struct vertexclip
|
||||
{
|
||||
float x,y,z;
|
||||
int visible;
|
||||
float x, y, z;
|
||||
int clip;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -22,6 +24,10 @@ struct vertexclip
|
||||
*
|
||||
* function returns the number of vertices in the resulting polygon
|
||||
*/
|
||||
int ClipPolygon(vertexclip *** final, vertexclip * vbp, int numVertices);
|
||||
unsigned int clipInScreenSpace(vertexclip *** final, vertexclip * vbp, unsigned int numVertices);
|
||||
|
||||
unsigned int clipW(const SPVertex ** _vsrc, SPVertex * _vdst);
|
||||
|
||||
void clipInHomogeneousSpace(SPVertex * pFragments, std::vector<SPVertex> & _vResult, int _clipPlane = 1);
|
||||
|
||||
#endif // CLIP_POLYGON_H
|
||||
@@ -256,7 +256,7 @@ public:
|
||||
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
|
||||
if (_glinfo.noPerspective) {
|
||||
ss << "#extension GL_NV_shader_noperspective_interpolation : enable" << std::endl
|
||||
<< "noperspective OUT highp float vZCoord;" << std::endl << "uniform lowp int uClampMode;" << std::endl;
|
||||
<< "noperspective OUT highp float vZCoord;" << std::endl;
|
||||
}
|
||||
m_part = ss.str();
|
||||
}
|
||||
@@ -322,7 +322,6 @@ public:
|
||||
"{ \n"
|
||||
" gl_Position = aPosition; \n"
|
||||
" vShadeColor = aColor; \n"
|
||||
" vShadeColorNoperspective = aColor; \n"
|
||||
" vec2 texCoord = aTexCoord; \n"
|
||||
" texCoord *= uTexScale; \n"
|
||||
" if (uTexturePersp == 0 && aModify[2] == 0.0) texCoord *= 0.5;\n"
|
||||
@@ -354,6 +353,7 @@ public:
|
||||
" vShadeColor.rgb = vec3(fp); \n"
|
||||
" } \n"
|
||||
" vBaryCoords = vec4(aBaryCoords, 1.0 - aBaryCoords.x - aBaryCoords.y, 0.5); \n"
|
||||
" vShadeColorNoperspective = vShadeColor; \n"
|
||||
;
|
||||
}
|
||||
};
|
||||
@@ -388,7 +388,6 @@ public:
|
||||
"{ \n"
|
||||
" gl_Position = aPosition; \n"
|
||||
" vShadeColor = aColor; \n"
|
||||
" vShadeColorNoperspective = aColor; \n"
|
||||
" vNumLights = aNumLights; \n"
|
||||
" if (aModify != vec4(0.0)) { \n"
|
||||
" if ((aModify[0]) != 0.0) { \n"
|
||||
@@ -414,6 +413,7 @@ public:
|
||||
" vShadeColor.rgb = vec3(fp); \n"
|
||||
" } \n"
|
||||
" vBaryCoords = vec4(aBaryCoords, 1.0 - aBaryCoords.x - aBaryCoords.y, 0.5); \n"
|
||||
" vShadeColorNoperspective = vShadeColor; \n"
|
||||
;
|
||||
}
|
||||
};
|
||||
@@ -489,12 +489,17 @@ public:
|
||||
m_part =
|
||||
" gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n"
|
||||
;
|
||||
} else if (config.generalEmulation.enableFragmentDepthWrite != 0 && _glinfo.noPerspective) {
|
||||
m_part =
|
||||
" vZCoord = gl_Position.z / gl_Position.w; \n"
|
||||
" if (uClampMode > 0) \n"
|
||||
" gl_Position.z = 0.0; \n"
|
||||
;
|
||||
} else if (config.generalEmulation.enableClipping != 0) {
|
||||
|
||||
if (config.generalEmulation.enableFragmentDepthWrite != 0 && _glinfo.noPerspective) {
|
||||
m_part = " vZCoord = gl_Position.z / gl_Position.w; \n";
|
||||
m_part += " gl_Position.z = 0.0; \n";
|
||||
} else {
|
||||
// Move the near plane towards the camera.
|
||||
// It helps to avoid issues with near-plane clipping in games, which do not use it.
|
||||
// Z must be scaled back in fragment shader.
|
||||
m_part = " gl_Position.z /= 8.0; \n";
|
||||
}
|
||||
}
|
||||
m_part +=
|
||||
" gl_Position.zw *= vec2(uClipRatio); \n"
|
||||
@@ -1171,15 +1176,15 @@ public:
|
||||
m_part =
|
||||
"highp float writeDepth();\n";
|
||||
;
|
||||
if (_glinfo.isGLESX && _glinfo.noPerspective) {
|
||||
m_part =
|
||||
"noperspective IN highp float vZCoord; \n"
|
||||
"uniform lowp float uPolygonOffset; \n"
|
||||
"uniform lowp int uClampMode; \n"
|
||||
+ m_part
|
||||
;
|
||||
}
|
||||
}
|
||||
if (_glinfo.isGLESX && _glinfo.noPerspective) {
|
||||
m_part =
|
||||
"noperspective IN highp float vZCoord; \n"
|
||||
"uniform lowp float uPolygonOffset; \n"
|
||||
+ m_part
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1507,8 +1512,16 @@ public:
|
||||
" lowp vec4 vec_color; \n"
|
||||
" lowp float alpha1; \n"
|
||||
" lowp vec3 color1, input_color; \n"
|
||||
" lowp vec4 shadeColor = uScreenSpaceTriangle == 0 ? vShadeColor : vShadeColorNoperspective; \n"
|
||||
;
|
||||
if (config.generalEmulation.enableClipping != 0)
|
||||
m_part +=
|
||||
" lowp vec4 shadeColor = vShadeColorNoperspective; \n"
|
||||
;
|
||||
else
|
||||
m_part +=
|
||||
" lowp vec4 shadeColor = uScreenSpaceTriangle == 0 ? vShadeColor : vShadeColorNoperspective; \n"
|
||||
;
|
||||
|
||||
m_part += "#define WRAP(x, low, high) mod((x)-(low), (high)-(low)) + (low) \n"; // Return wrapped value of x in interval [low, high)
|
||||
// m_part += "#define WRAP(x, low, high) (x) - ((high)-(low)) * floor(((x)-(low))/((high)-(low))) \n"; // Perhaps more compatible?
|
||||
// m_part += "#define WRAP(x, low, high) (x) + ((high)-(low)) * (1.0-step(low,x)) - ((high)-(low)) * step(high,x) \n"; // Step based version. Only wraps correctly if input is in the range [low-(high-low), high + (high-low)). Similar to old code.
|
||||
@@ -1534,8 +1547,16 @@ public:
|
||||
" lowp vec4 vec_color, combined_color; \n"
|
||||
" lowp float alpha1, alpha2; \n"
|
||||
" lowp vec3 color1, color2, input_color; \n"
|
||||
" lowp vec4 shadeColor = uScreenSpaceTriangle == 0 ? vShadeColor : vShadeColorNoperspective; \n"
|
||||
;
|
||||
if (config.generalEmulation.enableClipping != 0)
|
||||
m_part +=
|
||||
" lowp vec4 shadeColor = vShadeColorNoperspective; \n"
|
||||
;
|
||||
else
|
||||
m_part +=
|
||||
" lowp vec4 shadeColor = uScreenSpaceTriangle == 0 ? vShadeColor : vShadeColorNoperspective; \n"
|
||||
;
|
||||
|
||||
m_part += "#define WRAP(x, low, high) mod((x)-(low), (high)-(low)) + (low) \n"; // Return wrapped value of x in interval [low, high)
|
||||
// m_part += "#define WRAP(x, low, high) (x) - ((high)-(low)) * floor(((x)-(low))/((high)-(low))) \n"; // Perhaps more compatible?
|
||||
// m_part += "#define WRAP(x, low, high) (x) + (2.0) * (1.0-step(low,x)) - (2.0) * step(high,x) \n"; // Step based version. Only wraps correctly if input is in the range [low-(high-low), high + (high-low)). Similar to old code.
|
||||
@@ -1909,12 +1930,18 @@ public:
|
||||
"highp float writeDepth() \n"
|
||||
"{ \n"
|
||||
;
|
||||
if (_glinfo.isGLESX && _glinfo.noPerspective) {
|
||||
m_part +=
|
||||
" if (uClampMode == 1 && (vZCoord > 1.0)) discard; \n"
|
||||
" highp float FragDepth = (uDepthSource != 0) ? uPrimDepth : \n"
|
||||
" clamp((vZCoord - uPolygonOffset) * uDepthScale.s + uDepthScale.t, 0.0, 1.0); \n"
|
||||
;
|
||||
if (_glinfo.isGLESX && config.generalEmulation.enableClipping != 0) {
|
||||
if (_glinfo.noPerspective) {
|
||||
m_part +=
|
||||
" highp float FragDepth = (uDepthSource != 0) ? uPrimDepth : \n"
|
||||
" clamp((vZCoord - uPolygonOffset) * uDepthScale.s + uDepthScale.t, 0.0, 1.0); \n"
|
||||
;
|
||||
} else {
|
||||
m_part +=
|
||||
" highp float FragDepth = (uDepthSource != 0) ? uPrimDepth : \n"
|
||||
" clamp(8.0 * (gl_FragCoord.z * 2.0 - 1.0) * uDepthScale.s + uDepthScale.t, 0.0, 1.0); \n"
|
||||
;
|
||||
}
|
||||
} else {
|
||||
m_part +=
|
||||
" highp float FragDepth = (uDepthSource != 0) ? uPrimDepth : \n"
|
||||
@@ -1922,23 +1949,33 @@ public:
|
||||
;
|
||||
}
|
||||
m_part +=
|
||||
" highp int iZ = FragDepth > 0.999 ? 262143 : int(floor(FragDepth * 262143.0)); \n"
|
||||
" highp int iZ = FragDepth > 0.999 ? 262143 : int(floor(FragDepth * 262143.0)); \n"
|
||||
" mediump int y0 = clamp(iZ/512, 0, 511); \n"
|
||||
" mediump int x0 = iZ - 512*y0; \n"
|
||||
" highp uint iN64z = texelFetch(uZlutImage,ivec2(x0,y0), 0).r; \n"
|
||||
" return clamp(float(iN64z)/65532.0, 0.0, 1.0); \n"
|
||||
" highp uint iN64z = texelFetch(uZlutImage,ivec2(x0,y0), 0).r; \n"
|
||||
" return clamp(float(iN64z)/65532.0, 0.0, 1.0); \n"
|
||||
"} \n"
|
||||
;
|
||||
} else {
|
||||
if (_glinfo.isGLESX && _glinfo.noPerspective) {
|
||||
m_part =
|
||||
"highp float writeDepth() \n"
|
||||
"{ \n"
|
||||
" if (uClampMode == 1 && (vZCoord > 1.0)) discard; \n"
|
||||
" if (uDepthSource != 0) return uPrimDepth; \n"
|
||||
" return clamp((vZCoord - uPolygonOffset) * uDepthScale.s + uDepthScale.t, 0.0, 1.0); \n"
|
||||
"} \n"
|
||||
;
|
||||
if (_glinfo.isGLESX && config.generalEmulation.enableClipping != 0) {
|
||||
if (_glinfo.noPerspective) {
|
||||
m_part =
|
||||
"highp float writeDepth() \n"
|
||||
"{ \n"
|
||||
" if (uDepthSource != 0) return uPrimDepth; \n"
|
||||
" return clamp((vZCoord - uPolygonOffset) * uDepthScale.s + uDepthScale.t, 0.0, 1.0); \n"
|
||||
"} \n"
|
||||
;
|
||||
} else {
|
||||
m_part =
|
||||
"highp float writeDepth() \n"
|
||||
"{ \n"
|
||||
" if (uDepthSource != 0) return uPrimDepth; \n"
|
||||
" return clamp(8.0 * (gl_FragCoord.z * 2.0 - 1.0) * uDepthScale.s + uDepthScale.t, 0.0, 1.0); \n"
|
||||
"} \n"
|
||||
;
|
||||
}
|
||||
|
||||
} else {
|
||||
m_part =
|
||||
"highp float writeDepth() \n"
|
||||
@@ -1946,7 +1983,7 @@ public:
|
||||
" if (uDepthSource != 0) return uPrimDepth; \n"
|
||||
" return clamp((gl_FragCoord.z * 2.0 - 1.0) * uDepthScale.s + uDepthScale.t, 0.0, 1.0); \n"
|
||||
"} \n"
|
||||
;
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,35 +709,6 @@ private:
|
||||
iUniform uRenderTarget;
|
||||
};
|
||||
|
||||
class UClampMode : public UniformGroup
|
||||
{
|
||||
public:
|
||||
UClampMode(GLuint _program) {
|
||||
LocateUniform(uClampMode);
|
||||
}
|
||||
|
||||
void update(bool _force) override
|
||||
{
|
||||
int clampMode = -1;
|
||||
switch (gfxContext.getClampMode())
|
||||
{
|
||||
case graphics::ClampMode::ClippingEnabled:
|
||||
clampMode = 0;
|
||||
break;
|
||||
case graphics::ClampMode::NoNearPlaneClipping:
|
||||
clampMode = 1;
|
||||
break;
|
||||
case graphics::ClampMode::NoClipping:
|
||||
clampMode = 2;
|
||||
break;
|
||||
}
|
||||
uClampMode.set(clampMode, _force);
|
||||
}
|
||||
|
||||
private:
|
||||
iUniform uClampMode;
|
||||
};
|
||||
|
||||
class UClipRatio : public UniformGroup
|
||||
{
|
||||
public:
|
||||
@@ -771,7 +742,6 @@ private:
|
||||
fUniform uPolygonOffset;
|
||||
};
|
||||
|
||||
|
||||
class UScreenCoordsScale : public UniformGroup
|
||||
{
|
||||
public:
|
||||
@@ -1162,7 +1132,6 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
|
||||
_uniforms.emplace_back(new URenderTarget(_program));
|
||||
|
||||
if (m_glInfo.isGLESX && m_glInfo.noPerspective) {
|
||||
_uniforms.emplace_back(new UClampMode(_program));
|
||||
_uniforms.emplace_back(new UPolygonOffset(_program));
|
||||
}
|
||||
|
||||
|
||||
@@ -202,12 +202,10 @@ bool ShaderStorage::saveShadersStorage(const graphics::Combiners & _combiners) c
|
||||
|
||||
static
|
||||
CombinerProgramImpl * _readCombinerProgramFromStream(std::istream & _is,
|
||||
CombinerKey& _cmbKey,
|
||||
CombinerProgramUniformFactory & _uniformFactory,
|
||||
opengl::CachedUseProgram * _useProgram)
|
||||
{
|
||||
CombinerKey cmbKey;
|
||||
cmbKey.read(_is);
|
||||
|
||||
int inputs;
|
||||
_is.read((char*)&inputs, sizeof(inputs));
|
||||
CombinerInputs cmbInputs(inputs);
|
||||
@@ -220,15 +218,17 @@ CombinerProgramImpl * _readCombinerProgramFromStream(std::istream & _is,
|
||||
_is.read(binary.data(), binaryLength);
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
const bool isRect = cmbKey.isRectKey();
|
||||
const bool isRect = _cmbKey.isRectKey();
|
||||
glsl::Utils::locateAttributes(program, isRect, cmbInputs.usesTexture());
|
||||
glProgramBinary(program, binaryFormat, binary.data(), binaryLength);
|
||||
assert(glsl::Utils::checkProgramLinkStatus(program));
|
||||
if (!glsl::Utils::checkProgramLinkStatus(program, true)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UniformGroups uniforms;
|
||||
_uniformFactory.buildUniforms(program, cmbInputs, cmbKey, uniforms);
|
||||
_uniformFactory.buildUniforms(program, cmbInputs, _cmbKey, uniforms);
|
||||
|
||||
return new CombinerProgramImpl(cmbKey, program, _useProgram, cmbInputs, std::move(uniforms));
|
||||
return new CombinerProgramImpl(_cmbKey, program, _useProgram, cmbInputs, std::move(uniforms));
|
||||
}
|
||||
|
||||
bool ShaderStorage::_loadFromCombinerKeys(graphics::Combiners & _combiners)
|
||||
@@ -344,9 +344,21 @@ bool ShaderStorage::loadShadersStorage(graphics::Combiners & _combiners)
|
||||
f32 progress = 0.0f;
|
||||
f32 percents = percent;
|
||||
for (u32 i = 0; i < len; ++i) {
|
||||
CombinerProgramImpl * pCombiner = _readCombinerProgramFromStream(fin, uniformFactory, m_useProgram);
|
||||
pCombiner->update(true);
|
||||
_combiners[pCombiner->getKey()] = pCombiner;
|
||||
CombinerKey cmbKey;
|
||||
cmbKey.read(fin);
|
||||
|
||||
CombinerProgramImpl * pCombiner = _readCombinerProgramFromStream(fin, cmbKey, uniformFactory, m_useProgram);
|
||||
|
||||
if (pCombiner != nullptr) {
|
||||
pCombiner->update(true);
|
||||
_combiners[pCombiner->getKey()] = pCombiner;
|
||||
} else {
|
||||
LOG(LOG_ERROR, "Shader is not a valid binary compiling from key instead");
|
||||
graphics::CombinerProgram *pCombinerFromKey = Combiner_Compile(cmbKey);
|
||||
pCombinerFromKey->update(true);
|
||||
_combiners[cmbKey] = pCombinerFromKey;
|
||||
}
|
||||
|
||||
progress += step;
|
||||
if (progress > percents) {
|
||||
displayLoadProgress(L"LOAD COMBINER SHADERS %.1f%%", f32(i + 1) * 100.f / f32(len) );
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace glsl {
|
||||
bool _saveCombinerKeys(const graphics::Combiners & _combiners) const;
|
||||
bool _loadFromCombinerKeys(graphics::Combiners & _combiners);
|
||||
|
||||
const u32 m_formatVersion = 0x30U;
|
||||
const u32 m_formatVersion = 0x31U;
|
||||
const u32 m_keysFormatVersion = 0x05;
|
||||
const opengl::GLInfo & m_glinfo;
|
||||
opengl::CachedUseProgram * m_useProgram;
|
||||
|
||||
@@ -52,9 +52,9 @@ bool Utils::checkShaderCompileStatus(GLuint obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utils::checkProgramLinkStatus(GLuint obj)
|
||||
static
|
||||
bool _checkProgramLinkStatus(GLuint obj)
|
||||
{
|
||||
#ifdef GL_DEBUG
|
||||
GLint status;
|
||||
glGetProgramiv(obj, GL_LINK_STATUS, &status);
|
||||
if (status == GL_FALSE) {
|
||||
@@ -64,10 +64,20 @@ bool Utils::checkProgramLinkStatus(GLuint obj)
|
||||
LOG(LOG_ERROR, "shader_link error: %s", shader_log);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utils::checkProgramLinkStatus(GLuint obj, bool _force)
|
||||
{
|
||||
#ifdef GL_DEBUG
|
||||
return _checkProgramLinkStatus(obj);
|
||||
#else
|
||||
if (_force)
|
||||
return _checkProgramLinkStatus(obj);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Utils::logErrorShader(GLenum _shaderType, const std::string & _strShader)
|
||||
{
|
||||
LOG(LOG_ERROR, "Error in %s shader", _shaderType == GL_VERTEX_SHADER ? "vertex" : "fragment");
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace glsl {
|
||||
struct Utils {
|
||||
static void locateAttributes(GLuint _program, bool _rect, bool _textures);
|
||||
static bool checkShaderCompileStatus(GLuint obj);
|
||||
static bool checkProgramLinkStatus(GLuint obj);
|
||||
static bool checkProgramLinkStatus(GLuint obj, bool _force = false);
|
||||
static void logErrorShader(GLenum _shaderType, const std::string & _strShader);
|
||||
static GLuint createRectShaderProgram(const char * _strVertex, const char * _strFragment);
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ const u8 * ColorBufferReaderWithEGLImage::_readPixels(const ReadColorBufferParam
|
||||
_stride = m_pTexture->width;
|
||||
} else {
|
||||
gpuData = m_pixelData.data();
|
||||
glReadPixels(_params.x0, _params.y0, _params.width, _params.height, format, type, gpuData);
|
||||
glReadPixels(_params.x0, _params.y0, m_pTexture->width, _params.height, format, type, gpuData);
|
||||
_heightOffset = 0;
|
||||
_stride = m_pTexture->width;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ namespace graphics {
|
||||
namespace drawmode {
|
||||
DrawModeParam TRIANGLES(GL_TRIANGLES);
|
||||
DrawModeParam TRIANGLE_STRIP(GL_TRIANGLE_STRIP);
|
||||
DrawModeParam TRIANGLE_FAN(GL_TRIANGLE_FAN);
|
||||
DrawModeParam LINES(GL_LINES);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ namespace graphics {
|
||||
namespace drawmode {
|
||||
extern DrawModeParam TRIANGLES;
|
||||
extern DrawModeParam TRIANGLE_STRIP;
|
||||
extern DrawModeParam TRIANGLE_FAN;
|
||||
extern DrawModeParam LINES;
|
||||
}
|
||||
|
||||
|
||||
@@ -813,7 +813,6 @@ void GraphicsDrawer::drawTriangles()
|
||||
}
|
||||
|
||||
_prepareDrawTriangle(DrawingState::Triangle);
|
||||
|
||||
Context::DrawTriangleParameters triParams;
|
||||
triParams.mode = drawmode::TRIANGLES;
|
||||
triParams.flatColors = m_bFlatColors;
|
||||
@@ -823,11 +822,16 @@ void GraphicsDrawer::drawTriangles()
|
||||
triParams.vertices = triangles.vertices.data();
|
||||
triParams.elements = triangles.elements.data();
|
||||
triParams.combiner = currentCombiner();
|
||||
gfxContext.drawTriangles(triParams);
|
||||
g_debugger.addTriangles(triParams);
|
||||
|
||||
if (config.frameBufferEmulation.enable != 0) {
|
||||
const f32 maxY = renderTriangles(triangles.vertices.data(), triangles.elements.data(), triangles.num);
|
||||
f32 maxY;
|
||||
if (config.generalEmulation.enableClipping != 0) {
|
||||
maxY = renderAndDrawTriangles(triangles.vertices.data(), triangles.elements.data(), triangles.num, m_bFlatColors);
|
||||
} else {
|
||||
gfxContext.drawTriangles(triParams);
|
||||
maxY = renderTriangles(triangles.vertices.data(), triangles.elements.data(), triangles.num);
|
||||
}
|
||||
frameBufferList().setBufferChanged(maxY);
|
||||
if (config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||
gDP.otherMode.depthUpdate != 0) {
|
||||
@@ -835,6 +839,8 @@ void GraphicsDrawer::drawTriangles()
|
||||
if (pCurrentDepthBuffer != nullptr)
|
||||
pCurrentDepthBuffer->setDirty();
|
||||
}
|
||||
} else {
|
||||
gfxContext.drawTriangles(triParams);
|
||||
}
|
||||
|
||||
triangles.num = 0;
|
||||
@@ -880,7 +886,7 @@ void GraphicsDrawer::drawScreenSpaceTriangle(u32 _numVtx, graphics::DrawModePara
|
||||
m_dmaVerticesNum = 0;
|
||||
|
||||
if (config.frameBufferEmulation.enable != 0) {
|
||||
const f32 maxY = renderTriangles(m_dmaVertices.data(), nullptr, _numVtx);
|
||||
const f32 maxY = renderScreenSpaceTriangles(m_dmaVertices.data(), _numVtx);
|
||||
frameBufferList().setBufferChanged(maxY);
|
||||
if (config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||
gDP.otherMode.depthUpdate != 0) {
|
||||
@@ -905,12 +911,18 @@ void GraphicsDrawer::drawDMATriangles(u32 _numVtx)
|
||||
triParams.verticesCount = _numVtx;
|
||||
triParams.vertices = m_dmaVertices.data();
|
||||
triParams.combiner = currentCombiner();
|
||||
gfxContext.drawTriangles(triParams);
|
||||
g_debugger.addTriangles(triParams);
|
||||
m_dmaVerticesNum = 0;
|
||||
|
||||
if (config.frameBufferEmulation.enable != 0) {
|
||||
const f32 maxY = renderTriangles(m_dmaVertices.data(), nullptr, _numVtx);
|
||||
f32 maxY;
|
||||
if (config.generalEmulation.enableClipping != 0) {
|
||||
maxY = renderAndDrawTriangles(m_dmaVertices.data(), nullptr, _numVtx, m_bFlatColors);
|
||||
}
|
||||
else {
|
||||
gfxContext.drawTriangles(triParams);
|
||||
maxY = renderTriangles(m_dmaVertices.data(), nullptr, _numVtx);
|
||||
}
|
||||
frameBufferList().setBufferChanged(maxY);
|
||||
if (config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||
gDP.otherMode.depthUpdate != 0) {
|
||||
@@ -918,6 +930,8 @@ void GraphicsDrawer::drawDMATriangles(u32 _numVtx)
|
||||
if (pCurrentDepthBuffer != nullptr)
|
||||
pCurrentDepthBuffer->setDirty();
|
||||
}
|
||||
} else {
|
||||
gfxContext.drawTriangles(triParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+242
-54
@@ -1,5 +1,6 @@
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "DepthBufferRender/ClipPolygon.h"
|
||||
#include "DepthBufferRender/DepthBufferRender.h"
|
||||
#include "gSP.h"
|
||||
@@ -8,25 +9,70 @@
|
||||
#include "DepthBuffer.h"
|
||||
#include "Config.h"
|
||||
|
||||
static
|
||||
bool calcScreenCoordinates(const SPVertex** _vsrc, vertexclip * _vclip, u32 _numVertex, bool & _clockwise)
|
||||
{
|
||||
for (u32 i = 0; i < _numVertex; ++i) {
|
||||
const SPVertex& v = *_vsrc[i];
|
||||
|
||||
if ((v.modify & MODIFY_XY) == 0) {
|
||||
_vclip[i].x = gSP.viewport.vtrans[0] + (v.x / v.w) * gSP.viewport.vscale[0];
|
||||
_vclip[i].y = gSP.viewport.vtrans[1] + (v.y / v.w) * -gSP.viewport.vscale[1];
|
||||
} else {
|
||||
_vclip[i].x = v.x;
|
||||
_vclip[i].y = v.y;
|
||||
}
|
||||
|
||||
if ((v.modify & MODIFY_Z) == 0) {
|
||||
_vclip[i].z = (gSP.viewport.vtrans[2] + (v.z / v.w) * gSP.viewport.vscale[2]) * 32767.0f;
|
||||
} else {
|
||||
_vclip[i].z = v.z * 32767.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Check culling
|
||||
const float x1 = _vclip[0].x - _vclip[1].x;
|
||||
const float y1 = _vclip[0].y - _vclip[1].y;
|
||||
const float x2 = _vclip[2].x - _vclip[1].x;
|
||||
const float y2 = _vclip[2].y - _vclip[1].y;
|
||||
|
||||
_clockwise = (x1*y2 - y1 * x2) >= 0.0f;
|
||||
|
||||
const u32 cullMode = (gSP.geometryMode & G_CULL_BOTH);
|
||||
if (cullMode == G_CULL_BOTH && GBI.isCullBoth()) {
|
||||
// Cull front and back
|
||||
return false;
|
||||
} else if (cullMode == G_CULL_FRONT) {
|
||||
if (_clockwise) //clockwise, negative
|
||||
return false;
|
||||
} else if (cullMode == G_CULL_BACK) {
|
||||
if (!_clockwise) //counter-clockwise, positive
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
void clipTest(vertexclip & _vtx)
|
||||
{
|
||||
_vtx.visible = 0;
|
||||
_vtx.clip = 0;
|
||||
if (_vtx.x > gSP.viewport.width)
|
||||
_vtx.visible |= RIGHT;
|
||||
_vtx.clip |= RIGHT;
|
||||
if (_vtx.x < 0)
|
||||
_vtx.visible |= LEFT;
|
||||
_vtx.clip |= LEFT;
|
||||
if (_vtx.y > gSP.viewport.height)
|
||||
_vtx.visible |= TOP;
|
||||
_vtx.clip |= TOP;
|
||||
if (_vtx.y < 0)
|
||||
_vtx.visible |= BOT;
|
||||
_vtx.clip |= BOT;
|
||||
if (_vtx.clip != 0)
|
||||
int t = 0;
|
||||
}
|
||||
|
||||
static
|
||||
bool calcScreenCoordinates(SPVertex * _vsrc, vertexclip * _vclip, u32 _numVertex, bool & _clockwise)
|
||||
bool calcScreenCoordinates(const SPVertex * _vsrc, vertexclip * _vclip, u32 _numVertex, bool _wClipped, bool & _clockwise)
|
||||
{
|
||||
for (u32 i = 0; i < _numVertex; ++i) {
|
||||
SPVertex & v = _vsrc[i];
|
||||
const SPVertex & v = _vsrc[i];
|
||||
|
||||
if ((v.modify & MODIFY_XY) == 0) {
|
||||
_vclip[i].x = gSP.viewport.vtrans[0] + (v.x / v.w) * gSP.viewport.vscale[0];
|
||||
@@ -45,7 +91,7 @@ bool calcScreenCoordinates(SPVertex * _vsrc, vertexclip * _vclip, u32 _numVertex
|
||||
clipTest(_vclip[i]);
|
||||
}
|
||||
|
||||
if (_numVertex > 3) // Don't cull w-clipped vertices
|
||||
if (_wClipped) // Don't cull w-clipped vertices
|
||||
return true;
|
||||
|
||||
// Check culling
|
||||
@@ -54,13 +100,13 @@ bool calcScreenCoordinates(SPVertex * _vsrc, vertexclip * _vclip, u32 _numVertex
|
||||
const float x2 = _vclip[2].x - _vclip[1].x;
|
||||
const float y2 = _vclip[2].y - _vclip[1].y;
|
||||
|
||||
_clockwise = (x1*y2 - y1*x2) >= 0.0f;
|
||||
if (RSP.LLE)
|
||||
return true;
|
||||
_clockwise = (x1*y2 - y1 * x2) >= 0.0f;
|
||||
|
||||
const u32 cullMode = (gSP.geometryMode & G_CULL_BOTH);
|
||||
|
||||
if (cullMode == G_CULL_FRONT) {
|
||||
if (cullMode == G_CULL_BOTH && GBI.isCullBoth()) {
|
||||
// Cull front and back
|
||||
return false;
|
||||
} else if (cullMode == G_CULL_FRONT) {
|
||||
if (_clockwise) //clockwise, negative
|
||||
return false;
|
||||
} else if (cullMode == G_CULL_BACK) {
|
||||
@@ -71,6 +117,19 @@ bool calcScreenCoordinates(SPVertex * _vsrc, vertexclip * _vclip, u32 _numVertex
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool isClockwise(const SPVertex ** _vsrc)
|
||||
{
|
||||
// Check culling
|
||||
const float x1 = _vsrc[0]->x - _vsrc[1]->x;
|
||||
const float y1 = _vsrc[0]->y - _vsrc[1]->y;
|
||||
const float x2 = _vsrc[2]->x - _vsrc[1]->x;
|
||||
const float y2 = _vsrc[2]->y - _vsrc[1]->y;
|
||||
|
||||
return (x1*y2 - y1 * x2) >= 0.0f;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
int floatToFixed16(double _v)
|
||||
{
|
||||
@@ -78,7 +137,7 @@ int floatToFixed16(double _v)
|
||||
}
|
||||
|
||||
static
|
||||
int calcDzDx(vertexclip * _v)
|
||||
int calcDzDx(const vertexclip* _v)
|
||||
{
|
||||
double X0 = _v[0].x;
|
||||
double Y0 = _v[0].y;
|
||||
@@ -101,6 +160,30 @@ int calcDzDx(vertexclip * _v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int calcDzDx(const SPVertex ** _v)
|
||||
{
|
||||
double X0 = _v[0]->x;
|
||||
double Y0 = _v[0]->y;
|
||||
double X1 = _v[1]->x;
|
||||
double Y1 = _v[1]->y;
|
||||
double X2 = _v[2]->x;
|
||||
double Y2 = _v[2]->y;
|
||||
double diffy_02 = Y0 - Y2;
|
||||
double diffy_12 = Y1 - Y2;
|
||||
double diffx_02 = X0 - X2;
|
||||
double diffx_12 = X1 - X2;
|
||||
|
||||
double denom = (diffx_02 * diffy_12 - diffx_12 * diffy_02);
|
||||
if (denom*denom > 0.0) {
|
||||
double diffz_02 = _v[0]->z - _v[2]->z;
|
||||
double diffz_12 = _v[1]->z - _v[2]->z;
|
||||
double fdzdx = (diffz_02 * diffy_12 - diffz_12 * diffy_02) / denom;
|
||||
return floatToFixed16(fdzdx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int calcDzDx2(const SPVertex ** _vsrc)
|
||||
{
|
||||
@@ -131,40 +214,44 @@ int calcDzDx2(const SPVertex ** _vsrc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline
|
||||
void copyVertex(SPVertex & _dst, const SPVertex * _src)
|
||||
f32 renderScreenSpaceTriangles(const SPVertex *_pVertices, u32 _numElements)
|
||||
{
|
||||
_dst.x = _src->x;
|
||||
_dst.y = _src->y;
|
||||
_dst.z = _src->z;
|
||||
_dst.w = _src->w;
|
||||
_dst.modify = _src->modify;
|
||||
}
|
||||
vertexi vdraw[3];
|
||||
const SPVertex * vsrc[3];
|
||||
f32 maxY = 0.0f;
|
||||
const bool needResterise = (depthBufferList().getCurrent() != nullptr &&
|
||||
config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||
gDP.otherMode.depthUpdate != 0);
|
||||
|
||||
static
|
||||
u32 clipW(const SPVertex ** _vsrc, SPVertex * _vdst)
|
||||
{
|
||||
u32 dsti = 0;
|
||||
for (int n = 0; n < 3; ++n) {
|
||||
const SPVertex * src1 = _vsrc[n]; // current vertex
|
||||
const SPVertex * src2 = _vsrc[n + 1]; // next vertex
|
||||
if (src1->w >= 0.01f) {
|
||||
copyVertex(_vdst[dsti++], src1); // add visible vertex to list
|
||||
if (src2->w >= 0.01f)
|
||||
continue;
|
||||
} else if (src2->w < 0.01f)
|
||||
continue;
|
||||
float a = (-src1->w) / (src2->w - src1->w);
|
||||
float ima = 1.0f - a;
|
||||
// create new vertex
|
||||
_vdst[dsti].x = src1->x*ima + src2->x*a;
|
||||
_vdst[dsti].y = src1->y*ima + src2->y*a;
|
||||
_vdst[dsti].z = src1->z*ima + src2->z*a;
|
||||
_vdst[dsti].w = 0.01f;
|
||||
_vdst[dsti].modify = 0;
|
||||
dsti++;
|
||||
for (u32 i = 0; i < _numElements; i += 3) {
|
||||
for (u32 j = 0; j < 3; ++j) {
|
||||
vsrc[j] = &_pVertices[i + j];
|
||||
}
|
||||
|
||||
if (isClockwise(vsrc)) {
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
maxY = std::max(maxY, vsrc[k]->y);
|
||||
vdraw[k].x = floatToFixed16(vsrc[k]->x);
|
||||
vdraw[k].y = floatToFixed16(vsrc[k]->y);
|
||||
vdraw[k].z = floatToFixed16(vsrc[k]->z);
|
||||
}
|
||||
} else {
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
const u32 idx = 3 - k - 1;
|
||||
maxY = std::max(maxY, vsrc[idx]->y);
|
||||
vdraw[k].x = floatToFixed16(vsrc[idx]->x);
|
||||
vdraw[k].y = floatToFixed16(vsrc[idx]->y);
|
||||
vdraw[k].z = floatToFixed16(vsrc[idx]->z);
|
||||
}
|
||||
}
|
||||
|
||||
//Current depth buffer can be null if we are loading from a save state
|
||||
if (needResterise) {
|
||||
const int dzdx = calcDzDx(vsrc);
|
||||
Rasterize(vdraw, 3, dzdx);
|
||||
}
|
||||
}
|
||||
return dsti;
|
||||
return maxY;
|
||||
}
|
||||
|
||||
f32 renderTriangles(const SPVertex * _pVertices, const u16 * _pElements, u32 _numElements)
|
||||
@@ -174,6 +261,11 @@ f32 renderTriangles(const SPVertex * _pVertices, const u16 * _pElements, u32 _nu
|
||||
const SPVertex * vsrc[4];
|
||||
SPVertex vdata[6];
|
||||
f32 maxY = 0.0f;
|
||||
//Current depth buffer can be null if we are loading from a save state
|
||||
const bool needResterise = (depthBufferList().getCurrent() != nullptr &&
|
||||
config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||
gDP.otherMode.depthUpdate != 0);
|
||||
|
||||
for (u32 i = 0; i < _numElements; i += 3) {
|
||||
u32 orbits = 0;
|
||||
if (_pElements != nullptr) {
|
||||
@@ -191,12 +283,11 @@ f32 renderTriangles(const SPVertex * _pVertices, const u16 * _pElements, u32 _nu
|
||||
|
||||
u32 numVertex = clipW(vsrc, vdata);
|
||||
|
||||
const bool wClipped = (orbits & CLIP_W) != 0;
|
||||
bool clockwise = true;
|
||||
if (!calcScreenCoordinates(vdata, vclip, numVertex, clockwise))
|
||||
if (!calcScreenCoordinates(vdata, vclip, numVertex, wClipped, clockwise))
|
||||
continue;
|
||||
|
||||
const int dzdx = ((orbits & CLIP_W) == 0) ? calcDzDx(vclip) : calcDzDx2(vsrc);
|
||||
|
||||
if (orbits == 0) {
|
||||
assert(numVertex == 3);
|
||||
if (clockwise) {
|
||||
@@ -217,7 +308,7 @@ f32 renderTriangles(const SPVertex * _pVertices, const u16 * _pElements, u32 _nu
|
||||
}
|
||||
} else {
|
||||
vertexclip ** vtx;
|
||||
numVertex = ClipPolygon(&vtx, vclip, numVertex);
|
||||
numVertex = clipInScreenSpace(&vtx, vclip, numVertex);
|
||||
if (numVertex < 3)
|
||||
continue;
|
||||
|
||||
@@ -239,11 +330,108 @@ f32 renderTriangles(const SPVertex * _pVertices, const u16 * _pElements, u32 _nu
|
||||
}
|
||||
}
|
||||
|
||||
//Current depth buffer can be null if we are loading from a save state
|
||||
if (depthBufferList().getCurrent() != nullptr &&
|
||||
config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||
gDP.otherMode.depthUpdate != 0)
|
||||
if (needResterise) {
|
||||
const int dzdx = !wClipped ? calcDzDx(vclip) : calcDzDx2(vsrc);
|
||||
Rasterize(vdraw, numVertex, dzdx);
|
||||
}
|
||||
}
|
||||
return maxY;
|
||||
}
|
||||
|
||||
f32 renderAndDrawTriangles(const SPVertex *_pVertices, const u16 *_pElements, u32 _numElements, bool _flatColors)
|
||||
{
|
||||
f32 maxY = 0.0f;
|
||||
std::vector<SPVertex> vResult;
|
||||
vResult.reserve(_numElements * 3);
|
||||
|
||||
//Current depth buffer can be null if we are loading from a save state
|
||||
const bool needResterise = (depthBufferList().getCurrent() != nullptr &&
|
||||
config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
|
||||
gDP.otherMode.depthUpdate != 0);
|
||||
|
||||
auto rasterise = [&maxY](const vertexclip* pVtxClip, bool clockwise)
|
||||
{
|
||||
int dzdx = calcDzDx(pVtxClip);
|
||||
vertexi vdraw[3];
|
||||
for (u32 k = 0; k < 3; ++k) {
|
||||
for (u32 k = 0; k < 3; ++k) {
|
||||
const u32 idx = clockwise ? k : 3 - k - 1;
|
||||
maxY = std::max(maxY, pVtxClip[idx].y);
|
||||
vdraw[k].x = floatToFixed16(pVtxClip[idx].x);
|
||||
vdraw[k].y = floatToFixed16(pVtxClip[idx].y);
|
||||
vdraw[k].z = floatToFixed16(pVtxClip[idx].z);
|
||||
}
|
||||
}
|
||||
Rasterize(vdraw, 3, dzdx);
|
||||
};
|
||||
|
||||
for (u32 i = 0; i < _numElements; i += 3) {
|
||||
u32 orbits = 0;
|
||||
u32 modify = 0;
|
||||
const SPVertex* vsrc[3];
|
||||
for (u32 j = 0; j < 3; ++j) {
|
||||
vsrc[j] = _pElements != nullptr ? &_pVertices[_pElements[i + j]] : &_pVertices[i + j];
|
||||
orbits |= vsrc[j]->clip;
|
||||
modify |= vsrc[j]->modify & (MODIFY_XY | MODIFY_Z);
|
||||
}
|
||||
|
||||
if (orbits == 0) {
|
||||
// No clipping is necessary.
|
||||
vertexclip vclip[3];
|
||||
bool clockwise = true;
|
||||
if (!calcScreenCoordinates(vsrc, vclip, 3, clockwise))
|
||||
// Culled
|
||||
continue;
|
||||
|
||||
// Copy vertices to result
|
||||
for (u32 k = 0; k < 3; ++k) {
|
||||
vResult.push_back(*vsrc[k]);
|
||||
SPVertex& v = vResult.back();
|
||||
v.bc0 = (k % 3 == 0) ? 1.0f : 0.0f;
|
||||
v.bc1 = (k % 3 == 1) ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
if (needResterise)
|
||||
rasterise(vclip, clockwise);
|
||||
} else {
|
||||
assert(modify == 0);
|
||||
// No screen space coordinates, so use clipping in homogeneous space.
|
||||
SPVertex vCopy[3];
|
||||
for (u32 k = 0; k < 3; ++k) {
|
||||
SPVertex& v = vCopy[k];
|
||||
v = *vsrc[k];
|
||||
v.bc0 = (k % 3 == 0) ? 1.0f : 0.0f;
|
||||
v.bc1 = (k % 3 == 1) ? 1.0f : 0.0f;
|
||||
}
|
||||
auto prevNumVtx = vResult.size();
|
||||
clipInHomogeneousSpace(vCopy, vResult);
|
||||
const u32 numVertex = vResult.size() - prevNumVtx;
|
||||
if (!needResterise || numVertex == 0)
|
||||
continue;
|
||||
|
||||
std::vector<vertexclip> vclip(numVertex);
|
||||
const bool wClipped = (orbits & CLIP_W) != 0;
|
||||
bool clockwise = true;
|
||||
if (!calcScreenCoordinates(vResult.data() + prevNumVtx, vclip.data(), numVertex, wClipped, clockwise)) {
|
||||
vResult.resize(prevNumVtx);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (u32 l = 0; l < numVertex; l += 3)
|
||||
rasterise(vclip.data() + l, clockwise);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vResult.empty()) {
|
||||
vResult[0].HWLight = _pVertices[0].HWLight;
|
||||
graphics::Context::DrawTriangleParameters triParams;
|
||||
triParams.mode = graphics::drawmode::TRIANGLES;
|
||||
triParams.flatColors = _flatColors;
|
||||
triParams.combiner = currentCombiner();
|
||||
triParams.verticesCount = static_cast<u32>(vResult.size());
|
||||
triParams.vertices = vResult.data();
|
||||
gfxContext.drawTriangles(triParams);
|
||||
}
|
||||
|
||||
return maxY;
|
||||
}
|
||||
@@ -2,7 +2,22 @@
|
||||
#define SOFTWARE_RENDER_H
|
||||
|
||||
#include "gSP.h"
|
||||
#include "Graphics/Context.h"
|
||||
|
||||
f32 renderTriangles(const SPVertex * _pVertices, const u16 * _pElements, u32 _numElements);
|
||||
/* Software render triangles to N64 depth buffer
|
||||
* Coordinates of vertices must be in screen space.
|
||||
* No coordinate clipping applied.
|
||||
*/
|
||||
f32 renderScreenSpaceTriangles(const SPVertex *_pVertices, u32 _numElements);
|
||||
|
||||
/* Software render triangles to N64 depth buffer
|
||||
* Coordinates of vertices can be in screen space or in homogeneous space
|
||||
*/
|
||||
f32 renderTriangles(const SPVertex *_pVertices, const u16 *_pElements, u32 _numElements);
|
||||
|
||||
/* Software render triangles to N64 depth buffer and draw them with GPU
|
||||
* Software clipping is used before rendering and drawing.
|
||||
*/
|
||||
f32 renderAndDrawTriangles(const SPVertex *_pVertices, const u16 *_pElements, u32 _numElements, bool _flatColors);
|
||||
|
||||
#endif // SOFTWARE_RENDER_H
|
||||
@@ -850,8 +850,9 @@ void gDPTextureRectangle(f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, s16 s, s1
|
||||
dsdx /= 4.0f;
|
||||
lrx += 1.0f;
|
||||
lry += 1.0f;
|
||||
} else if (lry - uly < 1.0f) {
|
||||
lry = ceil(lry);
|
||||
}
|
||||
lry = ceil(lry);
|
||||
|
||||
gDPTile *textureTileOrg[2];
|
||||
textureTileOrg[0] = gSP.textureTile[0];
|
||||
|
||||
@@ -2077,8 +2077,8 @@ void gSPSprite2DBase(u32 _base)
|
||||
|
||||
f32 uls = pSprite->imageX;
|
||||
f32 ult = pSprite->imageY;
|
||||
f32 lrs = uls + pSprite->imageW - 1;
|
||||
f32 lrt = ult + pSprite->imageH - 1;
|
||||
f32 lrs = uls + pSprite->imageW;
|
||||
f32 lrt = ult + pSprite->imageH;
|
||||
|
||||
// Hack for WCW Nitro.
|
||||
if ((config.generalEmulation.hacks & hack_WCWNitro) != 0) {
|
||||
|
||||
@@ -151,6 +151,8 @@ bool Config_SetDefault()
|
||||
assert(res == M64ERR_SUCCESS);
|
||||
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableCoverage", config.generalEmulation.enableCoverage, "Enable pixel coverage calculation. Used for better blending emulation and wire-frame mode. Needs fast GPU.");
|
||||
assert(res == M64ERR_SUCCESS);
|
||||
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableClipping", config.generalEmulation.enableClipping, "Enable software vertices clipping. Brings various benefits.");
|
||||
assert(res == M64ERR_SUCCESS);
|
||||
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableShadersStorage", config.generalEmulation.enableShadersStorage, "Use persistent storage for compiled shaders.");
|
||||
assert(res == M64ERR_SUCCESS);
|
||||
res = ConfigSetDefaultBool(g_configVideoGliden64, "EnableLegacyBlending", config.generalEmulation.enableLegacyBlending, "Do not use shaders to emulate N64 blending modes. Works faster on slow GPU. Can cause glitches.");
|
||||
@@ -364,6 +366,8 @@ void Config_LoadCustomConfig()
|
||||
if (result == M64ERR_SUCCESS) config.generalEmulation.enableHWLighting = atoi(value);
|
||||
result = ConfigExternalGetParameter(fileHandle, sectionName, "generalEmulation\\enableCoverage", value, sizeof(value));
|
||||
if (result == M64ERR_SUCCESS) config.generalEmulation.enableCoverage = atoi(value);
|
||||
result = ConfigExternalGetParameter(fileHandle, sectionName, "generalEmulation\\enableClipping", value, sizeof(value));
|
||||
if (result == M64ERR_SUCCESS) config.generalEmulation.enableClipping = atoi(value);
|
||||
result = ConfigExternalGetParameter(fileHandle, sectionName, "generalEmulation\\enableShadersStorage", value, sizeof(value));
|
||||
if (result == M64ERR_SUCCESS) config.generalEmulation.enableShadersStorage = atoi(value);
|
||||
result = ConfigExternalGetParameter(fileHandle, sectionName, "generalEmulation\\enableLegacyBlending", value, sizeof(value));
|
||||
@@ -488,6 +492,7 @@ void Config_LoadConfig()
|
||||
config.generalEmulation.enableLOD = ConfigGetParamBool(g_configVideoGliden64, "EnableLOD");
|
||||
config.generalEmulation.enableHWLighting = ConfigGetParamBool(g_configVideoGliden64, "EnableHWLighting");
|
||||
config.generalEmulation.enableCoverage = ConfigGetParamBool(g_configVideoGliden64, "EnableCoverage");
|
||||
config.generalEmulation.enableClipping = ConfigGetParamBool(g_configVideoGliden64, "enableClipping");
|
||||
config.generalEmulation.enableShadersStorage = ConfigGetParamBool(g_configVideoGliden64, "EnableShadersStorage");
|
||||
config.generalEmulation.enableLegacyBlending = ConfigGetParamBool(g_configVideoGliden64, "EnableLegacyBlending");
|
||||
config.generalEmulation.enableHybridFilter = ConfigGetParamBool(g_configVideoGliden64, "EnableHybridFilter");
|
||||
|
||||
Reference in new issue
Block a user