启用 DEPTH_TEST 时 OpenGL 屏幕闪烁

Posted

技术标签:

【中文标题】启用 DEPTH_TEST 时 OpenGL 屏幕闪烁【英文标题】:OpenGL screen is flickering when enabling DEPTH_TEST 【发布时间】:2017-05-13 14:38:55 【问题描述】:

我的 OpenGL 应用程序有问题。当我没有启用 DEPTH_TEST 时,它可以正常绘制(除了错误的绘制顺序),但是如果我启用它,一切都会开始闪烁。 OpenGL 不会给出任何错误。我也没有忘记glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);。我对导致我的问题的原因一无所知。任何帮助,将不胜感激。

main.cpp

#include <iostream>

#include <SDL2\SDL.h>
#include <GL\glew.h>

#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>

#include <fstream>
#include <string>

#include "vertexdata.h"

#define WIDTH 800
#define HEIGHT 600

std::string filetobuf(const char*);

int main(int, char**) 

    // Init the window with an OpenGL context
    SDL_Window *window;
    SDL_Init(SDL_INIT_EVERYTHING);
    window = SDL_CreateWindow("SDL window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
    SDL_GLContext context = SDL_GL_CreateContext(window);
    glewInit();

    // Create the shaders
    std::string vertexsourceString = filetobuf("tutorial2.vert");
    std::string fragmentsourceString = filetobuf("tutorial2.frag");
    const char* vertexsource = vertexsourceString.c_str();
    const char* fragmentsource = fragmentsourceString.c_str();
    GLuint vertexshader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0);
    glCompileShader(vertexshader);
    GLuint fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0);
    glCompileShader(fragmentshader);
    GLuint shaderprogram = glCreateProgram();
    glAttachShader(shaderprogram, vertexshader);
    glAttachShader(shaderprogram, fragmentshader);
    glBindAttribLocation(shaderprogram, 0, "in_Position");
    glBindAttribLocation(shaderprogram, 1, "in_Color");
    glLinkProgram(shaderprogram);
    glUseProgram(shaderprogram);

    // Setup rectangles
    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    GLuint vbo[3];
    glGenBuffers(3, vbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_SIZE, indices, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
    glBufferData(GL_ARRAY_BUFFER, COLOR_BUFFER_SIZE, colors, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(1);

    GLint projectionMatrixLocation = glGetUniformLocation(shaderprogram, "projectionMatrix");
    glm::mat4 projectionMatrix = glm::perspective(70.0f, (float)WIDTH / (float)HEIGHT, 0.0f, 100.0f);
    glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]);

    GLint modelMatrixLocation = glGetUniformLocation(shaderprogram, "modelMatrix");

    glClearColor(0, 0, 1, 1);

    glEnable(GL_DEPTH_TEST);

    bool running = true;
    while (running) 
        SDL_Event e;
        while (SDL_PollEvent(&e)) 
            if (e.type == SDL_QUIT) 
                running = false;
            
        

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glm::mat4 modelMatrix(1);
        modelMatrix = glm::translate(modelMatrix, glm::vec3(0, 0, -5));
        modelMatrix = glm::rotate(modelMatrix, SDL_GetTicks() / 500.0f, glm::vec3(0, 1, 0));
        glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]);

        glDrawElements(GL_TRIANGLES, INDICES_SIZE, GL_UNSIGNED_BYTE, 0);

        SDL_GL_SwapWindow(window);
    

    SDL_GL_DeleteContext(context);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;


std::string filetobuf(const char* path)

    if (path == nullptr) 
        std::cout << "No file specified!" << std::endl;
        return 0;
    

    std::ifstream file(path);
    if (!file.is_open()) 
        std::cout << "File not found! '" << path << "'" << std::endl;
        return 0;
    

    std::string source;
    std::string line;

    while (file.good()) 
        std::getline(file, line);
        source += line + "\n";
    
    file.close();

    return source;

顶点数据.h

#pragma once

#include <GL\GL.h>

#define INDICES_SIZE        12
#define COLOR_VECTOR_SIZE   3
#define VERTEX_VECTOR_SIZE  3
#define VERTEX_COUNT        8
#define COLOR_BUFFER_SIZE   COLOR_VECTOR_SIZE * VERTEX_COUNT * sizeof(GLfloat)
#define VERTEX_BUFFER_SIZE  VERTEX_VECTOR_SIZE * VERTEX_COUNT * sizeof(GLfloat)

static GLubyte indices[] = 
    0, 1, 2,
    2, 3, 0,

    4, 5, 6,
    6, 7, 4,
;

static GLfloat colors[] = 
    1, 0, 0,
    1, 0, 0,
    1, 0, 0,
    1, 0, 0,

    0, 1, 0,
    0, 1, 0,
    0, 1, 0,
    0, 1, 0,
;

static GLfloat vertices[] = 
    1,  1, 1,
    1, -1, 1,
    -1, -1, 1,
    -1,  1, 1,

    1,  1, -1,
    1, -1, -1,
    -1, -1, -1,
    -1,  1, -1,
;

注意:我从 main.cpp 文件中删除了错误检查以减小文件大小。

【问题讨论】:

【参考方案1】:

您不能将平面附近设置为零。换上一些合理的东西,比如0.1f

glm::mat4 projectionMatrix = glm::perspective(70.0f, (float)WIDTH / (float)HEIGHT, 0.1f, 100.0f);

【讨论】:

谢谢。做到了!

以上是关于启用 DEPTH_TEST 时 OpenGL 屏幕闪烁的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL - 启用调试 - 运行时 System.AccessViolationException

启用深度测试时的二维文本工件 Opengl

OpenGL ES 2.0 剪裁测试

OpenGL着色器程序在使用时导致屏幕变黑

OpenGL:绘制多边形时,如果第一个顶点在屏幕空间之外怎么办(三角扇)

OpenGL 中的 BMP 屏幕截图