OpenGL Renderer: Fix issues that would throw a GL error.
- glTexParameteri() with GL_TEXTURE_2D_MULTISAMPLE throws INVALID_ENUM when trying to assign a sampler-related state, so these calls have been removed. - glMapBufferRange() throws GL_INVALID_OPERATION if the buffer size is 0, so check for this condition first.
This commit is contained in:
parent
aaf88d9f14
commit
241ca96cf1
|
@ -4354,205 +4354,207 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
|
||||||
|
|
||||||
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
|
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
|
||||||
|
|
||||||
if (this->isVBOSupported)
|
if (this->_clippedPolyCount > 0)
|
||||||
{
|
{
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
|
if (this->isVBOSupported)
|
||||||
|
|
||||||
if (this->isShaderSupported)
|
|
||||||
{
|
{
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(NDSVertex) * renderGList.rawVertCount, renderGList.rawVtxList);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If shaders aren't supported, we need to use the client-side buffers here.
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the clipped polygon list.
|
if (this->isShaderSupported)
|
||||||
bool renderNeedsToonTable = false;
|
|
||||||
|
|
||||||
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
|
|
||||||
{
|
|
||||||
const CPoly &cPoly = this->_clippedPolyList[i];
|
|
||||||
const POLY &rawPoly = this->_rawPolyList[cPoly.index];
|
|
||||||
const size_t polyType = rawPoly.type;
|
|
||||||
|
|
||||||
if (this->isShaderSupported)
|
|
||||||
{
|
|
||||||
for (size_t j = 0; j < polyType; j++)
|
|
||||||
{
|
{
|
||||||
const GLushort vertIndex = rawPoly.vertIndexes[j];
|
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(NDSVertex) * renderGList.rawVertCount, renderGList.rawVtxList);
|
||||||
// While we're looping through our vertices, add each vertex index to
|
|
||||||
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
|
|
||||||
// vertices here to convert them to GL_TRIANGLES, which are much easier
|
|
||||||
// to work with and won't be deprecated in future OpenGL versions.
|
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
|
|
||||||
if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
|
|
||||||
{
|
|
||||||
if (j == 2)
|
|
||||||
{
|
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
|
|
||||||
}
|
|
||||||
else if (j == 3)
|
|
||||||
{
|
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
const GLfloat thePolyAlpha = (GFX3D_IsPolyWireframe(rawPoly)) ? 1.0f : divide5bitBy31_LUT[rawPoly.attribute.Alpha];
|
|
||||||
|
|
||||||
for (size_t j = 0; j < polyType; j++)
|
|
||||||
{
|
{
|
||||||
const GLushort vtxIndex = rawPoly.vertIndexes[j];
|
// If shaders aren't supported, we need to use the client-side buffers here.
|
||||||
const size_t positionIndex = vtxIndex * 4;
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
const size_t texCoordIndex = vtxIndex * 2;
|
|
||||||
const size_t colorIndex = vtxIndex * 4;
|
|
||||||
const NDSVertex &vtx = renderGList.rawVtxList[vtxIndex];
|
|
||||||
|
|
||||||
// Since we can't use shaders, we can't perform any data format conversions
|
|
||||||
// of the vertex data on the GPU. Therefore, we need to do the conversions
|
|
||||||
// on the CPU instead.
|
|
||||||
OGLRef.position4fBuffer[positionIndex+0] = (float)vtx.position.x / 4096.0f;
|
|
||||||
OGLRef.position4fBuffer[positionIndex+1] = (float)vtx.position.y / 4096.0f;
|
|
||||||
OGLRef.position4fBuffer[positionIndex+2] = (float)vtx.position.z / 4096.0f;
|
|
||||||
OGLRef.position4fBuffer[positionIndex+3] = (float)vtx.position.w / 4096.0f;
|
|
||||||
|
|
||||||
OGLRef.texCoord2fBuffer[texCoordIndex+0] = (float)vtx.texCoord.s / 16.0f;
|
|
||||||
OGLRef.texCoord2fBuffer[texCoordIndex+1] = (float)vtx.texCoord.t / 16.0f;
|
|
||||||
|
|
||||||
OGLRef.color4fBuffer[colorIndex+0] = divide6bitBy63_LUT[vtx.color.r];
|
|
||||||
OGLRef.color4fBuffer[colorIndex+1] = divide6bitBy63_LUT[vtx.color.g];
|
|
||||||
OGLRef.color4fBuffer[colorIndex+2] = divide6bitBy63_LUT[vtx.color.b];
|
|
||||||
OGLRef.color4fBuffer[colorIndex+3] = thePolyAlpha;
|
|
||||||
|
|
||||||
// While we're looping through our vertices, add each vertex index to a
|
|
||||||
// buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
|
|
||||||
// vertices here to convert them to GL_TRIANGLES, which are much easier
|
|
||||||
// to work with and won't be deprecated in future OpenGL versions.
|
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = vtxIndex;
|
|
||||||
if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
|
|
||||||
{
|
|
||||||
if (j == 2)
|
|
||||||
{
|
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = vtxIndex;
|
|
||||||
}
|
|
||||||
else if (j == 3)
|
|
||||||
{
|
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderNeedsToonTable = (renderNeedsToonTable || (rawPoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT)) && this->isShaderSupported;
|
// Generate the clipped polygon list.
|
||||||
|
bool renderNeedsToonTable = false;
|
||||||
|
|
||||||
// Get the texture that is to be attached to this polygon.
|
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
|
||||||
this->_textureList[i] = this->GetLoadedTextureFromPolygon(rawPoly, this->_enableTextureSampling);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->isVBOSupported)
|
|
||||||
{
|
|
||||||
// Replace the entire index buffer as a hint to the driver that we can orphan the index 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 = (renderState.DISP3DCNT.EnableAntialiasing) ? GL_TRUE : GL_FALSE;
|
|
||||||
this->_pendingRenderStates.enableFogAlphaOnly = (renderState.DISP3DCNT.FogOnlyAlpha) ? GL_TRUE : GL_FALSE;
|
|
||||||
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
|
|
||||||
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
|
|
||||||
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[renderState.alphaTestRef];
|
|
||||||
|
|
||||||
if (this->_enableFog && this->_deviceInfo.isFogSupported)
|
|
||||||
{
|
|
||||||
this->_fogProgramKey.key = 0;
|
|
||||||
this->_fogProgramKey.offset = renderState.fogOffset & 0x7FFF;
|
|
||||||
this->_fogProgramKey.shift = renderState.fogShift;
|
|
||||||
|
|
||||||
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(renderState.fogColor ) & 0x0000001F];
|
|
||||||
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(renderState.fogColor >> 5) & 0x0000001F];
|
|
||||||
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(renderState.fogColor >> 10) & 0x0000001F];
|
|
||||||
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(renderState.fogColor >> 16) & 0x0000001F];
|
|
||||||
this->_pendingRenderStates.fogOffset = (GLfloat)(renderState.fogOffset & 0x7FFF) / 32767.0f;
|
|
||||||
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> renderState.fogShift) / 32767.0f;
|
|
||||||
|
|
||||||
u8 fogDensityTable[32];
|
|
||||||
for (size_t i = 0; i < 32; i++)
|
|
||||||
{
|
{
|
||||||
fogDensityTable[i] = (renderState.fogDensityTable[i] == 127) ? 255 : renderState.fogDensityTable[i] << 1;
|
const CPoly &cPoly = this->_clippedPolyList[i];
|
||||||
|
const POLY &rawPoly = this->_rawPolyList[cPoly.index];
|
||||||
|
const size_t polyType = rawPoly.type;
|
||||||
|
|
||||||
|
if (this->isShaderSupported)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < polyType; j++)
|
||||||
|
{
|
||||||
|
const GLushort vertIndex = rawPoly.vertIndexes[j];
|
||||||
|
|
||||||
|
// While we're looping through our vertices, add each vertex index to
|
||||||
|
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
|
||||||
|
// vertices here to convert them to GL_TRIANGLES, which are much easier
|
||||||
|
// to work with and won't be deprecated in future OpenGL versions.
|
||||||
|
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
|
||||||
|
if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
|
||||||
|
{
|
||||||
|
if (j == 2)
|
||||||
|
{
|
||||||
|
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
|
||||||
|
}
|
||||||
|
else if (j == 3)
|
||||||
|
{
|
||||||
|
OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const GLfloat thePolyAlpha = (GFX3D_IsPolyWireframe(rawPoly)) ? 1.0f : divide5bitBy31_LUT[rawPoly.attribute.Alpha];
|
||||||
|
|
||||||
|
for (size_t j = 0; j < polyType; j++)
|
||||||
|
{
|
||||||
|
const GLushort vtxIndex = rawPoly.vertIndexes[j];
|
||||||
|
const size_t positionIndex = vtxIndex * 4;
|
||||||
|
const size_t texCoordIndex = vtxIndex * 2;
|
||||||
|
const size_t colorIndex = vtxIndex * 4;
|
||||||
|
const NDSVertex &vtx = renderGList.rawVtxList[vtxIndex];
|
||||||
|
|
||||||
|
// Since we can't use shaders, we can't perform any data format conversions
|
||||||
|
// of the vertex data on the GPU. Therefore, we need to do the conversions
|
||||||
|
// on the CPU instead.
|
||||||
|
OGLRef.position4fBuffer[positionIndex+0] = (float)vtx.position.x / 4096.0f;
|
||||||
|
OGLRef.position4fBuffer[positionIndex+1] = (float)vtx.position.y / 4096.0f;
|
||||||
|
OGLRef.position4fBuffer[positionIndex+2] = (float)vtx.position.z / 4096.0f;
|
||||||
|
OGLRef.position4fBuffer[positionIndex+3] = (float)vtx.position.w / 4096.0f;
|
||||||
|
|
||||||
|
OGLRef.texCoord2fBuffer[texCoordIndex+0] = (float)vtx.texCoord.s / 16.0f;
|
||||||
|
OGLRef.texCoord2fBuffer[texCoordIndex+1] = (float)vtx.texCoord.t / 16.0f;
|
||||||
|
|
||||||
|
OGLRef.color4fBuffer[colorIndex+0] = divide6bitBy63_LUT[vtx.color.r];
|
||||||
|
OGLRef.color4fBuffer[colorIndex+1] = divide6bitBy63_LUT[vtx.color.g];
|
||||||
|
OGLRef.color4fBuffer[colorIndex+2] = divide6bitBy63_LUT[vtx.color.b];
|
||||||
|
OGLRef.color4fBuffer[colorIndex+3] = thePolyAlpha;
|
||||||
|
|
||||||
|
// While we're looping through our vertices, add each vertex index to a
|
||||||
|
// buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
|
||||||
|
// vertices here to convert them to GL_TRIANGLES, which are much easier
|
||||||
|
// to work with and won't be deprecated in future OpenGL versions.
|
||||||
|
OGLRef.vertIndexBuffer[vertIndexCount++] = vtxIndex;
|
||||||
|
if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
|
||||||
|
{
|
||||||
|
if (j == 2)
|
||||||
|
{
|
||||||
|
OGLRef.vertIndexBuffer[vertIndexCount++] = vtxIndex;
|
||||||
|
}
|
||||||
|
else if (j == 3)
|
||||||
|
{
|
||||||
|
OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNeedsToonTable = (renderNeedsToonTable || (rawPoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT)) && this->isShaderSupported;
|
||||||
|
|
||||||
|
// Get the texture that is to be attached to this polygon.
|
||||||
|
this->_textureList[i] = this->GetLoadedTextureFromPolygon(rawPoly, this->_enableTextureSampling);
|
||||||
}
|
}
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
if (this->isVBOSupported)
|
||||||
glBindTexture(GL_TEXTURE_1D, OGLRef.texFogDensityTableID);
|
|
||||||
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RED, GL_UNSIGNED_BYTE, fogDensityTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported)
|
|
||||||
{
|
|
||||||
const u8 alpha8 = (renderState.DISP3DCNT.EnableAntialiasing) ? 0x80 : 0xFF;
|
|
||||||
Color4u8 edgeColor32[8];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; i++)
|
|
||||||
{
|
{
|
||||||
edgeColor32[i].value = COLOR555TO8888(renderState.edgeMarkColorTable[i] & 0x7FFF, alpha8);
|
// Replace the entire index buffer as a hint to the driver that we can orphan the index buffer and
|
||||||
|
// avoid a synchronization cost.
|
||||||
|
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(OGLRef.vertIndexBuffer), OGLRef.vertIndexBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
// Set up rendering states that will remain constant for the entire frame.
|
||||||
glBindTexture(GL_TEXTURE_1D, OGLRef.texEdgeColorTableID);
|
this->_pendingRenderStates.enableAntialiasing = (renderState.DISP3DCNT.EnableAntialiasing) ? GL_TRUE : GL_FALSE;
|
||||||
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 8, GL_RGBA, OGL_TEXTURE_SRC_EDGE_COLOR, edgeColor32);
|
this->_pendingRenderStates.enableFogAlphaOnly = (renderState.DISP3DCNT.FogOnlyAlpha) ? GL_TRUE : GL_FALSE;
|
||||||
}
|
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
|
||||||
|
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
|
||||||
|
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[renderState.alphaTestRef];
|
||||||
|
|
||||||
if (this->isShaderSupported)
|
if (this->_enableFog && this->_deviceInfo.isFogSupported)
|
||||||
{
|
|
||||||
this->_geometryProgramFlags.value = 0;
|
|
||||||
this->_geometryProgramFlags.EnableWDepth = renderState.SWAP_BUFFERS.DepthMode;
|
|
||||||
this->_geometryProgramFlags.EnableAlphaTest = renderState.DISP3DCNT.EnableAlphaTest;
|
|
||||||
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
|
|
||||||
this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading;
|
|
||||||
this->_geometryProgramFlags.EnableFog = (this->_enableFog && this->_deviceInfo.isFogSupported) ? 1 : 0;
|
|
||||||
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0;
|
|
||||||
this->_geometryProgramFlags.OpaqueDrawMode = (this->_isDepthLEqualPolygonFacingSupported) ? 1 : 0;
|
|
||||||
|
|
||||||
this->_SetupGeometryShaders(this->_geometryProgramFlags);
|
|
||||||
|
|
||||||
if (renderNeedsToonTable)
|
|
||||||
{
|
{
|
||||||
|
this->_fogProgramKey.key = 0;
|
||||||
|
this->_fogProgramKey.offset = renderState.fogOffset & 0x7FFF;
|
||||||
|
this->_fogProgramKey.shift = renderState.fogShift;
|
||||||
|
|
||||||
|
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(renderState.fogColor ) & 0x0000001F];
|
||||||
|
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(renderState.fogColor >> 5) & 0x0000001F];
|
||||||
|
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(renderState.fogColor >> 10) & 0x0000001F];
|
||||||
|
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(renderState.fogColor >> 16) & 0x0000001F];
|
||||||
|
this->_pendingRenderStates.fogOffset = (GLfloat)(renderState.fogOffset & 0x7FFF) / 32767.0f;
|
||||||
|
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> renderState.fogShift) / 32767.0f;
|
||||||
|
|
||||||
|
u8 fogDensityTable[32];
|
||||||
|
for (size_t i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
fogDensityTable[i] = (renderState.fogDensityTable[i] == 127) ? 255 : renderState.fogDensityTable[i] << 1;
|
||||||
|
}
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
||||||
glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID);
|
glBindTexture(GL_TEXTURE_1D, OGLRef.texFogDensityTableID);
|
||||||
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, OGL_TEXTURE_SRC_TOON_TABLE, renderState.toonTable16);
|
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RED, GL_UNSIGNED_BYTE, fogDensityTable);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#if !defined(GL_ES_VERSION_3_0)
|
if (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported)
|
||||||
else
|
|
||||||
{
|
|
||||||
if (renderState.DISP3DCNT.EnableAlphaTest && (renderState.alphaTestRef > 0))
|
|
||||||
{
|
{
|
||||||
glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[renderState.alphaTestRef]);
|
const u8 alpha8 = (renderState.DISP3DCNT.EnableAntialiasing) ? 0x80 : 0xFF;
|
||||||
|
Color4u8 edgeColor32[8];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
edgeColor32[i].value = COLOR555TO8888(renderState.edgeMarkColorTable[i] & 0x7FFF, alpha8);
|
||||||
|
}
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
||||||
|
glBindTexture(GL_TEXTURE_1D, OGLRef.texEdgeColorTableID);
|
||||||
|
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 8, GL_RGBA, OGL_TEXTURE_SRC_EDGE_COLOR, edgeColor32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->isShaderSupported)
|
||||||
|
{
|
||||||
|
this->_geometryProgramFlags.value = 0;
|
||||||
|
this->_geometryProgramFlags.EnableWDepth = renderState.SWAP_BUFFERS.DepthMode;
|
||||||
|
this->_geometryProgramFlags.EnableAlphaTest = renderState.DISP3DCNT.EnableAlphaTest;
|
||||||
|
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
|
||||||
|
this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading;
|
||||||
|
this->_geometryProgramFlags.EnableFog = (this->_enableFog && this->_deviceInfo.isFogSupported) ? 1 : 0;
|
||||||
|
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0;
|
||||||
|
this->_geometryProgramFlags.OpaqueDrawMode = (this->_isDepthLEqualPolygonFacingSupported) ? 1 : 0;
|
||||||
|
|
||||||
|
this->_SetupGeometryShaders(this->_geometryProgramFlags);
|
||||||
|
|
||||||
|
if (renderNeedsToonTable)
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
||||||
|
glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID);
|
||||||
|
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, OGL_TEXTURE_SRC_TOON_TABLE, renderState.toonTable16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if !defined(GL_ES_VERSION_3_0)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glAlphaFunc(GL_GREATER, 0);
|
if (renderState.DISP3DCNT.EnableAlphaTest && (renderState.alphaTestRef > 0))
|
||||||
}
|
{
|
||||||
|
glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[renderState.alphaTestRef]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glAlphaFunc(GL_GREATER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
if (this->isFBOSupported)
|
if (this->isFBOSupported)
|
||||||
{
|
{
|
||||||
glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID);
|
glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID);
|
glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID);
|
||||||
|
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
|
|
||||||
|
@ -4654,6 +4656,11 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
|
||||||
|
|
||||||
Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer()
|
Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer()
|
||||||
{
|
{
|
||||||
|
if (this->_clippedPolyCount < 1)
|
||||||
|
{
|
||||||
|
return OGLERROR_NOERR;
|
||||||
|
}
|
||||||
|
|
||||||
OGLRenderRef &OGLRef = *this->ref;
|
OGLRenderRef &OGLRef = *this->ref;
|
||||||
|
|
||||||
if ( (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ||
|
if ( (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ||
|
||||||
|
|
|
@ -1038,18 +1038,10 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples)
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
|
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID);
|
||||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, GL_TRUE);
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, GL_TRUE);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
|
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID);
|
||||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, GL_TRUE);
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, GL_TRUE);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
@ -2289,200 +2281,203 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
|
||||||
|
|
||||||
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
|
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
|
if (this->_clippedPolyCount > 0)
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
|
|
||||||
|
|
||||||
// Copy the vertex data to the GPU asynchronously due to the potentially large upload size.
|
|
||||||
// This buffer write will need to be synchronized before we start drawing.
|
|
||||||
if (this->_syncBufferSetup != NULL)
|
|
||||||
{
|
{
|
||||||
glWaitSync(this->_syncBufferSetup, 0, GL_TIMEOUT_IGNORED);
|
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
|
||||||
glDeleteSync(this->_syncBufferSetup);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
|
||||||
}
|
|
||||||
|
|
||||||
const size_t vtxBufferSize = sizeof(NDSVertex) * renderGList.rawVertCount;
|
// Copy the vertex data to the GPU asynchronously due to the potentially large upload size.
|
||||||
NDSVertex *vtxPtr = (NDSVertex *)glMapBufferRange(GL_ARRAY_BUFFER, 0, vtxBufferSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
|
// This buffer write will need to be synchronized before we start drawing.
|
||||||
memcpy(vtxPtr, renderGList.rawVtxList, vtxBufferSize);
|
if (this->_syncBufferSetup != NULL)
|
||||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
||||||
|
|
||||||
this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
||||||
|
|
||||||
// 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 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.
|
|
||||||
bool renderNeedsToonTable = false;
|
|
||||||
|
|
||||||
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
|
|
||||||
{
|
|
||||||
const CPoly &cPoly = this->_clippedPolyList[i];
|
|
||||||
const POLY &rawPoly = this->_rawPolyList[cPoly.index];
|
|
||||||
const size_t polyType = rawPoly.type;
|
|
||||||
|
|
||||||
for (size_t j = 0; j < polyType; j++)
|
|
||||||
{
|
{
|
||||||
const GLushort vertIndex = rawPoly.vertIndexes[j];
|
glWaitSync(this->_syncBufferSetup, 0, GL_TIMEOUT_IGNORED);
|
||||||
|
glDeleteSync(this->_syncBufferSetup);
|
||||||
|
}
|
||||||
|
|
||||||
// While we're looping through our vertices, add each vertex index to
|
const size_t vtxBufferSize = sizeof(NDSVertex) * renderGList.rawVertCount;
|
||||||
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
|
NDSVertex *vtxPtr = (NDSVertex *)glMapBufferRange(GL_ARRAY_BUFFER, 0, vtxBufferSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
|
||||||
// vertices here to convert them to GL_TRIANGLES, which are much easier
|
memcpy(vtxPtr, renderGList.rawVtxList, vtxBufferSize);
|
||||||
// to work with and won't be deprecated in future OpenGL versions.
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
|
|
||||||
if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
|
this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
|
||||||
|
// 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 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.
|
||||||
|
bool renderNeedsToonTable = false;
|
||||||
|
|
||||||
|
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
|
||||||
|
{
|
||||||
|
const CPoly &cPoly = this->_clippedPolyList[i];
|
||||||
|
const POLY &rawPoly = this->_rawPolyList[cPoly.index];
|
||||||
|
const size_t polyType = rawPoly.type;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < polyType; j++)
|
||||||
{
|
{
|
||||||
if (j == 2)
|
const GLushort vertIndex = rawPoly.vertIndexes[j];
|
||||||
|
|
||||||
|
// While we're looping through our vertices, add each vertex index to
|
||||||
|
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
|
||||||
|
// vertices here to convert them to GL_TRIANGLES, which are much easier
|
||||||
|
// to work with and won't be deprecated in future OpenGL versions.
|
||||||
|
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
|
||||||
|
if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
|
||||||
{
|
{
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
|
if (j == 2)
|
||||||
}
|
{
|
||||||
else if (j == 3)
|
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
|
||||||
{
|
}
|
||||||
OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
|
else if (j == 3)
|
||||||
|
{
|
||||||
|
OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderNeedsToonTable = renderNeedsToonTable || (rawPoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT);
|
||||||
|
|
||||||
|
// Get the texture that is to be attached to this polygon.
|
||||||
|
this->_textureList[i] = this->GetLoadedTextureFromPolygon(rawPoly, this->_enableTextureSampling);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 = (renderState.DISP3DCNT.EnableAntialiasing) ? GL_TRUE : GL_FALSE;
|
||||||
|
this->_pendingRenderStates.enableFogAlphaOnly = (renderState.DISP3DCNT.FogOnlyAlpha) ? GL_TRUE : GL_FALSE;
|
||||||
|
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
|
||||||
|
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
|
||||||
|
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[renderState.alphaTestRef];
|
||||||
|
|
||||||
|
if (renderNeedsToonTable)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
this->_pendingRenderStates.toonColor[i].r = divide5bitBy31_LUT[(renderState.toonTable16[i] ) & 0x001F];
|
||||||
|
this->_pendingRenderStates.toonColor[i].g = divide5bitBy31_LUT[(renderState.toonTable16[i] >> 5) & 0x001F];
|
||||||
|
this->_pendingRenderStates.toonColor[i].b = divide5bitBy31_LUT[(renderState.toonTable16[i] >> 10) & 0x001F];
|
||||||
|
this->_pendingRenderStates.toonColor[i].a = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderNeedsToonTable = renderNeedsToonTable || (rawPoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT);
|
if (this->_enableFog)
|
||||||
|
|
||||||
// Get the texture that is to be attached to this polygon.
|
|
||||||
this->_textureList[i] = this->GetLoadedTextureFromPolygon(rawPoly, this->_enableTextureSampling);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 = (renderState.DISP3DCNT.EnableAntialiasing) ? GL_TRUE : GL_FALSE;
|
|
||||||
this->_pendingRenderStates.enableFogAlphaOnly = (renderState.DISP3DCNT.FogOnlyAlpha) ? GL_TRUE : GL_FALSE;
|
|
||||||
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
|
|
||||||
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
|
|
||||||
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[renderState.alphaTestRef];
|
|
||||||
|
|
||||||
if (renderNeedsToonTable)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < 32; i++)
|
|
||||||
{
|
{
|
||||||
this->_pendingRenderStates.toonColor[i].r = divide5bitBy31_LUT[(renderState.toonTable16[i] ) & 0x001F];
|
this->_fogProgramKey.key = 0;
|
||||||
this->_pendingRenderStates.toonColor[i].g = divide5bitBy31_LUT[(renderState.toonTable16[i] >> 5) & 0x001F];
|
this->_fogProgramKey.offset = renderState.fogOffset & 0x7FFF;
|
||||||
this->_pendingRenderStates.toonColor[i].b = divide5bitBy31_LUT[(renderState.toonTable16[i] >> 10) & 0x001F];
|
this->_fogProgramKey.shift = renderState.fogShift;
|
||||||
this->_pendingRenderStates.toonColor[i].a = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->_enableFog)
|
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(renderState.fogColor ) & 0x0000001F];
|
||||||
{
|
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(renderState.fogColor >> 5) & 0x0000001F];
|
||||||
this->_fogProgramKey.key = 0;
|
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(renderState.fogColor >> 10) & 0x0000001F];
|
||||||
this->_fogProgramKey.offset = renderState.fogOffset & 0x7FFF;
|
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(renderState.fogColor >> 16) & 0x0000001F];
|
||||||
this->_fogProgramKey.shift = renderState.fogShift;
|
this->_pendingRenderStates.fogOffset = (GLfloat)(renderState.fogOffset & 0x7FFF) / 32767.0f;
|
||||||
|
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> renderState.fogShift) / 32767.0f;
|
||||||
|
|
||||||
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(renderState.fogColor ) & 0x0000001F];
|
u8 fogDensityTable[32];
|
||||||
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(renderState.fogColor >> 5) & 0x0000001F];
|
for (size_t i = 0; i < 32; i++)
|
||||||
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(renderState.fogColor >> 10) & 0x0000001F];
|
{
|
||||||
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(renderState.fogColor >> 16) & 0x0000001F];
|
fogDensityTable[i] = (renderState.fogDensityTable[i] == 127) ? 255 : renderState.fogDensityTable[i] << 1;
|
||||||
this->_pendingRenderStates.fogOffset = (GLfloat)(renderState.fogOffset & 0x7FFF) / 32767.0f;
|
}
|
||||||
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> renderState.fogShift) / 32767.0f;
|
|
||||||
|
|
||||||
u8 fogDensityTable[32];
|
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
||||||
for (size_t i = 0; i < 32; i++)
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 32, 1, GL_RED, GL_UNSIGNED_BYTE, fogDensityTable);
|
||||||
{
|
|
||||||
fogDensityTable[i] = (renderState.fogDensityTable[i] == 127) ? 255 : renderState.fogDensityTable[i] << 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
if (this->_enableEdgeMark)
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 32, 1, GL_RED, GL_UNSIGNED_BYTE, fogDensityTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->_enableEdgeMark)
|
|
||||||
{
|
|
||||||
const GLfloat edgeColorAlpha = (renderState.DISP3DCNT.EnableAntialiasing) ? (16.0f/31.0f) : 1.0f;
|
|
||||||
for (size_t i = 0; i < 8; i++)
|
|
||||||
{
|
{
|
||||||
this->_pendingRenderStates.edgeColor[i].r = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] ) & 0x001F];
|
const GLfloat edgeColorAlpha = (renderState.DISP3DCNT.EnableAntialiasing) ? (16.0f/31.0f) : 1.0f;
|
||||||
this->_pendingRenderStates.edgeColor[i].g = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] >> 5) & 0x001F];
|
for (size_t i = 0; i < 8; i++)
|
||||||
this->_pendingRenderStates.edgeColor[i].b = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] >> 10) & 0x001F];
|
{
|
||||||
this->_pendingRenderStates.edgeColor[i].a = edgeColorAlpha;
|
this->_pendingRenderStates.edgeColor[i].r = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] ) & 0x001F];
|
||||||
|
this->_pendingRenderStates.edgeColor[i].g = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] >> 5) & 0x001F];
|
||||||
|
this->_pendingRenderStates.edgeColor[i].b = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] >> 10) & 0x001F];
|
||||||
|
this->_pendingRenderStates.edgeColor[i].a = edgeColorAlpha;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboRenderStatesID);
|
glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboRenderStatesID);
|
||||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(this->_pendingRenderStates), &this->_pendingRenderStates);
|
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(this->_pendingRenderStates), &this->_pendingRenderStates);
|
||||||
|
|
||||||
OGLPolyStates *polyStates = this->_pendingPolyStates;
|
OGLPolyStates *polyStates = this->_pendingPolyStates;
|
||||||
|
|
||||||
#if defined(GL_VERSION_3_1) || defined(GL_ES_VERSION_3_2)
|
#if defined(GL_VERSION_3_1) || defined(GL_ES_VERSION_3_2)
|
||||||
if (OGLRef.tboPolyStatesID != 0)
|
if (OGLRef.tboPolyStatesID != 0)
|
||||||
{
|
{
|
||||||
// Some drivers seem to have problems with GL_TEXTURE_BUFFER used as the target for
|
// Some drivers seem to have problems with GL_TEXTURE_BUFFER used as the target for
|
||||||
// glMapBufferRange() or glBufferSubData(), causing certain polygons to intermittently
|
// glMapBufferRange() or glBufferSubData(), causing certain polygons to intermittently
|
||||||
// flicker in certain games. Therefore, we'll use glMapBuffer() in this case in order
|
// flicker in certain games. Therefore, we'll use glMapBuffer() in this case in order
|
||||||
// to prevent these glitches from happening.
|
// to prevent these glitches from happening.
|
||||||
polyStates = (OGLPolyStates *)glMapBuffer(GL_TEXTURE_BUFFER, GL_WRITE_ONLY);
|
polyStates = (OGLPolyStates *)glMapBuffer(GL_TEXTURE_BUFFER, GL_WRITE_ONLY);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (size_t i = 0; i < this->_clippedPolyCount; i++)
|
for (size_t i = 0; i < this->_clippedPolyCount; i++)
|
||||||
{
|
{
|
||||||
const POLY &rawPoly = this->_rawPolyList[this->_clippedPolyList[i].index];
|
const POLY &rawPoly = this->_rawPolyList[this->_clippedPolyList[i].index];
|
||||||
|
|
||||||
// Get all of the polygon states that can be handled within the shader.
|
// Get all of the polygon states that can be handled within the shader.
|
||||||
const NDSTextureFormat packFormat = this->_textureList[i]->GetPackFormat();
|
const NDSTextureFormat packFormat = this->_textureList[i]->GetPackFormat();
|
||||||
|
|
||||||
polyStates[i].packedState = 0;
|
polyStates[i].packedState = 0;
|
||||||
polyStates[i].PolygonID = rawPoly.attribute.PolygonID;
|
polyStates[i].PolygonID = rawPoly.attribute.PolygonID;
|
||||||
polyStates[i].PolygonMode = rawPoly.attribute.Mode;
|
polyStates[i].PolygonMode = rawPoly.attribute.Mode;
|
||||||
|
|
||||||
polyStates[i].PolygonAlpha = (GFX3D_IsPolyWireframe(rawPoly)) ? 0x1F : rawPoly.attribute.Alpha;
|
polyStates[i].PolygonAlpha = (GFX3D_IsPolyWireframe(rawPoly)) ? 0x1F : rawPoly.attribute.Alpha;
|
||||||
polyStates[i].IsWireframe = (GFX3D_IsPolyWireframe(rawPoly)) ? 1 : 0;
|
polyStates[i].IsWireframe = (GFX3D_IsPolyWireframe(rawPoly)) ? 1 : 0;
|
||||||
polyStates[i].EnableFog = (rawPoly.attribute.Fog_Enable) ? 1 : 0;
|
polyStates[i].EnableFog = (rawPoly.attribute.Fog_Enable) ? 1 : 0;
|
||||||
polyStates[i].SetNewDepthForTranslucent = (rawPoly.attribute.TranslucentDepthWrite_Enable) ? 1 : 0;
|
polyStates[i].SetNewDepthForTranslucent = (rawPoly.attribute.TranslucentDepthWrite_Enable) ? 1 : 0;
|
||||||
|
|
||||||
polyStates[i].EnableTexture = (this->_textureList[i]->IsSamplingEnabled()) ? 1 : 0;
|
polyStates[i].EnableTexture = (this->_textureList[i]->IsSamplingEnabled()) ? 1 : 0;
|
||||||
polyStates[i].TexSingleBitAlpha = (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? 1 : 0;
|
polyStates[i].TexSingleBitAlpha = (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? 1 : 0;
|
||||||
polyStates[i].TexSizeShiftS = rawPoly.texParam.SizeShiftS; // Note that we are using the preshifted size of S
|
polyStates[i].TexSizeShiftS = rawPoly.texParam.SizeShiftS; // Note that we are using the preshifted size of S
|
||||||
polyStates[i].TexSizeShiftT = rawPoly.texParam.SizeShiftT; // Note that we are using the preshifted size of T
|
polyStates[i].TexSizeShiftT = rawPoly.texParam.SizeShiftT; // Note that we are using the preshifted size of T
|
||||||
|
|
||||||
polyStates[i].IsBackFacing = (this->_clippedPolyList[i].isPolyBackFacing) ? 1 : 0;
|
polyStates[i].IsBackFacing = (this->_clippedPolyList[i].isPolyBackFacing) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OGLRef.uboPolyStatesID != 0)
|
if (OGLRef.uboPolyStatesID != 0)
|
||||||
{
|
{
|
||||||
// Replace the entire buffer as a hint to the driver to orphan the buffer and avoid a synchronization cost.
|
// Replace the entire buffer as a hint to the driver to orphan the buffer and avoid a synchronization cost.
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboPolyStatesID);
|
glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboPolyStatesID);
|
||||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, MAX_CLIPPED_POLY_COUNT_FOR_UBO * sizeof(OGLPolyStates), this->_pendingPolyStates);
|
glBufferSubData(GL_UNIFORM_BUFFER, 0, MAX_CLIPPED_POLY_COUNT_FOR_UBO * sizeof(OGLPolyStates), this->_pendingPolyStates);
|
||||||
}
|
}
|
||||||
#if defined(GL_VERSION_3_1) || defined(GL_ES_VERSION_3_2)
|
#if defined(GL_VERSION_3_1) || defined(GL_ES_VERSION_3_2)
|
||||||
else if (OGLRef.tboPolyStatesID != 0)
|
else if (OGLRef.tboPolyStatesID != 0)
|
||||||
{
|
{
|
||||||
glUnmapBuffer(GL_TEXTURE_BUFFER);
|
glUnmapBuffer(GL_TEXTURE_BUFFER);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const GLsizei texH = (GLsizei)((this->_clippedPolyCount >> 8) & 0x007F) + 1;
|
const GLsizei texH = (GLsizei)((this->_clippedPolyCount >> 8) & 0x007F) + 1;
|
||||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_PolyStates);
|
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_PolyStates);
|
||||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texPolyStatesID); // Why is this bind necessary? Theoretically, it shouldn't be necessary, but real-world testing has proven otherwise...
|
glBindTexture(GL_TEXTURE_2D, OGLRef.texPolyStatesID); // Why is this bind necessary? Theoretically, it shouldn't be necessary, but real-world testing has proven otherwise...
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, texH, GL_RED_INTEGER, GL_INT, this->_pendingPolyStates);
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, texH, GL_RED_INTEGER, GL_INT, this->_pendingPolyStates);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the default draw call states.
|
||||||
|
this->_geometryProgramFlags.value = 0;
|
||||||
|
this->_geometryProgramFlags.EnableWDepth = renderState.SWAP_BUFFERS.DepthMode;
|
||||||
|
this->_geometryProgramFlags.EnableAlphaTest = renderState.DISP3DCNT.EnableAlphaTest;
|
||||||
|
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
|
||||||
|
this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading;
|
||||||
|
this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0;
|
||||||
|
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0;
|
||||||
|
this->_geometryProgramFlags.OpaqueDrawMode = 1;
|
||||||
|
|
||||||
|
this->_SetupGeometryShaders(this->_geometryProgramFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the default draw call states.
|
|
||||||
this->_geometryProgramFlags.value = 0;
|
|
||||||
this->_geometryProgramFlags.EnableWDepth = renderState.SWAP_BUFFERS.DepthMode;
|
|
||||||
this->_geometryProgramFlags.EnableAlphaTest = renderState.DISP3DCNT.EnableAlphaTest;
|
|
||||||
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
|
|
||||||
this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading;
|
|
||||||
this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0;
|
|
||||||
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0;
|
|
||||||
this->_geometryProgramFlags.OpaqueDrawMode = 1;
|
|
||||||
|
|
||||||
this->_SetupGeometryShaders(this->_geometryProgramFlags);
|
|
||||||
glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID);
|
glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID);
|
||||||
|
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
|
|
||||||
|
@ -2493,6 +2488,11 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
|
||||||
|
|
||||||
Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer()
|
Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer()
|
||||||
{
|
{
|
||||||
|
if (this->_clippedPolyCount < 1)
|
||||||
|
{
|
||||||
|
return OGLERROR_NOERR;
|
||||||
|
}
|
||||||
|
|
||||||
OGLRenderRef &OGLRef = *this->ref;
|
OGLRenderRef &OGLRef = *this->ref;
|
||||||
|
|
||||||
if (this->_enableEdgeMark || this->_enableFog)
|
if (this->_enableEdgeMark || this->_enableFog)
|
||||||
|
|
Loading…
Reference in New Issue