gsdx ogl: correct most of Z-depth issue

Best setting if you driver support GL_NV_depth_buffer_float => GL_NV_Depth = 1 & logz = 0
Otherwise => GL_NV_Depth = 0 & logz = 1

Explanation of the bug:
Dx z position ranges from 0.0f to 1.0f (FS ranges 0.0f to 1.0f)
GL z Position ranges from -1.0f to 1.0f (FS ranges 0.0f to 1.0f)

Why it sucks:
GS small depth value will be "mapped" to -1.0f. In others all small values will be 1.0f! Terrible lost
of accuraccy.

The GL_NV_depth_buffer_float extension allow to set the near plane as -1.0f.
So
"GL z Position ranges from -1.0f to 1.0f (FS ranges 0.0f to 1.0f)"
will become
"GL z Position ranges from -1.0f to 1.0f (FS ranges -1.0f to 1.0f)"
and therefore
"z posision [0.0f;1.0f] will map to FS [0.0f;1.0f]" as DX

Yes we just get back all precision lost previously :)
However you need hardware (intel?) and driver support (free driver?/gles?) :(





git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5860 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2014-01-31 21:30:54 +00:00
parent e27d04ff08
commit 84895eadd9
10 changed files with 62 additions and 21 deletions

View File

@ -118,6 +118,8 @@ PFNGLMAKETEXTUREHANDLERESIDENTARBPROC gl_MakeTextureHandleResidentARB = NULL;
PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC gl_MakeTextureHandleNonResidentARB = NULL;
PFNGLUNIFORMHANDLEUI64VARBPROC gl_UniformHandleui64vARB = NULL;
PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC gl_ProgramUniformHandleui64vARB = NULL;
PFNGLDEPTHRANGEDNVPROC gl_DepthRangedNV = NULL;
#endif
namespace GLLoader {

View File

@ -183,6 +183,8 @@ extern PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC gl_MakeTextureHandleNonResidentA
extern PFNGLUNIFORMHANDLEUI64VARBPROC gl_UniformHandleui64vARB;
extern PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC gl_ProgramUniformHandleui64vARB;
extern PFNGLDEPTHRANGEDNVPROC gl_DepthRangedNV;
#else
#define gl_ActiveTexture glActiveTexture
#define gl_BlendColor glBlendColor

View File

@ -167,7 +167,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
// ****************************************************************
// Various object
// ****************************************************************
m_shader = new GSShaderOGL(!!theApp.GetConfig("debug_ogl_shader", 1));
m_shader = new GSShaderOGL(!!theApp.GetConfig("debug_ogl_shader", 1), !!theApp.GetConfig("GL_NV_Depth", 0));
gl_GenFramebuffers(1, &m_fbo);
gl_GenFramebuffers(1, &m_fbo_read);

View File

@ -23,8 +23,9 @@
#include "GSShaderOGL.h"
#include "GLState.h"
GSShaderOGL::GSShaderOGL(bool debug) :
GSShaderOGL::GSShaderOGL(bool debug, bool nv_depth) :
m_debug_shader(debug),
m_nv_depth(nv_depth),
m_vs_sub_count(0),
m_ps_sub_count(0)
{
@ -397,6 +398,10 @@ std::string GSShaderOGL::GenGlslHeader(const std::string& entry, GLenum type, co
header += "#define ENABLE_BINDLESS_TEX\n";
}
if (m_nv_depth) {
// Specific nvidia extension that seem to help for z fighting
header += "#define NV_DEPTH\n";
}
#else
header = "#version 300 es\n";

View File

@ -25,6 +25,7 @@ class GSShaderOGL {
GLuint m_pipeline;
hash_map<uint64, GLuint > m_single_prog;
const bool m_debug_shader;
const bool m_nv_depth;
GLuint m_vs_sub_count;
GLuint m_ps_sub_count;
@ -46,7 +47,7 @@ class GSShaderOGL {
GLuint LinkNewProgram();
public:
GSShaderOGL(bool debug);
GSShaderOGL(bool debug, bool nv_depth);
~GSShaderOGL();
void GS(GLuint s);

View File

@ -59,6 +59,10 @@ void GSDeviceOGL::CreateTextureFX()
// Help to debug FS in apitrace
m_apitrace = CompilePS(PSSelector());
if (!!theApp.GetConfig("GL_NV_Depth", 0)) {
gl_DepthRangedNV(-1.0f, 1.0f);
}
}
GSDepthStencilOGL* GSDeviceOGL::CreateDepthStencil(OMDepthStencilSelector dssel)

View File

@ -234,8 +234,12 @@ public:
switch (layout[i].type) {
case GL_UNSIGNED_SHORT:
case GL_UNSIGNED_INT:
if (layout[i].normalize) {
gl_VertexAttribPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].normalize, layout[i].stride, layout[i].offset);
} else {
// Rule: when shader use integral (not normalized) you must use gl_VertexAttribIPointer (note the extra I)
gl_VertexAttribIPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].stride, layout[i].offset);
}
break;
default:
gl_VertexAttribPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].normalize, layout[i].stride, layout[i].offset);

View File

@ -120,6 +120,7 @@ void GSWndGL::PopulateGlFunction()
*(void**)&(gl_UniformHandleui64vARB) = GetProcAddress("glUniformHandleui64vARB", true);
*(void**)&(gl_ProgramUniformHandleui64vARB) = GetProcAddress("glProgramUniformHandleui64vARB", true);
*(void**)&(gl_DepthRangedNV) = GetProcAddress("glDepthRangedNV", true);
#endif
}

View File

@ -665,6 +665,7 @@ static const char* tfx_glsl =
"};\n"
"\n"
"const float exp_min32 = exp2(-32.0f);\n"
"const float exp_min31 = exp2(-31.0f);\n"
"\n"
"#ifdef SUBROUTINE_GL40\n"
"// Function pointer type\n"
@ -722,7 +723,7 @@ static const char* tfx_glsl =
"\n"
"void vs_main()\n"
"{\n"
" uint z;\n"
" highp uint z;\n"
" if(VS_BPPZ == 1) // 24\n"
" z = i_z & uint(0xffffff);\n"
" else if(VS_BPPZ == 2) // 16\n"
@ -734,16 +735,26 @@ static const char* tfx_glsl =
" // example: ceil(afterseveralvertextransformations(y = 133)) => 134 => line 133 stays empty\n"
" // input granularity is 1/16 pixel, anything smaller than that won't step drawing up/left by one pixel\n"
" // example: 133.0625 (133 + 1/16) should start from line 134, ceil(133.0625 - 0.05) still above 133\n"
" vec4 p;\n"
"\n"
" vec3 p = vec3(i_p, z) - vec3(0.05f, 0.05f, 0.0f);\n"
" p = p * vec3(VertexScale, exp_min32) - vec3(VertexOffset, 0.0f);\n"
"\n"
" if(VS_LOGZ == 1)\n"
" {\n"
" p.z = log2(1.0f + float(z)) / 32.0f;\n"
" p.xy = vec2(i_p) - vec2(0.05f, 0.05f);\n"
" p.xy = p.xy * VertexScale - VertexOffset;\n"
" p.w = 1.0f;\n"
"#ifdef NV_DEPTH\n"
" if(VS_LOGZ == 1) {\n"
" p.z = log2(float(1u+z)) / 32.0f;\n"
" } else {\n"
" p.z = float(z) * exp_min32;\n"
" }\n"
"#else\n"
" if(VS_LOGZ == 1) {\n"
" p.z = log2(float(1u+z)) / 31.0f - 1.0f;\n"
" } else {\n"
" p.z = float(z) * exp_min31 - 1.0f;\n"
" }\n"
"#endif\n"
"\n"
" gl_Position = vec4(p, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position\n"
" gl_Position = p;\n"
"\n"
" texture_coord();\n"
"\n"

View File

@ -106,6 +106,7 @@ layout(std140, binding = 20) uniform cb20
};
const float exp_min32 = exp2(-32.0f);
const float exp_min31 = exp2(-31.0f);
#ifdef SUBROUTINE_GL40
// Function pointer type
@ -163,7 +164,7 @@ void texture_coord()
void vs_main()
{
uint z;
highp uint z;
if(VS_BPPZ == 1) // 24
z = i_z & uint(0xffffff);
else if(VS_BPPZ == 2) // 16
@ -175,16 +176,26 @@ void vs_main()
// example: ceil(afterseveralvertextransformations(y = 133)) => 134 => line 133 stays empty
// input granularity is 1/16 pixel, anything smaller than that won't step drawing up/left by one pixel
// example: 133.0625 (133 + 1/16) should start from line 134, ceil(133.0625 - 0.05) still above 133
vec4 p;
vec3 p = vec3(i_p, z) - vec3(0.05f, 0.05f, 0.0f);
p = p * vec3(VertexScale, exp_min32) - vec3(VertexOffset, 0.0f);
if(VS_LOGZ == 1)
{
p.z = log2(1.0f + float(z)) / 32.0f;
p.xy = vec2(i_p) - vec2(0.05f, 0.05f);
p.xy = p.xy * VertexScale - VertexOffset;
p.w = 1.0f;
#ifdef NV_DEPTH
if(VS_LOGZ == 1) {
p.z = log2(float(1u+z)) / 32.0f;
} else {
p.z = float(z) * exp_min32;
}
#else
if(VS_LOGZ == 1) {
p.z = log2(float(1u+z)) / 31.0f - 1.0f;
} else {
p.z = float(z) * exp_min31 - 1.0f;
}
#endif
gl_Position = vec4(p, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
gl_Position = p;
texture_coord();