mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-13 17:49:47 +12:00
renderer_gl: Implement stencil testing
This commit is contained in:
parent
037d16ae7c
commit
95a8917589
3 changed files with 59 additions and 1 deletions
|
@ -55,6 +55,8 @@ namespace PICA {
|
||||||
BlendFunc = 0x101,
|
BlendFunc = 0x101,
|
||||||
BlendColour = 0x103,
|
BlendColour = 0x103,
|
||||||
AlphaTestConfig = 0x104,
|
AlphaTestConfig = 0x104,
|
||||||
|
StencilTest = 0x105,
|
||||||
|
StencilOp = 0x106,
|
||||||
DepthAndColorMask = 0x107,
|
DepthAndColorMask = 0x107,
|
||||||
DepthBufferFormat = 0x116,
|
DepthBufferFormat = 0x116,
|
||||||
ColourBufferFormat = 0x117,
|
ColourBufferFormat = 0x117,
|
||||||
|
|
|
@ -61,6 +61,7 @@ class RendererGL final : public Renderer {
|
||||||
|
|
||||||
MAKE_LOG_FUNCTION(log, rendererLogger)
|
MAKE_LOG_FUNCTION(log, rendererLogger)
|
||||||
void setupBlending();
|
void setupBlending();
|
||||||
|
void setupStencilTest(bool stencilEnable);
|
||||||
void bindDepthBuffer();
|
void bindDepthBuffer();
|
||||||
void setupTextureEnvState();
|
void setupTextureEnvState();
|
||||||
void bindTexturesToSlots();
|
void bindTexturesToSlots();
|
||||||
|
@ -79,4 +80,4 @@ class RendererGL final : public Renderer {
|
||||||
|
|
||||||
// Take a screenshot of the screen and store it in a file
|
// Take a screenshot of the screen and store it in a file
|
||||||
void screenshot(const std::string& name) override;
|
void screenshot(const std::string& name) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -205,6 +205,51 @@ void RendererGL::setupBlending() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererGL::setupStencilTest(bool stencilEnable) {
|
||||||
|
if (!stencilEnable) {
|
||||||
|
OpenGL::disableStencil();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr std::array<GLenum, 8> stencilFuncs = {
|
||||||
|
GL_NEVER,
|
||||||
|
GL_ALWAYS,
|
||||||
|
GL_EQUAL,
|
||||||
|
GL_NOTEQUAL,
|
||||||
|
GL_LESS,
|
||||||
|
GL_LEQUAL,
|
||||||
|
GL_GREATER,
|
||||||
|
GL_GEQUAL
|
||||||
|
};
|
||||||
|
OpenGL::enableStencil();
|
||||||
|
|
||||||
|
const u32 stencilConfig = regs[PICA::InternalRegs::StencilTest];
|
||||||
|
const u32 stencilFunc = getBits<4, 3>(stencilConfig);
|
||||||
|
const u32 stencilBufferMask = getBits<8, 8>(stencilConfig);
|
||||||
|
const s32 reference = s8(getBits<16, 8>(stencilConfig)); // Signed reference value
|
||||||
|
const u32 stencilRefMask = getBits<24, 8>(stencilConfig);
|
||||||
|
|
||||||
|
glStencilFunc(stencilFuncs[stencilFunc], reference, stencilRefMask);
|
||||||
|
glStencilMask(stencilBufferMask);
|
||||||
|
|
||||||
|
static constexpr std::array<GLenum, 8> stencilOps = {
|
||||||
|
GL_KEEP,
|
||||||
|
GL_ZERO,
|
||||||
|
GL_REPLACE,
|
||||||
|
GL_INCR,
|
||||||
|
GL_DECR,
|
||||||
|
GL_INVERT,
|
||||||
|
GL_INCR_WRAP,
|
||||||
|
GL_DECR_WRAP
|
||||||
|
};
|
||||||
|
const u32 stencilOpConfig = regs[PICA::InternalRegs::StencilOp];
|
||||||
|
const u32 stencilFailOp = getBits<0, 3>(stencilOpConfig);
|
||||||
|
const u32 depthFailOp = getBits<4, 3>(stencilOpConfig);
|
||||||
|
const u32 passOp = getBits<8, 3>(stencilOpConfig);
|
||||||
|
|
||||||
|
glStencilOp(stencilOps[stencilFailOp], stencilOps[depthFailOp], stencilOps[passOp]);
|
||||||
|
}
|
||||||
|
|
||||||
void RendererGL::setupTextureEnvState() {
|
void RendererGL::setupTextureEnvState() {
|
||||||
// TODO: Only update uniforms when the TEV config changed. Use an UBO potentially.
|
// TODO: Only update uniforms when the TEV config changed. Use an UBO potentially.
|
||||||
|
|
||||||
|
@ -356,6 +401,9 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span<const Vertex> v
|
||||||
GLsizei viewportHeight = GLsizei(f24::fromRaw(regs[PICA::InternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0f);
|
GLsizei viewportHeight = GLsizei(f24::fromRaw(regs[PICA::InternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0f);
|
||||||
OpenGL::setViewport(viewportWidth, viewportHeight);
|
OpenGL::setViewport(viewportWidth, viewportHeight);
|
||||||
|
|
||||||
|
const u32 stencilConfig = regs[PICA::InternalRegs::StencilTest];
|
||||||
|
const bool stencilEnable = getBit<0>(stencilConfig);
|
||||||
|
|
||||||
// Note: The code below must execute after we've bound the colour buffer & its framebuffer
|
// Note: The code below must execute after we've bound the colour buffer & its framebuffer
|
||||||
// Because it attaches a depth texture to the aforementioned colour buffer
|
// Because it attaches a depth texture to the aforementioned colour buffer
|
||||||
if (depthEnable) {
|
if (depthEnable) {
|
||||||
|
@ -371,9 +419,15 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span<const Vertex> v
|
||||||
bindDepthBuffer();
|
bindDepthBuffer();
|
||||||
} else {
|
} else {
|
||||||
gl.disableDepth();
|
gl.disableDepth();
|
||||||
|
|
||||||
|
if (stencilEnable) {
|
||||||
|
bindDepthBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupStencilTest(stencilEnable);
|
||||||
|
|
||||||
vbo.bufferVertsSub(vertices);
|
vbo.bufferVertsSub(vertices);
|
||||||
OpenGL::draw(primitiveTopology, GLsizei(vertices.size()));
|
OpenGL::draw(primitiveTopology, GLsizei(vertices.size()));
|
||||||
}
|
}
|
||||||
|
@ -476,6 +530,7 @@ void RendererGL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u
|
||||||
gl.disableBlend();
|
gl.disableBlend();
|
||||||
gl.disableDepth();
|
gl.disableDepth();
|
||||||
gl.disableScissor();
|
gl.disableScissor();
|
||||||
|
OpenGL::disableStencil();
|
||||||
gl.setColourMask(true, true, true, true);
|
gl.setColourMask(true, true, true, true);
|
||||||
gl.useProgram(displayProgram);
|
gl.useProgram(displayProgram);
|
||||||
gl.bindVAO(dummyVAO);
|
gl.bindVAO(dummyVAO);
|
||||||
|
|
Loading…
Add table
Reference in a new issue