天天看点

openGL API glDepthFunc详解

openGL API glDepthFunc详解

文章目录

  • ​​openGL API glDepthFunc详解​​
  • ​​官方说明​​
  • ​​翻译​​
  • ​​例子​​
  • ​​主程序main.cpp​​
  • ​​顶点着色器 vertShader.glsl​​
  • ​​片元着色器 fragShader.glsl​​
  • ​​运行效果​​
  • ​​源码下载​​

官方说明

​​官方文档解释​​

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详解

例子

主程序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;
}      

运行效果

源码下载