Render3D: Refactor the Render3D class in order to better reflect how the 3D renderers do things now.

This commit is contained in:
rogerman 2019-02-01 17:57:33 -08:00
parent 3e73a550e3
commit 4f8b788e97
9 changed files with 727 additions and 658 deletions

View File

@ -341,9 +341,9 @@ varying vec2 vtxTexCoord;\n\
varying vec4 vtxColor;\n\
\n\
uniform sampler2D texRenderObject;\n\
uniform sampler1D texToonTable;\n\
\n\
uniform float stateAlphaTestRef;\n\
uniform vec4 stateToonColor[32];\n\
\n\
uniform int polyMode;\n\
uniform bool polyIsWireframe;\n\
@ -411,7 +411,7 @@ void main()\n\
}\n\
else if (polyMode == 2)\n\
{\n\
vec3 newToonColor = vec3(texture1D(texToonTable, vtxColor.r).rgb);\n\
vec3 newToonColor = stateToonColor[int((vtxColor.r * 31.0) + 0.5)].rgb;\n\
#if TOON_SHADING_MODE\n\
newFragColor.rgb = min((mainTexColor.rgb * vtxColor.r) + newToonColor.rgb, 1.0);\n\
#else\n\
@ -1308,13 +1308,15 @@ OpenGLRenderer::OpenGLRenderer()
_workingTextureUnpackBuffer = (FragmentColor *)malloc_alignedCacheLine(1024 * 1024 * sizeof(FragmentColor));
_pixelReadNeedsFinish = false;
_needsZeroDstAlphaPass = true;
_renderNeedsDepthEqualsTest = false;
_currentPolyIndex = 0;
_currentAlphaTestRef = 0;
_enableAlphaBlending = true;
_lastTextureDrawTarget = OGLTextureUnitID_GColor;
_geometryProgramFlags.value = 0;
_fogProgramKey.key = 0;
_fogProgramMap.clear();
_clearImageIndex = 0;
memset(&_pendingRenderStates, 0, sizeof(_pendingRenderStates));
}
OpenGLRenderer::~OpenGLRenderer()
@ -1884,13 +1886,13 @@ OpenGLTexture* OpenGLRenderer::GetLoadedTextureFromPolygon(const POLY &thePoly,
}
template <OGLPolyDrawMode DRAWMODE>
size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr)
size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr)
{
OGLRenderRef &OGLRef = *this->ref;
if (lastIndex > (this->_clippedPolyCount - 1))
if (lastIndex > (clippedPolyCount - 1))
{
lastIndex = this->_clippedPolyCount - 1;
lastIndex = clippedPolyCount - 1;
}
if (firstIndex > lastIndex)
@ -1915,7 +1917,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const
};
// Set up the initial polygon
const POLY &initialPoly = *this->_clippedPolyList[firstIndex].poly;
const POLY &initialPoly = *clippedPolyList[firstIndex].poly;
TEXIMAGE_PARAM lastTexParams = initialPoly.texParam;
u32 lastTexPalette = initialPoly.texPalette;
u32 lastViewport = initialPoly.viewport;
@ -1929,7 +1931,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const
for (size_t i = firstIndex; i <= lastIndex; i++)
{
const POLY &thePoly = *this->_clippedPolyList[i].poly;
const POLY &thePoly = *clippedPolyList[i].poly;
// Set up the polygon if it changed
if (lastPolyAttr.value != thePoly.attribute.value)
@ -1969,7 +1971,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const
// the same and we're not drawing a line loop or line strip.
if (i+1 <= lastIndex)
{
const POLY &nextPoly = *this->_clippedPolyList[i+1].poly;
const POLY &nextPoly = *clippedPolyList[i+1].poly;
if (lastPolyAttr.value == nextPoly.attribute.value &&
lastTexParams.value == nextPoly.texParam.value &&
@ -3217,9 +3219,7 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
glUseProgram(OGLRef.programGeometryID[flagsValue]);
const GLint uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texRenderObject");
const GLint uniformTexToonTable = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texToonTable");
glUniform1i(uniformTexRenderObject, 0);
glUniform1i(uniformTexToonTable, OGLTextureUnitID_ToonTable);
if (this->_emulateDepthLEqualPolygonFacing && !programFlags.OpaqueDrawMode)
{
@ -3228,6 +3228,7 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
}
OGLRef.uniformStateAlphaTestRef[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "stateAlphaTestRef");
OGLRef.uniformStateToonColor[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "stateToonColor");
OGLRef.uniformPolyTexScale[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyTexScale");
OGLRef.uniformPolyMode[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyMode");
@ -3246,8 +3247,6 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
OGLRef.uniformPolyDepthOffsetMode[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffsetMode");
}
this->CreateToonTable();
return OGLERROR_NOERR;
}
@ -3278,8 +3277,6 @@ void OpenGLRenderer_1_2::DestroyGeometryPrograms()
glDeleteShader(OGLRef.vertexGeometryShaderID);
OGLRef.vertexGeometryShaderID = 0;
this->DestroyToonTable();
}
Render3DError OpenGLRenderer_1_2::CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString)
@ -3429,8 +3426,16 @@ Render3DError OpenGLRenderer_1_2::CreateFogProgram(const OGLFogProgramKey fogPro
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
if (vtxShaderCString == NULL)
{
INFO("OpenGL: The FOG vertex shader is unavailable.\n");
error = OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR;
return error;
}
else if (fragShaderCString == NULL)
{
INFO("OpenGL: The FOG fragment shader is unavailable.\n");
error = OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR;
return error;
}
@ -3913,36 +3918,6 @@ Render3DError OpenGLRenderer_1_2::InitPostprocessingPrograms(const char *edgeMar
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::CreateToonTable()
{
OGLRenderRef &OGLRef = *this->ref;
u16 tempToonTable[32];
memset(tempToonTable, 0, sizeof(tempToonTable));
// The toon table is a special 1D texture where each pixel corresponds
// to a specific color in the toon table.
glGenTextures(1, &OGLRef.texToonTableID);
glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable);
glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, tempToonTable);
glActiveTextureARB(GL_TEXTURE0_ARB);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::DestroyToonTable()
{
glDeleteTextures(1, &this->ref->texToonTableID);
this->ref->texToonTableID = 0;
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID)
{
OGLRenderRef &OGLRef = *this->ref;
@ -4022,13 +3997,15 @@ void OpenGLRenderer_1_2::_SetupGeometryShaders(const OGLGeometryFlags flags)
if (!this->isShaderSupported)
{
if (this->isFBOSupported)
{
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
}
return;
}
glUseProgram(OGLRef.programGeometryID[flags.value]);
glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID);
glUniform1f(OGLRef.uniformStateClearDepth, (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF);
glUniform1f(OGLRef.uniformStateAlphaTestRef[flags.value], divide5bitBy31_LUT[this->_currentAlphaTestRef]);
glUniform1f(OGLRef.uniformStateAlphaTestRef[flags.value], this->_pendingRenderStates.alphaTestRef);
glUniform1i(OGLRef.uniformTexDrawOpaque[flags.value], GL_FALSE);
glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[flags.value], GL_FALSE);
glUniform1i(OGLRef.uniformPolyDrawShadow[flags.value], GL_FALSE);
@ -4037,10 +4014,6 @@ void OpenGLRenderer_1_2::_SetupGeometryShaders(const OGLGeometryFlags flags)
{
glDrawBuffers(4, GeometryDrawBuffersEnum[flags.DrawBuffersMode]);
}
else
{
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
}
}
Render3DError OpenGLRenderer_1_2::EnableVertexAttributes()
@ -4112,7 +4085,7 @@ Render3DError OpenGLRenderer_1_2::DisableVertexAttributes()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
{
OGLRenderRef &OGLRef = *this->ref;
@ -4195,7 +4168,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(polyList, indexList, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(clippedPolyList, clippedPolyCount, this->_clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr);
// Restore OpenGL states back to normal.
this->_geometryProgramFlags = oldGProgramFlags;
@ -4397,7 +4370,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
{
OGLRenderRef &OGLRef = *this->ref;
if(!BEGINGL())
if (!BEGINGL())
{
return OGLERROR_BEGINGL_FAILED;
}
@ -4406,6 +4379,8 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
this->_clippedPolyList = engine.clippedPolyList;
this->_enableAlphaBlending = (engine.renderState.enableAlphaBlending) ? true : false;
if (this->isVBOSupported)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
@ -4423,7 +4398,9 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
}
// Generate the clipped polygon list.
this->_renderNeedsDepthEqualsTest = false;
bool renderNeedsToonTable = false;
bool renderNeedsDepthEqualsTest = false;
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
{
const POLY &thePoly = *this->_clippedPolyList[i].poly;
@ -4507,7 +4484,8 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x);
}
this->_renderNeedsDepthEqualsTest = this->_renderNeedsDepthEqualsTest || (thePoly.attribute.DepthEqualTest_Enable != 0);
renderNeedsToonTable = (renderNeedsToonTable || (thePoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT)) && this->isShaderSupported;
renderNeedsDepthEqualsTest = renderNeedsDepthEqualsTest || (thePoly.attribute.DepthEqualTest_Enable != 0);
this->_isPolyFrontFacing[i] = (facing < 0);
// Get the texture that is to be attached to this polygon.
@ -4521,23 +4499,76 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(OGLRef.vertIndexBuffer), OGLRef.vertIndexBuffer);
}
// Set up rendering states that will remain constant for the entire frame.
this->_pendingRenderStates.enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[engine.renderState.alphaTestRef];
if (renderNeedsToonTable)
{
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.toonColor[i].r = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] ) & 0x001F];
this->_pendingRenderStates.toonColor[i].g = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.toonColor[i].b = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.toonColor[i].a = 1.0f;
}
}
if (this->_deviceInfo.isFogSupported && this->_enableFog)
{
this->_fogProgramKey.key = 0;
this->_fogProgramKey.offset = engine.renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = engine.renderState.fogShift;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(engine.renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(engine.renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(engine.renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(engine.renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(engine.renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> engine.renderState.fogShift) / 32767.0f;
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.fogDensity[i] = (engine.renderState.fogDensityTable[i] == 127) ? 1.0f : (GLfloat)engine.renderState.fogDensityTable[i] / 128.0f;
}
}
if (this->_deviceInfo.isEdgeMarkSupported && this->_enableEdgeMark)
{
const GLfloat edgeColorAlpha = (engine.renderState.enableAntialiasing) ? (16.0f/31.0f) : 1.0f;
for (size_t i = 0; i < 8; i++)
{
this->_pendingRenderStates.edgeColor[i].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] ) & 0x001F];
this->_pendingRenderStates.edgeColor[i].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.edgeColor[i].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.edgeColor[i].a = edgeColorAlpha;
}
}
if (this->isShaderSupported)
{
this->_geometryProgramFlags.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0;
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (renderNeedsDepthEqualsTest) ? 1 : 0;
this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0;
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0;
this->_geometryProgramFlags.OpaqueDrawMode = 1;
this->_currentAlphaTestRef = engine.renderState.alphaTestRef;
this->_SetupGeometryShaders(this->_geometryProgramFlags);
if (renderNeedsToonTable)
{
glUniform4fv(OGLRef.uniformStateToonColor[this->_geometryProgramFlags.value], 32, (const GLfloat *)&this->_pendingRenderStates.toonColor);
}
}
else
{
if(engine.renderState.enableAlphaTest && (engine.renderState.alphaTestRef > 0))
if (engine.renderState.enableAlphaTest && (engine.renderState.alphaTestRef > 0))
{
glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
}
@ -4548,11 +4579,11 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
}
if (!this->isFBOSupported || !this->isShaderSupported)
{
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
if (this->isFBOSupported)
{
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
}
}
glReadBuffer(GL_COLOROUT_ATTACHMENT_ID);
@ -4565,14 +4596,14 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList)
Render3DError OpenGLRenderer_1_2::RenderGeometry()
{
if (this->_clippedPolyCount > 0)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
if (renderState.enableAlphaBlending)
if (this->_enableAlphaBlending)
{
glEnable(GL_BLEND);
}
@ -4593,7 +4624,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
if (this->_clippedPolyOpaqueCount > 0)
{
this->SetupPolygon(firstPoly, false, true);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(polyList, indexList, 0, this->_clippedPolyOpaqueCount - 1, indexOffset, lastPolyAttr);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(this->_clippedPolyList, this->_clippedPolyCount, 0, this->_clippedPolyOpaqueCount - 1, indexOffset, lastPolyAttr);
}
if (this->_clippedPolyOpaqueCount < this->_clippedPolyCount)
@ -4607,7 +4638,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
this->SetupPolygon(firstPoly, true, false);
}
this->ZeroDstAlphaPass(polyList, indexList, renderState.enableAlphaBlending, indexOffset, lastPolyAttr);
this->ZeroDstAlphaPass(this->_clippedPolyList, this->_clippedPolyCount, this->_enableAlphaBlending, indexOffset, lastPolyAttr);
if (this->_clippedPolyOpaqueCount > 0)
{
@ -4637,7 +4668,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
this->_ResolveWorkingBackFacing();
}
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(polyList, indexList, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr);
}
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@ -4652,188 +4683,109 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias)
Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer()
{
if (!this->_deviceInfo.isEdgeMarkSupported)
{
return OGLERROR_FEATURE_UNSUPPORTED;
}
OGLRenderRef &OGLRef = *this->ref;
const GLfloat alpha = (useAntialias) ? (16.0f/31.0f) : 1.0f;
const GLfloat oglColor[4*8] = {divide5bitBy31_LUT[(colorTable[0] ) & 0x001F],
divide5bitBy31_LUT[(colorTable[0] >> 5) & 0x001F],
divide5bitBy31_LUT[(colorTable[0] >> 10) & 0x001F],
alpha,
divide5bitBy31_LUT[(colorTable[1] ) & 0x001F],
divide5bitBy31_LUT[(colorTable[1] >> 5) & 0x001F],
divide5bitBy31_LUT[(colorTable[1] >> 10) & 0x001F],
alpha,
divide5bitBy31_LUT[(colorTable[2] ) & 0x001F],
divide5bitBy31_LUT[(colorTable[2] >> 5) & 0x001F],
divide5bitBy31_LUT[(colorTable[2] >> 10) & 0x001F],
alpha,
divide5bitBy31_LUT[(colorTable[3] ) & 0x001F],
divide5bitBy31_LUT[(colorTable[3] >> 5) & 0x001F],
divide5bitBy31_LUT[(colorTable[3] >> 10) & 0x001F],
alpha,
divide5bitBy31_LUT[(colorTable[4] ) & 0x001F],
divide5bitBy31_LUT[(colorTable[4] >> 5) & 0x001F],
divide5bitBy31_LUT[(colorTable[4] >> 10) & 0x001F],
alpha,
divide5bitBy31_LUT[(colorTable[5] ) & 0x001F],
divide5bitBy31_LUT[(colorTable[5] >> 5) & 0x001F],
divide5bitBy31_LUT[(colorTable[5] >> 10) & 0x001F],
alpha,
divide5bitBy31_LUT[(colorTable[6] ) & 0x001F],
divide5bitBy31_LUT[(colorTable[6] >> 5) & 0x001F],
divide5bitBy31_LUT[(colorTable[6] >> 10) & 0x001F],
alpha,
divide5bitBy31_LUT[(colorTable[7] ) & 0x001F],
divide5bitBy31_LUT[(colorTable[7] >> 5) & 0x001F],
divide5bitBy31_LUT[(colorTable[7] >> 10) & 0x001F],
alpha};
// Set up the postprocessing states
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
if (this->isVAOSupported)
if ( (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ||
(this->_enableFog && this->_deviceInfo.isFogSupported) )
{
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
}
else
{
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8));
}
if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending)
{
// Pass 1: Determine the pixels with zero alpha
glDrawBuffer(GL_NONE);
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0x40, 0x40);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0x40);
// Set up the postprocessing states
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
// Pass 2: Unblended edge mark colors to zero-alpha pixels
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glUseProgram(OGLRef.programEdgeMarkID);
glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID);
glUniform1f(OGLRef.uniformStateClearDepth, (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF);
glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Pass 3: Blended edge mark
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
else
{
glUseProgram(OGLRef.programEdgeMarkID);
glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID);
glUniform1f(OGLRef.uniformStateClearDepth, (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF);
glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor);
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
if (this->isVAOSupported)
{
glBindVertexArray(0);
}
else
{
glDisableVertexAttribArray(OGLVertexAttributeID_Position);
glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
}
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 color, const u16 offset, const u8 shift, const bool alphaOnly)
{
if (!this->_deviceInfo.isFogSupported)
{
return OGLERROR_FEATURE_UNSUPPORTED;
}
OGLFogProgramKey fogProgramKey;
fogProgramKey.key = 0;
fogProgramKey.offset = offset;
fogProgramKey.shift = shift;
std::map<u32, OGLFogShaderID>::iterator it = this->_fogProgramMap.find(fogProgramKey.key);
if (it == this->_fogProgramMap.end())
{
Render3DError error = this->CreateFogProgram(fogProgramKey, FogVtxShader_100, FogFragShader_100);
if (error != OGLERROR_NOERR)
if (this->isVAOSupported)
{
return error;
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
}
else
{
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8));
}
}
else
{
return OGLERROR_NOERR;
}
if (this->_enableEdgeMark)
{
if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending)
{
// Pass 1: Determine the pixels with zero alpha
glDrawBuffer(GL_NONE);
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0x40, 0x40);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0x40);
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Pass 2: Unblended edge mark colors to zero-alpha pixels
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glUseProgram(OGLRef.programEdgeMarkID);
glUniform1i(OGLRef.uniformStateClearPolyID, this->_pendingRenderStates.clearPolyID);
glUniform1f(OGLRef.uniformStateClearDepth, this->_pendingRenderStates.clearDepth);
glUniform4fv(OGLRef.uniformStateEdgeColor, 8, (const GLfloat *)this->_pendingRenderStates.edgeColor);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Pass 3: Blended edge mark
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
else
{
glUseProgram(OGLRef.programEdgeMarkID);
glUniform1i(OGLRef.uniformStateClearPolyID, this->_pendingRenderStates.clearPolyID);
glUniform1f(OGLRef.uniformStateClearDepth, this->_pendingRenderStates.clearDepth);
glUniform4fv(OGLRef.uniformStateEdgeColor, 8, (const GLfloat *)this->_pendingRenderStates.edgeColor);
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
OGLFogShaderID shaderID = this->_fogProgramMap[fogProgramKey.key];
OGLRenderRef &OGLRef = *this->ref;
static GLfloat oglDensityTable[32];
for (size_t i = 0; i < 32; i++)
if (this->_enableFog)
{
oglDensityTable[i] = (densityTable[i] == 127) ? 1.0f : (GLfloat)densityTable[i] / 128.0f;
std::map<u32, OGLFogShaderID>::iterator it = this->_fogProgramMap.find(this->_fogProgramKey.key);
if (it == this->_fogProgramMap.end())
{
Render3DError error = this->CreateFogProgram(this->_fogProgramKey, FogVtxShader_100, FogFragShader_100);
if (error != OGLERROR_NOERR)
{
return error;
}
}
OGLFogShaderID shaderID = this->_fogProgramMap[this->_fogProgramKey.key];
glDrawBuffer(GL_WORKING_ATTACHMENT_ID);
glUseProgram(shaderID.program);
glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, this->_pendingRenderStates.enableFogAlphaOnly);
glUniform4fv(OGLRef.uniformStateFogColor, 1, (const GLfloat *)&this->_pendingRenderStates.fogColor);
glUniform1fv(OGLRef.uniformStateFogDensity, 32, (const GLfloat *)this->_pendingRenderStates.fogDensity);
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
}
const GLfloat oglColor[4] = {divide5bitBy31_LUT[(color ) & 0x0000001F],
divide5bitBy31_LUT[(color >> 5) & 0x0000001F],
divide5bitBy31_LUT[(color >> 10) & 0x0000001F],
divide5bitBy31_LUT[(color >> 16) & 0x0000001F]};
glDrawBuffer(GL_WORKING_ATTACHMENT_ID);
glUseProgram(shaderID.program);
glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (alphaOnly) ? GL_TRUE : GL_FALSE);
glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]);
glUniform1fv(OGLRef.uniformStateFogDensity, 32, oglDensityTable);
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
if (this->isVAOSupported)
{
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
}
else
{
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8));
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (this->isVAOSupported)
{
glBindVertexArray(0);
@ -4844,12 +4796,10 @@ Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 co
glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
}
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount)
Render3DError OpenGLRenderer_1_2::EndRender()
{
//needs to happen before endgl because it could free some textureids for expired cache items
texCache.Evict();
@ -4861,17 +4811,6 @@ Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount)
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::UpdateToonTable(const u16 *toonTableBuffer)
{
if (this->isShaderSupported)
{
glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer);
}
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID)
{
if (!this->isFBOSupported)
@ -5420,13 +5359,13 @@ Render3DError OpenGLRenderer_1_2::Reset()
memset(OGLRef.color4fBuffer, 0, VERTLIST_SIZE * 4 * sizeof(GLfloat));
}
this->_renderNeedsDepthEqualsTest = false;
this->_currentPolyIndex = 0;
OGLRef.vtxPtrPosition = (GLvoid *)offsetof(VERT, coord);
OGLRef.vtxPtrTexCoord = (GLvoid *)offsetof(VERT, texcoord);
OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)offsetof(VERT, color) : OGLRef.color4fBuffer;
memset(&this->_pendingRenderStates, 0, sizeof(this->_pendingRenderStates));
memset(this->_isPolyFrontFacing, 0, sizeof(this->_isPolyFrontFacing));
texCache.Reset();
@ -5711,7 +5650,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
{
OGLRenderRef &OGLRef = *this->ref;
if(!BEGINGL())
if (!BEGINGL())
{
return OGLERROR_BEGINGL_FAILED;
}
@ -5720,6 +5659,8 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
this->_clippedPolyList = engine.clippedPolyList;
this->_enableAlphaBlending = (engine.renderState.enableAlphaBlending) ? true : false;
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
@ -5727,7 +5668,9 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * engine.vertListCount, engine.vertList);
// Generate the clipped polygon list.
this->_renderNeedsDepthEqualsTest = false;
bool renderNeedsToonTable = false;
bool renderNeedsDepthEqualsTest = false;
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
{
const POLY &thePoly = *this->_clippedPolyList[i].poly;
@ -5773,7 +5716,8 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x);
}
this->_renderNeedsDepthEqualsTest = this->_renderNeedsDepthEqualsTest || (thePoly.attribute.DepthEqualTest_Enable != 0);
renderNeedsToonTable = renderNeedsToonTable || (thePoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT);
renderNeedsDepthEqualsTest = renderNeedsDepthEqualsTest || (thePoly.attribute.DepthEqualTest_Enable != 0);
this->_isPolyFrontFacing[i] = (facing < 0);
// Get the texture that is to be attached to this polygon.
@ -5784,18 +5728,72 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
// avoid a synchronization cost.
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(OGLRef.vertIndexBuffer), OGLRef.vertIndexBuffer);
// Set up rendering states that will remain constant for the entire frame.
this->_pendingRenderStates.enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[engine.renderState.alphaTestRef];
if (renderNeedsToonTable)
{
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.toonColor[i].r = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] ) & 0x001F];
this->_pendingRenderStates.toonColor[i].g = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.toonColor[i].b = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.toonColor[i].a = 1.0f;
}
}
if (this->_deviceInfo.isFogSupported && this->_enableFog)
{
this->_fogProgramKey.key = 0;
this->_fogProgramKey.offset = engine.renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = engine.renderState.fogShift;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(engine.renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(engine.renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(engine.renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(engine.renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(engine.renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> engine.renderState.fogShift) / 32767.0f;
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.fogDensity[i] = (engine.renderState.fogDensityTable[i] == 127) ? 1.0f : (GLfloat)engine.renderState.fogDensityTable[i] / 128.0f;
}
}
if (this->_deviceInfo.isEdgeMarkSupported && this->_enableEdgeMark)
{
const GLfloat edgeColorAlpha = (engine.renderState.enableAntialiasing) ? (16.0f/31.0f) : 1.0f;
for (size_t i = 0; i < 8; i++)
{
this->_pendingRenderStates.edgeColor[i].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] ) & 0x001F];
this->_pendingRenderStates.edgeColor[i].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.edgeColor[i].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.edgeColor[i].a = edgeColorAlpha;
}
}
// Setup render states
this->_geometryProgramFlags.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0;
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (renderNeedsDepthEqualsTest) ? 1 : 0;
this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0;
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0;
this->_geometryProgramFlags.OpaqueDrawMode = 1;
this->_currentAlphaTestRef = engine.renderState.alphaTestRef;
this->_SetupGeometryShaders(this->_geometryProgramFlags);
if (renderNeedsToonTable)
{
glUniform4fv(OGLRef.uniformStateToonColor[this->_geometryProgramFlags.value], 32, (const GLfloat *)&this->_pendingRenderStates.toonColor);
}
glReadBuffer(GL_COLOROUT_ATTACHMENT_ID);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@ -5890,6 +5888,6 @@ Render3DError OpenGLRenderer_2_1::RenderFlush(bool willFlushBuffer32, bool willF
return RENDER3DERROR_NOERR;
}
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);

View File

@ -312,7 +312,6 @@ enum OGLTextureUnitID
{
// Main textures will always be on texture unit 0.
OGLTextureUnitID_FinalColor = 1,
OGLTextureUnitID_ToonTable,
OGLTextureUnitID_GColor,
OGLTextureUnitID_DepthStencil,
OGLTextureUnitID_GPolyID,
@ -394,8 +393,8 @@ struct OGLRenderStates
GLfloat fogOffset;
GLfloat fogStep;
GLfloat pad_0; // This needs to be here to preserve alignment
GLfloat fogDensity[32];
GLvec4 fogColor;
GLvec4 fogDensity[32]; // Array of floats need to be padded as vec4
GLvec4 edgeColor[8];
GLvec4 toonColor[32];
};
@ -553,6 +552,7 @@ struct OGLRenderRef
GLint uniformStateFogDensity;
GLint uniformStateAlphaTestRef[256];
GLint uniformStateToonColor[256];
GLint uniformPolyTexScale[256];
GLint uniformPolyMode[256];
GLint uniformPolyIsWireframe[256];
@ -570,8 +570,6 @@ struct OGLRenderRef
GLint uniformPolyDepthOffsetMode[256];
GLint uniformPolyDrawShadow[256];
GLuint texToonTableID;
// VAO
GLuint vaoGeometryStatesID;
GLuint vaoPostprocessStatesID;
@ -713,13 +711,15 @@ protected:
FragmentColor *_workingTextureUnpackBuffer;
bool _pixelReadNeedsFinish;
bool _needsZeroDstAlphaPass;
bool _renderNeedsDepthEqualsTest;
size_t _currentPolyIndex;
u8 _currentAlphaTestRef;
bool _enableAlphaBlending;
OGLTextureUnitID _lastTextureDrawTarget;
OGLGeometryFlags _geometryProgramFlags;
OGLFogProgramKey _fogProgramKey;
std::map<u32, OGLFogShaderID> _fogProgramMap;
CACHE_ALIGN OGLRenderStates _pendingRenderStates;
bool _enableMultisampledRendering;
int _selectedMultisampleSize;
bool _isPolyFrontFacing[POLYLIST_SIZE];
@ -728,7 +728,7 @@ protected:
Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16);
OpenGLTexture* GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing);
template<OGLPolyDrawMode DRAWMODE> size_t DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template<OGLPolyDrawMode DRAWMODE> size_t DrawPolygonsForIndexRange(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template<OGLPolyDrawMode DRAWMODE> Render3DError DrawAlphaTexturePolygon(const GLenum polyPrimitive,
const GLsizei vertIndexCount,
const GLushort *indexBufferPtr,
@ -779,8 +779,6 @@ protected:
const char *framebufferOutputRGBA6665FragShader,
const char *framebufferOutputRGBA8888FragShader) = 0;
virtual Render3DError CreateToonTable() = 0;
virtual Render3DError DestroyToonTable() = 0;
virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID) = 0;
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet) = 0;
@ -856,25 +854,22 @@ protected:
const char *framebufferOutputRGBA6665FragShader,
const char *framebufferOutputRGBA8888FragShader);
virtual Render3DError CreateToonTable();
virtual Render3DError DestroyToonTable();
virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels();
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u16 offset, const u8 shift, const bool alphaOnly);
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError RenderGeometry();
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError EndRender();
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);
@ -890,7 +885,6 @@ public:
~OpenGLRenderer_1_2();
virtual Render3DError InitExtensions();
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError Reset();
virtual Render3DError RenderPowerOff();
virtual Render3DError RenderFinish();

View File

@ -194,8 +194,39 @@ layout (std140) uniform RenderStates\n\
float fogOffset;\n\
float fogStep;\n\
float pad_0;\n\
float fogDensity_00;\n\
float fogDensity_01;\n\
float fogDensity_02;\n\
float fogDensity_03;\n\
float fogDensity_04;\n\
float fogDensity_05;\n\
float fogDensity_06;\n\
float fogDensity_07;\n\
float fogDensity_08;\n\
float fogDensity_09;\n\
float fogDensity_10;\n\
float fogDensity_11;\n\
float fogDensity_12;\n\
float fogDensity_13;\n\
float fogDensity_14;\n\
float fogDensity_15;\n\
float fogDensity_16;\n\
float fogDensity_17;\n\
float fogDensity_18;\n\
float fogDensity_19;\n\
float fogDensity_20;\n\
float fogDensity_21;\n\
float fogDensity_22;\n\
float fogDensity_23;\n\
float fogDensity_24;\n\
float fogDensity_25;\n\
float fogDensity_26;\n\
float fogDensity_27;\n\
float fogDensity_28;\n\
float fogDensity_29;\n\
float fogDensity_30;\n\
float fogDensity_31;\n\
vec4 fogColor;\n\
float fogDensity[32];\n\
vec4 edgeColor[8];\n\
vec4 toonColor[32];\n\
} state;\n\
@ -417,8 +448,39 @@ layout (std140) uniform RenderStates\n\
float fogOffset;\n\
float fogStep;\n\
float pad_0;\n\
float fogDensity_00;\n\
float fogDensity_01;\n\
float fogDensity_02;\n\
float fogDensity_03;\n\
float fogDensity_04;\n\
float fogDensity_05;\n\
float fogDensity_06;\n\
float fogDensity_07;\n\
float fogDensity_08;\n\
float fogDensity_09;\n\
float fogDensity_10;\n\
float fogDensity_11;\n\
float fogDensity_12;\n\
float fogDensity_13;\n\
float fogDensity_14;\n\
float fogDensity_15;\n\
float fogDensity_16;\n\
float fogDensity_17;\n\
float fogDensity_18;\n\
float fogDensity_19;\n\
float fogDensity_20;\n\
float fogDensity_21;\n\
float fogDensity_22;\n\
float fogDensity_23;\n\
float fogDensity_24;\n\
float fogDensity_25;\n\
float fogDensity_26;\n\
float fogDensity_27;\n\
float fogDensity_28;\n\
float fogDensity_29;\n\
float fogDensity_30;\n\
float fogDensity_31;\n\
vec4 fogColor;\n\
float fogDensity[32];\n\
vec4 edgeColor[8];\n\
vec4 toonColor[32];\n\
} state;\n\
@ -457,8 +519,39 @@ layout (std140) uniform RenderStates\n\
float fogOffset;\n\
float fogStep;\n\
float pad_0;\n\
float fogDensity_00;\n\
float fogDensity_01;\n\
float fogDensity_02;\n\
float fogDensity_03;\n\
float fogDensity_04;\n\
float fogDensity_05;\n\
float fogDensity_06;\n\
float fogDensity_07;\n\
float fogDensity_08;\n\
float fogDensity_09;\n\
float fogDensity_10;\n\
float fogDensity_11;\n\
float fogDensity_12;\n\
float fogDensity_13;\n\
float fogDensity_14;\n\
float fogDensity_15;\n\
float fogDensity_16;\n\
float fogDensity_17;\n\
float fogDensity_18;\n\
float fogDensity_19;\n\
float fogDensity_20;\n\
float fogDensity_21;\n\
float fogDensity_22;\n\
float fogDensity_23;\n\
float fogDensity_24;\n\
float fogDensity_25;\n\
float fogDensity_26;\n\
float fogDensity_27;\n\
float fogDensity_28;\n\
float fogDensity_29;\n\
float fogDensity_30;\n\
float fogDensity_31;\n\
vec4 fogColor;\n\
float fogDensity[32];\n\
vec4 edgeColor[8];\n\
vec4 toonColor[32];\n\
} state;\n\
@ -568,8 +661,39 @@ layout (std140) uniform RenderStates\n\
float fogOffset;\n\
float fogStep;\n\
float pad_0;\n\
float fogDensity_00;\n\
float fogDensity_01;\n\
float fogDensity_02;\n\
float fogDensity_03;\n\
float fogDensity_04;\n\
float fogDensity_05;\n\
float fogDensity_06;\n\
float fogDensity_07;\n\
float fogDensity_08;\n\
float fogDensity_09;\n\
float fogDensity_10;\n\
float fogDensity_11;\n\
float fogDensity_12;\n\
float fogDensity_13;\n\
float fogDensity_14;\n\
float fogDensity_15;\n\
float fogDensity_16;\n\
float fogDensity_17;\n\
float fogDensity_18;\n\
float fogDensity_19;\n\
float fogDensity_20;\n\
float fogDensity_21;\n\
float fogDensity_22;\n\
float fogDensity_23;\n\
float fogDensity_24;\n\
float fogDensity_25;\n\
float fogDensity_26;\n\
float fogDensity_27;\n\
float fogDensity_28;\n\
float fogDensity_29;\n\
float fogDensity_30;\n\
float fogDensity_31;\n\
vec4 fogColor;\n\
float fogDensity[32];\n\
vec4 edgeColor[8];\n\
vec4 toonColor[32];\n\
} state;\n\
@ -597,8 +721,39 @@ layout (std140) uniform RenderStates\n\
float fogOffset;\n\
float fogStep;\n\
float pad_0;\n\
float fogDensity_00;\n\
float fogDensity_01;\n\
float fogDensity_02;\n\
float fogDensity_03;\n\
float fogDensity_04;\n\
float fogDensity_05;\n\
float fogDensity_06;\n\
float fogDensity_07;\n\
float fogDensity_08;\n\
float fogDensity_09;\n\
float fogDensity_10;\n\
float fogDensity_11;\n\
float fogDensity_12;\n\
float fogDensity_13;\n\
float fogDensity_14;\n\
float fogDensity_15;\n\
float fogDensity_16;\n\
float fogDensity_17;\n\
float fogDensity_18;\n\
float fogDensity_19;\n\
float fogDensity_20;\n\
float fogDensity_21;\n\
float fogDensity_22;\n\
float fogDensity_23;\n\
float fogDensity_24;\n\
float fogDensity_25;\n\
float fogDensity_26;\n\
float fogDensity_27;\n\
float fogDensity_28;\n\
float fogDensity_29;\n\
float fogDensity_30;\n\
float fogDensity_31;\n\
vec4 fogColor;\n\
float fogDensity[32];\n\
vec4 edgeColor[8];\n\
vec4 toonColor[32];\n\
} state;\n\
@ -623,135 +778,135 @@ void main()\n\
\n\
if (inFragDepth <= FOG_DEPTH_COMPARE_0)\n\
{\n\
fogMixWeight = state.fogDensity[0];\n\
fogMixWeight = state.fogDensity_00;\n\
}\n\
else if (inFragDepth >= FOG_DEPTH_COMPARE_31)\n\
{\n\
fogMixWeight = state.fogDensity[31];\n\
fogMixWeight = state.fogDensity_31;\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_1)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 0], state.fogDensity[ 1], (inFragDepth - FOG_DEPTH_COMPARE_0) * FOG_DEPTH_INVDIFF_1);\n\
fogMixWeight = mix(state.fogDensity_00, state.fogDensity_01, (inFragDepth - FOG_DEPTH_COMPARE_0) * FOG_DEPTH_INVDIFF_1);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_2)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 1], state.fogDensity[ 2], (inFragDepth - FOG_DEPTH_COMPARE_1) * FOG_DEPTH_INVDIFF_2);\n\
fogMixWeight = mix(state.fogDensity_01, state.fogDensity_02, (inFragDepth - FOG_DEPTH_COMPARE_1) * FOG_DEPTH_INVDIFF_2);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_3)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 2], state.fogDensity[ 3], (inFragDepth - FOG_DEPTH_COMPARE_2) * FOG_DEPTH_INVDIFF_3);\n\
fogMixWeight = mix(state.fogDensity_02, state.fogDensity_03, (inFragDepth - FOG_DEPTH_COMPARE_2) * FOG_DEPTH_INVDIFF_3);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_4)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 3], state.fogDensity[ 4], (inFragDepth - FOG_DEPTH_COMPARE_3) * FOG_DEPTH_INVDIFF_4);\n\
fogMixWeight = mix(state.fogDensity_03, state.fogDensity_04, (inFragDepth - FOG_DEPTH_COMPARE_3) * FOG_DEPTH_INVDIFF_4);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_5)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 4], state.fogDensity[ 5], (inFragDepth - FOG_DEPTH_COMPARE_4) * FOG_DEPTH_INVDIFF_5);\n\
fogMixWeight = mix(state.fogDensity_04, state.fogDensity_05, (inFragDepth - FOG_DEPTH_COMPARE_4) * FOG_DEPTH_INVDIFF_5);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_6)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 5], state.fogDensity[ 6], (inFragDepth - FOG_DEPTH_COMPARE_5) * FOG_DEPTH_INVDIFF_6);\n\
fogMixWeight = mix(state.fogDensity_05, state.fogDensity_06, (inFragDepth - FOG_DEPTH_COMPARE_5) * FOG_DEPTH_INVDIFF_6);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_7)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 6], state.fogDensity[ 7], (inFragDepth - FOG_DEPTH_COMPARE_6) * FOG_DEPTH_INVDIFF_7);\n\
fogMixWeight = mix(state.fogDensity_06, state.fogDensity_07, (inFragDepth - FOG_DEPTH_COMPARE_6) * FOG_DEPTH_INVDIFF_7);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_8)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 7], state.fogDensity[ 8], (inFragDepth - FOG_DEPTH_COMPARE_7) * FOG_DEPTH_INVDIFF_8);\n\
fogMixWeight = mix(state.fogDensity_07, state.fogDensity_08, (inFragDepth - FOG_DEPTH_COMPARE_7) * FOG_DEPTH_INVDIFF_8);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_9)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 8], state.fogDensity[ 9], (inFragDepth - FOG_DEPTH_COMPARE_8) * FOG_DEPTH_INVDIFF_9);\n\
fogMixWeight = mix(state.fogDensity_08, state.fogDensity_09, (inFragDepth - FOG_DEPTH_COMPARE_8) * FOG_DEPTH_INVDIFF_9);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_10)\n\
{\n\
fogMixWeight = mix(state.fogDensity[ 9], state.fogDensity[10], (inFragDepth - FOG_DEPTH_COMPARE_9) * FOG_DEPTH_INVDIFF_10);\n\
fogMixWeight = mix(state.fogDensity_09, state.fogDensity_10, (inFragDepth - FOG_DEPTH_COMPARE_9) * FOG_DEPTH_INVDIFF_10);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_11)\n\
{\n\
fogMixWeight = mix(state.fogDensity[10], state.fogDensity[11], (inFragDepth - FOG_DEPTH_COMPARE_10) * FOG_DEPTH_INVDIFF_11);\n\
fogMixWeight = mix(state.fogDensity_10, state.fogDensity_11, (inFragDepth - FOG_DEPTH_COMPARE_10) * FOG_DEPTH_INVDIFF_11);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_12)\n\
{\n\
fogMixWeight = mix(state.fogDensity[11], state.fogDensity[12], (inFragDepth - FOG_DEPTH_COMPARE_11) * FOG_DEPTH_INVDIFF_12);\n\
fogMixWeight = mix(state.fogDensity_11, state.fogDensity_12, (inFragDepth - FOG_DEPTH_COMPARE_11) * FOG_DEPTH_INVDIFF_12);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_13)\n\
{\n\
fogMixWeight = mix(state.fogDensity[12], state.fogDensity[13], (inFragDepth - FOG_DEPTH_COMPARE_12) * FOG_DEPTH_INVDIFF_13);\n\
fogMixWeight = mix(state.fogDensity_12, state.fogDensity_13, (inFragDepth - FOG_DEPTH_COMPARE_12) * FOG_DEPTH_INVDIFF_13);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_14)\n\
{\n\
fogMixWeight = mix(state.fogDensity[13], state.fogDensity[14], (inFragDepth - FOG_DEPTH_COMPARE_13) * FOG_DEPTH_INVDIFF_14);\n\
fogMixWeight = mix(state.fogDensity_13, state.fogDensity_14, (inFragDepth - FOG_DEPTH_COMPARE_13) * FOG_DEPTH_INVDIFF_14);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_15)\n\
{\n\
fogMixWeight = mix(state.fogDensity[14], state.fogDensity[15], (inFragDepth - FOG_DEPTH_COMPARE_14) * FOG_DEPTH_INVDIFF_15);\n\
fogMixWeight = mix(state.fogDensity_14, state.fogDensity_15, (inFragDepth - FOG_DEPTH_COMPARE_14) * FOG_DEPTH_INVDIFF_15);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_16)\n\
{\n\
fogMixWeight = mix(state.fogDensity[15], state.fogDensity[16], (inFragDepth - FOG_DEPTH_COMPARE_15) * FOG_DEPTH_INVDIFF_16);\n\
fogMixWeight = mix(state.fogDensity_15, state.fogDensity_16, (inFragDepth - FOG_DEPTH_COMPARE_15) * FOG_DEPTH_INVDIFF_16);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_17)\n\
{\n\
fogMixWeight = mix(state.fogDensity[16], state.fogDensity[17], (inFragDepth - FOG_DEPTH_COMPARE_16) * FOG_DEPTH_INVDIFF_17);\n\
fogMixWeight = mix(state.fogDensity_16, state.fogDensity_17, (inFragDepth - FOG_DEPTH_COMPARE_16) * FOG_DEPTH_INVDIFF_17);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_18)\n\
{\n\
fogMixWeight = mix(state.fogDensity[17], state.fogDensity[18], (inFragDepth - FOG_DEPTH_COMPARE_17) * FOG_DEPTH_INVDIFF_18);\n\
fogMixWeight = mix(state.fogDensity_17, state.fogDensity_18, (inFragDepth - FOG_DEPTH_COMPARE_17) * FOG_DEPTH_INVDIFF_18);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_19)\n\
{\n\
fogMixWeight = mix(state.fogDensity[18], state.fogDensity[19], (inFragDepth - FOG_DEPTH_COMPARE_18) * FOG_DEPTH_INVDIFF_19);\n\
fogMixWeight = mix(state.fogDensity_18, state.fogDensity_19, (inFragDepth - FOG_DEPTH_COMPARE_18) * FOG_DEPTH_INVDIFF_19);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_20)\n\
{\n\
fogMixWeight = mix(state.fogDensity[19], state.fogDensity[20], (inFragDepth - FOG_DEPTH_COMPARE_19) * FOG_DEPTH_INVDIFF_20);\n\
fogMixWeight = mix(state.fogDensity_19, state.fogDensity_20, (inFragDepth - FOG_DEPTH_COMPARE_19) * FOG_DEPTH_INVDIFF_20);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_21)\n\
{\n\
fogMixWeight = mix(state.fogDensity[20], state.fogDensity[21], (inFragDepth - FOG_DEPTH_COMPARE_20) * FOG_DEPTH_INVDIFF_21);\n\
fogMixWeight = mix(state.fogDensity_20, state.fogDensity_21, (inFragDepth - FOG_DEPTH_COMPARE_20) * FOG_DEPTH_INVDIFF_21);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_22)\n\
{\n\
fogMixWeight = mix(state.fogDensity[21], state.fogDensity[22], (inFragDepth - FOG_DEPTH_COMPARE_21) * FOG_DEPTH_INVDIFF_22);\n\
fogMixWeight = mix(state.fogDensity_21, state.fogDensity_22, (inFragDepth - FOG_DEPTH_COMPARE_21) * FOG_DEPTH_INVDIFF_22);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_23)\n\
{\n\
fogMixWeight = mix(state.fogDensity[22], state.fogDensity[23], (inFragDepth - FOG_DEPTH_COMPARE_22) * FOG_DEPTH_INVDIFF_23);\n\
fogMixWeight = mix(state.fogDensity_22, state.fogDensity_23, (inFragDepth - FOG_DEPTH_COMPARE_22) * FOG_DEPTH_INVDIFF_23);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_24)\n\
{\n\
fogMixWeight = mix(state.fogDensity[23], state.fogDensity[24], (inFragDepth - FOG_DEPTH_COMPARE_23) * FOG_DEPTH_INVDIFF_24);\n\
fogMixWeight = mix(state.fogDensity_23, state.fogDensity_24, (inFragDepth - FOG_DEPTH_COMPARE_23) * FOG_DEPTH_INVDIFF_24);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_25)\n\
{\n\
fogMixWeight = mix(state.fogDensity[24], state.fogDensity[25], (inFragDepth - FOG_DEPTH_COMPARE_24) * FOG_DEPTH_INVDIFF_25);\n\
fogMixWeight = mix(state.fogDensity_24, state.fogDensity_25, (inFragDepth - FOG_DEPTH_COMPARE_24) * FOG_DEPTH_INVDIFF_25);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_26)\n\
{\n\
fogMixWeight = mix(state.fogDensity[25], state.fogDensity[26], (inFragDepth - FOG_DEPTH_COMPARE_25) * FOG_DEPTH_INVDIFF_26);\n\
fogMixWeight = mix(state.fogDensity_25, state.fogDensity_26, (inFragDepth - FOG_DEPTH_COMPARE_25) * FOG_DEPTH_INVDIFF_26);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_27)\n\
{\n\
fogMixWeight = mix(state.fogDensity[26], state.fogDensity[27], (inFragDepth - FOG_DEPTH_COMPARE_26) * FOG_DEPTH_INVDIFF_27);\n\
fogMixWeight = mix(state.fogDensity_26, state.fogDensity_27, (inFragDepth - FOG_DEPTH_COMPARE_26) * FOG_DEPTH_INVDIFF_27);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_28)\n\
{\n\
fogMixWeight = mix(state.fogDensity[27], state.fogDensity[28], (inFragDepth - FOG_DEPTH_COMPARE_27) * FOG_DEPTH_INVDIFF_28);\n\
fogMixWeight = mix(state.fogDensity_27, state.fogDensity_28, (inFragDepth - FOG_DEPTH_COMPARE_27) * FOG_DEPTH_INVDIFF_28);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_29)\n\
{\n\
fogMixWeight = mix(state.fogDensity[28], state.fogDensity[29], (inFragDepth - FOG_DEPTH_COMPARE_28) * FOG_DEPTH_INVDIFF_29);\n\
fogMixWeight = mix(state.fogDensity_28, state.fogDensity_29, (inFragDepth - FOG_DEPTH_COMPARE_28) * FOG_DEPTH_INVDIFF_29);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_30)\n\
{\n\
fogMixWeight = mix(state.fogDensity[29], state.fogDensity[30], (inFragDepth - FOG_DEPTH_COMPARE_29) * FOG_DEPTH_INVDIFF_30);\n\
fogMixWeight = mix(state.fogDensity_29, state.fogDensity_30, (inFragDepth - FOG_DEPTH_COMPARE_29) * FOG_DEPTH_INVDIFF_30);\n\
}\n\
else if (inFragDepth <= FOG_DEPTH_COMPARE_31)\n\
{\n\
fogMixWeight = mix(state.fogDensity[30], state.fogDensity[31], (inFragDepth - FOG_DEPTH_COMPARE_30) * FOG_DEPTH_INVDIFF_31);\n\
fogMixWeight = mix(state.fogDensity_30, state.fogDensity_31, (inFragDepth - FOG_DEPTH_COMPARE_30) * FOG_DEPTH_INVDIFF_31);\n\
}\n\
\n\
outFragColor = mix(outFragColor, (state.enableFogAlphaOnly) ? vec4(outFragColor.rgb, state.fogColor.a) : state.fogColor, fogMixWeight);\n\
@ -1724,8 +1879,16 @@ Render3DError OpenGLRenderer_3_2::CreateFogProgram(const OGLFogProgramKey fogPro
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
if (vtxShaderCString == NULL)
{
INFO("OpenGL: The FOG vertex shader is unavailable.\n");
error = OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR;
return error;
}
else if (fragShaderCString == NULL)
{
INFO("OpenGL: The FOG fragment shader is unavailable.\n");
error = OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR;
return error;
}
@ -1998,7 +2161,7 @@ Render3DError OpenGLRenderer_3_2::DisableVertexAttributes()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
{
OGLRenderRef &OGLRef = *this->ref;
@ -2056,7 +2219,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(polyList, indexList, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(clippedPolyList, clippedPolyCount, this->_clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr);
// Restore OpenGL states back to normal.
this->_geometryProgramFlags = oldGProgramFlags;
@ -2224,6 +2387,8 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
this->_clippedPolyList = engine.clippedPolyList;
this->_enableAlphaBlending = (engine.renderState.enableAlphaBlending) ? true : false;
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
@ -2242,59 +2407,20 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
// Set up rendering states that will remain constant for the entire frame.
this->_pendingRenderStates.enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[engine.renderState.alphaTestRef];
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(engine.renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(engine.renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(engine.renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(engine.renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(engine.renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> engine.renderState.fogShift) / 32767.0f;
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.fogDensity[i].r = (engine.renderState.fogDensityTable[i] == 127) ? 1.0f : (GLfloat)engine.renderState.fogDensityTable[i] / 128.0f;
this->_pendingRenderStates.fogDensity[i].g = 0.0f;
this->_pendingRenderStates.fogDensity[i].b = 0.0f;
this->_pendingRenderStates.fogDensity[i].a = 0.0f;
}
const GLfloat edgeColorAlpha = (engine.renderState.enableAntialiasing) ? (16.0f/31.0f) : 1.0f;
for (size_t i = 0; i < 8; i++)
{
this->_pendingRenderStates.edgeColor[i].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] ) & 0x001F];
this->_pendingRenderStates.edgeColor[i].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.edgeColor[i].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.edgeColor[i].a = edgeColorAlpha;
}
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.toonColor[i].r = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] ) & 0x001F];
this->_pendingRenderStates.toonColor[i].g = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.toonColor[i].b = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.toonColor[i].a = 1.0f;
}
glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboRenderStatesID);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(this->_pendingRenderStates), &this->_pendingRenderStates);
// Generate the clipped polygon list.
if ( (OGLRef.uboPolyStatesID != 0) && (this->_clippedPolyCount > MAX_CLIPPED_POLY_COUNT_FOR_UBO) )
{
// In practice, there shouldn't be any game scene with a clipped polygon count that
// would exceed POLYLIST_SIZE. But if for some reason there is, then we need to limit
// the polygon count here. Please report if this happens!
// would exceed MAX_CLIPPED_POLY_COUNT_FOR_UBO. But if for some reason there is, then
// we need to limit the polygon count here. Please report if this happens!
printf("OpenGL: Clipped poly count of %d exceeds %d. Please report!!!\n", (int)this->_clippedPolyCount, MAX_CLIPPED_POLY_COUNT_FOR_UBO);
this->_clippedPolyCount = MAX_CLIPPED_POLY_COUNT_FOR_UBO;
}
// Set up the polygon states.
this->_renderNeedsDepthEqualsTest = false;
bool renderNeedsToonTable = false;
bool renderNeedsDepthEqualsTest = false;
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
{
const POLY &thePoly = *this->_clippedPolyList[i].poly;
@ -2340,7 +2466,8 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x);
}
this->_renderNeedsDepthEqualsTest = this->_renderNeedsDepthEqualsTest || (thePoly.attribute.DepthEqualTest_Enable != 0);
renderNeedsToonTable = renderNeedsToonTable || (thePoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT);
renderNeedsDepthEqualsTest = renderNeedsDepthEqualsTest || (thePoly.attribute.DepthEqualTest_Enable != 0);
this->_isPolyFrontFacing[i] = (facing < 0);
// Get the texture that is to be attached to this polygon.
@ -2350,6 +2477,58 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
// Replace the entire buffer as a hint to the driver to orphan the buffer and avoid a synchronization cost.
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(OGLRef.vertIndexBuffer), OGLRef.vertIndexBuffer);
// Set up rendering states that will remain constant for the entire frame.
this->_pendingRenderStates.enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[engine.renderState.alphaTestRef];
if (renderNeedsToonTable)
{
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.toonColor[i].r = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] ) & 0x001F];
this->_pendingRenderStates.toonColor[i].g = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.toonColor[i].b = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.toonColor[i].a = 1.0f;
}
}
if (this->_enableFog)
{
this->_fogProgramKey.key = 0;
this->_fogProgramKey.offset = engine.renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = engine.renderState.fogShift;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(engine.renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(engine.renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(engine.renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(engine.renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(engine.renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> engine.renderState.fogShift) / 32767.0f;
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.fogDensity[i] = (engine.renderState.fogDensityTable[i] == 127) ? 1.0f : (GLfloat)engine.renderState.fogDensityTable[i] / 128.0f;
}
}
if (this->_enableEdgeMark)
{
const GLfloat edgeColorAlpha = (engine.renderState.enableAntialiasing) ? (16.0f/31.0f) : 1.0f;
for (size_t i = 0; i < 8; i++)
{
this->_pendingRenderStates.edgeColor[i].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] ) & 0x001F];
this->_pendingRenderStates.edgeColor[i].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.edgeColor[i].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.edgeColor[i].a = edgeColorAlpha;
}
}
glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboRenderStatesID);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(this->_pendingRenderStates), &this->_pendingRenderStates);
OGLPolyStates *polyStates = this->_pendingPolyStates;
if (OGLRef.uboPolyStatesID == 0)
@ -2399,12 +2578,11 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (renderNeedsDepthEqualsTest) ? 1 : 0;
this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0;
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0;
this->_geometryProgramFlags.OpaqueDrawMode = 1;
this->_currentAlphaTestRef = engine.renderState.alphaTestRef;
this->_SetupGeometryShaders(this->_geometryProgramFlags);
glReadBuffer(GL_COLOROUT_ATTACHMENT_ID);
@ -2416,113 +2594,89 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias)
Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer()
{
OGLRenderRef &OGLRef = *this->ref;
// Set up the postprocessing states
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending)
if (this->_enableEdgeMark || this->_enableFog)
{
// Pass 1: Determine the pixels with zero alpha
glDrawBuffer(GL_NONE);
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0x40, 0x40);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0x40);
// Set up the postprocessing states
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Pass 2: Unblended edge mark colors to zero-alpha pixels
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glUseProgram(OGLRef.programEdgeMarkID);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Pass 3: Blended edge mark
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
}
else
{
glUseProgram(OGLRef.programEdgeMarkID);
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
return OGLERROR_NOERR;
}
glBindVertexArray(0);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 color, const u16 offset, const u8 shift, const bool alphaOnly)
{
OGLRenderRef &OGLRef = *this->ref;
OGLFogProgramKey fogProgramKey;
fogProgramKey.key = 0;
fogProgramKey.offset = offset;
fogProgramKey.shift = shift;
std::map<u32, OGLFogShaderID>::iterator it = this->_fogProgramMap.find(fogProgramKey.key);
if (it == this->_fogProgramMap.end())
if (this->_enableEdgeMark)
{
Render3DError error = this->CreateFogProgram(fogProgramKey, FogVtxShader_150, FogFragShader_150);
if (error != OGLERROR_NOERR)
if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending)
{
return error;
// Pass 1: Determine the pixels with zero alpha
glDrawBuffer(GL_NONE);
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0x40, 0x40);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0x40);
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Pass 2: Unblended edge mark colors to zero-alpha pixels
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glUseProgram(OGLRef.programEdgeMarkID);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Pass 3: Blended edge mark
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
else
{
glUseProgram(OGLRef.programEdgeMarkID);
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
OGLFogShaderID shaderID = this->_fogProgramMap[fogProgramKey.key];
if (this->_enableFog)
{
std::map<u32, OGLFogShaderID>::iterator it = this->_fogProgramMap.find(this->_fogProgramKey.key);
if (it == this->_fogProgramMap.end())
{
Render3DError error = this->CreateFogProgram(this->_fogProgramKey, FogVtxShader_150, FogFragShader_150);
if (error != OGLERROR_NOERR)
{
return error;
}
}
OGLFogShaderID shaderID = this->_fogProgramMap[this->_fogProgramKey.key];
glDrawBuffer(GL_WORKING_ATTACHMENT_ID);
glUseProgram(shaderID.program);
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
}
glDrawBuffer(GL_WORKING_ATTACHMENT_ID);
glUseProgram(shaderID.program);
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::CreateToonTable()
{
// Do nothing. The toon table is updated in the render states UBO.
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::DestroyToonTable()
{
// Do nothing. The toon table is updated in the render states UBO.
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::UpdateToonTable(const u16 *toonTableBuffer)
{
// Do nothing. The toon table is updated in the render states UBO.
return OGLERROR_NOERR;
}

View File

@ -66,7 +66,6 @@ class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
protected:
bool _is64kUBOSupported;
GLsync _syncBufferSetup;
CACHE_ALIGN OGLRenderStates _pendingRenderStates;
CACHE_ALIGN OGLPolyStates _pendingPolyStates[POLYLIST_SIZE];
virtual Render3DError InitExtensions();
@ -93,17 +92,13 @@ protected:
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels();
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u16 offset, const u8 shift, const bool alphaOnly);
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError CreateToonTable();
virtual Render3DError DestroyToonTable();
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);

View File

@ -565,7 +565,7 @@ struct GFX3D_State
u32 fogShift;
bool invalidateToon;
u16 u16ToonTable[32];
CACHE_ALIGN u16 u16ToonTable[32];
u8 shininessTable[128];
u8 *fogDensityTable; // Alias to MMU.ARM9_REG+0x0360
u16 *edgeMarkColorTable; // Alias to MMU.ARM9_REG+0x0330

View File

@ -64,6 +64,7 @@
#include "NDSSystem.h"
#include "utils/bits.h"
#include "utils/task.h"
#include "./utils/colorspacehandler/colorspacehandler.h"
#include "filter/filter.h"
#include "filter/xbrz.h"
@ -1282,7 +1283,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::Render()
for (size_t i = 0; i < polyCount; i++)
{
if (!RENDERER) _debug_thisPoly = (i == this->_softRender->_debug_drawClippedUserPoly);
if (!this->_softRender->polyVisible[i]) continue;
if (!this->_softRender->isPolyVisible[i]) continue;
this->_polynum = i;
const CPoly &clippedPoly = this->_softRender->GetClippedPolyByIndex(i);
@ -1305,7 +1306,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::Render()
for (size_t j = vertCount; j < MAX_CLIPPED_VERTS; j++)
this->_verts[j] = NULL;
if (!this->_softRender->polyBackfacing[i])
if (!this->_softRender->isPolyBackFacing[i])
{
if (polyAttr.Mode == POLYGON_MODE_SHADOW)
{
@ -1376,12 +1377,10 @@ void* SoftRasterizer_RunRasterizerUnit(void *arg)
return 0;
}
static void* SoftRasterizer_RunCalculateVertices(void *arg)
static void* SoftRasterizer_RunProcessAllVertices(void *arg)
{
SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg;
softRender->performViewportTransforms();
softRender->performBackfaceTests();
softRender->performCoordAdjustment();
softRender->ProcessAllVertices();
return NULL;
}
@ -1394,16 +1393,6 @@ static void* SoftRasterizer_RunGetAndLoadAllTextures(void *arg)
return NULL;
}
static void* SoftRasterizer_RunUpdateTables(void *arg)
{
SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg;
softRender->UpdateToonTable(softRender->currentRenderState->u16ToonTable);
softRender->UpdateFogTable(softRender->currentRenderState->fogDensityTable);
softRender->UpdateEdgeMarkColorTable(softRender->currentRenderState->edgeMarkColorTable);
return NULL;
}
static void* SoftRasterizer_RunClearFramebuffer(void *arg)
{
SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg;
@ -1816,7 +1805,7 @@ SoftRasterizerRenderer::SoftRasterizerRenderer()
}
}
InitTables();
__InitTables();
Reset();
if (_threadCount == 0)
@ -1845,7 +1834,7 @@ SoftRasterizerRenderer::~SoftRasterizerRenderer()
this->_framebufferAttributes = NULL;
}
Render3DError SoftRasterizerRenderer::InitTables()
void SoftRasterizerRenderer::__InitTables()
{
static bool needTableInit = true;
@ -1863,8 +1852,6 @@ Render3DError SoftRasterizerRenderer::InitTables()
needTableInit = false;
}
return RENDER3DERROR_NOERR;
}
ClipperMode SoftRasterizerRenderer::GetPreferredPolygonClippingMode() const
@ -1872,7 +1859,7 @@ ClipperMode SoftRasterizerRenderer::GetPreferredPolygonClippingMode() const
return (this->_enableHighPrecisionColorInterpolation) ? ClipperMode_FullColorInterpolate : ClipperMode_Full;
}
void SoftRasterizerRenderer::performViewportTransforms()
void SoftRasterizerRenderer::_TransformVertices()
{
const float wScalar = (float)this->_framebufferWidth / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH;
const float hScalar = (float)this->_framebufferHeight / (float)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
@ -1928,24 +1915,57 @@ void SoftRasterizerRenderer::performViewportTransforms()
vert.coord[0] *= wScalar;
vert.coord[1] *= hScalar;
//here is a hack which needs to be removed.
//at some point our shape engine needs these to be converted to "fixed point"
//which is currently just a float
vert.coord[0] = (float)iround(16.0f * vert.coord[0]);
vert.coord[1] = (float)iround(16.0f * vert.coord[1]);
}
}
}
void SoftRasterizerRenderer::performCoordAdjustment()
void SoftRasterizerRenderer::_GetPolygonStates()
{
static const bool visibleFunction[2][4] = {
//always false, backfacing, !backfacing, always true
{ false, false, true, true },
{ false, true, false, true }
};
for (size_t i = 0; i < this->_clippedPolyCount; i++)
{
CPoly &clippedPoly = this->_clippedPolyList[i];
const PolygonType type = clippedPoly.type;
VERT *verts = &clippedPoly.clipVerts[0];
const CPoly &clippedPoly = this->_clippedPolyList[i];
const POLY &thePoly = *clippedPoly.poly;
const PolygonType polyType = clippedPoly.type;
const VERT *vert = &clippedPoly.clipVerts[0];
const u8 cullingMode = thePoly.attribute.SurfaceCullingMode;
//here is a hack which needs to be removed.
//at some point our shape engine needs these to be converted to "fixed point"
//which is currently just a float
for (size_t j = 0; j < type; j++)
for (size_t k = 0; k < 2; k++)
verts[j].coord[k] = (float)iround(16.0f * verts[j].coord[k]);
//HACK: backface culling
//this should be moved to gfx3d, but first we need to redo the way the lists are built
//because it is too convoluted right now.
//(must we throw out verts if a poly gets backface culled? if not, then it might be easier)
//an older approach
//(not good enough for quads and other shapes)
//float ab[2], ac[2]; Vector2Copy(ab, verts[1].coord); Vector2Copy(ac, verts[2].coord); Vector2Subtract(ab, verts[0].coord);
//Vector2Subtract(ac, verts[0].coord); float cross = Vector2Cross(ab, ac); polyAttr.backfacing = (cross>0);
//a better approach
// we have to support somewhat non-convex polygons (see NSMB world map 1st screen).
// this version should handle those cases better.
const size_t n = polyType - 1;
float facing = (vert[0].y + vert[n].y) * (vert[0].x - vert[n].x) +
(vert[1].y + vert[0].y) * (vert[1].x - vert[0].x) +
(vert[2].y + vert[1].y) * (vert[2].x - vert[1].x);
for (size_t j = 2; j < n; j++)
{
facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x);
}
this->isPolyBackFacing[i] = (facing < 0);
this->isPolyVisible[i] = visibleFunction[this->isPolyBackFacing[i]][cullingMode];
}
}
@ -1964,46 +1984,10 @@ void SoftRasterizerRenderer::GetAndLoadAllTextures()
}
}
void SoftRasterizerRenderer::performBackfaceTests()
void SoftRasterizerRenderer::ProcessAllVertices()
{
for (size_t i = 0; i < this->_clippedPolyCount; i++)
{
const CPoly &clippedPoly = this->_clippedPolyList[i];
const POLY &thePoly = *clippedPoly.poly;
const PolygonType type = clippedPoly.type;
const VERT *verts = &clippedPoly.clipVerts[0];
const u8 cullingMode = thePoly.attribute.SurfaceCullingMode;
//HACK: backface culling
//this should be moved to gfx3d, but first we need to redo the way the lists are built
//because it is too convoluted right now.
//(must we throw out verts if a poly gets backface culled? if not, then it might be easier)
//an older approach
//(not good enough for quads and other shapes)
//float ab[2], ac[2]; Vector2Copy(ab, verts[1].coord); Vector2Copy(ac, verts[2].coord); Vector2Subtract(ab, verts[0].coord);
//Vector2Subtract(ac, verts[0].coord); float cross = Vector2Cross(ab, ac); polyAttr.backfacing = (cross>0);
//a better approach
// we have to support somewhat non-convex polygons (see NSMB world map 1st screen).
// this version should handle those cases better.
const size_t n = type - 1;
float facing = (verts[0].y + verts[n].y) * (verts[0].x - verts[n].x)
+ (verts[1].y + verts[0].y) * (verts[1].x - verts[0].x)
+ (verts[2].y + verts[1].y) * (verts[2].x - verts[1].x);
for (size_t j = 2; j < n; j++)
facing += (verts[j+1].y + verts[j].y) * (verts[j+1].x - verts[j].x);
polyBackfacing[i] = (facing < 0);
static const bool visibleFunction[2][4] = {
//always false, backfacing, !backfacing, always true
{ false, false, true, true },
{ false, true, false, true }
};
polyVisible[i] = visibleFunction[polyBackfacing[i]][cullingMode];
}
this->_TransformVertices();
this->_GetPolygonStates();
}
Render3DError SoftRasterizerRenderer::ApplyRenderingSettings(const GFX3D_State &renderState)
@ -2034,26 +2018,25 @@ Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine)
if (doMultithreadedStateSetup)
{
this->_task[0].execute(&SoftRasterizer_RunGetAndLoadAllTextures, this);
this->_task[1].execute(&SoftRasterizer_RunCalculateVertices, this);
this->_task[1].execute(&SoftRasterizer_RunProcessAllVertices, this);
}
else
{
this->GetAndLoadAllTextures();
this->performViewportTransforms();
this->performBackfaceTests();
this->performCoordAdjustment();
this->ProcessAllVertices();
}
this->UpdateToonTable(engine.renderState.u16ToonTable);
// Convert the toon table colors
ColorspaceConvertBuffer555To6665Opaque<false, false>(engine.renderState.u16ToonTable, (u32 *)this->toonColor32LUT, 32);
if (this->_enableEdgeMark)
{
this->UpdateEdgeMarkColorTable(this->currentRenderState->edgeMarkColorTable);
this->_UpdateEdgeMarkColorTable(this->currentRenderState->edgeMarkColorTable);
}
if (this->_enableFog)
{
this->UpdateFogTable(this->currentRenderState->fogDensityTable);
this->_UpdateFogTable(this->currentRenderState->fogDensityTable);
}
if (doMultithreadedStateSetup)
@ -2062,12 +2045,10 @@ Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine)
this->_task[0].finish();
}
this->ClearFramebuffer(engine.renderState);
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList)
Render3DError SoftRasterizerRenderer::RenderGeometry()
{
// Render the geometry
if (this->_threadCount > 0)
@ -2109,24 +2090,22 @@ Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderSt
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable)
void SoftRasterizerRenderer::_UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable)
{
//TODO: need to test and find out whether these get grabbed at flush time, or at render time
//we can do this by rendering a 3d frame and then freezing the system, but only changing the edge mark colors
for (size_t i = 0; i < 8; i++)
{
this->edgeMarkTable[i].color = COLOR555TO6665(edgeMarkColorTable[i] & 0x7FFF, (this->currentRenderState->enableAntialiasing) ? 0x10 : 0x1F);
this->_edgeMarkTable[i].color = COLOR555TO6665(edgeMarkColorTable[i] & 0x7FFF, (this->currentRenderState->enableAntialiasing) ? 0x10 : 0x1F);
//zero 20-jun-2013 - this doesnt make any sense. at least, it should be related to the 0x8000 bit. if this is undocumented behaviour, lets write about which scenario proves it here, or which scenario is requiring this code.
//// this seems to be the only thing that selectively disables edge marking
//edgeMarkDisabled[i] = (col == 0x7FFF);
this->edgeMarkDisabled[i] = false;
//_edgeMarkDisabled[i] = (col == 0x7FFF);
this->_edgeMarkDisabled[i] = false;
}
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable)
void SoftRasterizerRenderer::_UpdateFogTable(const u8 *fogDensityTable)
{
#if 0
//TODO - this might be a little slow;
@ -2136,7 +2115,7 @@ Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable)
{
if (i < offset)
{
fogTable[i] = densityTable[0];
this->_fogTable[i] = densityTable[0];
continue;
}
@ -2147,17 +2126,17 @@ Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable)
{
if (j == 0)
{
fogTable[i] = densityTable[0];
this->_fogTable[i] = densityTable[0];
goto done;
}
else
{
fogTable[i] = ((value-i)*(densityTable[j-1]) + (increment-(value-i))*(densityTable[j]))/increment;
this->_fogTable[i] = ((value-i)*(densityTable[j-1]) + (increment-(value-i))*(densityTable[j]))/increment;
goto done;
}
}
}
fogTable[i] = (densityTable[31]);
this->_fogTable[i] = (densityTable[31]);
done: ;
}
#else
@ -2173,7 +2152,7 @@ Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable)
// If the fog factor is 127, then treat it as 128.
u8 fogFactor = (fogDensityTable[0] == 127) ? 128 : fogDensityTable[0];
memset(this->fogTable, fogFactor, iMin);
memset(this->_fogTable, fogFactor, iMin);
for(u32 i = iMin; i < iMax; i++)
{
@ -2183,14 +2162,12 @@ Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable)
u32 diff = value - i;
assert(j >= 1 && j < 32);
fogFactor = ((diff*(fogDensityTable[j-1]) + (increment-diff)*(fogDensityTable[j])) >> incrementDivShift);
this->fogTable[i] = (fogFactor == 127) ? 128 : fogFactor;
this->_fogTable[i] = (fogFactor == 127) ? 128 : fogFactor;
}
fogFactor = (fogDensityTable[31] == 127) ? 128 : fogDensityTable[31];
memset(this->fogTable+iMax, fogFactor, 32768-iMax);
memset(this->_fogTable+iMax, fogFactor, 32768-iMax);
#endif
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasterizerPostProcessParams &param)
@ -2210,7 +2187,7 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasteriz
// - the level-start intro gets a pseudo-antialiasing effect around the silhouette,
// - the character edges in-level are clearly transparent, and also show well through shield powerups.
if (!this->edgeMarkDisabled[polyID>>3] && this->_framebufferAttributes->isTranslucentPoly[i] == 0)
if (!this->_edgeMarkDisabled[polyID>>3] && this->_framebufferAttributes->isTranslucentPoly[i] == 0)
{
const bool isEdgeMarkingClearValues = ((polyID != this->_clearAttributes.opaquePolyID) && (depth < this->_clearAttributes.depth));
@ -2219,34 +2196,34 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasteriz
const bool left = (x < 1) ? isEdgeMarkingClearValues : ((polyID != this->_framebufferAttributes->opaquePolyID[i-1]) && (depth >= this->_framebufferAttributes->depth[i-1]));
const bool up = (y < 1) ? isEdgeMarkingClearValues : ((polyID != this->_framebufferAttributes->opaquePolyID[i-this->_framebufferWidth]) && (depth >= this->_framebufferAttributes->depth[i-this->_framebufferWidth]));
FragmentColor edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i] >> 3];
FragmentColor edgeMarkColor = this->_edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i] >> 3];
if (right)
{
if (x < this->_framebufferWidth - 1)
{
edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i+1] >> 3];
edgeMarkColor = this->_edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i+1] >> 3];
}
}
else if (down)
{
if (y < this->_framebufferHeight - 1)
{
edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i+this->_framebufferWidth] >> 3];
edgeMarkColor = this->_edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i+this->_framebufferWidth] >> 3];
}
}
else if (left)
{
if (x > 0)
{
edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i-1] >> 3];
edgeMarkColor = this->_edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i-1] >> 3];
}
}
else if (up)
{
if (y > 0)
{
edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i-this->_framebufferWidth] >> 3];
edgeMarkColor = this->_edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i-this->_framebufferWidth] >> 3];
}
}
@ -2264,7 +2241,7 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasteriz
const size_t fogIndex = depth >> 9;
assert(fogIndex < 32768);
const u8 fog = (this->_framebufferAttributes->isFogged[i] != 0) ? this->fogTable[fogIndex] : 0;
const u8 fog = (this->_framebufferAttributes->isFogged[i] != 0) ? this->_fogTable[fogIndex] : 0;
if (!param.fogAlphaOnly)
{
@ -2305,17 +2282,6 @@ SoftRasterizerTexture* SoftRasterizerRenderer::GetLoadedTextureFromPolygon(const
return theTexture;
}
Render3DError SoftRasterizerRenderer::UpdateToonTable(const u16 *toonTableBuffer)
{
//convert the toon colors
for (size_t i = 0; i < 32; i++)
{
this->toonColor32LUT[i].color = COLOR555TO666(toonTableBuffer[i] & 0x7FFF);
}
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID)
{
const size_t xRatio = (size_t)((GPU_FRAMEBUFFER_NATIVE_WIDTH << 16) / this->_framebufferWidth) + 1;
@ -2396,38 +2362,7 @@ Render3DError SoftRasterizerRenderer::Reset()
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::Render(const GFX3D &engine)
{
Render3DError error = RENDER3DERROR_NOERR;
this->_isPoweredOn = true;
const u32 clearColorSwapped = LE_TO_LOCAL_32(engine.renderState.clearColor);
this->_clearColor6665.color = COLOR555TO6665(clearColorSwapped & 0x7FFF, (clearColorSwapped >> 16) & 0x1F);
this->_clearAttributes.opaquePolyID = (clearColorSwapped >> 24) & 0x3F;
//special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display
//I am not sure whether it is right, though. previously this was cleared to 0, as a guess,
//but in spiderman2 some fires with polyid 0 try to render on top of the background
this->_clearAttributes.translucentPolyID = kUnsetTranslucentPolyID;
this->_clearAttributes.depth = engine.renderState.clearDepth;
this->_clearAttributes.stencil = 0;
this->_clearAttributes.isTranslucentPoly = 0;
this->_clearAttributes.polyFacing = PolyFacing_Unwritten;
this->_clearAttributes.isFogged = BIT15(clearColorSwapped);
error = this->BeginRender(engine);
if (error != RENDER3DERROR_NOERR)
{
return error;
}
this->RenderGeometry(engine.renderState, engine.polylist, &engine.indexlist);
this->EndRender(engine.render3DFrameCount);
return error;
}
Render3DError SoftRasterizerRenderer::EndRender(const u64 frameCount)
Render3DError SoftRasterizerRenderer::EndRender()
{
// If we're not multithreaded, then just do the post-processing steps now.
if (!this->_renderGeometryNeedsFinish)

View File

@ -144,6 +144,9 @@ class SoftRasterizerRenderer : public Render3D_Altivec
class SoftRasterizerRenderer : public Render3D
#endif
{
private:
void __InitTables();
protected:
Task *_task;
SoftRasterizerClearParam _threadClearParam[SOFTRASTERIZER_MAX_THREADS];
@ -158,9 +161,9 @@ protected:
size_t _customLinesPerThread;
size_t _customPixelsPerThread;
u8 fogTable[32768];
FragmentColor edgeMarkTable[8];
bool edgeMarkDisabled[8];
u8 _fogTable[32768];
FragmentColor _edgeMarkTable[8];
bool _edgeMarkDisabled[8];
bool _renderGeometryNeedsFinish;
@ -168,22 +171,25 @@ protected:
bool _enableLineHack;
// SoftRasterizer-specific methods
virtual Render3DError InitTables();
void _UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable);
void _UpdateFogTable(const u8 *fogDensityTable);
void _TransformVertices();
void _GetPolygonStates();
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError RenderGeometry();
virtual Render3DError EndRender();
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);
public:
int _debug_drawClippedUserPoly;
FragmentColor toonColor32LUT[32];
CACHE_ALIGN FragmentColor toonColor32LUT[32];
FragmentAttributesBuffer *_framebufferAttributes;
bool polyVisible[POLYLIST_SIZE];
bool polyBackfacing[POLYLIST_SIZE];
bool isPolyVisible[POLYLIST_SIZE];
bool isPolyBackFacing[POLYLIST_SIZE];
GFX3D_State *currentRenderState;
bool _enableFragmentSamplingHack;
@ -193,21 +199,15 @@ public:
virtual ClipperMode GetPreferredPolygonClippingMode() const;
void performViewportTransforms();
void performBackfaceTests();
void performCoordAdjustment();
void GetAndLoadAllTextures();
Render3DError UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable);
Render3DError UpdateFogTable(const u8 *fogDensityTable);
void ProcessAllVertices();
Render3DError RenderEdgeMarkingAndFog(const SoftRasterizerPostProcessParams &param);
SoftRasterizerTexture* GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing);
// Base rendering methods
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError Reset();
virtual Render3DError ApplyRenderingSettings(const GFX3D_State &renderState);
virtual Render3DError Render(const GFX3D &engine);
virtual Render3DError RenderFinish();
virtual Render3DError RenderFlush(bool willFlushBuffer32, bool willFlushBuffer16);
virtual void ClearUsingValues_Execute(const size_t startPixel, const size_t endPixel);

View File

@ -445,22 +445,17 @@ Render3DError Render3D::BeginRender(const GFX3D &engine)
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList)
Render3DError Render3D::RenderGeometry()
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias)
Render3DError Render3D::PostprocessFramebuffer()
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::RenderFog(const u8 *densityTable, const u32 color, const u16 offset, const u8 shift, const bool alphaOnly)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::EndRender(const u64 frameCount)
Render3DError Render3D::EndRender()
{
return RENDER3DERROR_NOERR;
}
@ -508,11 +503,6 @@ Render3DError Render3D::FlushFramebuffer(const FragmentColor *__restrict srcFram
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::UpdateToonTable(const u16 *toonTableBuffer)
{
return RENDER3DERROR_NOERR;
}
template <bool ISCOLORBLANK, bool ISDEPTHBLANK>
void Render3D::_ClearImageScrolledLoop(const u8 xScroll, const u8 yScroll, const u16 *__restrict inColor16, const u16 *__restrict inDepth16,
u16 *__restrict outColor16, u32 *__restrict outDepth24, u8 *__restrict outFog)
@ -719,27 +709,32 @@ Render3DError Render3D::Render(const GFX3D &engine)
error = this->BeginRender(engine);
if (error != RENDER3DERROR_NOERR)
{
this->EndRender();
return error;
}
this->UpdateToonTable(engine.renderState.u16ToonTable);
this->ClearFramebuffer(engine.renderState);
this->RenderGeometry(engine.renderState, engine.polylist, &engine.indexlist);
if (this->_enableEdgeMark)
error = this->ClearFramebuffer(engine.renderState);
if (error != RENDER3DERROR_NOERR)
{
this->RenderEdgeMarking(engine.renderState.edgeMarkColorTable, engine.renderState.enableAntialiasing);
this->EndRender();
return error;
}
if (this->_enableFog)
error = this->RenderGeometry();
if (error != RENDER3DERROR_NOERR)
{
this->RenderFog(engine.renderState.fogDensityTable, engine.renderState.fogColor, (engine.renderState.fogOffset & 0x7FFF), engine.renderState.fogShift, engine.renderState.enableFogAlphaOnly);
this->EndRender();
return error;
}
this->EndRender(engine.render3DFrameCount);
return error;
error = this->PostprocessFramebuffer();
if (error != RENDER3DERROR_NOERR)
{
this->EndRender();
return error;
}
return this->EndRender();
}
Render3DError Render3D::RenderFinish()

View File

@ -198,10 +198,9 @@ protected:
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u16 offset, const u8 shift, const bool alphaOnly);
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError RenderGeometry();
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError EndRender();
virtual Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16);
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
@ -224,7 +223,6 @@ public:
size_t GetFramebufferHeight();
bool IsFramebufferNativeSize();
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError ClearFramebuffer(const GFX3D_State &renderState);
virtual Render3DError ApplyRenderingSettings(const GFX3D_State &renderState);