aboutsummaryrefslogtreecommitdiff
path: root/src/GPU3D_OpenGL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/GPU3D_OpenGL.cpp')
-rw-r--r--src/GPU3D_OpenGL.cpp151
1 files changed, 115 insertions, 36 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();
}