mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 13:55:38 +00:00
Floating point reversed z-buffer and new clipping code
Also always draw nodes with culling disabled even if they test as being outside the visible frustum
This commit is contained in:
parent
6f409539a7
commit
9f66fcaac7
|
@ -149,14 +149,12 @@ void Mat4::Rotate(float angle, float x, float y, float z)
|
||||||
Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
|
Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mat4::Frustum(float left, float right, float bottom, float top, float nearVal, float farVal)
|
void Mat4::Frustum(float left, float right, float bottom, float top, float nearVal)
|
||||||
{
|
{
|
||||||
float x = (2.0F*nearVal) / (right - left);
|
float x = 2.0F / (right - left);
|
||||||
float y = (2.0F*nearVal) / (top - bottom);
|
float y = 2.0F / (top - bottom);
|
||||||
float a = (right + left) / (right - left);
|
float a = (right + left) / (right - left);
|
||||||
float b = (top + bottom) / (top - bottom);
|
float b = (top + bottom) / (top - bottom);
|
||||||
float c = -(farVal + nearVal) / (farVal - nearVal);
|
|
||||||
float d = -(2.0F*farVal*nearVal) / (farVal - nearVal);
|
|
||||||
|
|
||||||
float m[16];
|
float m[16];
|
||||||
m[0] = x;
|
m[0] = x;
|
||||||
|
@ -171,30 +169,30 @@ void Mat4::Frustum(float left, float right, float bottom, float top, float nearV
|
||||||
|
|
||||||
m[8] = a;
|
m[8] = a;
|
||||||
m[9] = b;
|
m[9] = b;
|
||||||
m[10] = c;
|
m[10] = 0.f;
|
||||||
m[11] = -1.f;
|
m[11] = -1.f;
|
||||||
|
|
||||||
m[12] = 0.f;
|
m[12] = 0.f;
|
||||||
m[13] = 0.f;
|
m[13] = 0.f;
|
||||||
m[14] = d;
|
m[14] = nearVal;
|
||||||
m[15] = 0.f;
|
m[15] = 0.f;
|
||||||
|
|
||||||
Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
|
Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mat4::Perspective(float fovy, float aspect, float zNear, float zFar)
|
void Mat4::Perspective(float fovy, float aspect, float zNear)
|
||||||
{
|
{
|
||||||
float ymax = zNear * tanf(fovy * (float)(M_PI / 360.0));
|
float ymax = tanf(fovy * (float)(M_PI / 360.0));
|
||||||
float xmax = ymax * aspect;
|
float xmax = ymax * aspect;
|
||||||
|
|
||||||
Frustum(-xmax, xmax, -ymax, ymax, zNear, zFar);
|
Frustum(-xmax, xmax, -ymax, ymax, zNear);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mat4::Ortho(float left, float right, float bottom, float top, float nearVal, float farVal)
|
void Mat4::Ortho(float left, float right, float bottom, float top, float nearVal, float farVal)
|
||||||
{
|
{
|
||||||
float tx = -(right + left) / (right - left);
|
float tx = -(right + left) / (right - left);
|
||||||
float ty = -(top + bottom) / (top - bottom);
|
float ty = -(top + bottom) / (top - bottom);
|
||||||
float tz = -(farVal + nearVal) / (farVal - nearVal);
|
float tz = (farVal + nearVal - 1.f) / (farVal - nearVal);
|
||||||
|
|
||||||
float m[16];
|
float m[16];
|
||||||
m[0] = 2.f/(right-left);
|
m[0] = 2.f/(right-left);
|
||||||
|
@ -209,7 +207,7 @@ void Mat4::Ortho(float left, float right, float bottom, float top, float nearVal
|
||||||
|
|
||||||
m[8] = 0.f;
|
m[8] = 0.f;
|
||||||
m[9] = 0.f;
|
m[9] = 0.f;
|
||||||
m[10] = -2.f/(farVal-nearVal);
|
m[10] = 1.f/(farVal-nearVal);
|
||||||
m[11] = 0.f;
|
m[11] = 0.f;
|
||||||
|
|
||||||
m[12] = tx;
|
m[12] = tx;
|
||||||
|
|
|
@ -15,8 +15,8 @@ public:
|
||||||
void Translate (float x, float y, float z);
|
void Translate (float x, float y, float z);
|
||||||
void Rotate (float angle, float x, float y, float z);
|
void Rotate (float angle, float x, float y, float z);
|
||||||
void Scale (float x, float y, float z);
|
void Scale (float x, float y, float z);
|
||||||
void Frustum (float left, float right, float bottom, float top, float nearVal, float farVal);
|
void Frustum (float left, float right, float bottom, float top, float nearVal);
|
||||||
void Perspective (float fovy, float aspect, float zNear, float zFar);
|
void Perspective (float fovy, float aspect, float zNear);
|
||||||
void Ortho (float left, float right, float bottom, float top, float nearVal, float farVal);
|
void Ortho (float left, float right, float bottom, float top, float nearVal, float farVal);
|
||||||
void MultMatrix (const float *m);
|
void MultMatrix (const float *m);
|
||||||
void LoadMatrix (const float *m);
|
void LoadMatrix (const float *m);
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
#define BYTE_TO_FLOAT(B) ((2.0f * (B) + 1.0f) * (float)(1.0/255.0))
|
#define BYTE_TO_FLOAT(B) ((2.0f * (B) + 1.0f) * (float)(1.0/255.0))
|
||||||
|
|
||||||
|
#define NEAR_PLANE 1e-3f
|
||||||
|
|
||||||
namespace New3D {
|
namespace New3D {
|
||||||
|
|
||||||
CNew3D::CNew3D(const Util::Config::Node &config, const std::string& gameName) :
|
CNew3D::CNew3D(const Util::Config::Node &config, const std::string& gameName) :
|
||||||
|
@ -267,7 +269,7 @@ bool CNew3D::RenderScene(int priority, bool renderOverlay, Layer layer)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CalcViewport(&n.viewport, std::abs(m_nfPairs[priority].zNear*0.96f), std::abs(m_nfPairs[priority].zFar*1.05f)); // make planes 5% bigger
|
CalcViewport(&n.viewport);
|
||||||
glViewport(n.viewport.x, n.viewport.y, n.viewport.width, n.viewport.height);
|
glViewport(n.viewport.x, n.viewport.y, n.viewport.width, n.viewport.height);
|
||||||
|
|
||||||
m_r3dShader.SetViewportUniforms(&n.viewport);
|
m_r3dShader.SetViewportUniforms(&n.viewport);
|
||||||
|
@ -323,7 +325,7 @@ void CNew3D::SetRenderStates()
|
||||||
|
|
||||||
m_r3dShader.SetShader(true);
|
m_r3dShader.SetShader(true);
|
||||||
|
|
||||||
glDepthFunc (GL_LEQUAL);
|
glDepthFunc (GL_GEQUAL);
|
||||||
glEnable (GL_DEPTH_TEST);
|
glEnable (GL_DEPTH_TEST);
|
||||||
glDepthMask (GL_TRUE);
|
glDepthMask (GL_TRUE);
|
||||||
glActiveTexture (GL_TEXTURE0);
|
glActiveTexture (GL_TEXTURE0);
|
||||||
|
@ -348,11 +350,6 @@ void CNew3D::DisableRenderStates()
|
||||||
|
|
||||||
void CNew3D::RenderFrame(void)
|
void CNew3D::RenderFrame(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
m_nfPairs[i].zNear = -std::numeric_limits<float>::max();
|
|
||||||
m_nfPairs[i].zFar = std::numeric_limits<float>::max();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_losMutex);
|
std::lock_guard<std::mutex> guard(m_losMutex);
|
||||||
std::swap(m_losBack, m_losFront);
|
std::swap(m_losBack, m_losFront);
|
||||||
|
@ -411,6 +408,7 @@ void CNew3D::RenderFrame(void)
|
||||||
|
|
||||||
m_r3dFrameBuffers.SetFBO(Layer::colour);
|
m_r3dFrameBuffers.SetFBO(Layer::colour);
|
||||||
|
|
||||||
|
glClearDepth(0.0);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
m_r3dShader.DiscardAlpha(true);
|
m_r3dShader.DiscardAlpha(true);
|
||||||
|
@ -421,7 +419,7 @@ void CNew3D::RenderFrame(void)
|
||||||
ProcessLos(pri);
|
ProcessLos(pri);
|
||||||
}
|
}
|
||||||
|
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_GREATER);
|
||||||
|
|
||||||
m_r3dShader.DiscardAlpha(false);
|
m_r3dShader.DiscardAlpha(false);
|
||||||
|
|
||||||
|
@ -537,10 +535,6 @@ bool CNew3D::DrawModel(UINT32 modelAddr)
|
||||||
CacheModel(m, modelAddress);
|
CacheModel(m, modelAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_nodeAttribs.currentClipStatus != Clip::INSIDE) {
|
|
||||||
ClipModel(m); // not storing clipped values, only working out the Z range
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,7 +599,6 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
||||||
|
|
||||||
const UINT32 *node, *lodPtr;
|
const UINT32 *node, *lodPtr;
|
||||||
UINT32 matrixOffset, child1Ptr, sibling2Ptr;
|
UINT32 matrixOffset, child1Ptr, sibling2Ptr;
|
||||||
BBox bbox;
|
|
||||||
UINT16 uCullRadius;
|
UINT16 uCullRadius;
|
||||||
float fCullRadius;
|
float fCullRadius;
|
||||||
UINT16 uBlendRadius;
|
UINT16 uBlendRadius;
|
||||||
|
@ -679,10 +672,10 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
||||||
|
|
||||||
// apply translation vector
|
// apply translation vector
|
||||||
if (node[0x00] & 0x10) {
|
if (node[0x00] & 0x10) {
|
||||||
float x = Util::Uint32AsFloat(node[0x04 - m_offset]);
|
float centroid_x = Util::Uint32AsFloat(node[0x04 - m_offset]);
|
||||||
float y = Util::Uint32AsFloat(node[0x05 - m_offset]);
|
float centroid_y = Util::Uint32AsFloat(node[0x05 - m_offset]);
|
||||||
float z = Util::Uint32AsFloat(node[0x06 - m_offset]);
|
float centroid_z = Util::Uint32AsFloat(node[0x06 - m_offset]);
|
||||||
m_modelMat.Translate(x, y, z);
|
m_modelMat.Translate(centroid_x, centroid_y, centroid_z);
|
||||||
}
|
}
|
||||||
// multiply matrix, if specified
|
// multiply matrix, if specified
|
||||||
else if (matrixOffset) {
|
else if (matrixOffset) {
|
||||||
|
@ -693,42 +686,29 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
||||||
ResetMatrix(m_modelMat);
|
ResetMatrix(m_modelMat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float& x = m_modelMat.currentMatrix[12];
|
||||||
|
float& y = m_modelMat.currentMatrix[13];
|
||||||
|
float& z = m_modelMat.currentMatrix[14];
|
||||||
|
|
||||||
uCullRadius = node[9 - m_offset] & 0xFFFF;
|
uCullRadius = node[9 - m_offset] & 0xFFFF;
|
||||||
fCullRadius = R3DFloat::GetFloat16(uCullRadius);
|
fCullRadius = R3DFloat::GetFloat16(uCullRadius) * m_nodeAttribs.currentModelScale;;
|
||||||
|
|
||||||
uBlendRadius = node[9 - m_offset] >> 16;
|
uBlendRadius = node[9 - m_offset] >> 16;
|
||||||
fBlendRadius = R3DFloat::GetFloat16(uBlendRadius);
|
fBlendRadius = R3DFloat::GetFloat16(uBlendRadius) * m_nodeAttribs.currentModelScale;;
|
||||||
|
|
||||||
if (m_nodeAttribs.currentClipStatus != Clip::INSIDE) {
|
bool outsideFrustum = false;
|
||||||
|
if ((z * m_planes.bnlu - x * m_planes.bnlv * m_planes.correction) > fCullRadius ||
|
||||||
if (uCullRadius != R3DFloat::Pro16BitMax) {
|
(z * m_planes.bntu + y * m_planes.bntw) > fCullRadius ||
|
||||||
|
(z * m_planes.bnru - x * m_planes.bnrv * m_planes.correction) > fCullRadius ||
|
||||||
CalcBox(fCullRadius, bbox);
|
(z * m_planes.bnbu + y * m_planes.bnbw) > fCullRadius)
|
||||||
TransformBox(m_modelMat, bbox);
|
{
|
||||||
|
outsideFrustum = true;
|
||||||
m_nodeAttribs.currentClipStatus = ClipBox(bbox, m_planes);
|
|
||||||
|
|
||||||
if (m_nodeAttribs.currentClipStatus == Clip::INSIDE) {
|
|
||||||
CalcBoxExtents(bbox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_nodeAttribs.currentClipStatus = Clip::NOT_SET;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float LODscale;
|
float LODscale = m_nodeAttribs.currentDisableCulling ? std::numeric_limits<float>::max() : (fBlendRadius / std::hypot(x, y, z));
|
||||||
if (m_nodeAttribs.currentDisableCulling) {
|
const LOD *lod = m_LODBlendTable->table[lodTablePointer].lod;
|
||||||
LODscale = std::numeric_limits<float>::max();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
float distance = std::hypot(m_modelMat.currentMatrix[12], m_modelMat.currentMatrix[13], m_modelMat.currentMatrix[14]);
|
|
||||||
LODscale = fBlendRadius * m_nodeAttribs.currentModelScale / distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LODFeatureType& lodTableEntry = m_LODBlendTable->table[lodTablePointer];
|
if (m_nodeAttribs.currentDisableCulling || (!outsideFrustum && LODscale >= lod[3].deleteSize)) {
|
||||||
|
|
||||||
if (m_nodeAttribs.currentClipStatus != Clip::OUTSIDE && LODscale >= lodTableEntry.lod[3].deleteSize) {
|
|
||||||
|
|
||||||
// Descend down first link
|
// Descend down first link
|
||||||
if ((node[0x00] & 0x08)) // 4-element LOD table
|
if ((node[0x00] & 0x08)) // 4-element LOD table
|
||||||
|
@ -740,17 +720,17 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
||||||
int modelLOD;
|
int modelLOD;
|
||||||
for (modelLOD = 0; modelLOD < 3; modelLOD++)
|
for (modelLOD = 0; modelLOD < 3; modelLOD++)
|
||||||
{
|
{
|
||||||
if (LODscale >= lodTableEntry.lod[modelLOD].deleteSize && lodPtr[modelLOD] & 0x1000000)
|
if (LODscale >= lod[modelLOD].deleteSize && lodPtr[modelLOD] & 0x1000000)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
float tempAlpha = m_nodeAttribs.currentModelAlpha;
|
float tempAlpha = m_nodeAttribs.currentModelAlpha;
|
||||||
|
|
||||||
float nodeAlpha = lodTableEntry.lod[modelLOD].blendFactor * (LODscale - lodTableEntry.lod[modelLOD].deleteSize);
|
float nodeAlpha = lod[modelLOD].blendFactor * (LODscale - lod[modelLOD].deleteSize);
|
||||||
nodeAlpha = std::clamp(nodeAlpha, 0.0f, 1.0f);
|
nodeAlpha = std::clamp(nodeAlpha, 0.0f, 1.0f);
|
||||||
if (nodeAlpha > 15.0f / 16.0f) // shader discards pixels below 1/16 alpha
|
if (nodeAlpha > 31.0f / 32.0f) // shader discards pixels below 1/32 alpha
|
||||||
nodeAlpha = 1.0f;
|
nodeAlpha = 1.0f;
|
||||||
else if (nodeAlpha < 1.0f / 16.0f)
|
else if (nodeAlpha < 1.0f / 32.0f)
|
||||||
nodeAlpha = 0.0f;
|
nodeAlpha = 0.0f;
|
||||||
m_nodeAttribs.currentModelAlpha *= nodeAlpha; // alpha of each node multiples by the alpha of its parent
|
m_nodeAttribs.currentModelAlpha *= nodeAlpha; // alpha of each node multiples by the alpha of its parent
|
||||||
|
|
||||||
|
@ -776,7 +756,7 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
float nodeAlpha = lodTableEntry.lod[3].blendFactor * (LODscale - lodTableEntry.lod[3].deleteSize);
|
float nodeAlpha = lod[3].blendFactor * (LODscale - lod[3].deleteSize);
|
||||||
nodeAlpha = std::clamp(nodeAlpha, 0.0f, 1.0f);
|
nodeAlpha = std::clamp(nodeAlpha, 0.0f, 1.0f);
|
||||||
m_nodeAttribs.currentModelAlpha *= nodeAlpha; // alpha of each node multiples by the alpha of its parent
|
m_nodeAttribs.currentModelAlpha *= nodeAlpha; // alpha of each node multiples by the alpha of its parent
|
||||||
|
|
||||||
|
@ -1015,28 +995,27 @@ void CNew3D::RenderViewport(UINT32 addr)
|
||||||
|
|
||||||
m_LODBlendTable = (LODBlendTable*)TranslateCullingAddress(vpnode[0x17] & 0xFFFFFF);
|
m_LODBlendTable = (LODBlendTable*)TranslateCullingAddress(vpnode[0x17] & 0xFFFFFF);
|
||||||
|
|
||||||
/*
|
|
||||||
vp->angle_left = -atan2f(Util::Uint32AsFloat(vpnode[12]), Util::Uint32AsFloat(vpnode[13])); // These values work out as the normals for the clipping planes.
|
|
||||||
vp->angle_right = atan2f(Util::Uint32AsFloat(vpnode[16]), -Util::Uint32AsFloat(vpnode[17])); // Sometimes these values (dirt devils,lost world) are totally wrong
|
|
||||||
vp->angle_top = atan2f(Util::Uint32AsFloat(vpnode[14]), Util::Uint32AsFloat(vpnode[15])); // and don't work for the frustum values exactly.
|
|
||||||
vp->angle_bottom = -atan2f(Util::Uint32AsFloat(vpnode[18]), -Util::Uint32AsFloat(vpnode[19])); // Perhaps they are just used for culling and not rendering.
|
|
||||||
*/
|
|
||||||
|
|
||||||
float cv = Util::Uint32AsFloat(vpnode[0x8]); // 1/(left-right)
|
float cv = Util::Uint32AsFloat(vpnode[0x8]); // 1/(left-right)
|
||||||
float cw = Util::Uint32AsFloat(vpnode[0x9]); // 1/(top-bottom)
|
float cw = Util::Uint32AsFloat(vpnode[0x9]); // 1/(top-bottom)
|
||||||
float io = Util::Uint32AsFloat(vpnode[0xa]); // top / bottom (ratio) - ish
|
float io = Util::Uint32AsFloat(vpnode[0xa]); // top / bottom (ratio) - ish
|
||||||
float jo = Util::Uint32AsFloat(vpnode[0xb]); // left / right (ratio)
|
float jo = Util::Uint32AsFloat(vpnode[0xb]); // left / right (ratio)
|
||||||
|
|
||||||
|
// clipping plane normals
|
||||||
|
m_planes.bnlu = Util::Uint32AsFloat(vpnode[0xc]);
|
||||||
|
m_planes.bnlv = Util::Uint32AsFloat(vpnode[0xd]);
|
||||||
|
m_planes.bntu = Util::Uint32AsFloat(vpnode[0xe]);
|
||||||
|
m_planes.bntw = Util::Uint32AsFloat(vpnode[0xf]);
|
||||||
|
m_planes.bnru = Util::Uint32AsFloat(vpnode[0x10]);
|
||||||
|
m_planes.bnrv = Util::Uint32AsFloat(vpnode[0x11]);
|
||||||
|
m_planes.bnbu = Util::Uint32AsFloat(vpnode[0x12]);
|
||||||
|
m_planes.bnbw = Util::Uint32AsFloat(vpnode[0x13]);
|
||||||
|
|
||||||
vp->angle_left = (0.0f - jo) / cv;
|
vp->angle_left = (0.0f - jo) / cv;
|
||||||
vp->angle_right = (1.0f - jo) / cv;
|
vp->angle_right = (1.0f - jo) / cv;
|
||||||
vp->angle_bottom = -(1.0f - io)/ cw;
|
vp->angle_bottom = -(1.0f - io)/ cw;
|
||||||
vp->angle_top = -(0.0f - io)/ cw;
|
vp->angle_top = -(0.0f - io)/ cw;
|
||||||
|
|
||||||
// calculate the frustum shape, near/far pair are dummy values
|
CalcViewport(vp);
|
||||||
CalcViewport(vp, 1.f, 1000.f);
|
|
||||||
|
|
||||||
// calculate frustum planes
|
|
||||||
CalcFrustumPlanes(m_planes, vp->projectionMatrix); // we need to calc a 'projection matrix' to get the correct frustum planes for clipping
|
|
||||||
|
|
||||||
// Lighting (note that sun vector points toward sun -- away from vertex)
|
// Lighting (note that sun vector points toward sun -- away from vertex)
|
||||||
vp->lightingParams[0] = Util::Uint32AsFloat(vpnode[0x05]); // sun X
|
vp->lightingParams[0] = Util::Uint32AsFloat(vpnode[0x05]); // sun X
|
||||||
|
@ -1520,283 +1499,12 @@ bool CNew3D::IsVROMModel(UINT32 modelAddr)
|
||||||
return modelAddr >= 0x100000;
|
return modelAddr >= 0x100000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNew3D::CalcFrustumPlanes(Plane p[5], const float* matrix)
|
void CNew3D::CalcViewport(Viewport* vp)
|
||||||
{
|
{
|
||||||
// Left Plane
|
float l = vp->angle_left; // we need to calc the shape of the projection frustum for culling
|
||||||
p[0].a = matrix[3] + matrix[0];
|
float r = vp->angle_right;
|
||||||
p[0].b = matrix[7] + matrix[4];
|
float t = vp->angle_top;
|
||||||
p[0].c = matrix[11] + matrix[8];
|
float b = vp->angle_bottom;
|
||||||
p[0].d = matrix[15] + matrix[12];
|
|
||||||
p[0].Normalise();
|
|
||||||
|
|
||||||
// Right Plane
|
|
||||||
p[1].a = matrix[3] - matrix[0];
|
|
||||||
p[1].b = matrix[7] - matrix[4];
|
|
||||||
p[1].c = matrix[11] - matrix[8];
|
|
||||||
p[1].d = matrix[15] - matrix[12];
|
|
||||||
p[1].Normalise();
|
|
||||||
|
|
||||||
// Bottom Plane
|
|
||||||
p[2].a = matrix[3] + matrix[1];
|
|
||||||
p[2].b = matrix[7] + matrix[5];
|
|
||||||
p[2].c = matrix[11] + matrix[9];
|
|
||||||
p[2].d = matrix[15] + matrix[13];
|
|
||||||
p[2].Normalise();
|
|
||||||
|
|
||||||
// Top Plane
|
|
||||||
p[3].a = matrix[3] - matrix[1];
|
|
||||||
p[3].b = matrix[7] - matrix[5];
|
|
||||||
p[3].c = matrix[11] - matrix[9];
|
|
||||||
p[3].d = matrix[15] - matrix[13];
|
|
||||||
p[3].Normalise();
|
|
||||||
|
|
||||||
// Front Plane
|
|
||||||
p[4].a = 0.f;
|
|
||||||
p[4].b = 0.f;
|
|
||||||
p[4].c = -1.f;
|
|
||||||
p[4].d = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNew3D::CalcBox(float distance, BBox& box)
|
|
||||||
{
|
|
||||||
//bottom left front
|
|
||||||
box.points[0][0] = -distance;
|
|
||||||
box.points[0][1] = -distance;
|
|
||||||
box.points[0][2] = distance;
|
|
||||||
box.points[0][3] = 1.f;
|
|
||||||
|
|
||||||
//bottom left back
|
|
||||||
box.points[1][0] = -distance;
|
|
||||||
box.points[1][1] = -distance;
|
|
||||||
box.points[1][2] = -distance;
|
|
||||||
box.points[1][3] = 1.f;
|
|
||||||
|
|
||||||
//bottom right back
|
|
||||||
box.points[2][0] = distance;
|
|
||||||
box.points[2][1] = -distance;
|
|
||||||
box.points[2][2] = -distance;
|
|
||||||
box.points[2][3] = 1.f;
|
|
||||||
|
|
||||||
//bottom right front
|
|
||||||
box.points[3][0] = distance;
|
|
||||||
box.points[3][1] = -distance;
|
|
||||||
box.points[3][2] = distance;
|
|
||||||
box.points[3][3] = 1.f;
|
|
||||||
|
|
||||||
//top left front
|
|
||||||
box.points[4][0] = -distance;
|
|
||||||
box.points[4][1] = distance;
|
|
||||||
box.points[4][2] = distance;
|
|
||||||
box.points[4][3] = 1.f;
|
|
||||||
|
|
||||||
//top left back
|
|
||||||
box.points[5][0] = -distance;
|
|
||||||
box.points[5][1] = distance;
|
|
||||||
box.points[5][2] = -distance;
|
|
||||||
box.points[5][3] = 1.f;
|
|
||||||
|
|
||||||
//top right back
|
|
||||||
box.points[6][0] = distance;
|
|
||||||
box.points[6][1] = distance;
|
|
||||||
box.points[6][2] = -distance;
|
|
||||||
box.points[6][3] = 1.f;
|
|
||||||
|
|
||||||
//top right front
|
|
||||||
box.points[7][0] = distance;
|
|
||||||
box.points[7][1] = distance;
|
|
||||||
box.points[7][2] = distance;
|
|
||||||
box.points[7][3] = 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNew3D::MultVec(const float matrix[16], const float in[4], float out[4])
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
out[i] =
|
|
||||||
in[0] * matrix[0 * 4 + i] +
|
|
||||||
in[1] * matrix[1 * 4 + i] +
|
|
||||||
in[2] * matrix[2 * 4 + i] +
|
|
||||||
in[3] * matrix[3 * 4 + i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNew3D::TransformBox(const float *m, BBox& box)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
float v[4];
|
|
||||||
MultVec(m, box.points[i], v);
|
|
||||||
box.points[i][0] = v[0];
|
|
||||||
box.points[i][1] = v[1];
|
|
||||||
box.points[i][2] = v[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Clip CNew3D::ClipBox(const BBox& box, Plane planes[5])
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
|
|
||||||
int temp = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < 5; j++) {
|
|
||||||
if (planes[j].DistanceToPoint(box.points[i]) >= 0.f) {
|
|
||||||
temp++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (temp == 5) count++; // point is inside all 4 frustum planes
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 8) return Clip::INSIDE;
|
|
||||||
if (count > 0) return Clip::INTERCEPT;
|
|
||||||
|
|
||||||
//if we got here all points are outside of the view frustum
|
|
||||||
//check for all points being side same of any plane, means box outside of view
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
|
|
||||||
int temp = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
if (planes[i].DistanceToPoint(box.points[j]) >= 0.f) {
|
|
||||||
temp++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (temp == 0) {
|
|
||||||
return Clip::OUTSIDE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if we got here, box is traversing view frustum
|
|
||||||
|
|
||||||
return Clip::INTERCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNew3D::CalcBoxExtents(const BBox& box)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
if (box.points[i][2] < 0.f) {
|
|
||||||
m_nfPairs[m_currentPriority].zNear = std::max(box.points[i][2], m_nfPairs[m_currentPriority].zNear);
|
|
||||||
m_nfPairs[m_currentPriority].zFar = std::min(box.points[i][2], m_nfPairs[m_currentPriority].zFar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNew3D::ClipPolygon(ClipPoly& clipPoly, Plane planes[5])
|
|
||||||
{
|
|
||||||
//============
|
|
||||||
ClipPoly temp;
|
|
||||||
ClipPoly *in;
|
|
||||||
ClipPoly *out;
|
|
||||||
//============
|
|
||||||
|
|
||||||
in = &clipPoly;
|
|
||||||
out = &temp;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
|
|
||||||
//=================
|
|
||||||
bool currentIn;
|
|
||||||
float currentDot;
|
|
||||||
//=================
|
|
||||||
|
|
||||||
currentDot = planes[i].DotProduct(in->list[0].pos);
|
|
||||||
currentIn = (currentDot + planes[i].d) >= 0.f;
|
|
||||||
out->count = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < in->count; j++) {
|
|
||||||
|
|
||||||
if (currentIn) {
|
|
||||||
out->list[out->count] = in->list[j];
|
|
||||||
out->count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nextIndex = j + 1;
|
|
||||||
if (nextIndex >= in->count) {
|
|
||||||
nextIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float nextDot = planes[i].DotProduct(in->list[nextIndex].pos);
|
|
||||||
bool nextIn = (nextDot + planes[i].d) >= 0.f;
|
|
||||||
|
|
||||||
// we have an intersection
|
|
||||||
if (currentIn != nextIn) {
|
|
||||||
|
|
||||||
float u = (currentDot + planes[i].d) / (currentDot - nextDot);
|
|
||||||
|
|
||||||
const float* p1 = in->list[j].pos;
|
|
||||||
const float* p2 = in->list[nextIndex].pos;
|
|
||||||
|
|
||||||
out->list[out->count].pos[0] = p1[0] + ((p2[0] - p1[0]) * u);
|
|
||||||
out->list[out->count].pos[1] = p1[1] + ((p2[1] - p1[1]) * u);
|
|
||||||
out->list[out->count].pos[2] = p1[2] + ((p2[2] - p1[2]) * u);
|
|
||||||
out->count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDot = nextDot;
|
|
||||||
currentIn = nextIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::swap(in, out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNew3D::ClipModel(const Model *m)
|
|
||||||
{
|
|
||||||
//===============================
|
|
||||||
ClipPoly clipPoly;
|
|
||||||
std::vector<FVertex>* vertices;
|
|
||||||
int offset;
|
|
||||||
//===============================
|
|
||||||
|
|
||||||
if (m->dynamic) {
|
|
||||||
vertices = &m_polyBufferRam;
|
|
||||||
offset = MAX_ROM_VERTS;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vertices = &m_polyBufferRom;
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &mesh : *m->meshes) {
|
|
||||||
|
|
||||||
int start = mesh.vboOffset - offset;
|
|
||||||
|
|
||||||
for (int i = 0; i < mesh.vertexCount; i += m_numPolyVerts) { // inc to next poly
|
|
||||||
|
|
||||||
for (int j = 0; j < m_numPolyVerts; j++) {
|
|
||||||
MultVec(m->modelMat, (*vertices)[start + i + j].pos, clipPoly.list[j].pos); // copy all 3 of 4 our transformed vertices into our clip poly struct
|
|
||||||
}
|
|
||||||
|
|
||||||
clipPoly.count = m_numPolyVerts;
|
|
||||||
|
|
||||||
ClipPolygon(clipPoly, m_planes);
|
|
||||||
|
|
||||||
for (int j = 0; j < clipPoly.count; j++) {
|
|
||||||
if (clipPoly.list[j].pos[2] < 0.f) {
|
|
||||||
m_nfPairs[m_currentPriority].zNear = std::max(clipPoly.list[j].pos[2], m_nfPairs[m_currentPriority].zNear);
|
|
||||||
m_nfPairs[m_currentPriority].zFar = std::min(clipPoly.list[j].pos[2], m_nfPairs[m_currentPriority].zFar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNew3D::CalcViewport(Viewport* vp, float near, float far)
|
|
||||||
{
|
|
||||||
if (far > 1e30f) {
|
|
||||||
far = near * 1000000.f; // fix for ocean hunter which passes some FLT_MAX for a few matrices. HW must have some safe guard for these
|
|
||||||
}
|
|
||||||
|
|
||||||
if (near < far / 1000000.f) {
|
|
||||||
near = far / 1000000.f; // if we get really close to zero somehow, we will have almost no depth precision
|
|
||||||
}
|
|
||||||
|
|
||||||
float l = near * vp->angle_left; // we need to calc the shape of the projection frustum for culling
|
|
||||||
float r = near * vp->angle_right;
|
|
||||||
float t = near * vp->angle_top;
|
|
||||||
float b = near * vp->angle_bottom;
|
|
||||||
|
|
||||||
vp->projectionMatrix.LoadIdentity(); // reset matrix
|
vp->projectionMatrix.LoadIdentity(); // reset matrix
|
||||||
|
|
||||||
|
@ -1828,13 +1536,14 @@ void CNew3D::CalcViewport(Viewport* vp, float near, float far)
|
||||||
// screen and non-wide-screen modes have identical resolution parameters
|
// screen and non-wide-screen modes have identical resolution parameters
|
||||||
// and only their scissor box differs)
|
// and only their scissor box differs)
|
||||||
float correction = windowAR / viewableAreaAR;
|
float correction = windowAR / viewableAreaAR;
|
||||||
|
m_planes.correction = 1.0f / correction;
|
||||||
|
|
||||||
vp->x = 0;
|
vp->x = 0;
|
||||||
vp->y = m_yOffs + (int)((float)(384 - (vp->vpY + vp->vpHeight))*m_yRatio);
|
vp->y = m_yOffs + (int)((float)(384 - (vp->vpY + vp->vpHeight))*m_yRatio);
|
||||||
vp->width = m_totalXRes;
|
vp->width = m_totalXRes;
|
||||||
vp->height = (int)((float)vp->vpHeight*m_yRatio);
|
vp->height = (int)((float)vp->vpHeight*m_yRatio);
|
||||||
|
|
||||||
vp->projectionMatrix.Frustum(l*correction, r*correction, b, t, near, far);
|
vp->projectionMatrix.Frustum(l*correction, r*correction, b, t, NEAR_PLANE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
@ -1843,7 +1552,7 @@ void CNew3D::CalcViewport(Viewport* vp, float near, float far)
|
||||||
vp->width = (int)((float)vp->vpWidth*m_xRatio);
|
vp->width = (int)((float)vp->vpWidth*m_xRatio);
|
||||||
vp->height = (int)((float)vp->vpHeight*m_yRatio);
|
vp->height = (int)((float)vp->vpHeight*m_yRatio);
|
||||||
|
|
||||||
vp->projectionMatrix.Frustum(l, r, b, t, near, far);
|
vp->projectionMatrix.Frustum(l, r, b, t, NEAR_PLANE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1883,17 +1592,10 @@ bool CNew3D::ProcessLos(int priority)
|
||||||
int losX, losY;
|
int losX, losY;
|
||||||
TranslateLosPosition(n.viewport.losPosX, n.viewport.losPosY, losX, losY);
|
TranslateLosPosition(n.viewport.losPosX, n.viewport.losPosY, losX, losY);
|
||||||
|
|
||||||
float depth;
|
float range;
|
||||||
glReadPixels(losX, losY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
|
glReadPixels(losX, losY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &range);
|
||||||
|
|
||||||
depth = 2.0f * depth - 1.0f;
|
float zVal = range / NEAR_PLANE;
|
||||||
|
|
||||||
float zNear = m_nfPairs[priority].zNear;
|
|
||||||
float zFar = m_nfPairs[priority].zFar;
|
|
||||||
float zVal = 2.0f * zNear * zFar / (zFar + zNear - depth * (zFar - zNear));
|
|
||||||
|
|
||||||
// real3d test program indicates that return values are 1/zVal
|
|
||||||
zVal = 1.0f / zVal;
|
|
||||||
|
|
||||||
GLubyte stencilVal;
|
GLubyte stencilVal;
|
||||||
glReadPixels(losX, losY, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &stencilVal);
|
glReadPixels(losX, losY, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &stencilVal);
|
||||||
|
|
|
@ -287,31 +287,22 @@ private:
|
||||||
R3DScrollFog m_r3dScrollFog;
|
R3DScrollFog m_r3dScrollFog;
|
||||||
R3DFrameBuffers m_r3dFrameBuffers;
|
R3DFrameBuffers m_r3dFrameBuffers;
|
||||||
|
|
||||||
Plane m_planes[5];
|
|
||||||
|
|
||||||
struct BBox
|
|
||||||
{
|
|
||||||
V4::Vec4 points[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NFPair
|
|
||||||
{
|
|
||||||
float zNear;
|
|
||||||
float zFar;
|
|
||||||
};
|
|
||||||
|
|
||||||
NFPair m_nfPairs[4];
|
|
||||||
int m_currentPriority;
|
int m_currentPriority;
|
||||||
|
|
||||||
void CalcFrustumPlanes (Plane p[5], const float* matrix);
|
struct
|
||||||
void CalcBox (float distance, BBox& box);
|
{
|
||||||
void TransformBox (const float *m, BBox& box);
|
float bnlu;
|
||||||
void MultVec (const float matrix[16], const float in[4], float out[4]);
|
float bnlv;
|
||||||
Clip ClipBox (const BBox& box, Plane planes[5]);
|
float bntu;
|
||||||
void ClipModel (const Model *m);
|
float bntw;
|
||||||
void ClipPolygon (ClipPoly& clipPoly, Plane planes[5]);
|
float bnru;
|
||||||
void CalcBoxExtents (const BBox& box);
|
float bnrv;
|
||||||
void CalcViewport (Viewport* vp, float near, float far);
|
float bnbu;
|
||||||
|
float bnbw;
|
||||||
|
float correction;
|
||||||
|
} m_planes;
|
||||||
|
|
||||||
|
void CalcViewport (Viewport* vp);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // New3D
|
} // New3D
|
||||||
|
|
|
@ -59,7 +59,7 @@ bool R3DFrameBuffers::CreateFBO(int width, int height)
|
||||||
// depth/stencil attachment
|
// depth/stencil attachment
|
||||||
glGenRenderbuffers(1, &m_renderBufferID);
|
glGenRenderbuffers(1, &m_renderBufferID);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, m_renderBufferID);
|
glBindRenderbuffer(GL_RENDERBUFFER, m_renderBufferID);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, width, height);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferID);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferID);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferID);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferID);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ bool R3DFrameBuffers::CreateFBODepthCopy(int width, int height)
|
||||||
|
|
||||||
glGenRenderbuffers(1, &m_renderBufferIDCopy);
|
glGenRenderbuffers(1, &m_renderBufferIDCopy);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, m_renderBufferIDCopy);
|
glBindRenderbuffer(GL_RENDERBUFFER, m_renderBufferIDCopy);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, width, height);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferIDCopy);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferIDCopy);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferIDCopy);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferIDCopy);
|
||||||
|
|
||||||
|
|
|
@ -353,7 +353,7 @@ void QuadraticInterpolation()
|
||||||
depth = vertex.z * interp_oneOverW;
|
depth = vertex.z * interp_oneOverW;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FragDepth = depth * 0.5 + 0.5;
|
gl_FragDepth = depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
|
@ -376,7 +376,7 @@ void main()
|
||||||
Step15Luminous(colData); // no-op for step 2.0+
|
Step15Luminous(colData); // no-op for step 2.0+
|
||||||
finalData = tex1Data * colData;
|
finalData = tex1Data * colData;
|
||||||
|
|
||||||
if (finalData.a < (1.0/16.0)) { // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports
|
if (finalData.a < (1.0/32.0)) { // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +433,8 @@ void main()
|
||||||
sunFactor = clamp(sunFactor,-1.0,1.0);
|
sunFactor = clamp(sunFactor,-1.0,1.0);
|
||||||
|
|
||||||
// Optional clamping, value is allowed to be negative
|
// Optional clamping, value is allowed to be negative
|
||||||
if(sunClamp) {
|
// We suspect that translucent polygons are always clamped (e.g. lasers in Daytona 2)
|
||||||
|
if(sunClamp || fsColor.a < 0.99) {
|
||||||
sunFactor = max(sunFactor,0.0);
|
sunFactor = max(sunFactor,0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,9 @@ uniform bool fixedShading;
|
||||||
uniform int hardwareStep;
|
uniform int hardwareStep;
|
||||||
uniform int colourLayer;
|
uniform int colourLayer;
|
||||||
|
|
||||||
|
// matrices (shared with vertex shader)
|
||||||
|
uniform mat4 projMat;
|
||||||
|
|
||||||
//interpolated inputs from vertex shader
|
//interpolated inputs from vertex shader
|
||||||
in vec3 fsViewVertex;
|
in vec3 fsViewVertex;
|
||||||
in vec3 fsViewNormal; // per vertex normal vector
|
in vec3 fsViewNormal; // per vertex normal vector
|
||||||
|
@ -135,7 +138,9 @@ void main()
|
||||||
if(fsDiscard > 0) {
|
if(fsDiscard > 0) {
|
||||||
discard; //emulate back face culling here
|
discard; //emulate back face culling here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gl_FragDepth = projMat[3][2] * gl_FragCoord.w;
|
||||||
|
|
||||||
fogData = vec4(fogColour.rgb * fogAmbient, CalcFog());
|
fogData = vec4(fogColour.rgb * fogAmbient, CalcFog());
|
||||||
tex1Data = vec4(1.0, 1.0, 1.0, 1.0);
|
tex1Data = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
@ -147,7 +152,7 @@ void main()
|
||||||
Step15Luminous(colData); // no-op for step 2.0+
|
Step15Luminous(colData); // no-op for step 2.0+
|
||||||
finalData = tex1Data * colData;
|
finalData = tex1Data * colData;
|
||||||
|
|
||||||
if (finalData.a < (1.0/16.0)) { // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports
|
if (finalData.a < (1.0/32.0)) { // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +209,8 @@ void main()
|
||||||
sunFactor = clamp(sunFactor,-1.0,1.0);
|
sunFactor = clamp(sunFactor,-1.0,1.0);
|
||||||
|
|
||||||
// Optional clamping, value is allowed to be negative
|
// Optional clamping, value is allowed to be negative
|
||||||
if(sunClamp) {
|
// We suspect that translucent polygons are always clamped (e.g. lasers in Daytona 2)
|
||||||
|
if(sunClamp || fsColor.a < 0.99) {
|
||||||
sunFactor = max(sunFactor,0.0);
|
sunFactor = max(sunFactor,0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue