Я работаю над приложением OpenGL на C ++. Это сцена в космосе с большими расстояниями и геометриями, поэтому я использую логарифмическую шкалу глубины. Я включил основы кода ниже. По сути, я не могу дать правильное тестирование глубины. На картинке ниже должен быть куб перед серой сферой. Кроме того, вы можете видеть, что треугольники на большой сфере сзади неправильно упорядочены по глубине.
Вот как я инициализирую буфер глубины в моем приложении (я использую 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
}