openGL API glDepthFunc详解


文章目录

官方说明

​官方文档解释​

Name
glDepthFunc — specify the value used for depth buffer comparisons

C Specification
void glDepthFunc( GLenum func);

Parameters
func
Specifies the depth comparison function. Symbolic constants GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, and GL_ALWAYS are accepted. The initial value is GL_LESS.

Description
glDepthFunc specifies the function used to compare each incoming pixel depth value with the depth value present in the depth buffer. The comparison is performed only if depth testing is enabled. (See glEnable and glDisable of GL_DEPTH_TEST.)

func specifies the conditions under which the pixel will be drawn. The comparison functions are as follows:

GL_NEVER
Never passes.

GL_LESS
Passes if the incoming depth value is less than the stored depth value.

GL_EQUAL
Passes if the incoming depth value is equal to the stored depth value.

GL_LEQUAL
Passes if the incoming depth value is less than or equal to the stored depth value.

GL_GREATER
Passes if the incoming depth value is greater than the stored depth value.

GL_NOTEQUAL
Passes if the incoming depth value is not equal to the stored depth value.

GL_GEQUAL
Passes if the incoming depth value is greater than or equal to the stored depth value.

GL_ALWAYS
Always passes.

The initial value of func is GL_LESS. Initially, depth testing is disabled. If depth testing is disabled or if no depth buffer exists, it is as if the depth test always passes.

Notes
Even if the depth buffer exists and the depth mask is non-zero, the depth buffer is not updated if the depth test is disabled. In order to unconditionally write to the depth buffer, the depth test should be enabled and set to GL_ALWAYS.

Errors
GL_INVALID_ENUM is generated if func is not an accepted value.

Associated Gets
glGet with argument GL_DEPTH_FUNC

glIsEnabled with argument GL_DEPTH_TEST

Version Support
OpenGL Version
Function / Feature Name 2.0 2.1 3.0 3.1 3.2 3.3 4.0 4.1 4.2 4.3 4.4 4.5
glDepthFunc ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔
See Also
glDepthRange, glEnable, glPolygonOffset

Copyright
Copyright © 1991-2006 Silicon Graphics, Inc. Copyright © 2010-2014 Khronos Group. This document is licensed under the SGI Free Software B License. For details, see https://khronos.org/registry/OpenGL-Refpages/LICENSES/LicenseRef-FreeB.txt.

翻译

glDepthFunc

函数名:

glDepthFunc——指定用于深度缓冲比较值;

函数原型:

void glDepthFunc (int func)

参数说明:

func指定深度比较函数。

描述:

func值

openGL API glDepthFunc详解_glfw

例子

主程序main.cpp

#include "glew/glew.h"
#include "glfw/glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "Utils.h"
#include <string>
#include <iostream>
#include <fstream>

using namespace std;

Utils utils = Utils();
double cameraX = 0.0f, cameraY = 0.0f, cameraZ = 0.0f;
double cubeX = 0.0f, cubeY = 0.0f, cubeZ = 0.0f;
GLuint renderingProgram = 0;

// variable allocation for display
GLuint mvLoc = 0, projLoc = 0;
int width = 0, height = 0;
float aspect = 0.0;
glm::mat4 pMat(1.0), vMat(1.0), mMat(1.0), mvMat(1.0), tMat(1.0), rMat(1.0);

static const int Screen_Width = 1920;
static const int Screen_Height = 1080;
static const int NumberVAOs = 1;
static const int numberVBOs = 2;
GLuint vao[NumberVAOs] = { 0 };
GLuint vbo[numberVBOs] = { 0 };

void setupVertices(void)
{
float vertexPositions[108] = {
-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f
};

//生成顶点数组对象
glGenVertexArrays(NumberVAOs, vao);
//激活顶点数组对象
glBindVertexArray(vao[0]);
//生成顶点缓冲区对象
glGenBuffers(numberVBOs, vbo);
//激活顶点缓冲区对象
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
//把顶点数据vertexPositions拷贝到顶点缓冲区
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
}


void init(GLFWwindow* window)
{
renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");

glfwGetFramebufferSize(window, &width, &height);
aspect = (float)width / (float)height;

//必须要创建透视投影矩阵计算公式,否则第一帧渲染时,立方体不在视口中 :1.0472 radians = 60 degrees
pMat = glm::perspective(glm::radians(45.f), aspect, 0.01f, 1000.f);

cameraX = 0.f;
cameraY = 0.f;
cameraZ = 8.f;

cubeX = 0.f;
cubeY = -2.f;
cubeZ = 0.f;

setupVertices();

}

void display(GLFWwindow* window, double currentTime)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.f, 0.7f, 1.f, 1.f);

//启动着色器程序,在GPU上安装GLSL代码,这不会运行着色器程序,
glUseProgram(renderingProgram);

/*Utils::printProgramLog(renderingProgram);*/ //printProgramLog()是私有函数
//获取uniform变量在着色器程序中的位置序号,通过该序号可以设置一致变量的值,如果没有该变量则返回-1
mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");

glfwGetFramebufferSize(window, &width, &height);
aspect = (float)width / (float)height;
//glm::perspective使用模板定义,所以函数各个参数类型要一致
glm::perspective(glm::radians(45.f), aspect, 0.01f, 1000.f);

//相机平移矩阵
//vMat = glm::translate(vMat, glm::vec3(-cameraX, -cameraY, -cameraZ));
vMat = glm::translate(glm::mat4(1.f), glm::vec3(-cameraX, -cameraY, -cameraZ));
//给模型使用的平移矩阵
tMat = glm::translate(glm::mat4(1.f), glm::vec3(glm::sin(0.35f * currentTime) * 2.f, glm::cos(0.52f * currentTime) * 2.f, glm::cos(0.7f * currentTime) * 2.f));
//给模型使用的旋转矩阵:currentTime控制旋转速度
//rMat = glm::rotate(glm::mat4(1.f), 1.75f * (float)(currentTime*0.5), glm::vec3(0.f, 1.f, 0.f));
rMat = glm::rotate(glm::mat4(1.f), 1.75f * (float)(currentTime), glm::vec3(0.f, 1.f, 0.f));
rMat = glm::rotate(rMat, 1.75f * (float)(currentTime), glm::vec3(1.f, 0.f, 0.f));
rMat = glm::rotate(rMat, 1.75f * (float)(currentTime), glm::vec3(0.f, 0.f, 1.f));

mMat = tMat * rMat;
mvMat = mMat * vMat;

//更改一个uniform矩阵变量或数组的值。要更改的uniform变量的位置由location指定,location的值应该由glGetUniformLocation函数返回
// 将透视矩阵和MV 矩阵复制给相应的统一变量
glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));

//激活顶点缓冲区,目前只用了第一个顶点缓冲区,第二个vbo[1]顶点缓冲区暂时没用
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);

//指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置
/*Parameters
index
指定要修改的顶点属性的索引值

size
指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(梦维:如position是由3个(x, y, z)组成,而颜色是4个(r, g, b, a))

type
指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。

normalized
指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。

stride
指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。

pointer
指定一个指针,指向数组中第一个顶点属性的第一个组件。初始值为0。
*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

//开启深度测试
glEnable(GL_DEPTH_TEST);
//指定用于深度缓冲比较值;
glDepthFunc(GL_LEQUAL);

glDrawArrays(GL_TRIANGLES, 0, 36);
}

void windows_size_callback(GLFWwindow* window, int newWidth, int newHeight)
{
aspect = (float)newWidth / (float)newHeight;
glViewport(0, 0, newWidth, newHeight);
pMat = glm::perspective(glm::radians(45.f), aspect, 0.001f, 1000.f);
}


int main(int argc, char** argv)
{
int glfwState = glfwInit();
if (GLFW_FALSE == glfwState)
{
cout << "GLFW initialize failed, Invoke glfwInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}

/*因为我们要使用OpenGL 4.6,所以我们把GLFW_CONTEXT_VERSION_MAJOR和GLFW_CONTEXT_VERSION_MINOR对应的hint都设置为4和6。
因为我们要使用OpenGL核心模式(这个后面会提到更多),所以我们把GLFW_OPENGL_PROFILE对应的hint设置为GLFW_OPENGL_CORE_PROFILE,
表示使用OpenGL核心模式。最后,把GLFW_RESIZABLE对应的hint设置为GLFW_FALSE,表示窗口不允许用户调整大小。
之所以这样做是因为如果允许用户调整大小,大小发生变化后,窗口的绘制区域默认不变(依然是原来窗口的区域),
也就是说窗口上绘制的图像的大小、位置不会发生改变。为了避免这种现象发生,我们就简单地不让用户调整窗口大小
(当然也有更好的方法,就是用GLFW设置一个窗口大小的回调函数,但这样比较简单)。*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

GLFWwindow* window = glfwCreateWindow(Screen_Width, Screen_Height, "Draw rotate color cube", nullptr, nullptr);
if (!window)
{
cout << "GLFW create window failed, Invoke glfwCreateWindow()......Error file:" << __FILE__ << ".....Error line:" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}

/*此函数使调用线程上的指定窗口的 OpenGL 或 OpenGL ES 上下文成为当前上下文。
一次只能在单个线程上使上下文成为当前上下文,并且每个线程一次只能有一个当前上下文。
在线程之间移动上下文时,必须先使其在旧线程上变为非当前状态,然后再在新线程上变为当前状态。
*/
glfwMakeContextCurrent(window);

int glewState = glewInit();
if (GLEW_OK != glewState)
{
cout << "GLEW initialize failed, Invoke glewInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << std::endl;
exit(EXIT_FAILURE);
}

/*此函数设置当前 OpenGL 或 OpenGL ES 上下文的交换间隔,即从调用glfwSwapBuffers开始等待的屏幕更新次数,
然后再交换缓冲区并返回。这有时称为垂直同步、垂直回扫同步或仅vsync。
支持WGL_EXT_swap_control_tear和GLX_EXT_swap_control_tear扩展的上下文也接受负交换间隔,这允许驱动程序立即交换,
即使帧到达有点晚。您可以使用glfwExtensionSupported检查这些扩展。
上下文必须在调用线程上是最新的。在没有当前上下文的情况下调用此函数将导致GLFW_NO_CURRENT_CONTEXT错误。
此功能不适用于 Vulkan。如果您使用 Vulkan 进行渲染,请改为查看交换链的当前模式。
*/
glfwSwapInterval(1);

glfwSetWindowSizeCallback(window, windows_size_callback);

init(window);

while (!glfwWindowShouldClose(window))
{
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}

glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);

return 0;
}

顶点着色器 vertShader.glsl

#version 430 core

layout(location = 0) in vec3 aPosition;

uniform mat4 mMat;
uniform mat4 vMat;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

out vec4 varyingColor;

void main()
{
gl_Position = proj_matrix * mv_matrix * vec4(aPosition, 1.f);
varyingColor = vec4(aPosition, 1.f) * 0.5f + vec4(0.5f, 0.5f, 0.5f, 0.5f);
}

片元着色器 fragShader.glsl

#version 430 core

in vec4 varyingColor;

out vec4 color;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

void main()
{
color = varyingColor;
}

运行效果

openGL API glDepthFunc详解_#include_02

源码下载

​工程完整源码下载​