miserable, feeble little attempt at edge marking
This commit is contained in:
parent
434a3007e2
commit
086354a420
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue