【问题标题】:Depth testing is not working at all深度测试根本不起作用
【发布时间】:2018-07-01 23:18:13
【问题描述】:

由于我的项目中的某些原因,我的深度测试无法正常工作。我已确保它已启用并且它不起作用。我知道这一点是因为我可以看到某些面孔被相互绘制,场景中的不同对象(立方体)被相互绘制。

我使用的是默认帧缓冲区,所以应该有深度。我还检查了 gl_FragCoord.z 并返回了正确的深度。我已经彻底检查了我的代码多年,搜索了几十个谷歌页面,但我仍然找不到答案。

以下是与此问题相关的按执行顺序显示的代码:

初始化()

void Program::Init()
{
    std::cout << "Initialising" << std::endl;
    glViewport(0, 0, Options::width, Options::height);

    glewExperimental = true; // Needed in core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        return;
    }

    window.setKeyRepeatEnabled(false);

    sf::Mouse::setPosition(sf::Vector2i(Options::width / 2, Options::height / 2), window);

    LoadGameState(GameState::INGAME, false);
    Run();
}

GLInit()

void Program::GLInit() {

    lampShader = Shader("StandardVertex.shader", "LightingFragmentShader.shader");
    ourShader = Shader("VertexShader.shader", "SimpleFragmentShader.shader");
    screenShader = Shader("FrameVertexShader.shader", "FrameFragmentShader.shader");
    skyboxShader = Shader("SkyboxVertex.shader", "SkyboxFragment.shader");
    cubeDepthShader = Shader("CubeDepthVertex.shader", "CubeDepthFragment.shader", &std::string("CubeDepthGeometry.shader"));
    debugDepthQuad = Shader("SimpleVertex.shader", "DepthFragment.shader");
    blurShader = Shader("SimpleVertex.shader", "BloomFragment.shader");
    bloomShader = Shader("SimpleVertex.shader", "FinalBloom.shader");

    depthShader = Shader("VertexDepth.shader", "EmptyFragment.shader");

    geometryPass = Shader("GeometryVertex.shader", "GeometryFragment.shader");
    lightingPass = Shader("SimpleVertex.shader", "LightingFragment.shader");
    shaderSSAO = Shader("SimpleVertex.shader", "SSAOFragment.shader");
    shaderSSAOblur = Shader("SimpleVertex.shader", "SSAOBlurFragment.shader");

    colliders = Shader("VertexShader.shader", "GreenFragment.shader");


    glEnable(GL_DEPTH_TEST);
}

和另一个重复运行的函数: RunGame()

void Program::RunGame()
{


    scene->mainCamera.Input(Options::deltaTime, window);

    if(timeSinceGameStart.getElapsedTime().asSeconds()<2)
    DoLights();

    if(timeSinceGameStart.getElapsedTime().asSeconds() > 5.0f)
    scene->DoPhysics();

    scene->CheckCollisions();

    glClearColor(0.32f, 0.5f, 0.58f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    projection = glm::mat4();
    view = glm::mat4();
    // view/projection transformations
    projection = glm::perspective(glm::radians(Options::fov), (float)Options::width / (float)Options::height, 0.1f, 100.0f);
    view = scene->mainCamera.GetViewMatrix();

    lampShader.use();
    lampShader.setMat4("projection", projection);
    lampShader.setMat4("view", view);
    lampShader.setInt("setting", Options::settings);
    glm::mat4 model;
    for (unsigned int i = 0; i < lights.size(); i++)
    {
        model = glm::mat4();
        model = glm::translate(model, lights[i].position);
        model = glm::scale(model, glm::vec3(0.125f));
        lampShader.setMat4("model", model);
        lampShader.setVec3("lightColor", lights[i].colour);
        Scene::renderCube();
    }


    if (Options::showColliders) {
        colliders.use();
        colliders.setMat4("projection", projection);
        colliders.setMat4("view", view);
        scene->RenderColliders(colliders);
    }

}

我查看了很多页面,并完成了所有建议:

  • 调用 glEnable(GL_DEPTH_TEST)
  • 清除深度缓冲区
  • 确保 zNear 不是一个小数字
  • 不调用会禁用深度的函数,如 glDepthMask(GL_FALSE)

欢迎提供任何帮助。我希望这是足够的代码,如果不是,我会提供任何请求的代码。大多数未显示的功能都是不言自明的。另外,如果您认为上面的所有代码都很好,请在 cmets 中告诉我,以便我知道问题不存在。

我显然也在使用 c++ 和 glew。我也在为我的窗口使用 SFML。 感谢您的任何回答

编辑: 负责创建sfml窗口的代码:

Program::Program()
    :settings(24, 8, 4, 3, 0),
    window(sf::VideoMode(Options::width, Options::height), "OpenGL", sf::Style::Default, settings)
{
    Init();
}

灯光的顶点着色器:

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoords;

out vec3 Normal;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

void main()
{
    Normal = transpose(inverse(mat3(model))) * aNormal;
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

窗口和设置声明

sf::RenderWindow window;
sf::ContextSettings settings;

【问题讨论】:

  • 请显示创建窗口的代码。也许还有顶点着色器。
  • @Angew 我刚刚添加了!
  • 请同时显示类Program 声明数据成员windowsettings 的部分。特别是,它们的顺序是什么?彼此?
  • @Angew 完成。写在类的头文件中。

标签: c++ opengl rendering depth-buffer


【解决方案1】:

问题在于,在 C++ 中,类的成员是按照它们的声明顺序初始化的,而不是按照它们在任何构造函数的 mem-initialiser 列表中列出的顺序。

如果您在编译器中打开了足够多的警告,它应该会警告您,在您展示的Program 构造函数中,settings 将在window 之后初始化。这正是您的问题,因为settings 在获得您为其指定的值之前已被使用。交换类中成员的顺序来解决它。


该规则的原因是 C++ 的基本规则是“具有自动存储持续时间的对象总是以与它们的构造完全相反的顺序被销毁”。因此,无论使用哪个构造函数创建对象,类的析构函数都需要一个销毁成员的顺序。因此,该顺序被固定为声明的顺序。注意,声明的顺序也用于控制其他上下文中的创建/销毁顺序(例如函数局部变量),所以在这里使用它是一致的。

【讨论】:

  • 你是神。现在我又把我所有的旧代码都放进去了,一切都恢复正常了!我很高兴我求助于这个论坛,否则我永远不会自己解决问题。
  • @CowNecromancer 好吧,使用调试器检查settings,因为它被传递到window 构造函数中,这可能已经让你失望了。启用尽可能多的警告也是一个好主意,并保持您的代码无警告(理想情况下启用警告作为错误)。仅当您发现某些警告无用(每个编译器都有一些警告)时,才明确禁用它们。
  • 好建议,主要是我关闭警告,因为它们会给出诸如“从'float'转换为'double'之类的错误。可能丢失数据。”和类似的东西。忽略转换错误是不是很糟糕?
  • @CowNecromancer floatdouble 不能丢失数据。 doublefloat 可以,而且通常应该避免。如果是文字,请附加f。如果它是用于值,并且您确实需要转换,请添加static_cast。但请记住,每次此类转换都有(一些)运行时间成本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-18
  • 2019-08-30
  • 2012-03-09
  • 2022-10-22
  • 2020-12-29
相关资源
最近更新 更多