diff options
author | Arisotura <thetotalworm@gmail.com> | 2019-05-25 04:28:00 +0200 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2019-05-25 04:28:00 +0200 |
commit | 7cdeb7fa4e365dd3ef4e505985c9fc9a4c4045ab (patch) | |
tree | c87803a61b36532978755b68e69c681b334c23b5 /src | |
parent | 04f1809dd17b5f7c034bcf394dbe040844c10712 (diff) |
feeble, miserable little attempt at emulating fog
Diffstat (limited to 'src')
-rw-r--r-- | src/GPU3D_OpenGL.cpp | 110 | ||||
-rw-r--r-- | src/GPU3D_OpenGL_shaders.h | 109 | ||||
-rw-r--r-- | src/OpenGLSupport.cpp | 4 |
3 files changed, 206 insertions, 17 deletions
diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index 264d3b9..f8ed773 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -47,12 +47,19 @@ GLuint ClearShaderPlain[3]; GLuint RenderShader[16][3]; GLuint CurShaderID = -1; +GLuint FinalPassShader[3]; + struct { float uScreenSize[2]; u32 uDispCnt; u32 __pad0; float uToonColors[32][4]; + float uEdgeColors[8][4]; + float uFogColor[4]; + float uFogDensity[34][4]; + u32 uFogOffset; + u32 uFogShift; } ShaderConfig; @@ -176,6 +183,8 @@ void SetupDefaultTexParams(GLuint tex) bool Init() { + GLint uni_id; + const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string const GLubyte* version = glGetString(GL_VERSION); // version as a string printf("OpenGL: renderer: %s\n", renderer); @@ -216,6 +225,23 @@ bool Init() kRenderVS_W, kRenderFS_WSM)) return false; + if (!OpenGL_BuildShaderProgram(kFinalPassVS, kFinalPassFS, FinalPassShader, "FinalPassShader")) + return false; + + uni_id = glGetUniformBlockIndex(FinalPassShader[2], "uConfig"); + glUniformBlockBinding(FinalPassShader[2], uni_id, 0); + + glBindAttribLocation(FinalPassShader[2], 0, "vPosition"); + glBindFragDataLocation(FinalPassShader[2], 0, "oColor"); + + glUseProgram(FinalPassShader[2]); + + uni_id = glGetUniformLocation(FinalPassShader[2], "DepthBuffer"); + glUniform1i(uni_id, 0); + uni_id = glGetUniformLocation(FinalPassShader[2], "AttrBuffer"); + glUniform1i(uni_id, 1); + + memset(&ShaderConfig, 0, sizeof(ShaderConfig)); glGenBuffers(1, &ShaderConfigUBO); @@ -277,8 +303,8 @@ bool Init() // attribute buffer // R: opaque polyID (for edgemarking) - // G: opaque polyID (for shadows, suppressed when rendering translucent polygons) - // B: stencil flag + // G: edge flag + // B: fog flag SetupDefaultTexParams(FramebufferTex[5]); SetupDefaultTexParams(FramebufferTex[7]); @@ -447,6 +473,7 @@ void SetupPolygon(RendererPolygon* rp, Polygon* polygon) if (polygon->IsShadow) rp->RenderKey |= 0x20000; else rp->RenderKey |= 0x10000; rp->RenderKey |= (polygon->Attr >> 10) & 0x2; // bit11 - depth write + rp->RenderKey |= (polygon->Attr >> 13) & 0x4; // bit15 - fog rp->RenderKey |= (polygon->Attr & 0x3F000000) >> 16; // polygon ID } else @@ -579,11 +606,13 @@ void RenderSceneChunk(int y, int h) if (h != 192) glScissor(0, y<<ScaleFactor, 256<<ScaleFactor, h<<ScaleFactor); + GLboolean fogenable = (RenderDispCnt & (1<<7)) ? GL_TRUE : GL_FALSE; + // pass 1: opaque pixels UseRenderShader(flags); - glColorMaski(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + glColorMaski(1, GL_TRUE, GL_FALSE, fogenable, GL_FALSE); glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); @@ -614,8 +643,6 @@ void RenderSceneChunk(int y, int h) if (NumOpaqueFinalPolys > -1) { - glColorMaski(1, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - // pass 2: if needed, render translucent pixels that are against background pixels // when background alpha is zero, those need to be rendered with blending disabled @@ -653,6 +680,10 @@ void RenderSceneChunk(int y, int h) u32 polyattr = rp->PolyData->Attr; u32 polyid = (polyattr >> 24) & 0x3F; + GLboolean transfog; + if (!(polyattr & (1<<15))) transfog = fogenable; + else transfog = GL_FALSE; + if (rp->PolyData->IsShadow) { // shadow against clear-plane will only pass if its polyID matches that of the clear plane @@ -661,7 +692,7 @@ void RenderSceneChunk(int y, int h) glEnable(GL_BLEND); glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glColorMaski(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + glColorMaski(1, GL_FALSE, GL_FALSE, transfog, GL_FALSE); glStencilFunc(GL_EQUAL, 0xFE, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); @@ -674,6 +705,9 @@ void RenderSceneChunk(int y, int h) } else { + glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glColorMaski(1, GL_FALSE, GL_FALSE, transfog, GL_FALSE); + glStencilFunc(GL_EQUAL, 0xFF, 0xFE); glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); glStencilMask(~(0x40|polyid)); // heheh @@ -727,6 +761,10 @@ void RenderSceneChunk(int y, int h) u32 polyattr = rp->PolyData->Attr; u32 polyid = (polyattr >> 24) & 0x3F; + GLboolean transfog; + if (!(polyattr & (1<<15))) transfog = fogenable; + else transfog = GL_FALSE; + // zorp glDepthFunc(GL_LESS); @@ -744,7 +782,7 @@ void RenderSceneChunk(int y, int h) glEnable(GL_BLEND); glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glColorMaski(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + glColorMaski(1, GL_FALSE, GL_FALSE, transfog, GL_FALSE); glStencilFunc(GL_EQUAL, 0xC0|polyid, 0x80); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); @@ -760,7 +798,7 @@ void RenderSceneChunk(int y, int h) { glEnable(GL_BLEND); glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glColorMaski(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + glColorMaski(1, GL_FALSE, GL_FALSE, transfog, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0x40|polyid, 0x7F); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); @@ -778,11 +816,33 @@ void RenderSceneChunk(int y, int h) } glFlush(); + + if (RenderDispCnt & 0x00A0) // fog/edge enabled + { + glUseProgram(FinalPassShader[2]); + + glDepthFunc(GL_ALWAYS); + glDepthMask(GL_FALSE); + glStencilFunc(GL_ALWAYS, 0, 0); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilMask(0); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]); + + glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID); + glBindVertexArray(ClearVertexArrayID); + glDrawArrays(GL_TRIANGLES, 0, 2*3); + } } void RenderFrame() { + CurShaderID = -1; + ShaderConfig.uScreenSize[0] = ScreenW; ShaderConfig.uScreenSize[1] = ScreenH; ShaderConfig.uDispCnt = RenderDispCnt; @@ -799,6 +859,40 @@ void RenderFrame() ShaderConfig.uToonColors[i][2] = (float)b / 31.0; } + for (int i = 0; i < 8; i++) + { + u16 c = RenderEdgeTable[i]; + u32 r = c & 0x1F; + u32 g = (c >> 5) & 0x1F; + u32 b = (c >> 10) & 0x1F; + + ShaderConfig.uEdgeColors[i][0] = (float)r / 31.0; + ShaderConfig.uEdgeColors[i][1] = (float)g / 31.0; + ShaderConfig.uEdgeColors[i][2] = (float)b / 31.0; + } + + { + u32 c = RenderFogColor; + u32 r = c & 0x1F; + u32 g = (c >> 5) & 0x1F; + u32 b = (c >> 10) & 0x1F; + u32 a = (c >> 16) & 0x1F; + + ShaderConfig.uFogColor[0] = (float)r / 31.0; + ShaderConfig.uFogColor[1] = (float)g / 31.0; + ShaderConfig.uFogColor[2] = (float)b / 31.0; + ShaderConfig.uFogColor[3] = (float)a / 31.0; + } + + for (int i = 0; i < 34; i++) + { + u8 d = RenderFogDensityTable[i]; + ShaderConfig.uFogDensity[i][0] = (float)d / 127.0; + } + + ShaderConfig.uFogOffset = RenderFogOffset; + ShaderConfig.uFogShift = RenderFogShift; + glBindBuffer(GL_UNIFORM_BUFFER, ShaderConfigUBO); void* unibuf = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); if (unibuf) memcpy(unibuf, &ShaderConfig, sizeof(ShaderConfig)); diff --git a/src/GPU3D_OpenGL_shaders.h b/src/GPU3D_OpenGL_shaders.h index e436544..0e4c4fe 100644 --- a/src/GPU3D_OpenGL_shaders.h +++ b/src/GPU3D_OpenGL_shaders.h @@ -47,13 +47,94 @@ out uvec3 oAttr; void main() { oColor = vec4(uColor).bgra / 31.0; - oAttr.r = uint(0); - oAttr.g = uOpaquePolyID; - oAttr.b = uint(0); + oAttr.r = uOpaquePolyID; + oAttr.g = uint(0); + oAttr.b = uFogFlag; +} +)"; + + + +const char* kFinalPassVS = kShaderHeader R"( + +in vec2 vPosition; + +void main() +{ + // heh + gl_Position = vec4(vPosition, 0.0, 1.0); +} +)"; + +const char* kFinalPassFS = kShaderHeader R"( + +uniform sampler2D DepthBuffer; +uniform usampler2D AttrBuffer; + +layout(std140) uniform uConfig +{ + vec2 uScreenSize; + int uDispCnt; + vec4 uToonColors[32]; + vec4 uEdgeColors[8]; + vec4 uFogColor; + float uFogDensity[34]; + int uFogOffset; + int uFogShift; +}; + +out vec4 oColor; + +vec4 CalculateFog(float depth) +{ + int idepth = int(depth * 16777216.0); + int densityid, densityfrac; + + if (idepth < uFogOffset) + { + densityid = 0; + densityfrac = 0; + } + else + { + uint udepth = uint(idepth); + udepth -= uint(uFogOffset); + udepth = (udepth >> 2) << uint(uFogShift); + + densityid = int(udepth >> 17); + if (densityid >= 32) + { + densityid = 32; + densityfrac = 0; + } + else + densityfrac = int(udepth & uint(0x1FFFF)); + } + + float density = + ((uFogDensity[densityid] * float(0x20000-densityfrac)) + + (uFogDensity[densityid+1] * float(densityfrac))) / float(0x20000); + + return vec4(uFogColor.bgr,density); + return uFogColor * density; +} + +void main() +{ + ivec2 coord = ivec2(gl_FragCoord.xy); + + vec4 ret = vec4(0,0,0,0); + vec4 depth = texelFetch(DepthBuffer, coord, 0); + ivec4 attr = ivec4(texelFetch(AttrBuffer, coord, 0)); + + if (attr.b != 0) ret = CalculateFog(depth.r); + + oColor = ret; } )"; + const char* kRenderVSCommon = R"( layout(std140) uniform uConfig @@ -61,6 +142,11 @@ layout(std140) uniform uConfig vec2 uScreenSize; int uDispCnt; vec4 uToonColors[32]; + vec4 uEdgeColors[8]; + vec4 uFogColor; + float uFogDensity[34]; + int uFogOffset; + int uFogShift; }; in uvec4 vPosition; @@ -83,6 +169,11 @@ layout(std140) uniform uConfig vec2 uScreenSize; int uDispCnt; vec4 uToonColors[32]; + vec4 uEdgeColors[8]; + vec4 uFogColor; + float uFogDensity[34]; + int uFogOffset; + int uFogShift; }; smooth in vec4 fColor; @@ -530,7 +621,8 @@ void main() if (col.a < 30.5/31) discard; oColor = col; - oAttr.g = uint((fPolygonAttr.x >> 24) & 0x3F); + oAttr.r = uint((fPolygonAttr.x >> 24) & 0x3F); + oAttr.b = uint((fPolygonAttr.x >> 15) & 0x1); } )"; @@ -544,7 +636,8 @@ void main() if (col.a < 30.5/31) discard; oColor = col; - oAttr.g = uint((fPolygonAttr.x >> 24) & 0x3F); + oAttr.r = uint((fPolygonAttr.x >> 24) & 0x3F); + oAttr.b = uint((fPolygonAttr.x >> 15) & 0x1); gl_FragDepth = fZ; } )"; @@ -558,7 +651,7 @@ void main() if (col.a >= 30.5/31) discard; oColor = col; - oAttr.g = uint(0xFF); + oAttr.b = uint(0); } )"; @@ -573,7 +666,7 @@ void main() if (col.a >= 30.5/31) discard; oColor = col; - oAttr.g = uint(0xFF); + oAttr.b = uint(0); gl_FragDepth = fZ; } )"; @@ -583,7 +676,6 @@ const char* kRenderFS_ZSM = R"( void main() { oColor = vec4(0,0,0,1); - oAttr.g = uint(0xFF); } )"; @@ -594,7 +686,6 @@ smooth in float fZ; void main() { oColor = vec4(0,0,0,1); - oAttr.g = uint(0xFF); gl_FragDepth = fZ; } )"; diff --git a/src/OpenGLSupport.cpp b/src/OpenGLSupport.cpp index 81a008b..0204835 100644 --- a/src/OpenGLSupport.cpp +++ b/src/OpenGLSupport.cpp @@ -71,6 +71,10 @@ bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, cons //printf("shader source:\n--\n%s\n--\n", fs); delete[] log; + FILE* logf = fopen("shaderfail.log", "w"); + fwrite(fs, len+1, 1, logf); + fclose(logf); + glDeleteShader(ids[0]); glDeleteShader(ids[1]); |