OpenGL Renderer:

- Add fog support.
This commit is contained in:
rogerman 2015-04-23 20:01:51 +00:00
parent 4fdcffa126
commit 2ae84828e5
6 changed files with 706 additions and 122 deletions

View File

@ -41,14 +41,18 @@ static OpenGLRenderer *_OGLRenderer = NULL;
// Lookup Tables
static CACHE_ALIGN GLfloat material_8bit_to_float[256] = {0};
static CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32] = {0.0, 0.03225806451613, 0.06451612903226, 0.09677419354839,
0.1290322580645, 0.1612903225806, 0.1935483870968, 0.2258064516129,
0.258064516129, 0.2903225806452, 0.3225806451613, 0.3548387096774,
0.3870967741935, 0.4193548387097, 0.4516129032258, 0.4838709677419,
0.5161290322581, 0.5483870967742, 0.5806451612903, 0.6129032258065,
0.6451612903226, 0.6774193548387, 0.7096774193548, 0.741935483871,
0.7741935483871, 0.8064516129032, 0.8387096774194, 0.8709677419355,
0.9032258064516, 0.9354838709677, 0.9677419354839, 1.0};
CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32] = {0.0, 0.03225806451613, 0.06451612903226, 0.09677419354839,
0.1290322580645, 0.1612903225806, 0.1935483870968, 0.2258064516129,
0.2580645161290, 0.2903225806452, 0.3225806451613, 0.3548387096774,
0.3870967741935, 0.4193548387097, 0.4516129032258, 0.4838709677419,
0.5161290322581, 0.5483870967742, 0.5806451612903, 0.6129032258065,
0.6451612903226, 0.6774193548387, 0.7096774193548, 0.7419354838710,
0.7741935483871, 0.8064516129032, 0.8387096774194, 0.8709677419355,
0.9032258064516, 0.9354838709677, 0.9677419354839, 1.0};
const GLfloat PostprocessVtxBuffer[16] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
const GLubyte PostprocessElementBuffer[6] = {0, 1, 2, 2, 3, 0};
const GLenum RenderDrawList[3] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};
@ -279,6 +283,13 @@ static const char *fragmentShader_100 = {"\
uniform bool polyEnableTexture; \n\
uniform bool polyEnableFog;\n\
\n\
vec3 packVec3FromFloat(const float value)\n\
{\n\
float expandedValue = value * 16777215.0;\n\
vec3 packedValue = vec3( fract(expandedValue/256.0), fract(((expandedValue/256.0) - fract(expandedValue/256.0)) / 256.0), fract(((expandedValue/65536.0) - fract(expandedValue/65536.0)) / 256.0) );\n\
return packedValue;\n\
}\n\
\n\
void main() \n\
{ \n\
vec4 mainTexColor = (polyEnableTexture) ? texture2D(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\
@ -311,12 +322,80 @@ static const char *fragmentShader_100 = {"\
float newFragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\
\n\
gl_FragData[0] = newFragColor;\n\
gl_FragData[1] = vec4( vec3(newFragDepth), 1.0);\n\
gl_FragData[1] = vec4( packVec3FromFloat(newFragDepth), 1.0);\n\
gl_FragData[2] = vec4( float(polyEnableFog), float(stateEnableFogAlphaOnly), 0.0, 1.0);\n\
gl_FragDepth = newFragDepth;\n\
} \n\
"};
// Vertex shader for post-processing, GLSL 1.00
static const char *PostprocessVertShader_100 = {"\
attribute vec2 inPosition;\n\
attribute vec2 inTexCoord0;\n\
varying vec2 texCoord;\n\
\n\
void main() \n\
{ \n\
texCoord = inTexCoord0; \n\
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
}\n\
"};
// Fragment shader for applying fog, GLSL 1.00
static const char *FogFragShader_100 = {"\
varying vec2 texCoord;\n\
\n\
uniform sampler2D texInFragColor;\n\
uniform sampler2D texInFragDepthOnly;\n\
uniform sampler2D texInFogAttributes;\n\
uniform vec4 stateFogColor;\n\
uniform float stateFogDensity[32];\n\
uniform float stateFogOffset;\n\
uniform float stateFogStep;\n\
\n\
float unpackFloatFromVec3(const vec3 value)\n\
{\n\
const vec3 unpackRatio = vec3(256.0, 65536.0, 16777216.0);\n\
return (dot(value, unpackRatio) / 16777215.0);\n\
}\n\
\n\
void main()\n\
{\n\
vec4 inFragColor = texture2D(texInFragColor, texCoord);\n\
float inFragDepth = unpackFloatFromVec3(texture2D(texInFragDepthOnly, texCoord).rgb);\n\
vec4 inFogAttributes = texture2D(texInFogAttributes, texCoord);\n\
\n\
bool polyEnableFog = bool(inFogAttributes.r);\n\
bool stateEnableFogAlphaOnly = bool(inFogAttributes.g) ;\n\
\n\
float fogMixWeight = 0.0;\n\
if (inFragDepth <= min(stateFogOffset + stateFogStep, 1.0))\n\
{\n\
fogMixWeight = stateFogDensity[0];\n\
}\n\
else if (inFragDepth >= min(stateFogOffset + (stateFogStep*32.0), 1.0))\n\
{\n\
fogMixWeight = stateFogDensity[31];\n\
}\n\
else\n\
{\n\
for (int i = 1; i < 32; i++)\n\
{\n\
float currentFogStep = min(stateFogOffset + (stateFogStep * float(i+1)), 1.0);\n\
if (inFragDepth <= currentFogStep)\n\
{\n\
float previousFogStep = min(stateFogOffset + (stateFogStep * float(i)), 1.0);\n\
fogMixWeight = mix(stateFogDensity[i-1], stateFogDensity[i], (inFragDepth - previousFogStep) / (currentFogStep - previousFogStep));\n\
break;\n\
}\n\
}\n\
}\n\
\n\
vec4 newFoggedColor = mix(inFragColor, stateFogColor, fogMixWeight);\n\
gl_FragData[0] = (polyEnableFog) ? ((stateEnableFogAlphaOnly) ? vec4(inFragColor.rgb, newFoggedColor.a) : newFoggedColor) : inFragColor;\n\
}\n\
"};
FORCEINLINE u32 BGRA8888_32_To_RGBA6665_32(const u32 srcPix)
{
const u32 dstPix = (srcPix >> 2) & 0x3F3F3F3F;
@ -781,7 +860,6 @@ OpenGLRenderer_1_2::OpenGLRenderer_1_2()
ref->fboRenderID = 0;
ref->fboMSIntermediateRenderID = 0;
ref->fboPostprocessID = 0;
ref->fboOutputID = 0;
ref->selectedRenderingFBO = 0;
}
@ -800,7 +878,8 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2()
delete[] ref->color4fBuffer;
ref->color4fBuffer = NULL;
DestroyShaders();
DestroyGeometryProgram();
DestroyPostprocessingProgram();
DestroyVAOs();
DestroyVBOs();
DestroyPBOs();
@ -846,22 +925,22 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
std::string vertexShaderProgram;
std::string fragmentShaderProgram;
error = this->LoadShaderPrograms(&vertexShaderProgram, &fragmentShaderProgram);
error = this->LoadGeometryShaders(vertexShaderProgram, fragmentShaderProgram);
if (error == OGLERROR_NOERR)
{
error = this->CreateShaders(&vertexShaderProgram, &fragmentShaderProgram);
error = this->InitGeometryProgram(vertexShaderProgram, fragmentShaderProgram);
if (error != OGLERROR_NOERR)
{
this->isShaderSupported = false;
if (error == OGLERROR_SHADER_CREATE_ERROR)
{
return error;
}
}
else
std::string postprocessVtxShaderString = std::string(PostprocessVertShader_100);
std::string postprocessFogFragShaderString = std::string(FogFragShader_100);
error = this->InitPostprocessingProgram(postprocessVtxShaderString, postprocessFogFragShaderString);
if (error != OGLERROR_NOERR)
{
this->CreateToonTable();
this->DestroyGeometryProgram();
this->isShaderSupported = false;
}
}
else
@ -941,13 +1020,21 @@ Render3DError OpenGLRenderer_1_2::CreateVBOs()
OGLRenderRef &OGLRef = *this->ref;
glGenBuffersARB(1, &OGLRef.vboGeometryVtxID);
glGenBuffersARB(1, &OGLRef.iboGeometryIndexID);
glGenBuffersARB(1, &OGLRef.vboPostprocessVtxID);
glGenBuffersARB(1, &OGLRef.iboPostprocessIndexID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, VERTLIST_SIZE * sizeof(VERT), NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glGenBuffersARB(1, &OGLRef.iboGeometryIndexID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort), NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(PostprocessVtxBuffer), PostprocessVtxBuffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboPostprocessIndexID);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(PostprocessElementBuffer), PostprocessElementBuffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
return OGLERROR_NOERR;
@ -963,10 +1050,12 @@ void OpenGLRenderer_1_2::DestroyVBOs()
OGLRenderRef &OGLRef = *this->ref;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glDeleteBuffersARB(1, &OGLRef.vboGeometryVtxID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glDeleteBuffersARB(1, &OGLRef.vboGeometryVtxID);
glDeleteBuffersARB(1, &OGLRef.iboGeometryIndexID);
glDeleteBuffersARB(1, &OGLRef.vboPostprocessVtxID);
glDeleteBuffersARB(1, &OGLRef.iboPostprocessIndexID);
this->isVBOSupported = false;
}
@ -998,18 +1087,18 @@ void OpenGLRenderer_1_2::DestroyPBOs()
this->isPBOSupported = false;
}
Render3DError OpenGLRenderer_1_2::LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram)
Render3DError OpenGLRenderer_1_2::LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram)
{
outVertexShaderProgram->clear();
outFragmentShaderProgram->clear();
outVertexShaderProgram.clear();
outFragmentShaderProgram.clear();
*outVertexShaderProgram += std::string(vertexShader_100);
*outFragmentShaderProgram += std::string(fragmentShader_100);
outVertexShaderProgram += std::string(vertexShader_100);
outFragmentShaderProgram += std::string(fragmentShader_100);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::SetupShaderIO()
Render3DError OpenGLRenderer_1_2::InitGeometryProgramBindings()
{
OGLRenderRef &OGLRef = *this->ref;
@ -1020,7 +1109,7 @@ Render3DError OpenGLRenderer_1_2::SetupShaderIO()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::CreateShaders(const std::string *vertexShaderProgram, const std::string *fragmentShaderProgram)
Render3DError OpenGLRenderer_1_2::InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram)
{
OGLRenderRef &OGLRef = *this->ref;
@ -1031,7 +1120,7 @@ Render3DError OpenGLRenderer_1_2::CreateShaders(const std::string *vertexShaderP
return OGLERROR_SHADER_CREATE_ERROR;
}
const char *vertexShaderProgramChar = vertexShaderProgram->c_str();
const char *vertexShaderProgramChar = vertexShaderProgram.c_str();
glShaderSource(OGLRef.vertexGeometryShaderID, 1, (const GLchar **)&vertexShaderProgramChar, NULL);
glCompileShader(OGLRef.vertexGeometryShaderID);
if (!this->ValidateShaderCompile(OGLRef.vertexGeometryShaderID))
@ -1049,7 +1138,7 @@ Render3DError OpenGLRenderer_1_2::CreateShaders(const std::string *vertexShaderP
return OGLERROR_SHADER_CREATE_ERROR;
}
const char *fragmentShaderProgramChar = fragmentShaderProgram->c_str();
const char *fragmentShaderProgramChar = fragmentShaderProgram.c_str();
glShaderSource(OGLRef.fragmentGeometryShaderID, 1, (const GLchar **)&fragmentShaderProgramChar, NULL);
glCompileShader(OGLRef.fragmentGeometryShaderID);
if (!this->ValidateShaderCompile(OGLRef.fragmentGeometryShaderID))
@ -1072,7 +1161,7 @@ Render3DError OpenGLRenderer_1_2::CreateShaders(const std::string *vertexShaderP
glAttachShader(OGLRef.programGeometryID, OGLRef.vertexGeometryShaderID);
glAttachShader(OGLRef.programGeometryID, OGLRef.fragmentGeometryShaderID);
this->SetupShaderIO();
this->InitGeometryProgramBindings();
glLinkProgram(OGLRef.programGeometryID);
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryID))
@ -1110,15 +1199,14 @@ Render3DError OpenGLRenderer_1_2::CreateShaders(const std::string *vertexShaderP
OGLRef.uniformPolyEnableTexture = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableTexture");
OGLRef.uniformPolyEnableFog = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableFog");
glUniform1i(OGLRef.uniformTexRenderObject, 0);
glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable);
INFO("OpenGL: Successfully created shaders.\n");
this->CreateToonTable();
return OGLERROR_NOERR;
}
void OpenGLRenderer_1_2::DestroyShaders()
void OpenGLRenderer_1_2::DestroyGeometryProgram()
{
if(!this->isShaderSupported)
{
@ -1145,34 +1233,48 @@ Render3DError OpenGLRenderer_1_2::CreateVAOs()
{
OGLRenderRef &OGLRef = *this->ref;
glGenVertexArrays(1, &OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoMainStatesID);
glGenVertexArrays(1, &OGLRef.vaoGeometryStatesID);
glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
glBindVertexArray(OGLRef.vaoGeometryStatesID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color));
glBindVertexArray(0);
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboPostprocessIndexID);
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));
glBindVertexArray(0);
return OGLERROR_NOERR;
}
void OpenGLRenderer_1_2::DestroyVAOs()
{
OGLRenderRef &OGLRef = *this->ref;
if (!this->isVAOSupported)
{
return;
}
glBindVertexArray(0);
glDeleteVertexArrays(1, &this->ref->vaoMainStatesID);
glDeleteVertexArrays(1, &OGLRef.vaoGeometryStatesID);
glDeleteVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
this->isVAOSupported = false;
}
@ -1279,7 +1381,6 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs()
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
OGLRef.fboOutputID = OGLRef.fboPostprocessID;
OGLRef.selectedRenderingFBO = OGLRef.fboRenderID;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO);
INFO("OpenGL: Successfully created FBOs.\n");
@ -1307,7 +1408,6 @@ void OpenGLRenderer_1_2::DestroyFBOs()
OGLRef.fboRenderID = 0;
OGLRef.fboPostprocessID = 0;
OGLRef.fboOutputID = 0;
this->isFBOSupported = false;
}
@ -1371,7 +1471,7 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO()
return OGLERROR_FBO_CREATE_ERROR;
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboOutputID);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
INFO("OpenGL: Successfully created multisampled FBO.\n");
return OGLERROR_NOERR;
@ -1461,6 +1561,21 @@ Render3DError OpenGLRenderer_1_2::InitTables()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader)
{
return OGLERROR_FEATURE_UNSUPPORTED;
}
Render3DError OpenGLRenderer_1_2::InitPostprocessingProgramBindings()
{
return OGLERROR_FEATURE_UNSUPPORTED;
}
Render3DError OpenGLRenderer_1_2::DestroyPostprocessingProgram()
{
return OGLERROR_FEATURE_UNSUPPORTED;
}
Render3DError OpenGLRenderer_1_2::CreateToonTable()
{
OGLRenderRef &OGLRef = *this->ref;
@ -1648,7 +1763,10 @@ Render3DError OpenGLRenderer_1_2::EnableVertexAttributes(const VERTLIST *vertLis
if (this->isVAOSupported)
{
glBindVertexArray(OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoGeometryStatesID);
glBindBuffer(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(VERT) * vertList->count, vertList);
glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, vertIndexCount * sizeof(GLushort), indexBuffer);
}
@ -1757,12 +1875,30 @@ Render3DError OpenGLRenderer_1_2::DownsampleFBO()
{
OGLRenderRef &OGLRef = *this->ref;
if (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)
if (this->isMultisampledFBOSupported && OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)
{
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboOutputID);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
// Blit the color buffer
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboOutputID);
// Blit the working depth buffer
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Blit the fog buffer
glReadBuffer(GL_COLOR_ATTACHMENT2_EXT);
glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);
glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Reset framebuffer targets
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glDrawBuffers(3, RenderDrawList);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
}
return OGLERROR_NOERR;
@ -1804,6 +1940,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState)
if (this->isShaderSupported)
{
glUseProgram(OGLRef.programGeometryID);
glUniform1i(OGLRef.uniformStateToonShadingMode, renderState->shading);
glUniform1i(OGLRef.uniformStateEnableAlphaTest, (renderState->enableAlphaTest) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableAntialiasing, (renderState->enableAntialiasing) ? GL_TRUE : GL_FALSE);
@ -1811,6 +1948,11 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState)
glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (renderState->enableFogAlphaOnly) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateUseWDepth, (renderState->wbuffer) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]);
glUniform1i(OGLRef.uniformTexRenderObject, 0);
glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable);
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
}
else
{
@ -1976,7 +2118,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf
this->UploadClearImage(colorBuffer, depthStencilBuffer, fogBuffer);
if (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)
if (this->isMultisampledFBOSupported && OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)
{
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID);
@ -2025,7 +2167,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const u8 r, const u8 g, const
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGDepthID
glClearColor((GLfloat)clearDepth / (GLfloat)0x00FFFFFF, 0.0, 0.0, 1.0);
glClearColor((GLfloat)(clearDepth & 0x000000FF)/255.0f, (GLfloat)((clearDepth >> 8) & 0x000000FF)/255.0f, (GLfloat)((clearDepth >> 16) & 0x000000FF)/255.0f, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); // texGFogAttrID
@ -2054,6 +2196,8 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY *thePoly)
if (this->isShaderSupported)
{
glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode);
glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f);
glUniform1i(OGLRef.uniformPolyID, attr.polygonID);
}
@ -2243,17 +2387,23 @@ Render3DError OpenGLRenderer_1_2::Reset()
if(this->isShaderSupported)
{
glUseProgram(OGLRef.programGeometryID);
glUniform1i(OGLRef.uniformStateToonShadingMode, 0);
glUniform1i(OGLRef.uniformStateEnableAlphaTest, GL_TRUE);
glUniform1i(OGLRef.uniformStateEnableAntialiasing, GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableEdgeMarking, GL_TRUE);
glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, GL_FALSE);
glUniform1i(OGLRef.uniformStateUseWDepth, GL_FALSE);
glUniform1f(OGLRef.uniformStateAlphaTestRef, 0.0f);
glUniform2f(OGLRef.uniformPolyTexScale, 1.0f, 1.0f);
glUniform1i(OGLRef.uniformPolyMode, 0);
glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, GL_TRUE);
glUniform1f(OGLRef.uniformPolyAlpha, 1.0f);
glUniform1i(OGLRef.uniformPolyID, 0);
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
glUniform1i(OGLRef.uniformPolyEnableFog, GL_FALSE);
}
else
{
@ -2400,13 +2550,21 @@ Render3DError OpenGLRenderer_1_5::CreateVBOs()
OGLRenderRef &OGLRef = *this->ref;
glGenBuffers(1, &OGLRef.vboGeometryVtxID);
glGenBuffers(1, &OGLRef.iboGeometryIndexID);
glGenBuffers(1, &OGLRef.vboPostprocessVtxID);
glGenBuffers(1, &OGLRef.iboPostprocessIndexID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBufferData(GL_ARRAY_BUFFER, VERTLIST_SIZE * sizeof(VERT), NULL, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &OGLRef.iboGeometryIndexID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort), NULL, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
glBufferData(GL_ARRAY_BUFFER, sizeof(PostprocessVtxBuffer), PostprocessVtxBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(PostprocessElementBuffer), PostprocessElementBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return OGLERROR_NOERR;
@ -2422,10 +2580,12 @@ void OpenGLRenderer_1_5::DestroyVBOs()
OGLRenderRef &OGLRef = *this->ref;
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &OGLRef.vboGeometryVtxID);
glDeleteBuffers(1, &OGLRef.iboGeometryIndexID);
glDeleteBuffers(1, &OGLRef.vboPostprocessVtxID);
glDeleteBuffers(1, &OGLRef.iboPostprocessIndexID);
this->isVBOSupported = false;
}
@ -2463,22 +2623,33 @@ Render3DError OpenGLRenderer_1_5::CreateVAOs()
{
OGLRenderRef &OGLRef = *this->ref;
glGenVertexArrays(1, &OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoMainStatesID);
glGenVertexArrays(1, &OGLRef.vaoGeometryStatesID);
glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
glBindVertexArray(OGLRef.vaoGeometryStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color));
glBindVertexArray(0);
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
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));
glBindVertexArray(0);
return OGLERROR_NOERR;
}
@ -2488,7 +2659,10 @@ Render3DError OpenGLRenderer_1_5::EnableVertexAttributes(const VERTLIST *vertLis
if (this->isVAOSupported)
{
glBindVertexArray(OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoGeometryStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * vertList->count, vertList);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, vertIndexCount * sizeof(GLushort), indexBuffer);
}
@ -2628,21 +2802,28 @@ Render3DError OpenGLRenderer_2_0::InitExtensions()
std::string vertexShaderProgram;
std::string fragmentShaderProgram;
error = this->LoadShaderPrograms(&vertexShaderProgram, &fragmentShaderProgram);
error = this->LoadGeometryShaders(vertexShaderProgram, fragmentShaderProgram);
if (error != OGLERROR_NOERR)
{
this->isShaderSupported = false;
return error;
}
error = this->CreateShaders(&vertexShaderProgram, &fragmentShaderProgram);
error = this->InitGeometryProgram(vertexShaderProgram, fragmentShaderProgram);
if (error != OGLERROR_NOERR)
{
this->isShaderSupported = false;
return error;
}
this->CreateToonTable();
std::string postprocessVtxShaderString = std::string(PostprocessVertShader_100);
std::string postprocessFogFragShaderString = std::string(FogFragShader_100);
error = this->InitPostprocessingProgram(postprocessVtxShaderString, postprocessFogFragShaderString);
if (error != OGLERROR_NOERR)
{
this->DestroyGeometryProgram();
this->isShaderSupported = false;
}
this->isVBOSupported = true;
this->CreateVBOs();
@ -2726,6 +2907,125 @@ Render3DError OpenGLRenderer_2_0::InitFinalRenderStates(const std::set<std::stri
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_2_0::InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
OGLRef.vertexPostprocessShaderID = glCreateShader(GL_VERTEX_SHADER);
if(!OGLRef.vertexPostprocessShaderID)
{
INFO("OpenGL: Failed to create the postprocess vertex shader.\n");
return OGLERROR_SHADER_CREATE_ERROR;
}
const char *vtxShaderCStr = vtxShader.c_str();
glShaderSource(OGLRef.vertexPostprocessShaderID, 1, (const GLchar **)&vtxShaderCStr, NULL);
glCompileShader(OGLRef.vertexPostprocessShaderID);
if (!this->ValidateShaderCompile(OGLRef.vertexPostprocessShaderID))
{
glDeleteShader(OGLRef.vertexPostprocessShaderID);
INFO("OpenGL: Failed to compile the postprocess vertex shader.\n");
return OGLERROR_SHADER_CREATE_ERROR;
}
OGLRef.fragmentFogShaderID = glCreateShader(GL_FRAGMENT_SHADER);
if(!OGLRef.fragmentFogShaderID)
{
glDeleteShader(OGLRef.vertexPostprocessShaderID);
INFO("OpenGL: Failed to create the fog fragment shader.\n");
return OGLERROR_SHADER_CREATE_ERROR;
}
const char *fragShaderCStr = fragShader.c_str();
glShaderSource(OGLRef.fragmentFogShaderID, 1, (const GLchar **)&fragShaderCStr, NULL);
glCompileShader(OGLRef.fragmentFogShaderID);
if (!this->ValidateShaderCompile(OGLRef.fragmentFogShaderID))
{
glDeleteShader(OGLRef.vertexPostprocessShaderID);
glDeleteShader(OGLRef.fragmentFogShaderID);
INFO("OpenGL: Failed to compile the fog fragment shader.\n");
return OGLERROR_SHADER_CREATE_ERROR;
}
OGLRef.programFogID = glCreateProgram();
if(!OGLRef.programFogID)
{
glDeleteShader(OGLRef.vertexPostprocessShaderID);
glDeleteShader(OGLRef.fragmentFogShaderID);
INFO("OpenGL: Failed to create the fog shader program.\n");
return OGLERROR_SHADER_CREATE_ERROR;
}
glAttachShader(OGLRef.programFogID, OGLRef.vertexPostprocessShaderID);
glAttachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID);
error = this->InitPostprocessingProgramBindings();
if (error != OGLERROR_NOERR)
{
glDetachShader(OGLRef.programFogID, OGLRef.vertexPostprocessShaderID);
glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID);
glDeleteProgram(OGLRef.programFogID);
glDeleteShader(OGLRef.vertexPostprocessShaderID);
glDeleteShader(OGLRef.fragmentFogShaderID);
INFO("OpenGL: Failed to make the fog shader bindings.\n");
return error;
}
glLinkProgram(OGLRef.programFogID);
if (!this->ValidateShaderProgramLink(OGLRef.programFogID))
{
glDetachShader(OGLRef.programFogID, OGLRef.vertexPostprocessShaderID);
glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID);
glDeleteProgram(OGLRef.programFogID);
glDeleteShader(OGLRef.vertexPostprocessShaderID);
glDeleteShader(OGLRef.fragmentFogShaderID);
INFO("OpenGL: Failed to link the fog shader program.\n");
return OGLERROR_SHADER_CREATE_ERROR;
}
glValidateProgram(OGLRef.programFogID);
glUseProgram(OGLRef.programFogID);
// Set up shader uniforms
OGLRef.uniformTexGColor = glGetUniformLocation(OGLRef.programFogID, "texInFragColor");
OGLRef.uniformTexGDepth = glGetUniformLocation(OGLRef.programFogID, "texInFragDepthOnly");
OGLRef.uniformTexGFog = glGetUniformLocation(OGLRef.programFogID, "texInFogAttributes");
OGLRef.uniformStateFogColor = glGetUniformLocation(OGLRef.programFogID, "stateFogColor");
OGLRef.uniformStateFogDensity = glGetUniformLocation(OGLRef.programFogID, "stateFogDensity");
OGLRef.uniformStateFogOffset = glGetUniformLocation(OGLRef.programFogID, "stateFogOffset");
OGLRef.uniformStateFogStep = glGetUniformLocation(OGLRef.programFogID, "stateFogStep");
glUseProgram(OGLRef.programGeometryID);
INFO("OpenGL: Successfully created postprocess shaders.\n");
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_2_0::InitPostprocessingProgramBindings()
{
OGLRenderRef &OGLRef = *this->ref;
glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_Position, "inPosition");
glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_2_0::DestroyPostprocessingProgram()
{
OGLRenderRef &OGLRef = *this->ref;
glUseProgram(0);
glDetachShader(OGLRef.programFogID, OGLRef.vertexPostprocessShaderID);
glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID);
glDeleteProgram(OGLRef.programFogID);
glDeleteShader(OGLRef.fragmentFogShaderID);
glDeleteShader(OGLRef.vertexPostprocessShaderID);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_2_0::SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount)
{
const size_t polyCount = polyList->count;
@ -2770,7 +3070,10 @@ Render3DError OpenGLRenderer_2_0::EnableVertexAttributes(const VERTLIST *vertLis
if (this->isVAOSupported)
{
glBindVertexArray(OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoGeometryStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * vertList->count, vertList);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, vertIndexCount * sizeof(GLushort), indexBuffer);
}
@ -2820,6 +3123,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State *renderState)
this->SelectRenderingFramebuffer();
glUseProgram(OGLRef.programGeometryID);
glUniform1i(OGLRef.uniformStateToonShadingMode, renderState->shading);
glUniform1i(OGLRef.uniformStateEnableAlphaTest, (renderState->enableAlphaTest) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableAntialiasing, (renderState->enableAntialiasing) ? GL_TRUE : GL_FALSE);
@ -2827,6 +3131,11 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State *renderState)
glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (renderState->enableFogAlphaOnly) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateUseWDepth, (renderState->wbuffer) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]);
glUniform1i(OGLRef.uniformTexRenderObject, 0);
glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable);
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
if(renderState->enableAlphaBlending)
{
@ -2842,14 +3151,93 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State *renderState)
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift)
{
OGLRenderRef &OGLRef = *this->ref;
static GLfloat oglDensityTable[32];
if (!this->isFBOSupported)
{
return OGLERROR_FEATURE_UNSUPPORTED;
}
for (size_t i = 0; i < 32; i++)
{
oglDensityTable[i] = (densityTable[i] == 127) ? 1.0f : (GLfloat)densityTable[i] / 128.0f;
}
const GLfloat oglColor[4] = {divide5bitBy31_LUT[(color ) & 0x0000001F],
divide5bitBy31_LUT[(color >> 5) & 0x0000001F],
divide5bitBy31_LUT[(color >> 10) & 0x0000001F],
divide5bitBy31_LUT[(color >> 16) & 0x0000001F]};
const GLfloat oglOffset = (GLfloat)offset / 32767.0f;
const GLfloat oglFogStep = (GLfloat)(0x0400 >> shift) / 32767.0f;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
glUseProgram(OGLRef.programFogID);
glUniform1i(OGLRef.uniformTexGColor, OGLTextureUnitID_GColor);
glUniform1i(OGLRef.uniformTexGDepth, OGLTextureUnitID_GDepth);
glUniform1i(OGLRef.uniformTexGFog, OGLTextureUnitID_FogAttr);
glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]);
glUniform1f(OGLRef.uniformStateFogOffset, oglOffset);
glUniform1f(OGLRef.uniformStateFogStep, oglFogStep);
glUniform1fv(OGLRef.uniformStateFogDensity, 32, oglDensityTable);
glViewport(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
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));
}
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth);
glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr);
glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID);
glActiveTexture(GL_TEXTURE0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
if (this->isVAOSupported)
{
glBindVertexArray(0);
}
else
{
glDisableVertexAttribArray(OGLVertexAttributeID_Position);
glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
}
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY *thePoly)
{
OGLRenderRef &OGLRef = *this->ref;
const PolygonAttributes attr = thePoly->getAttributes();
// Set up polygon attributes
assert(attr.polygonMode != 1);
glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode);
glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f);
glUniform1i(OGLRef.uniformPolyID, attr.polygonID);

View File

@ -327,7 +327,6 @@ struct OGLRenderRef
GLuint fboRenderID;
GLuint fboPostprocessID;
GLuint fboMSIntermediateRenderID;
GLuint fboOutputID;
GLuint selectedRenderingFBO;
// Shader states
@ -371,7 +370,7 @@ struct OGLRenderRef
GLuint texToonTableID;
// VAO
GLuint vaoMainStatesID;
GLuint vaoGeometryStatesID;
GLuint vaoPostprocessStatesID;
// Textures
@ -395,6 +394,9 @@ extern GPU3DInterface gpu3DglOld;
extern GPU3DInterface gpu3Dgl_3_2;
extern const GLenum RenderDrawList[3];
extern CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32];
extern const GLfloat PostprocessVtxBuffer[16];;
extern const GLubyte PostprocessElementBuffer[6];
//This is called by OGLRender whenever it initializes.
//Platforms, please be sure to set this up.
@ -457,16 +459,19 @@ protected:
virtual void DestroyFBOs() = 0;
virtual Render3DError CreateMultisampledFBO() = 0;
virtual void DestroyMultisampledFBO() = 0;
virtual Render3DError CreateShaders(const std::string *vertexShaderProgram, const std::string *fragmentShaderProgram) = 0;
virtual void DestroyShaders() = 0;
virtual Render3DError InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram) = 0;
virtual void DestroyGeometryProgram() = 0;
virtual Render3DError CreateVAOs() = 0;
virtual void DestroyVAOs() = 0;
virtual Render3DError InitTextures() = 0;
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError InitTables() = 0;
virtual Render3DError InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader) = 0;
virtual Render3DError InitPostprocessingProgramBindings() = 0;
virtual Render3DError DestroyPostprocessingProgram() = 0;
virtual Render3DError LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram) = 0;
virtual Render3DError SetupShaderIO() = 0;
virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram) = 0;
virtual Render3DError InitGeometryProgramBindings() = 0;
virtual Render3DError CreateToonTable() = 0;
virtual Render3DError DestroyToonTable() = 0;
virtual Render3DError UploadToonTable(const u16 *toonTableBuffer) = 0;
@ -481,28 +486,11 @@ protected:
virtual Render3DError DownsampleFBO() = 0;
virtual Render3DError ReadBackPixels() = 0;
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D_State *renderState) = 0;
virtual Render3DError RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList) = 0;
virtual Render3DError EndRender(const u64 frameCount) = 0;
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer) = 0;
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer, const bool *__restrict fogBuffer) = 0;
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil, const bool enableFog) const = 0;
virtual Render3DError SetupPolygon(const POLY *thePoly) = 0;
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing) = 0;
virtual Render3DError SetupViewport(const u32 viewportValue) = 0;
public:
OpenGLRenderer();
virtual ~OpenGLRenderer() {};
virtual Render3DError InitExtensions() = 0;
virtual Render3DError Reset() = 0;
virtual Render3DError RenderFinish() = 0;
virtual Render3DError DeleteTexture(const TexCacheItem *item) = 0;
bool IsExtensionPresent(const std::set<std::string> *oglExtensionSet, const std::string extensionName) const;
@ -525,16 +513,20 @@ protected:
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO();
virtual void DestroyMultisampledFBO();
virtual Render3DError CreateShaders(const std::string *vertexShaderProgram, const std::string *fragmentShaderProgram);
virtual void DestroyShaders();
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError InitTextures();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError InitTables();
virtual Render3DError LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram);
virtual Render3DError SetupShaderIO();
virtual Render3DError InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram);
virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram);
virtual Render3DError InitGeometryProgramBindings();
virtual void DestroyGeometryProgram();
virtual Render3DError InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader);
virtual Render3DError InitPostprocessingProgramBindings();
virtual Render3DError DestroyPostprocessingProgram();
virtual Render3DError CreateToonTable();
virtual Render3DError DestroyToonTable();
virtual Render3DError UploadToonTable(const u16 *toonTableBuffer);
@ -611,12 +603,16 @@ class OpenGLRenderer_2_0 : public OpenGLRenderer_1_5
protected:
virtual Render3DError InitExtensions();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader);
virtual Render3DError InitPostprocessingProgramBindings();
virtual Render3DError DestroyPostprocessingProgram();
virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount);
virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount);
virtual Render3DError DisableVertexAttributes();
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift);
virtual Render3DError SetupPolygon(const POLY *thePoly);
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);

View File

@ -72,8 +72,8 @@ void OGLLoadEntryPoints_3_2()
INITOGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Promote to core version
}
// Vertex Shader GLSL 1.50
static const char *vertexShader_150 = {"\
// Vertex shader for geometry, GLSL 1.50
static const char *GeometryVtxShader_150 = {"\
#version 150 \n\
\n\
in vec4 inPosition; \n\
@ -100,8 +100,8 @@ static const char *vertexShader_150 = {"\
} \n\
"};
// Fragment Shader GLSL 1.50
static const char *fragmentShader_150 = {"\
// Fragment shader for geometry, GLSL 1.50
static const char *GeometryFragShader_150 = {"\
#version 150 \n\
\n\
in vec4 vtxPosition; \n\
@ -130,6 +130,13 @@ static const char *fragmentShader_150 = {"\
out vec4 outFragDepth;\n\
out vec4 outFogAttributes;\n\
\n\
vec3 packVec3FromFloat(const float value)\n\
{\n\
float expandedValue = value * 16777215.0;\n\
vec3 packedValue = vec3( fract(expandedValue/256.0), fract(((expandedValue/256.0) - fract(expandedValue/256.0)) / 256.0), fract(((expandedValue/65536.0) - fract(expandedValue/65536.0)) / 256.0) );\n\
return packedValue;\n\
}\n\
\n\
void main() \n\
{ \n\
vec4 mainTexColor = (polyEnableTexture) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\
@ -162,12 +169,86 @@ static const char *fragmentShader_150 = {"\
float newFragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\
\n\
outFragColor = newFragColor;\n\
outFragDepth = vec4( vec3(newFragDepth), 1.0);\n\
outFragDepth = vec4( packVec3FromFloat(newFragDepth), 1.0);\n\
outFogAttributes = vec4( float(polyEnableFog), float(stateEnableFogAlphaOnly), 0.0, 1.0);\n\
gl_FragDepth = newFragDepth;\n\
} \n\
"};
// Vertex shader for post-processing, GLSL 1.50
static const char *PostprocessVtxShader_150 = {"\
#version 150\n\
\n\
in vec2 inPosition;\n\
in vec2 inTexCoord0;\n\
out vec2 texCoord;\n\
\n\
void main() \n\
{ \n\
texCoord = inTexCoord0; \n\
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
}\n\
"};
// Fragment shader for applying fog, GLSL 1.50
static const char *FogFragShader_150 = {"\
#version 150\n\
\n\
in vec2 texCoord;\n\
\n\
uniform sampler2D texInFragColor;\n\
uniform sampler2D texInFragDepthOnly;\n\
uniform sampler2D texInFogAttributes;\n\
uniform vec4 stateFogColor;\n\
uniform float stateFogDensity[32];\n\
uniform float stateFogOffset;\n\
uniform float stateFogStep;\n\
\n\
out vec4 outFragColor;\n\
\n\
float unpackFloatFromVec3(const vec3 value)\n\
{\n\
const vec3 unpackRatio = vec3(256.0, 65536.0, 16777216.0);\n\
return (dot(value, unpackRatio) / 16777215.0);\n\
}\n\
\n\
void main()\n\
{\n\
vec4 inFragColor = texture(texInFragColor, texCoord);\n\
float inFragDepth = unpackFloatFromVec3(texture(texInFragDepthOnly, texCoord).rgb);\n\
vec4 inFogAttributes = texture(texInFogAttributes, texCoord);\n\
\n\
bool polyEnableFog = bool(inFogAttributes.r);\n\
bool stateEnableFogAlphaOnly = bool(inFogAttributes.g) ;\n\
\n\
float fogMixWeight = 0.0;\n\
if (inFragDepth <= min(stateFogOffset + stateFogStep, 1.0))\n\
{\n\
fogMixWeight = stateFogDensity[0];\n\
}\n\
else if (inFragDepth >= min(stateFogOffset + (stateFogStep*32.0), 1.0))\n\
{\n\
fogMixWeight = stateFogDensity[31];\n\
}\n\
else\n\
{\n\
for (int i = 1; i < 32; i++)\n\
{\n\
float currentFogStep = min(stateFogOffset + (stateFogStep * float(i+1)), 1.0);\n\
if (inFragDepth <= currentFogStep)\n\
{\n\
float previousFogStep = min(stateFogOffset + (stateFogStep * float(i)), 1.0);\n\
fogMixWeight = mix(stateFogDensity[i-1], stateFogDensity[i], (inFragDepth - previousFogStep) / (currentFogStep - previousFogStep));\n\
break;\n\
}\n\
}\n\
}\n\
\n\
vec4 newFoggedColor = mix(inFragColor, stateFogColor, fogMixWeight);\n\
outFragColor = (polyEnableFog) ? ((stateEnableFogAlphaOnly) ? vec4(inFragColor.rgb, newFoggedColor.a) : newFoggedColor) : inFragColor;\n\
}\n\
"};
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr)
{
if (IsVersionSupported(3, 2, 0))
@ -202,21 +283,29 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
std::string vertexShaderProgram;
std::string fragmentShaderProgram;
error = this->LoadShaderPrograms(&vertexShaderProgram, &fragmentShaderProgram);
error = this->LoadGeometryShaders(vertexShaderProgram, fragmentShaderProgram);
if (error != OGLERROR_NOERR)
{
this->isShaderSupported = false;
return error;
}
error = this->CreateShaders(&vertexShaderProgram, &fragmentShaderProgram);
error = this->InitGeometryProgram(vertexShaderProgram, fragmentShaderProgram);
if (error != OGLERROR_NOERR)
{
this->isShaderSupported = false;
return error;
}
this->CreateToonTable();
std::string postprocessVtxShaderString = std::string(PostprocessVtxShader_150);
std::string postprocessFogFragShaderString = std::string(FogFragShader_150);
error = this->InitPostprocessingProgram(postprocessVtxShaderString, postprocessFogFragShaderString);
if (error != OGLERROR_NOERR)
{
this->DestroyGeometryProgram();
this->isShaderSupported = false;
return error;
}
this->isVBOSupported = true;
this->CreateVBOs();
@ -256,6 +345,16 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::InitPostprocessingProgramBindings()
{
OGLRenderRef &OGLRef = *this->ref;
glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_Position, "inPosition");
glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
glBindFragDataLocation(OGLRef.programFogID, 0, "outFragColor");
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::CreateFBOs()
{
OGLRenderRef &OGLRef = *this->ref;
@ -330,7 +429,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
OGLRef.fboRenderID = 0;
OGLRef.fboPostprocessID = 0;
OGLRef.fboOutputID = 0;
return OGLERROR_FBO_CREATE_ERROR;
}
@ -356,7 +454,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
OGLRef.fboRenderID = 0;
OGLRef.fboPostprocessID = 0;
OGLRef.fboOutputID = 0;
return OGLERROR_FBO_CREATE_ERROR;
}
@ -364,7 +461,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
OGLRef.fboOutputID = OGLRef.fboPostprocessID;
OGLRef.selectedRenderingFBO = OGLRef.fboRenderID;
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
INFO("OpenGL: Successfully created FBOs.\n");
@ -392,7 +488,6 @@ void OpenGLRenderer_3_2::DestroyFBOs()
OGLRef.fboRenderID = 0;
OGLRef.fboPostprocessID = 0;
OGLRef.fboOutputID = 0;
this->isFBOSupported = false;
}
@ -457,7 +552,7 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO()
return OGLERROR_FBO_CREATE_ERROR;
}
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboOutputID);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID);
INFO("OpenGL: Successfully created multisampled FBO.\n");
return OGLERROR_NOERR;
@ -488,22 +583,33 @@ Render3DError OpenGLRenderer_3_2::CreateVAOs()
{
OGLRenderRef &OGLRef = *this->ref;
glGenVertexArrays(1, &OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoMainStatesID);
glGenVertexArrays(1, &OGLRef.vaoGeometryStatesID);
glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
glBindVertexArray(OGLRef.vaoGeometryStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color));
glBindVertexArray(0);
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
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));
glBindVertexArray(0);
return OGLERROR_NOERR;
}
@ -514,21 +620,27 @@ void OpenGLRenderer_3_2::DestroyVAOs()
return;
}
OGLRenderRef &OGLRef = *this->ref;
glBindVertexArray(0);
glDeleteVertexArrays(1, &this->ref->vaoMainStatesID);
glDeleteVertexArrays(1, &OGLRef.vaoGeometryStatesID);
glDeleteVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
this->isVAOSupported = false;
}
Render3DError OpenGLRenderer_3_2::LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram)
Render3DError OpenGLRenderer_3_2::LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram)
{
*outVertexShaderProgram = std::string(vertexShader_150);
*outFragmentShaderProgram = std::string(fragmentShader_150);
outVertexShaderProgram.clear();
outFragmentShaderProgram.clear();
outVertexShaderProgram = std::string(GeometryVtxShader_150);
outFragmentShaderProgram = std::string(GeometryFragShader_150);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::SetupShaderIO()
Render3DError OpenGLRenderer_3_2::InitGeometryProgramBindings()
{
OGLRenderRef &OGLRef = *this->ref;
@ -558,7 +670,10 @@ Render3DError OpenGLRenderer_3_2::EnableVertexAttributes(const VERTLIST *vertLis
{
OGLRenderRef &OGLRef = *this->ref;
glBindVertexArray(OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoGeometryStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * vertList->count, vertList);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, vertIndexCount * sizeof(GLushort), indexBuffer);
@ -588,15 +703,87 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO()
if (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboOutputID);
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID);
// Blit the color buffer
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboOutputID);
// Blit the working depth buffer
glReadBuffer(GL_COLOR_ATTACHMENT1);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Blit the fog buffer
glReadBuffer(GL_COLOR_ATTACHMENT2);
glDrawBuffer(GL_COLOR_ATTACHMENT2);
glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Reset framebuffer targets
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffers(3, RenderDrawList);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID);
}
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift)
{
OGLRenderRef &OGLRef = *this->ref;
static GLfloat oglDensityTable[32];
for (size_t i = 0; i < 32; i++)
{
oglDensityTable[i] = (densityTable[i] == 127) ? 1.0f : (GLfloat)densityTable[i] / 128.0f;
}
const GLfloat oglColor[4] = {divide5bitBy31_LUT[(color ) & 0x0000001F],
divide5bitBy31_LUT[(color >> 5) & 0x0000001F],
divide5bitBy31_LUT[(color >> 10) & 0x0000001F],
divide5bitBy31_LUT[(color >> 16) & 0x0000001F]};
const GLfloat oglOffset = (GLfloat)offset / 32767.0f;
const GLfloat oglFogStep = (GLfloat)(0x0400 >> shift) / 32767.0f;
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID);
glUseProgram(OGLRef.programFogID);
glUniform1i(OGLRef.uniformTexGColor, OGLTextureUnitID_GColor);
glUniform1i(OGLRef.uniformTexGDepth, OGLTextureUnitID_GDepth);
glUniform1i(OGLRef.uniformTexGFog, OGLTextureUnitID_FogAttr);
glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]);
glUniform1f(OGLRef.uniformStateFogOffset, oglOffset);
glUniform1f(OGLRef.uniformStateFogStep, oglFogStep);
glUniform1fv(OGLRef.uniformStateFogDensity, 32, oglDensityTable);
glViewport(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth);
glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr);
glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID);
glActiveTexture(GL_TEXTURE0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer, const bool *__restrict fogBuffer)
{
OGLRenderRef &OGLRef = *this->ref;
@ -626,7 +813,7 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf
// Reset framebuffer targets
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffers(3, RenderDrawList);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID);
}
return OGLERROR_NOERR;

View File

@ -61,6 +61,7 @@ class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
{
protected:
virtual Render3DError InitExtensions();
virtual Render3DError InitPostprocessingProgramBindings();
virtual Render3DError CreateFBOs();
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO();
@ -68,14 +69,15 @@ protected:
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram);
virtual Render3DError SetupShaderIO();
virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram);
virtual Render3DError InitGeometryProgramBindings();
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount);
virtual Render3DError DisableVertexAttributes();
virtual Render3DError SelectRenderingFramebuffer();
virtual Render3DError DownsampleFBO();
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift);
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer, const bool *__restrict fogBuffer);

View File

@ -126,6 +126,11 @@ Render3DError Render3D::RenderGeometry(const GFX3D_State *renderState, const VER
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::EndRender(const u64 frameCount)
{
return RENDER3DERROR_NOERR;
@ -246,6 +251,11 @@ Render3DError Render3D::Render(const GFX3D_State *renderState, const VERTLIST *v
this->ClearFramebuffer(renderState);
this->RenderGeometry(renderState, vertList, polyList, indexList);
if (renderState->enableFog)
{
this->RenderFog(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360, renderState->fogColor, renderState->fogOffset, renderState->fogShift);
}
this->EndRender(frameCount);

View File

@ -90,6 +90,7 @@ protected:
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift);
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);