mirror of
https://github.com/MobileGL-Dev/MobileGlues.git
synced 2025-09-22 02:32:29 -04:00
[Fix] (GL): Force depth clear when glClear is called with depth=1.0 on ANGLE.
This commit is contained in:
parent
4bcd4d0dee
commit
d16d87fd26
@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Created by Swung0x48 on 2024/10/8.
|
||||
//
|
||||
|
||||
@ -7,16 +7,124 @@
|
||||
#include "glcorearb.h"
|
||||
#include "log.h"
|
||||
#include "../gles/loader.h"
|
||||
#include "../config/settings.h"
|
||||
#include "mg.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
static GLclampd currentDepthValue;
|
||||
|
||||
void glClearDepth(GLclampd depth) {
|
||||
LOG()
|
||||
currentDepthValue = depth;
|
||||
GLES.glClearDepthf((float)depth);
|
||||
CHECK_GL_ERROR
|
||||
}
|
||||
|
||||
static GLuint g_depthClearProgram = 0;
|
||||
static GLuint g_depthClearVAO = 0;
|
||||
static GLuint g_depthClearVBO = 0;
|
||||
|
||||
static const GLfloat kFullScreenTri[3][2] = {
|
||||
{ -1.0f, -1.0f },
|
||||
{ 3.0f, -1.0f },
|
||||
{ -1.0f, 3.0f }
|
||||
};
|
||||
|
||||
static const char* kDepthClearVS = R"glsl(
|
||||
#version 300 es
|
||||
layout(location = 0) in vec2 aPos;
|
||||
void main() {
|
||||
// Write far‐plane depth
|
||||
gl_Position = vec4(aPos, 1.0, 1.0);
|
||||
}
|
||||
)glsl";
|
||||
static const char* kDepthClearFS = R"glsl(
|
||||
#version 300 es
|
||||
precision mediump float;
|
||||
out vec4 fragColor;
|
||||
void main() {
|
||||
// Empty—color writes will be disabled
|
||||
fragColor = vec4(0.0);
|
||||
}
|
||||
)glsl";
|
||||
|
||||
void InitDepthClearCoreProfile() {
|
||||
if (g_depthClearProgram) return;
|
||||
|
||||
auto compile = [&](GLenum type, const char* src) {
|
||||
GLuint s = GLES.glCreateShader(type);
|
||||
GLES.glShaderSource(s, 1, &src, nullptr);
|
||||
GLES.glCompileShader(s);
|
||||
return s;
|
||||
};
|
||||
GLuint vs = compile(GL_VERTEX_SHADER, kDepthClearVS);
|
||||
GLuint fs = compile(GL_FRAGMENT_SHADER, kDepthClearFS);
|
||||
|
||||
g_depthClearProgram = GLES.glCreateProgram();
|
||||
GLES.glAttachShader(g_depthClearProgram, vs);
|
||||
GLES.glAttachShader(g_depthClearProgram, fs);
|
||||
GLES.glLinkProgram(g_depthClearProgram);
|
||||
GLES.glDeleteShader(vs);
|
||||
GLES.glDeleteShader(fs);
|
||||
|
||||
GLES.glGenVertexArrays(1, &g_depthClearVAO);
|
||||
GLES.glGenBuffers(1, &g_depthClearVBO);
|
||||
|
||||
GLES.glBindVertexArray(g_depthClearVAO);
|
||||
GLES.glBindBuffer(GL_ARRAY_BUFFER, g_depthClearVBO);
|
||||
GLES.glBufferData(GL_ARRAY_BUFFER, sizeof(kFullScreenTri), kFullScreenTri, GL_STATIC_DRAW);
|
||||
|
||||
GLES.glEnableVertexAttribArray(0);
|
||||
GLES.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
|
||||
GLES.glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
GLES.glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void DrawDepthClearTri() {
|
||||
InitDepthClearCoreProfile();
|
||||
|
||||
GLboolean prevColorMask[4];
|
||||
GLES.glGetBooleanv(GL_COLOR_WRITEMASK, prevColorMask);
|
||||
GLboolean prevDepthMask;
|
||||
GLES.glGetBooleanv(GL_DEPTH_WRITEMASK, &prevDepthMask);
|
||||
GLint prevDepthFunc;
|
||||
GLES.glGetIntegerv(GL_DEPTH_FUNC, &prevDepthFunc);
|
||||
|
||||
GLES.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
GLES.glDepthMask(GL_TRUE);
|
||||
GLES.glDepthFunc(GL_ALWAYS);
|
||||
|
||||
GLES.glUseProgram(g_depthClearProgram);
|
||||
GLES.glBindVertexArray(g_depthClearVAO);
|
||||
GLES.glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
GLES.glBindVertexArray(0);
|
||||
GLES.glUseProgram(0);
|
||||
|
||||
GLES.glDepthFunc(prevDepthFunc);
|
||||
GLES.glDepthMask(prevDepthMask);
|
||||
GLES.glColorMask(prevColorMask[0], prevColorMask[1], prevColorMask[2], prevColorMask[3]);
|
||||
}
|
||||
|
||||
void glClear(GLbitfield mask) {
|
||||
LOG();
|
||||
LOG_D("glClear, mask = 0x%x", mask);
|
||||
|
||||
if (global_settings.angle == AngleMode::Enabled && mask == GL_DEPTH_BUFFER_BIT && fabs(currentDepthValue - 1.0f) <= 0.001f) {
|
||||
// Workaround for ANGLE depth-clear bug: if depth≈1.0, draw a fullscreen triangle at z=1.0 to force actual depth buffer write.
|
||||
DrawDepthClearTri();
|
||||
// Clear again
|
||||
GLES.glClear(mask);
|
||||
} else {
|
||||
GLES.glClear(mask);
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void glHint(GLenum target, GLenum mode) {
|
||||
LOG()
|
||||
LOG_D("glHint, target = %s, mode = %s", glEnumToString(target), glEnumToString(mode))
|
||||
|
@ -27,7 +27,7 @@ NATIVE_FUNCTION_HEAD(void, glBlendFuncSeparate, GLenum sfactorRGB, GLenum dfacto
|
||||
//NATIVE_FUNCTION_HEAD(void, glBufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) NATIVE_FUNCTION_END_NO_RETURN(void, glBufferData, target,size,data,usage)
|
||||
NATIVE_FUNCTION_HEAD(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data) NATIVE_FUNCTION_END_NO_RETURN(void, glBufferSubData, target,offset,size,data)
|
||||
//NATIVE_FUNCTION_HEAD(GLenum, glCheckFramebufferStatus, GLenum target) NATIVE_FUNCTION_END(GLenum, glCheckFramebufferStatus, target)
|
||||
NATIVE_FUNCTION_HEAD(void, glClear, GLbitfield mask) NATIVE_FUNCTION_END_NO_RETURN(void, glClear, mask)
|
||||
//NATIVE_FUNCTION_HEAD(void, glClear, GLbitfield mask) NATIVE_FUNCTION_END_NO_RETURN(void, glClear, mask)
|
||||
NATIVE_FUNCTION_HEAD(void, glClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) NATIVE_FUNCTION_END_NO_RETURN(void, glClearColor, red,green,blue,alpha)
|
||||
NATIVE_FUNCTION_HEAD(void, glClearDepthf, GLfloat d) NATIVE_FUNCTION_END_NO_RETURN(void, glClearDepthf, d)
|
||||
NATIVE_FUNCTION_HEAD(void, glClearStencil, GLint s) NATIVE_FUNCTION_END_NO_RETURN(void, glClearStencil, s)
|
||||
|
@ -52,9 +52,9 @@ void internal_convert(GLenum* internal_format, GLenum* type, GLenum* format) {
|
||||
break;
|
||||
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
*internal_format = GL_DEPTH_COMPONENT32F;
|
||||
*internal_format = GL_DEPTH_COMPONENT;
|
||||
if(type)
|
||||
*type = GL_FLOAT;
|
||||
*type = GL_UNSIGNED_INT;
|
||||
break;
|
||||
|
||||
case GL_DEPTH_COMPONENT32F:
|
||||
|
Loading…
x
Reference in New Issue
Block a user