OpenGL 深度测试

487 阅读1分钟

前言

在上一篇OpenGL 绘制伞面基础上修改main.cpp文件,完成此demo

概念

深度

深度是指该像素点和视角的距离,也就是z值。

深度缓冲区

深度缓冲区是存储像素点深度值的一块内存区域,z值越大距离视角越远。

深度测试

深度测试是指在绘图时,⾸先将表面对应的像素的深度值与当前深度缓冲区中的值进行比较. 如果大于深度缓冲区中的值,则丢弃这部分.否则利⽤这个像素对应的深度值和颜⾊值.分别更新深度缓冲区和颜⾊缓存区。

如果不开启深度测试则有可能出现距离较远的元素后绘制,则会遮挡前面的元素。

使用方式

开启深度测试

glEnable(GL_DEPTH_TEST);

关闭深度测试

glDisable(GL_DEPTH_TEST);

案例

修改OpenGL 绘制伞面项目的main.cpp文件,如下:

#include "GLTools.h"
#include "GLMatrixStack.h"
#include "GLFrame.h"
#include "GLFrustum.h"
#include <math.h>
#include <GLUT/GLUT.h>

GLShaderManager shaderManager;
GLTriangleBatch cylinderBatch;

GLFrame viewFrame;
GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLFrustum viewFrustum;

void setupRC() {
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
    shaderManager.InitializeStockShaders();
    viewFrame.MoveForward(10.0f);
    gltMakeCylinder(cylinderBatch, 0.3f, 0.8f, 0.8f, 100, 1);
}

void changeSize(int w, int h) {
    glViewport(0, 0, w, h);

    viewFrustum.SetPerspective(20.0f, float(w) / float(h), 5.0f, 20.0f);
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
}

void specialKeys(int key, int x, int y) {
    if (key == GLUT_KEY_UP) {
        viewFrame.RotateWorld(m3dDegToRad(-4.0), 1.0f, 0.0f, 0.0f);
    }
    if (key == GLUT_KEY_DOWN) {
        viewFrame.RotateWorld(m3dDegToRad(4.0), 1.0f, 0.0f, 0.0f);
    }
    if (key == GLUT_KEY_RIGHT) {
        viewFrame.RotateWorld(m3dDegToRad(4.0), 0.0f, 1.0f, 0.0f);
    }
    if (key == GLUT_KEY_LEFT) {
        viewFrame.RotateWorld(m3dDegToRad(-4.0), 0.0f, 1.0f, 0.0f);
    }
    glutPostRedisplay();
}

void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    modelViewMatrix.PushMatrix(viewFrame);
    GLfloat vOrange[] = {1.0f,0.6f,0.0f,1.0f};
    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT,modelViewMatrix.GetMatrix(), projectionMatrix.GetMatrix(),vOrange);
    cylinderBatch.Draw();
    modelViewMatrix.PopMatrix();
    glDisable(GL_DEPTH_TEST);
    glutSwapBuffers();
}

int main(int argc, char* argv[]) {
    
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(800, 600);
    glutCreateWindow("dowZhang");
    glutReshapeFunc(changeSize);
    glutSpecialFunc(specialKeys);
    glutDisplayFunc(renderScene);
    
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        return 1;
    }
    
    setupRC();
    
    glutMainLoop();
    return 0;
}

不开启深度测试:

开启深度测试后: