gpt4 book ai didi

c++ - OpenGL 中的乱序 Z 缓冲区

转载 作者:行者123 更新时间:2023-11-28 01:14:02 25 4
gpt4 key购买 nike

我正在使用 C++ 开发 OpenGL 应用程序。这是一个距离和几何形状都很大的空间场景,因此我使用对数深度尺度。我已经包含了下面代码的基础知识。本质上,我似乎无法正确进行深度测试。下图应该让立方体出现在灰色球体之前。此外,您可以看到背面较大球体上的三角形深度排序不正确。

 B=

下面是我如何在我的应用程序中初始化深度缓冲区(我使用的是 SDL2 和 Glew)。我错过了什么吗?

(一些附加信息,蓝色球体直径为650000个单位,立方体宽度为100个单位,灰色球体直径为1000个单位)

#include <iostream.h>
#include <GL/glew.h>
#include <SDL.h>
#include <SDL_opengl.h>
#include <glm/mat4x4.hpp>

int main() {
// Set up the window
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute (SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3); //OpenGL 3+
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 3); //OpenGL 3.3
SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); //OpenGL core profile

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

displayWindow = SDL_CreateWindow(GAME_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)screenWidth, (int)screenHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

SDL_GLContext context = SDL_GL_CreateContext(displayWindow);
// SDL_GL_MakeCurrent(displayWindow, context);

SDL_GL_SetSwapInterval( 1 );

glewExperimental = GL_TRUE;
GLenum glewError = glewInit();
if( glewError != GLEW_OK ) {
std::cout << "Error Initializing GLEW" << std::endl;
exit(1);
}

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Enable Depth Buffering
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}

这是顶点着色器:

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;

uniform vec3 lightPosition;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 normalMatrix;

out vec3 Normal_camera;
out vec3 LightDirection_camera;
out vec3 Position_global;
out vec3 EyeDirection_camera;
out float logz;

void main()
{
// vec3 lightPosition = vec3(1, 1, 0);
// Position of the vertex, in worldspace : modelMatrix * position
Position_global = (modelMatrix * vec4(position, 1)).xyz;

// Vector that goes from the vertex to the camera, in camera space.
// In camera space, the camera is at the origin (0,0,0).
vec3 Position_camera = (viewMatrix * vec4(Position_global, 1)).xyz;
EyeDirection_camera = (vec4(0, 0, 0, 0) - vec4(Position_camera, 1)).xyz;

// Vector that goes from the vertex to the light, in camera space. M is ommited because it's identity.
vec3 LightPosition_camera = (viewMatrix * vec4(lightPosition, 1)).xyz;
LightDirection_camera = LightPosition_camera + EyeDirection_camera;

// Normal of the the vertex, in camera space
Normal_camera = (modelMatrix * vec4(normal, 0)).xyz;
// Only correct if ModelMatrix does not scale the model ! Use its inverse transpose if not

gl_Position = projectionMatrix * vec4(Position_camera, 1);
logz = 0.0f;
float ZNEAR = 0.0001;
float ZFAR = 1000000.0;
float FCOEF = 2.0 / log2(ZFAR + 1.0);
logz = FCOEF;
gl_Position.z = log2(max(ZNEAR, 1.0 + gl_Position.w)) * FCOEF - 1.0;
}

最后,片段着色器:

#version 330 core
uniform vec4 color;
uniform float lightPower;
uniform vec3 lightPosition;
uniform vec3 lightColor;

in vec3 Normal_camera;
in vec3 LightDirection_camera;
in vec3 Position_global;
in vec3 EyeDirection_camera;
in float logz;

out vec4 FragColor;

void main() {
vec3 n = normalize(Normal_camera);
vec3 l = normalize(lightPosition - Position_global);
float cosTheta = clamp(dot(n, l), 0.0, 1.0);
float distance = length( lightPosition - Position_global );

// Eye vector (towards the camera)
vec3 E = normalize(EyeDirection_camera);
// Direction in which the triangle reflects the light
vec3 R = reflect(-l,n);
// Cosine of the angle between the Eye vector and the Reflect vector,
// clamped to 0
// - Looking into the reflection -> 1
// - Looking elsewhere -> < 1
float cosAlpha = clamp( dot( E,R ), 0.0, 1.0);
float specularStrength = 0.3;
float shininess = 16.0;
float ambientStrength = 0.3;
float sqDistance = distance * distance;

vec3 MaterialAmbientColor = ambientStrength * lightColor;
//* lightPower / sqDistance;
vec3 MaterialDiffuseColor = lightColor * lightPower * cosTheta / sqDistance;
vec3 MaterialSpecularColor = specularStrength * lightColor * lightPower * pow(cosAlpha, shininess) / sqDistance;

vec4 c = color * vec4(MaterialAmbientColor + MaterialDiffuseColor + MaterialSpecularColor, 1);
FragColor = c;
gl_FragDepth = logz;

// Later on, I assign glm::perspective(radians(45.0f), SCREEN_HEIGHT/SCREEN_WIDTH, 1.0f, 1000.0f) to the perspective uniform
}

最佳答案

您的顶点着色器似乎将 logz 设置为常量值,然后将其传递给片段着色器,片段着色器随后将其分配给 gl_FragDepth。因此,您所有的片段都具有大致相同的深度。

我会尝试从顶点着色器中移除所有特殊的对数数学,而是在片段着色器中全部完成。 OpenGL 执行透视校正插值,因此期望顶点着色器的传出 Z 被剪裁在 -W 和 +W 之间。

关于c++ - OpenGL 中的乱序 Z 缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59287396/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com