mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 07:35:41 +12:00
[PICA] Attempt depth offset/scale and depthmap enable
This commit is contained in:
parent
e9673c9255
commit
f25bc2dd89
3 changed files with 67 additions and 15 deletions
|
@ -24,10 +24,19 @@ class Renderer {
|
||||||
OpenGL::VertexBuffer vbo;
|
OpenGL::VertexBuffer vbo;
|
||||||
GLint alphaControlLoc = -1;
|
GLint alphaControlLoc = -1;
|
||||||
GLint texUnitConfigLoc = -1;
|
GLint texUnitConfigLoc = -1;
|
||||||
|
|
||||||
|
// Depth configuration uniform locations
|
||||||
|
GLint depthOffsetLoc = -1;
|
||||||
|
GLint depthScaleLoc = -1;
|
||||||
|
GLint depthmapEnableLoc = -1;
|
||||||
|
|
||||||
u32 oldAlphaControl = 0;
|
u32 oldAlphaControl = 0;
|
||||||
u32 oldTexUnitConfig = 0;
|
u32 oldTexUnitConfig = 0;
|
||||||
|
|
||||||
|
float oldDepthScale = -1.0;
|
||||||
|
float oldDepthOffset = 0.0;
|
||||||
|
bool oldDepthmapEnable = false;
|
||||||
|
|
||||||
SurfaceCache<DepthBuffer, 10> depthBufferCache;
|
SurfaceCache<DepthBuffer, 10> depthBufferCache;
|
||||||
SurfaceCache<ColourBuffer, 10> colourBufferCache;
|
SurfaceCache<ColourBuffer, 10> colourBufferCache;
|
||||||
SurfaceCache<Texture, 16> textureCache;
|
SurfaceCache<Texture, 16> textureCache;
|
||||||
|
|
|
@ -143,14 +143,14 @@ struct DepthBuffer {
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr std::array<GLenum, 4> types = {
|
static constexpr std::array<GLenum, 4> types = {
|
||||||
GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_INT_24_8
|
GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT_24_8
|
||||||
};
|
};
|
||||||
|
|
||||||
auto internalFormat = internalFormats[(int)format];
|
auto internalFormat = internalFormats[(int)format];
|
||||||
auto fmt = formats[(int)format];
|
auto fmt = formats[(int)format];
|
||||||
auto type = types[(int)format];
|
auto type = types[(int)format];
|
||||||
|
|
||||||
texture.createDSTexture(size.x(), size.y(), internalFormat, fmt, nullptr, type);
|
texture.createDSTexture(size.x(), size.y(), internalFormat, fmt, nullptr, type, GL_TEXTURE_2D);
|
||||||
texture.bind();
|
texture.bind();
|
||||||
texture.setMinFilter(OpenGL::Linear);
|
texture.setMinFilter(OpenGL::Linear);
|
||||||
texture.setMagFilter(OpenGL::Linear);
|
texture.setMagFilter(OpenGL::Linear);
|
||||||
|
|
|
@ -18,7 +18,7 @@ const char* vertexShader = R"(
|
||||||
out vec2 tex0_UVs;
|
out vec2 tex0_UVs;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = coords * vec4(1.0, 1.0, -1.0, 1.0);
|
gl_Position = coords;
|
||||||
colour = vertexColour;
|
colour = vertexColour;
|
||||||
|
|
||||||
// Flip y axis of UVs because OpenGL uses an inverted y for texture sampling compared to the PICA
|
// Flip y axis of UVs because OpenGL uses an inverted y for texture sampling compared to the PICA
|
||||||
|
@ -37,6 +37,11 @@ const char* fragmentShader = R"(
|
||||||
uniform uint u_alphaControl;
|
uniform uint u_alphaControl;
|
||||||
uniform uint u_textureConfig;
|
uniform uint u_textureConfig;
|
||||||
|
|
||||||
|
// Depth control uniforms
|
||||||
|
uniform float u_depthScale;
|
||||||
|
uniform float u_depthOffset;
|
||||||
|
uniform bool u_depthmapEnable;
|
||||||
|
|
||||||
uniform sampler2D u_tex0;
|
uniform sampler2D u_tex0;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -46,6 +51,17 @@ const char* fragmentShader = R"(
|
||||||
fragColour = colour;
|
fragColour = colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get original depth value pre-perspective by converting from [near, far] = [0, 1] to [-1, 1]
|
||||||
|
// We do this by converting to [0, 2] first and subtracting 1 to go to [-1, 1]
|
||||||
|
float z_over_w = gl_FragCoord.z * 2.0f - 1.0;
|
||||||
|
float depth = z_over_w * u_depthScale + u_depthOffset;
|
||||||
|
|
||||||
|
if (!u_depthmapEnable) // Divide z by w if depthmap enable == 0 (ie using W-buffering)
|
||||||
|
depth /= gl_FragCoord.w;
|
||||||
|
|
||||||
|
// Write final fragment depth
|
||||||
|
gl_FragDepth = depth;
|
||||||
|
|
||||||
if ((u_alphaControl & 1u) != 0u) { // Check if alpha test is on
|
if ((u_alphaControl & 1u) != 0u) { // Check if alpha test is on
|
||||||
uint func = (u_alphaControl >> 4u) & 7u;
|
uint func = (u_alphaControl >> 4u) & 7u;
|
||||||
float reference = float((u_alphaControl >> 8u) & 0xffu) / 255.0;
|
float reference = float((u_alphaControl >> 8u) & 0xffu) / 255.0;
|
||||||
|
@ -136,11 +152,19 @@ void Renderer::reset() {
|
||||||
const auto oldProgram = OpenGL::getProgram();
|
const auto oldProgram = OpenGL::getProgram();
|
||||||
|
|
||||||
triangleProgram.use();
|
triangleProgram.use();
|
||||||
oldAlphaControl = 0;
|
oldAlphaControl = 0; // Default alpha control to 0
|
||||||
oldTexUnitConfig = 0;
|
oldTexUnitConfig = 0; // Default tex unit config to 0
|
||||||
|
|
||||||
|
oldDepthScale = -1.0; // Default depth scale to -1.0, which is what games typically use
|
||||||
|
oldDepthOffset = 0.0; // Default depth offset to 0
|
||||||
|
oldDepthmapEnable = false; // Enable w buffering
|
||||||
|
|
||||||
|
glUniform1ui(alphaControlLoc, oldAlphaControl);
|
||||||
|
glUniform1ui(texUnitConfigLoc, oldTexUnitConfig);
|
||||||
|
glUniform1f(depthScaleLoc, oldDepthScale);
|
||||||
|
glUniform1f(depthOffsetLoc, oldDepthOffset);
|
||||||
|
glUniform1i(depthmapEnableLoc, oldDepthmapEnable);
|
||||||
|
|
||||||
glUniform1ui(alphaControlLoc, 0); // Default alpha control to 0
|
|
||||||
glUniform1ui(texUnitConfigLoc, 0); // Default tex unit config to 0
|
|
||||||
glUseProgram(oldProgram); // Switch to old GL program
|
glUseProgram(oldProgram); // Switch to old GL program
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,6 +178,10 @@ void Renderer::initGraphicsContext() {
|
||||||
alphaControlLoc = OpenGL::uniformLocation(triangleProgram, "u_alphaControl");
|
alphaControlLoc = OpenGL::uniformLocation(triangleProgram, "u_alphaControl");
|
||||||
texUnitConfigLoc = OpenGL::uniformLocation(triangleProgram, "u_textureConfig");
|
texUnitConfigLoc = OpenGL::uniformLocation(triangleProgram, "u_textureConfig");
|
||||||
|
|
||||||
|
depthScaleLoc = OpenGL::uniformLocation(triangleProgram, "u_depthScale");
|
||||||
|
depthOffsetLoc = OpenGL::uniformLocation(triangleProgram, "u_depthOffset");
|
||||||
|
depthmapEnableLoc = OpenGL::uniformLocation(triangleProgram, "u_depthmapEnable");
|
||||||
|
|
||||||
OpenGL::Shader vertDisplay(displayVertexShader, OpenGL::Vertex);
|
OpenGL::Shader vertDisplay(displayVertexShader, OpenGL::Vertex);
|
||||||
OpenGL::Shader fragDisplay(displayFragmentShader, OpenGL::Fragment);
|
OpenGL::Shader fragDisplay(displayFragmentShader, OpenGL::Fragment);
|
||||||
displayProgram.create({ vertDisplay, fragDisplay });
|
displayProgram.create({ vertDisplay, fragDisplay });
|
||||||
|
@ -251,20 +279,34 @@ void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 c
|
||||||
poop.bind(OpenGL::DrawAndReadFramebuffer);
|
poop.bind(OpenGL::DrawAndReadFramebuffer);
|
||||||
|
|
||||||
const u32 depthControl = regs[PICAInternalRegs::DepthAndColorMask];
|
const u32 depthControl = regs[PICAInternalRegs::DepthAndColorMask];
|
||||||
bool depthEnable = depthControl & 1;
|
const bool depthEnable = depthControl & 1;
|
||||||
bool depthWriteEnable = (depthControl >> 12) & 1;
|
const bool depthWriteEnable = (depthControl >> 12) & 1;
|
||||||
int depthFunc = (depthControl >> 4) & 7;
|
const int depthFunc = (depthControl >> 4) & 7;
|
||||||
int colourMask = (depthControl >> 8) & 0xf;
|
const int colourMask = (depthControl >> 8) & 0xf;
|
||||||
|
|
||||||
static constexpr std::array<GLenum, 8> depthModes = {
|
static constexpr std::array<GLenum, 8> depthModes = {
|
||||||
GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL
|
GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL
|
||||||
};
|
};
|
||||||
|
|
||||||
f24 depthScale = f24::fromRaw(regs[PICAInternalRegs::DepthScale] & 0xffffff);
|
const float depthScale = f24::fromRaw(regs[PICAInternalRegs::DepthScale] & 0xffffff).toFloat32();
|
||||||
f24 depthOffset = f24::fromRaw(regs[PICAInternalRegs::DepthOffset] & 0xffffff);
|
const float depthOffset = f24::fromRaw(regs[PICAInternalRegs::DepthOffset] & 0xffffff).toFloat32();
|
||||||
|
const bool depthMapEnable = regs[PICAInternalRegs::DepthmapEnable] & 1;
|
||||||
|
|
||||||
//if (depthScale.toFloat32() != -1.0 || depthOffset.toFloat32() != 0.0)
|
// Update depth uniforms
|
||||||
// Helpers::panic("TODO: Implement depth scale/offset. Remove the depth *= -1.0 from vertex shader");
|
if (oldDepthScale != depthScale) {
|
||||||
|
oldDepthScale = depthScale;
|
||||||
|
glUniform1f(depthScaleLoc, depthScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldDepthOffset != depthOffset) {
|
||||||
|
oldDepthOffset = depthOffset;
|
||||||
|
glUniform1f(depthOffsetLoc, depthOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldDepthmapEnable != depthMapEnable) {
|
||||||
|
oldDepthmapEnable = depthMapEnable;
|
||||||
|
glUniform1i(depthmapEnableLoc, depthMapEnable);
|
||||||
|
}
|
||||||
|
|
||||||
// Hack for rendering texture 1
|
// Hack for rendering texture 1
|
||||||
if (regs[0x80] & 1) {
|
if (regs[0x80] & 1) {
|
||||||
|
@ -380,6 +422,7 @@ void Renderer::bindDepthBuffer() {
|
||||||
tex = depthBufferCache.add(sampleBuffer).texture.m_handle;
|
tex = depthBufferCache.add(sampleBuffer).texture.m_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DepthBuffer::Formats::Depth24Stencil8 != depthBufferFormat) Helpers::panic("TODO: Should we remove stencil attachment?");
|
||||||
auto attachment = depthBufferFormat == DepthBuffer::Formats::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
|
auto attachment = depthBufferFormat == DepthBuffer::Formats::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue