aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArisotura <thetotalworm@gmail.com>2019-06-09 19:32:02 +0200
committerArisotura <thetotalworm@gmail.com>2019-06-09 19:32:02 +0200
commit086354a42014488e8b97d71d7ed2bf7649ab33ed (patch)
treeb9ef85bb9bb5d3941af63d2ba6c833cd03fd89ae
parent434a3007e2f7c0b512f755d7c4739992c1242c07 (diff)
miserable, feeble little attempt at edge marking
-rw-r--r--src/GPU3D_OpenGL.cpp151
-rw-r--r--src/GPU3D_OpenGL_shaders.h101
2 files changed, 215 insertions, 37 deletions
diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp
index 56e783f..b334ffc 100644
--- a/src/GPU3D_OpenGL.cpp
+++ b/src/GPU3D_OpenGL.cpp
@@ -39,6 +39,7 @@ enum
RenderFlag_WBuffer = 0x01,
RenderFlag_Trans = 0x02,
RenderFlag_ShadowMask = 0x04,
+ RenderFlag_Edge = 0x08,
};
@@ -47,7 +48,8 @@ GLuint ClearShaderPlain[3];
GLuint RenderShader[16][3];
GLuint CurShaderID = -1;
-GLuint FinalPassShader[3];
+GLuint FinalPassEdgeShader[3];
+GLuint FinalPassFogShader[3];
struct
{
@@ -220,6 +222,10 @@ bool Init()
kRenderVS_Z, kRenderFS_ZO)) return false;
if (!BuildRenderShader(RenderFlag_WBuffer,
kRenderVS_W, kRenderFS_WO)) return false;
+ if (!BuildRenderShader(RenderFlag_Edge,
+ kRenderVS_Z, kRenderFS_ZE)) return false;
+ if (!BuildRenderShader(RenderFlag_Edge | RenderFlag_WBuffer,
+ kRenderVS_W, kRenderFS_WE)) return false;
if (!BuildRenderShader(RenderFlag_Trans,
kRenderVS_Z, kRenderFS_ZT)) return false;
if (!BuildRenderShader(RenderFlag_Trans | RenderFlag_WBuffer,
@@ -230,23 +236,41 @@ bool Init()
kRenderVS_W, kRenderFS_WSM)) return false;
- if (!OpenGL_BuildShaderProgram(kFinalPassVS, kFinalPassFS, FinalPassShader, "FinalPassShader"))
+ if (!OpenGL_BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, FinalPassEdgeShader, "FinalPassEdgeShader"))
+ return false;
+ if (!OpenGL_BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, FinalPassFogShader, "FinalPassFogShader"))
return false;
- glBindAttribLocation(FinalPassShader[2], 0, "vPosition");
- glBindFragDataLocation(FinalPassShader[2], 0, "oColor");
+ glBindAttribLocation(FinalPassEdgeShader[2], 0, "vPosition");
+ glBindFragDataLocation(FinalPassEdgeShader[2], 0, "oColor");
- if (!OpenGL_LinkShaderProgram(FinalPassShader))
+ if (!OpenGL_LinkShaderProgram(FinalPassEdgeShader))
return false;
- uni_id = glGetUniformBlockIndex(FinalPassShader[2], "uConfig");
- glUniformBlockBinding(FinalPassShader[2], uni_id, 0);
+ uni_id = glGetUniformBlockIndex(FinalPassEdgeShader[2], "uConfig");
+ glUniformBlockBinding(FinalPassEdgeShader[2], uni_id, 0);
- glUseProgram(FinalPassShader[2]);
+ glUseProgram(FinalPassEdgeShader[2]);
- uni_id = glGetUniformLocation(FinalPassShader[2], "DepthBuffer");
+ uni_id = glGetUniformLocation(FinalPassEdgeShader[2], "DepthBuffer");
glUniform1i(uni_id, 0);
- uni_id = glGetUniformLocation(FinalPassShader[2], "AttrBuffer");
+ uni_id = glGetUniformLocation(FinalPassEdgeShader[2], "AttrBuffer");
+ glUniform1i(uni_id, 1);
+
+ glBindAttribLocation(FinalPassFogShader[2], 0, "vPosition");
+ glBindFragDataLocation(FinalPassFogShader[2], 0, "oColor");
+
+ if (!OpenGL_LinkShaderProgram(FinalPassFogShader))
+ return false;
+
+ uni_id = glGetUniformBlockIndex(FinalPassFogShader[2], "uConfig");
+ glUniformBlockBinding(FinalPassFogShader[2], uni_id, 0);
+
+ glUseProgram(FinalPassFogShader[2]);
+
+ uni_id = glGetUniformLocation(FinalPassFogShader[2], "DepthBuffer");
+ glUniform1i(uni_id, 0);
+ uni_id = glGetUniformLocation(FinalPassFogShader[2], "AttrBuffer");
glUniform1i(uni_id, 1);
@@ -452,7 +476,7 @@ void UpdateDisplaySettings()
glBindBuffer(GL_PIXEL_PACK_BUFFER, PixelbufferID);
glBufferData(GL_PIXEL_PACK_BUFFER, 256*192*4, NULL, GL_DYNAMIC_READ);
- //glLineWidth(scale);
+ glLineWidth(scale);
}
@@ -580,13 +604,17 @@ void BuildPolygons(RendererPolygon* polygons, int npolys)
rp->EdgeIndices = eiptr;
rp->NumEdgeIndices = 0;
+ u32 vidx_cur = vidx_first;
for (int j = 1; j < poly->NumVertices; j++)
{
- *eiptr++ = vidx_first;
- *eiptr++ = vidx_first + 1;
- vidx_first++;
+ *eiptr++ = vidx_cur;
+ *eiptr++ = vidx_cur + 1;
+ vidx_cur++;
rp->NumEdgeIndices += 2;
}
+ *eiptr++ = vidx_cur;
+ *eiptr++ = vidx_first;
+ rp->NumEdgeIndices += 2;
}
NumTriangles = numtriangles;
@@ -620,15 +648,17 @@ int RenderPolygonBatch(int i)
return numpolys;
}
-int RenderPolygonEdges()
+int RenderPolygonEdgeBatch(int i)
{
- RendererPolygon* rp = &PolygonList[0];
+ RendererPolygon* rp = &PolygonList[i];
+ u32 key = rp->RenderKey;
int numpolys = 0;
u32 numindices = 0;
- for (int iend = 0; iend < NumOpaqueFinalPolys; iend++)
+ for (int iend = i; iend < NumFinalPolys; iend++)
{
RendererPolygon* cur_rp = &PolygonList[iend];
+ if (cur_rp->RenderKey != key) break;
numpolys++;
numindices += cur_rp->NumEdgeIndices;
@@ -651,7 +681,7 @@ void RenderSceneChunk(int y, int h)
UseRenderShader(flags);
- glColorMaski(1, GL_TRUE, GL_FALSE, fogenable, GL_FALSE);
+ glColorMaski(1, GL_TRUE, GL_TRUE, fogenable, GL_FALSE);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
@@ -677,6 +707,33 @@ void RenderSceneChunk(int y, int h)
i += RenderPolygonBatch(i);
}
+ // if edge marking is enabled, mark all opaque edges
+ if (RenderDispCnt & (1<<5))
+ {
+ UseRenderShader(flags | RenderFlag_Edge);
+
+ glColorMaski(0, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glColorMaski(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
+
+ glDepthFunc(GL_ALWAYS);
+ glDepthMask(GL_FALSE);
+
+ glStencilFunc(GL_ALWAYS, 0, 0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilMask(0);
+
+ for (int i = 0; i < NumFinalPolys; )
+ {
+ RendererPolygon* rp = &PolygonList[i];
+
+ if (rp->PolyData->IsShadowMask) { i++; continue; }
+
+ i += RenderPolygonEdgeBatch(i);
+ }
+
+ glDepthMask(GL_TRUE);
+ }
+
glEnable(GL_BLEND);
if (RenderDispCnt & (1<<3))
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
@@ -863,23 +920,8 @@ void RenderSceneChunk(int y, int h)
if (RenderDispCnt & 0x00A0) // fog/edge enabled
{
- glUseProgram(FinalPassShader[2]);
-
- glEnable(GL_BLEND);
- if (RenderDispCnt & (1<<6))
- glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA);
- else
- glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA);
-
- {
- u32 c = RenderFogColor;
- u32 r = c & 0x1F;
- u32 g = (c >> 5) & 0x1F;
- u32 b = (c >> 10) & 0x1F;
- u32 a = (c >> 16) & 0x1F;
-
- glBlendColor((float)b/31.0, (float)g/31.0, (float)r/31.0, (float)a/31.0);
- }
+ glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glColorMaski(1, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthFunc(GL_ALWAYS);
glDepthMask(GL_FALSE);
@@ -894,7 +936,44 @@ void RenderSceneChunk(int y, int h)
glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID);
glBindVertexArray(ClearVertexArrayID);
- glDrawArrays(GL_TRIANGLES, 0, 2*3);
+
+ if (RenderDispCnt & (1<<5))
+ {
+ // edge marking
+ // TODO: depth/polyid values at screen edges
+
+ glUseProgram(FinalPassEdgeShader[2]);
+
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
+
+ glDrawArrays(GL_TRIANGLES, 0, 2*3);
+ }
+
+ if (RenderDispCnt & (1<<7))
+ {
+ // fog
+
+ glUseProgram(FinalPassFogShader[2]);
+
+ glEnable(GL_BLEND);
+ if (RenderDispCnt & (1<<6))
+ glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA);
+ else
+ glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA);
+
+ {
+ u32 c = RenderFogColor;
+ u32 r = c & 0x1F;
+ u32 g = (c >> 5) & 0x1F;
+ u32 b = (c >> 10) & 0x1F;
+ u32 a = (c >> 16) & 0x1F;
+
+ glBlendColor((float)b/31.0, (float)g/31.0, (float)r/31.0, (float)a/31.0);
+ }
+
+ glDrawArrays(GL_TRIANGLES, 0, 2*3);
+ }
glFlush();
}
diff --git a/src/GPU3D_OpenGL_shaders.h b/src/GPU3D_OpenGL_shaders.h
index 4c5b82e..3a3c69c 100644
--- a/src/GPU3D_OpenGL_shaders.h
+++ b/src/GPU3D_OpenGL_shaders.h
@@ -67,7 +67,77 @@ void main()
}
)";
-const char* kFinalPassFS = kShaderHeader R"(
+const char* kFinalPassEdgeFS = kShaderHeader R"(
+
+uniform sampler2D DepthBuffer;
+uniform sampler2D 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;
+
+// make up for crapo zbuffer precision
+bool isless(float a, float b)
+{return true;
+ // a < b
+ float diff = a - b;
+ return diff < (256.0 / 16777216.0);
+}
+
+void main()
+{
+ ivec2 coord = ivec2(gl_FragCoord.xy);
+ int scale = int(uScreenSize.x / 256);
+
+ vec4 ret = vec4(0,0,0,0);
+ vec4 depth = texelFetch(DepthBuffer, coord, 0);
+ vec4 attr = texelFetch(AttrBuffer, coord, 0);
+
+ int polyid = int(attr.r * 63.0);
+
+ if (attr.g != 0)
+ {
+ vec4 depthU = texelFetch(DepthBuffer, coord + ivec2(0,-scale), 0);
+ vec4 attrU = texelFetch(AttrBuffer, coord + ivec2(0,-scale), 0);
+ vec4 depthD = texelFetch(DepthBuffer, coord + ivec2(0,scale), 0);
+ vec4 attrD = texelFetch(AttrBuffer, coord + ivec2(0,scale), 0);
+ vec4 depthL = texelFetch(DepthBuffer, coord + ivec2(-scale,0), 0);
+ vec4 attrL = texelFetch(AttrBuffer, coord + ivec2(-scale,0), 0);
+ vec4 depthR = texelFetch(DepthBuffer, coord + ivec2(scale,0), 0);
+ vec4 attrR = texelFetch(AttrBuffer, coord + ivec2(scale,0), 0);
+
+ if ((polyid != int(attrU.r * 63.0) && isless(depth.r, depthU.r)) ||
+ (polyid != int(attrD.r * 63.0) && isless(depth.r, depthD.r)) ||
+ (polyid != int(attrL.r * 63.0) && isless(depth.r, depthL.r)) ||
+ (polyid != int(attrR.r * 63.0) && isless(depth.r, depthR.r)))
+ {
+ // mark this pixel!
+
+ ret.rgb = uEdgeColors[polyid >> 3].bgr;
+
+ // this isn't quite accurate, but it will have to do
+ if ((uDispCnt & (1<<4)) != 0)
+ ret.a = 0.5;
+ else
+ ret.a = 1;
+ }
+ }
+
+ oColor = ret;
+}
+)";
+
+const char* kFinalPassFogFS = kShaderHeader R"(
uniform sampler2D DepthBuffer;
uniform sampler2D AttrBuffer;
@@ -620,6 +690,7 @@ void main()
oColor = col;
oAttr.r = float((fPolygonAttr.x >> 24) & 0x3F) / 63.0;
+ oAttr.g = 0;
oAttr.b = float((fPolygonAttr.x >> 15) & 0x1);
oAttr.a = 1;
}
@@ -636,12 +707,40 @@ void main()
oColor = col;
oAttr.r = float((fPolygonAttr.x >> 24) & 0x3F) / 63.0;
+ oAttr.g = 0;
oAttr.b = float((fPolygonAttr.x >> 15) & 0x1);
oAttr.a = 1;
gl_FragDepth = fZ;
}
)";
+const char* kRenderFS_ZE = R"(
+
+void main()
+{
+ vec4 col = FinalColor();
+ if (col.a < 30.5/31) discard;
+
+ oAttr.g = 1;
+ oAttr.a = 1;
+}
+)";
+
+const char* kRenderFS_WE = R"(
+
+smooth in float fZ;
+
+void main()
+{
+ vec4 col = FinalColor();
+ if (col.a < 30.5/31) discard;
+
+ oAttr.g = 1;
+ oAttr.a = 1;
+ gl_FragDepth = fZ;
+}
+)";
+
const char* kRenderFS_ZT = R"(
void main()