mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 05:45:38 +00:00
Merge pull request #122 from gm-matthew/floatZ
Floating point reversed z-buffer and new clipping code
This commit is contained in:
commit
33b84c89aa
|
@ -149,14 +149,14 @@ void Mat4::Rotate(float angle, float x, float y, float z)
|
|||
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 farVal)
|
||||
{
|
||||
float x = (2.0F*nearVal) / (right - left);
|
||||
float y = (2.0F*nearVal) / (top - bottom);
|
||||
float x = 2.0F / (right - left);
|
||||
float y = 2.0F / (top - bottom);
|
||||
float a = (right + left) / (right - left);
|
||||
float b = (top + bottom) / (top - bottom);
|
||||
float c = -(farVal + nearVal) / (farVal - nearVal);
|
||||
float d = -(2.0F*farVal*nearVal) / (farVal - nearVal);
|
||||
float d = -(2.0F * farVal * nearVal) / (farVal - nearVal);
|
||||
|
||||
float m[16];
|
||||
m[0] = x;
|
||||
|
@ -182,9 +182,40 @@ void Mat4::Frustum(float left, float right, float bottom, float top, float nearV
|
|||
Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
|
||||
}
|
||||
|
||||
void Mat4::FrustumRZ(float left, float right, float bottom, float top, float nearVal)
|
||||
{
|
||||
float x = 2.0F / (right - left);
|
||||
float y = 2.0F / (top - bottom);
|
||||
float a = (right + left) / (right - left);
|
||||
float b = (top + bottom) / (top - bottom);
|
||||
|
||||
float m[16];
|
||||
m[0] = x;
|
||||
m[1] = 0.f;
|
||||
m[2] = 0.f;
|
||||
m[3] = 0.f;
|
||||
|
||||
m[4] = 0.f;
|
||||
m[5] = y;
|
||||
m[6] = 0.f;
|
||||
m[7] = 0.f;
|
||||
|
||||
m[8] = a;
|
||||
m[9] = b;
|
||||
m[10] = 0.f;
|
||||
m[11] = -1.f;
|
||||
|
||||
m[12] = 0.f;
|
||||
m[13] = 0.f;
|
||||
m[14] = nearVal;
|
||||
m[15] = 0.f;
|
||||
|
||||
Mat4::MultiMatrices(currentMatrix, m, currentMatrix);
|
||||
}
|
||||
|
||||
void Mat4::Perspective(float fovy, float aspect, float zNear, float zFar)
|
||||
{
|
||||
float ymax = zNear * tanf(fovy * (float)(M_PI / 360.0));
|
||||
float ymax = tanf(fovy * (float)(M_PI / 360.0));
|
||||
float xmax = ymax * aspect;
|
||||
|
||||
Frustum(-xmax, xmax, -ymax, ymax, zNear, zFar);
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
void Rotate (float angle, 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 FrustumRZ (float left, float right, float bottom, float top, float nearVal);
|
||||
void Perspective (float fovy, float aspect, float zNear, float zFar);
|
||||
void Ortho (float left, float right, float bottom, float top, float nearVal, float farVal);
|
||||
void MultMatrix (const float *m);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#define BYTE_TO_FLOAT(B) ((2.0f * (B) + 1.0f) * (float)(1.0/255.0))
|
||||
|
||||
#define NEAR_PLANE 1e-3f
|
||||
|
||||
namespace New3D {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
m_r3dShader.SetViewportUniforms(&n.viewport);
|
||||
|
@ -323,7 +325,7 @@ void CNew3D::SetRenderStates()
|
|||
|
||||
m_r3dShader.SetShader(true);
|
||||
|
||||
glDepthFunc (GL_LEQUAL);
|
||||
glDepthFunc (GL_GEQUAL);
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
glDepthMask (GL_TRUE);
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
|
@ -348,11 +350,6 @@ void CNew3D::DisableRenderStates()
|
|||
|
||||
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::swap(m_losBack, m_losFront);
|
||||
|
@ -411,6 +408,7 @@ void CNew3D::RenderFrame(void)
|
|||
|
||||
m_r3dFrameBuffers.SetFBO(Layer::colour);
|
||||
|
||||
glClearDepth(0.0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
m_r3dShader.DiscardAlpha(true);
|
||||
|
@ -421,7 +419,7 @@ void CNew3D::RenderFrame(void)
|
|||
ProcessLos(pri);
|
||||
}
|
||||
|
||||
glDepthFunc(GL_LESS);
|
||||
glDepthFunc(GL_GREATER);
|
||||
|
||||
m_r3dShader.DiscardAlpha(false);
|
||||
|
||||
|
@ -537,10 +535,6 @@ bool CNew3D::DrawModel(UINT32 modelAddr)
|
|||
CacheModel(m, modelAddress);
|
||||
}
|
||||
|
||||
if (m_nodeAttribs.currentClipStatus != Clip::INSIDE) {
|
||||
ClipModel(m); // not storing clipped values, only working out the Z range
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -605,7 +599,6 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
|||
|
||||
const UINT32 *node, *lodPtr;
|
||||
UINT32 matrixOffset, child1Ptr, sibling2Ptr;
|
||||
BBox bbox;
|
||||
UINT16 uCullRadius;
|
||||
float fCullRadius;
|
||||
UINT16 uBlendRadius;
|
||||
|
@ -679,10 +672,10 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
|||
|
||||
// apply translation vector
|
||||
if (node[0x00] & 0x10) {
|
||||
float x = Util::Uint32AsFloat(node[0x04 - m_offset]);
|
||||
float y = Util::Uint32AsFloat(node[0x05 - m_offset]);
|
||||
float z = Util::Uint32AsFloat(node[0x06 - m_offset]);
|
||||
m_modelMat.Translate(x, y, z);
|
||||
float centroid_x = Util::Uint32AsFloat(node[0x04 - m_offset]);
|
||||
float centroid_y = Util::Uint32AsFloat(node[0x05 - m_offset]);
|
||||
float centroid_z = Util::Uint32AsFloat(node[0x06 - m_offset]);
|
||||
m_modelMat.Translate(centroid_x, centroid_y, centroid_z);
|
||||
}
|
||||
// multiply matrix, if specified
|
||||
else if (matrixOffset) {
|
||||
|
@ -693,42 +686,29 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
|||
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;
|
||||
fCullRadius = R3DFloat::GetFloat16(uCullRadius);
|
||||
fCullRadius = R3DFloat::GetFloat16(uCullRadius) * m_nodeAttribs.currentModelScale;;
|
||||
|
||||
uBlendRadius = node[9 - m_offset] >> 16;
|
||||
fBlendRadius = R3DFloat::GetFloat16(uBlendRadius);
|
||||
fBlendRadius = R3DFloat::GetFloat16(uBlendRadius) * m_nodeAttribs.currentModelScale;;
|
||||
|
||||
if (m_nodeAttribs.currentClipStatus != Clip::INSIDE) {
|
||||
|
||||
if (uCullRadius != R3DFloat::Pro16BitMax) {
|
||||
|
||||
CalcBox(fCullRadius, bbox);
|
||||
TransformBox(m_modelMat, bbox);
|
||||
|
||||
m_nodeAttribs.currentClipStatus = ClipBox(bbox, m_planes);
|
||||
|
||||
if (m_nodeAttribs.currentClipStatus == Clip::INSIDE) {
|
||||
CalcBoxExtents(bbox);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_nodeAttribs.currentClipStatus = Clip::NOT_SET;
|
||||
}
|
||||
bool outsideFrustum = false;
|
||||
if ((z * m_planes.bnlu - x * m_planes.bnlv * m_planes.correction) > fCullRadius ||
|
||||
(z * m_planes.bntu + y * m_planes.bntw) > fCullRadius ||
|
||||
(z * m_planes.bnru - x * m_planes.bnrv * m_planes.correction) > fCullRadius ||
|
||||
(z * m_planes.bnbu + y * m_planes.bnbw) > fCullRadius)
|
||||
{
|
||||
outsideFrustum = true;
|
||||
}
|
||||
|
||||
float LODscale;
|
||||
if (m_nodeAttribs.currentDisableCulling) {
|
||||
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;
|
||||
}
|
||||
float LODscale = m_nodeAttribs.currentDisableCulling ? std::numeric_limits<float>::max() : (fBlendRadius / std::hypot(x, y, z));
|
||||
const LOD *lod = m_LODBlendTable->table[lodTablePointer].lod;
|
||||
|
||||
const LODFeatureType& lodTableEntry = m_LODBlendTable->table[lodTablePointer];
|
||||
|
||||
if (m_nodeAttribs.currentClipStatus != Clip::OUTSIDE && LODscale >= lodTableEntry.lod[3].deleteSize) {
|
||||
if (m_nodeAttribs.currentDisableCulling || (!outsideFrustum && LODscale >= lod[3].deleteSize)) {
|
||||
|
||||
// Descend down first link
|
||||
if ((node[0x00] & 0x08)) // 4-element LOD table
|
||||
|
@ -740,17 +720,17 @@ void CNew3D::DescendCullingNode(UINT32 addr)
|
|||
int 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;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
else if (nodeAlpha < 1.0f / 16.0f)
|
||||
else if (nodeAlpha < 1.0f / 32.0f)
|
||||
nodeAlpha = 0.0f;
|
||||
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 {
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
/*
|
||||
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 cw = Util::Uint32AsFloat(vpnode[0x9]); // 1/(top-bottom)
|
||||
float io = Util::Uint32AsFloat(vpnode[0xa]); // top / bottom (ratio) - ish
|
||||
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_right = (1.0f - jo) / cv;
|
||||
vp->angle_bottom = -(1.0f - io)/ cw;
|
||||
vp->angle_top = -(0.0f - io)/ cw;
|
||||
|
||||
// calculate the frustum shape, near/far pair are dummy values
|
||||
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
|
||||
CalcViewport(vp);
|
||||
|
||||
// Lighting (note that sun vector points toward sun -- away from vertex)
|
||||
vp->lightingParams[0] = Util::Uint32AsFloat(vpnode[0x05]); // sun X
|
||||
|
@ -1520,283 +1499,12 @@ bool CNew3D::IsVROMModel(UINT32 modelAddr)
|
|||
return modelAddr >= 0x100000;
|
||||
}
|
||||
|
||||
void CNew3D::CalcFrustumPlanes(Plane p[5], const float* matrix)
|
||||
void CNew3D::CalcViewport(Viewport* vp)
|
||||
{
|
||||
// Left Plane
|
||||
p[0].a = matrix[3] + matrix[0];
|
||||
p[0].b = matrix[7] + matrix[4];
|
||||
p[0].c = matrix[11] + matrix[8];
|
||||
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;
|
||||
float l = vp->angle_left; // we need to calc the shape of the projection frustum for culling
|
||||
float r = vp->angle_right;
|
||||
float t = vp->angle_top;
|
||||
float b = vp->angle_bottom;
|
||||
|
||||
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
|
||||
// and only their scissor box differs)
|
||||
float correction = windowAR / viewableAreaAR;
|
||||
m_planes.correction = 1.0f / correction;
|
||||
|
||||
vp->x = 0;
|
||||
vp->y = m_yOffs + (int)((float)(384 - (vp->vpY + vp->vpHeight))*m_yRatio);
|
||||
vp->width = m_totalXRes;
|
||||
vp->height = (int)((float)vp->vpHeight*m_yRatio);
|
||||
|
||||
vp->projectionMatrix.Frustum(l*correction, r*correction, b, t, near, far);
|
||||
vp->projectionMatrix.FrustumRZ(l*correction, r*correction, b, t, NEAR_PLANE);
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -1843,7 +1552,7 @@ void CNew3D::CalcViewport(Viewport* vp, float near, float far)
|
|||
vp->width = (int)((float)vp->vpWidth*m_xRatio);
|
||||
vp->height = (int)((float)vp->vpHeight*m_yRatio);
|
||||
|
||||
vp->projectionMatrix.Frustum(l, r, b, t, near, far);
|
||||
vp->projectionMatrix.FrustumRZ(l, r, b, t, NEAR_PLANE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1883,17 +1592,10 @@ bool CNew3D::ProcessLos(int priority)
|
|||
int losX, losY;
|
||||
TranslateLosPosition(n.viewport.losPosX, n.viewport.losPosY, losX, losY);
|
||||
|
||||
float depth;
|
||||
glReadPixels(losX, losY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
|
||||
float range;
|
||||
glReadPixels(losX, losY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &range);
|
||||
|
||||
depth = 2.0f * depth - 1.0f;
|
||||
|
||||
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;
|
||||
float zVal = range / NEAR_PLANE;
|
||||
|
||||
GLubyte stencilVal;
|
||||
glReadPixels(losX, losY, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &stencilVal);
|
||||
|
|
|
@ -287,31 +287,22 @@ private:
|
|||
R3DScrollFog m_r3dScrollFog;
|
||||
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;
|
||||
|
||||
void CalcFrustumPlanes (Plane p[5], const float* matrix);
|
||||
void CalcBox (float distance, BBox& box);
|
||||
void TransformBox (const float *m, BBox& box);
|
||||
void MultVec (const float matrix[16], const float in[4], float out[4]);
|
||||
Clip ClipBox (const BBox& box, Plane planes[5]);
|
||||
void ClipModel (const Model *m);
|
||||
void ClipPolygon (ClipPoly& clipPoly, Plane planes[5]);
|
||||
void CalcBoxExtents (const BBox& box);
|
||||
void CalcViewport (Viewport* vp, float near, float far);
|
||||
struct
|
||||
{
|
||||
float bnlu;
|
||||
float bnlv;
|
||||
float bntu;
|
||||
float bntw;
|
||||
float bnru;
|
||||
float bnrv;
|
||||
float bnbu;
|
||||
float bnbw;
|
||||
float correction;
|
||||
} m_planes;
|
||||
|
||||
void CalcViewport (Viewport* vp);
|
||||
};
|
||||
|
||||
} // New3D
|
||||
|
|
|
@ -59,7 +59,7 @@ bool R3DFrameBuffers::CreateFBO(int width, int height)
|
|||
// depth/stencil attachment
|
||||
glGenRenderbuffers(1, &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_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferID);
|
||||
|
||||
|
@ -80,7 +80,7 @@ bool R3DFrameBuffers::CreateFBODepthCopy(int width, int height)
|
|||
|
||||
glGenRenderbuffers(1, &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_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_renderBufferIDCopy);
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader)
|
|||
m_locTextureInverted = glGetUniformLocation(m_shaderProgram, "textureInverted");
|
||||
m_locTexWrapMode = glGetUniformLocation(m_shaderProgram, "textureWrapMode");
|
||||
m_locColourLayer = glGetUniformLocation(m_shaderProgram, "colourLayer");
|
||||
m_locPolyAlpha = glGetUniformLocation(m_shaderProgram, "polyAlpha");
|
||||
|
||||
m_locFogIntensity = glGetUniformLocation(m_shaderProgram, "fogIntensity");
|
||||
m_locFogDensity = glGetUniformLocation(m_shaderProgram, "fogDensity");
|
||||
|
@ -292,6 +293,11 @@ void R3DShader::SetMeshUniforms(const Mesh* m)
|
|||
m_translatorMap = m->translatorMap;
|
||||
}
|
||||
|
||||
if (m_dirtyMesh || m->polyAlpha != m_polyAlpha) {
|
||||
glUniform1i(m_locPolyAlpha, m->polyAlpha);
|
||||
m_polyAlpha = m->polyAlpha;
|
||||
}
|
||||
|
||||
if (m_dirtyMesh || m->wrapModeU != m_texWrapMode[0] || m->wrapModeV != m_texWrapMode[1]) {
|
||||
m_texWrapMode[0] = m->wrapModeU;
|
||||
m_texWrapMode[1] = m->wrapModeV;
|
||||
|
|
|
@ -55,6 +55,7 @@ private:
|
|||
GLint m_locTexWrapMode;
|
||||
GLint m_locTranslatorMap;
|
||||
GLint m_locColourLayer;
|
||||
GLint m_locPolyAlpha;
|
||||
|
||||
// cached mesh values
|
||||
bool m_textured1;
|
||||
|
@ -68,6 +69,7 @@ private:
|
|||
bool m_specularEnabled;
|
||||
bool m_fixedShading;
|
||||
bool m_translatorMap;
|
||||
bool m_polyAlpha;
|
||||
|
||||
bool m_layered;
|
||||
bool m_noLosReturn;
|
||||
|
|
|
@ -211,6 +211,7 @@ uniform float fogAmbient;
|
|||
uniform bool fixedShading;
|
||||
uniform int hardwareStep;
|
||||
uniform int colourLayer;
|
||||
uniform bool polyAlpha;
|
||||
|
||||
// matrices (shared with vertex shader)
|
||||
uniform mat4 projMat;
|
||||
|
@ -353,7 +354,7 @@ void QuadraticInterpolation()
|
|||
depth = vertex.z * interp_oneOverW;
|
||||
}
|
||||
|
||||
gl_FragDepth = depth * 0.5 + 0.5;
|
||||
gl_FragDepth = depth;
|
||||
}
|
||||
|
||||
void main()
|
||||
|
@ -376,7 +377,7 @@ void main()
|
|||
Step15Luminous(colData); // no-op for step 2.0+
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -433,7 +434,8 @@ void main()
|
|||
sunFactor = clamp(sunFactor,-1.0,1.0);
|
||||
|
||||
// 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 || polyAlpha) {
|
||||
sunFactor = max(sunFactor,0.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,10 @@ uniform float fogAmbient;
|
|||
uniform bool fixedShading;
|
||||
uniform int hardwareStep;
|
||||
uniform int colourLayer;
|
||||
uniform bool polyAlpha;
|
||||
|
||||
// matrices (shared with vertex shader)
|
||||
uniform mat4 projMat;
|
||||
|
||||
//interpolated inputs from vertex shader
|
||||
in vec3 fsViewVertex;
|
||||
|
@ -135,7 +139,9 @@ void main()
|
|||
if(fsDiscard > 0) {
|
||||
discard; //emulate back face culling here
|
||||
}
|
||||
|
||||
|
||||
gl_FragDepth = projMat[3][2] * gl_FragCoord.w;
|
||||
|
||||
fogData = vec4(fogColour.rgb * fogAmbient, CalcFog());
|
||||
tex1Data = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
|
@ -147,7 +153,7 @@ void main()
|
|||
Step15Luminous(colData); // no-op for step 2.0+
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -204,7 +210,8 @@ void main()
|
|||
sunFactor = clamp(sunFactor,-1.0,1.0);
|
||||
|
||||
// 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 || polyAlpha) {
|
||||
sunFactor = max(sunFactor,0.0);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue