LearnOpenGL学习笔记——深度测试

计算机图形学笔记(七) 5.1何为“帧”缓冲区(Frame buffer)? 图形流水线 帧缓冲区(Frame buffer)与片元处理 1、缓冲区的每个单元对应的就是屏幕上一个个像素 2、对片元的处理就是在利用并修改缓冲区的数据 显示器的分类 光栅扫描显示器---Raster-Scan Display 随机扫描显示器(向量显示器)---Random-Scan Display(Vector Displays) .. 阅读详情

什么是深度测试

我们在绘制物体的时候,物体之间是有遮挡关系的。比如下图,箱子遮挡住地面。遮挡关系是由深度确定的。从视觉上来讲,可以简单的理解为从摄像机(眼睛)看过去,距离摄像机(眼睛距离越近),深度值越小,越不会被遮挡。如下图:
在这里插入图片描述
OpenGL中,默认是禁用深度测试的,也就是说,OpengGL在绘制物体时候,并不关心哪个物体遮挡哪个物体。后绘制的物体总是遮挡前面的。如果不做深度测试,那我们上图的地面和箱子就变成了下图:
在这里插入图片描述

现在大部分的GPU都提供一个叫做提前深度测试(Early Depth Testing)的硬件特性。提前深度测试允许深度测试在片段着色器之前运行。只要我们清楚一个片段永远不会是可见的(它在其他物体之后),我们就能提前丢弃这个片段。 片段着色器通常开销都是很大的,所以我们应该尽可能避免运行它们。当使用提前深度测试时,片段着色器的一个限制是你不能写入片段的深度值。如果一个片段着色器对它的深度值进行了写入,提前深度测试是不可能的。OpenGL不能提前知道深度值。

深度测试函数

//深度测试默认是禁用的,所以如果要启用深度测试的话,我们需要用GL_DEPTH_TEST选项来启用它:
glEnable(GL_DEPTH_TEST);
//当它启用的时候,如果一个片段通过了深度测试的话,OpenGL会在深度缓冲中储存该片段的z值;如果没有通过深度缓冲,则会丢弃该片段
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//你启用了深度缓冲,你还应该在每个渲染迭代之前使用GL_DEPTH_BUFFER_BIT来清除深度缓冲,否则你会仍在使用上一次渲染迭代中的写入的深度值
//可以想象,在某些情况下你会需要对所有片段都执行深度测试并丢弃相应的片段,但不希望更新深度缓冲。基本上来说,你在使用一个只读的(Read-only)深度缓冲。OpenGL允许我们禁用深度缓冲的写入,只需要设置它的深度掩码(Depth Mask)设置为GL_FALSE就可以了:
glDepthMask(GL_FALSE);

OpenGL允许我们修改深度测试中使用的比较运算符。

glDepthFunc(GL_LESS);

函数 描述
GL_ALWAYS 永远通过深度测试
GL_NEVER 永远不通过深度测试
GL_LESS 在片段深度值小于缓冲的深度值时通过测试
GL_EQUAL 在片段深度值等于缓冲区的深度值时通过测试
GL_LEQUAL 在片段深度值小于等于缓冲区的深度值时通过测试
GL_GREATER 在片段深度值大于缓冲区的深度值时通过测试
GL_NOTEQUAL 在片段深度值不等于缓冲区的深度值时通过测试
GL_GEQUAL 在片段深度值大于等于缓冲区的深度值时通过测试

深度值精度

深度缓冲包含了一个介于0.0和1.0之间的深度值,它将会与观察者视角所看见的场景中所有物体的z进行比较。观察空间的z值可能是投影平截头体的近平面和元平面之间的任何值。我们需要一种方式将这些观察空间的z值变换到[0, 1]范围之间,其中的一种方式就是将它们连线变换到[0, 1]范围之间。下面这个(线性)方程将z值变换到了0.0和1.0之间的深度值:
在这里插入图片描述
在这里插入图片描述
然而,在实践中是几乎永远不会使用这样的线性深度缓冲(Linear Depth Buffer)的。要想有正确的投影性质,需要使用一个非线性的深度方程,它是与 1/z 成正比的。它做的就是在z值很小的时候提供非常高的精度,而在z值很远的时候提供更少的精度。花时间想想这个:我们真的需要对1000单位远的深度值和只有1单位远的充满细节的物体使用相同的精度吗?线性方程并不会考虑这一点。
由于非线性方程与 1/z 成正比,在1.0和2.0之间的z值将会变换至1.0到0.5之间的深度值,这就是一个float提供给我们的一半精度了,这在z值很小的情况下提供了非常大的精度。在50.0和100.0之间的z值将会只占2%的float精度,这正是我们所需要的。这样的一个考虑了远近距离的方程是这样的:
在这里插入图片描述
在这里插入图片描述
深度值很大一部分是由很小的z值所决定的,这给了近处的物体很大的深度精度。这个(从观察者的视角)变换z值的方程是嵌入在投影矩阵中的,所以当我们想将一个顶点坐标从观察空间至裁剪空间的时候这个非线性方程就被应用了。
推介阅读:http://www.songho.ca/opengl/gl_projectionmatrix.html

深度缓冲的可视化

// 修改fragment着色器,返回z值,也就是深度值
void main()
{
    FragColor = vec4(vec3(gl_FragCoord.z), 1.0);
}

结果,几乎全是白色,说明z值全部接近1.看起来就想我们所有的深度值都是最大的1.0。所以为什么没有靠近0.0(即变暗)的深度值呢?
在这里插入图片描述
屏幕空间中的深度值是非线性的,即它在z值很小的时候有很高的精度,而z值很大的时候有较低的精度。片段的深度值会随着距离迅速增加,所以几乎所有的顶点的深度值都是接近于1.0的。如果我们小心地靠近物体,你可能会最终注意到颜色会渐渐变暗,显示它们的z值在逐渐变小:
在这里插入图片描述
这很清楚地展示了深度值的非线性性质。近处的物体比起远处的物体对深度值有着更大的影响。只需要移动几厘米就能让颜色从暗完全变白。
然而,我们也可以让片段非线性的深度值变换为线性的。要实现这个,我们需要仅仅反转深度值的投影变换。这也就意味着我们需要首先将深度值从[0, 1]范围重新变换到[-1, 1]范围的标准化设备坐标(裁剪空间)。接下来我们需要像投影矩阵那样反转这个非线性方程(方程2),并将这个反转的方程应用到最终的深度值上。最终的结果就是一个线性的深度值了。听起来是可行的,对吧?
首先我们将深度值变换为NDC,不是非常困难:

float z = depth * 2.0 - 1.0;

接下来使用获取到的z值,应用逆变换来获取线性的深度值:

float linearDepth = (2.0 * near * far) / (far + near - z * (far - near));

完整的着色器代码:

#version 330 core
out vec4 FragColor;
float near = 0.1; 
float far  = 100.0; 
float LinearizeDepth(float depth) 
{
    float z = depth * 2.0 - 1.0; // back to NDC 
    return (2.0 * near * far) / (far + near - z * (far - near));    
}
void main()
{             
    float depth = LinearizeDepth(gl_FragCoord.z) / far; // 为了演示除以far
    FragColor = vec4(vec3(depth), 1.0);
}

由于线性化的深度值处于near与far之间,它的大部分值都会大于1.0并显示为完全的白色。通过在main函数中将线性深度值除以far,我们近似地将线性深度值转化到[0, 1]的范围之间。这样子我们就能逐渐看到一个片段越接近投影平截头体的远平面,它就会变得越亮,更适用于展示目的。

如果我们现在运行程序,我们就能看见深度值随着距离增大是线性的了。尝试在场景中移动,看看深度值是怎样以线性变化的。

在这里插入图片描述
颜色大部分都是黑色,因为深度值的范围是0.1的近平面到100的远平面,它离我们还是非常远的。结果就是,我们相对靠近近平面,所以会得到更低的(更暗的)深度值。

深度冲突

一个很常见的视觉错误会在两个平面或者三角形非常紧密地平行排列在一起时会发生,深度缓冲没有足够的精度来决定两个形状哪个在前面。结果就是这两个形状不断地在切换前后顺序,这会导致很奇怪的花纹。这个现象叫做深度冲突(Z-fighting),因为它看起来像是这两个形状在争夺(Fight)谁该处于顶端。

防止深度冲突

  • 永远不要把多个物体摆得太靠近,以至于它们的一些三角形会重叠
  • 尽可能将近平面设置远一些
  • 使用更高精度的深度缓冲(大部分深度缓冲的精度都是24位的,但现在大部分的显卡都支持32位的深度缓冲,这将会极大地提高精度)

参考:
https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/01%20Depth%20testing/#_1

[openGL] 高级openGL实现 -深度测试 线性深度缓冲这个公式需要一个Z值来计算他的深度值,比如当我们设置near为1,far为50时对应的关系就应该如下图所示:2.1非线性深度缓冲重要的是要记住这种方式的深度缓冲中的值在屏幕空间中不是线性的​编辑深度值很大一部分是由很小的z值所决定的,这给了近处的物体很大的深度精度。这个(从观察者的视角)变换z值的方程是嵌入在投影矩阵中的,所以当我们想将一个顶点坐标从观察空间至裁剪空间的时候这个非线性方程就被应用了三 阅读详情

相关推荐

OpenGL深度测试

OpenGL深度测试1. 深度缓冲(Depth Buffer)2. 深度缓冲实现3. 深度测试函数测试对比4. 深度冲突(Z-fighting) 1. 深度缓冲(Depth Buffer) 深度缓冲是由窗口系统自动创建的,它会以16、24或32位float的形式储存它的深度值。在大部分的系统中,深度缓冲的精度都是24位的。 当深度测试(Depth Testing)被启用的时候,OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测试,如果这个测试通过了的话,深度缓冲将会更新为

牵LV小猪精的博客 2266

【OpenGL】笔记十九、深度测试

1. 流程 在前面的教程中,我们有简略介绍过深度测试,它的存在帮助我们最终渲染的画面不会存在那些本应被遮挡住了的图像,其实若深究其中的原理的话,倒也没多复杂,就是每次渲染一个图形时测测当前这个要渲染的像素是否是目前离屏幕最近的,若是,就说明没有被其他物体遮挡,就可以把它的颜色映射到屏幕上,而这个距离就是由depth_buffer所存储,每次渲染一个新图形的时候我们就去比较和更新这个buffer。 1.1 深度测试 一般情况下,深度测试默认是禁用的,所以如果要启用深度测试的话,我们需要用GL_DEPTH_T

ycrsw的博客 1507

【LearnOpenGL学习笔记】——15.模板测试

文章目录1.概念2.模板函数3.模板轮廓 1.概念 (1)模板值(8位):每个像素/片段上的一个属性 (2)模板缓冲:存储模板值 (3)模板测试:对模板值进行比较 (4)模板写入:在比较后修改模板值 2.模板函数 (1)glEnable(GL_STENCIL_TEST):开启模板测试 (2)glStencilFunc(GL_NOTEQUAL, 1, 0xFF):模板测试函数,第一个为op,第二个为模板值,第三个为与的值 (3)glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)

qq_45974407的博客 388

LearnOpenGL学习笔记—高级OpenGL 01:深度测试

LearnOpenGL学习笔记—高级OpenGL:深度测试1 深度测试1.1 知识回顾1.2 代码实现 1 深度测试 1.1 知识回顾 本节对应官网学习内容:深度测试 我们之前其实已经在 坐标系统 这节开启了并使用了深度测试 并在games101的 光栅化 那一课也学习了Z缓冲的知识 我们接着做一点补充: 我们之前运用了深度缓冲(Depth Buffer)来防止被阻挡的面渲染到其它面的前面。 当深度测试(Depth Testing)被启用的时候,OpenGL会将一个片段的的深度值与深度缓冲的内容进行对比。

清清!的博客 2503

learnOpenGL 4.1 深度测试

深度测试函数 OpenGL允许我们修改深度测试中使用的比较运算符。我们可以调用glDepthFunc函数来设置比较运算符。默认情况下,我们使用LESS。 glDepthFunc(GL_LESS); GL_ALWAYS 永远通过深度测试 GL_NEVER 永远不通过深度测试 GL_LESS 在片段深度值小于缓冲的深度值时通过测试 GL_EQUAL 在片段深度值等于缓冲区的深度值时通过测试 GL_LEQUAL 在片段深度值小于等于缓冲区的深度值时通过测试 GL_GREATER 在片段深度值大于缓冲

qq_43533956的博客 386

OpenGL 深度测试

深度缓冲就像颜色缓冲(Color Buffer)(储存所有的片段颜色:视觉输出)一样,在每个片段中储存了信息,并且(通常)和颜色缓冲有着一样的宽度和高度。深度缓冲是由窗口系统自动创建的,它会以16、24或32位float的形式储存它的深度值。在大部分的系统中,深度缓冲的精度都是24位的。当深度测试(Depth Testing)被启用的时候,OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测试,如果这个测试通过了的话,深度缓冲将会更新为新的深度值。

希望能帮助大家,希望大家多多支持,你们的支持是我前进的动力。 1173

【OpenGL】LearnOpenGL学习笔记13 - 深度测试、模板测试

LearnOpenGL学习笔记 - 模板测试、深度测试

Duo1J的随笔 1104

Verilator+VSCode实战:5分钟搞定Verilog语法检查与波形调试

本文详细介绍了如何将Verilator仿真器与VSCode编辑器高效集成,打造极速的Verilog开发工作流。通过环境配置、实时语法检查、一键仿真与波形生成等实战技巧,帮助IC设计工程师在几分钟内完成从代码编写到波形调试的全过程,大幅提升中小规模模块的验证效率。

weixin_28454475的博客 469

【LearnOpenGL学习笔记】——14.深度测试

LearnOpenGL学习笔记:深度测试

whl0071的专栏 774

企业数字化转型的 4A 架构指南:从概念解读到 TOGAF 阶段对应

4A企业架构是中国数字化转型实践中总结的简化框架,包含业务、应用、数据和技术四个架构层。它自上而下形成业务驱动应用的指导关系,自下而上构建技术支撑数据的实现路径,与国际标准TOGAF核心内容高度对应。该模型通过统一语言、战略对齐和系统梳理,有效连接业务需求与IT实施,已成为企业架构规划的实用工具。其分层结构清晰展示了从业务目标到技术落地的完整推导链,特别适合中国企业的数字化转型场景。

友莘居士的博客 2175

模板匹配加速之金字塔分层搜索

图像金字塔是一种多分辨率图像表示方法,它通过一系列逐渐缩小或放大的图像来表示原始图像的不同尺度。高斯金字塔(Gaussian Pyramid):通过不断下采样(降采样)生成更小的图像。拉普拉斯金字塔(Laplacian Pyramid):通过高斯金字塔和差分操作生成一组残差图像。在模板匹配中,我们主要使用高斯金字塔来实现多尺度匹配。金字塔灰度模板匹配通过多尺度搜索策略,在保持较高准确率的同时显著提升匹配速度,尤其适用于:高分辨率图像处理实时检测系统移动端设备等资源受限场景。

weixin_44969144的博客 1732

【learnOpenGL学习笔记_16】OpenGL高级教程 - 深度测试

前面我们在刚开始学习绘制立方体时,使用过深度测试,以防止被其他面遮挡的面渲染到前面。今天这篇文章,让我们一起来深入探讨深度缓冲系统的原理与配置方法。

同学小张的博客 1193

C/C++_五大常规算法_分治算法

分治法 一个装有 16 枚硬币的袋子,16 枚硬币中有一个是伪造的,伪造的硬币和普通硬币从表面上看不出有任何差别,但是那 个伪造的硬币比真的硬币要轻。现有给你一台天平,请你在尽可能最短的时间内找出那枚伪造的硬币。 常规思维: 每次从待比较的硬币中取两枚进行计较,如果天平平衡(相等)就继续取剩下的硬币进行比较 继续以上过程,直到找到硬币。 强者思维: 我们先将 16 枚硬币分为左右两个部分,各为 8 个硬币,分别称重,必然会有一半轻一半重,而我们要的就是轻的那组,重 的舍去。接下来我们继续对轻的进行五五分

weifc-wei 的博客 2725

【learnOpenGL学习笔记_16】OpenGL高级教程 - 深度测试_opengl教程

前面我们在刚开始学习绘制立方体时,使用过深度测试,以防止被其他面遮挡的面渲染到前面。今天这篇文章,让我们一起来深入探讨深度缓冲系统的原理与配置方法。

jennycisp的博客 1288

海洋科学—物理海洋学 第五章 海洋环流

本章是基于《海洋科学导论》,但里面涉及到的重要的公式推导是专门拎出来推的,主要借鉴董昌明老师的《物理海洋学导论》,其中有一些多出来的推导,会在更新完整个物理海洋学之后重新拿出来一一讲解,最后开一个番外篇

qq_58518586的博客 1万+

论文研读 Corundum: An Open-Source 100-Gbps NIC

Corundum 通过在 FPGA 上构建并行 pipeline、高效 DMA 通道、无阻塞队列结构、低延迟调度器,实现了在 PCIe Gen3 x16 接口上稳定跑满 100Gbps 吞吐量。

Double Galaxy 489

LearnOpenGL学习(高级OpenGL -- 深度测试,模板测试,环绕顺序)

用来防止被阻挡的面渲染到其他面的前面,深度缓冲就像颜色缓冲,在每个片段中储存了信息,当深度测试(Depth Testing)被启用的时候,OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测试,如果这个测试通过了的话,深度缓冲将会更新为新的深度值。如果深度测试失败了,片段将会被丢弃。深度缓冲运行在是GLSL内建变量,它是一个vec3,x和y分量代表了片段的屏幕坐标(左下角为原点),z分量为片段的深度值。

zaizai1007的博客 1200

CGAL 网格等高线计算

CGAL 网格等高线计算

dayuhaitang1的博客 452

LearnOpenGL-深度测试与模板测试

它会与将要写入缓冲的模板值进行与(AND)运算。默认情况下设置的位掩码0xFF所有位都为1,不影响输出,但如果我们将它设置为0x00,写入缓冲的所有模板值最后都会变成0.这与深度测试中的glDepthMask(GL_FALSE)是等价的。深度缓冲包含了一个介于0.0和1.0之间的深度值,观察空间的z值可能是投影平截头体的近平面(Near)和远平面(Far)之间的任何值。深度缓冲像颜色缓冲一样,在每个片段中存储了信息,并且有一样的宽度高度,都是由窗口自动创建的,在大部分系统中,深度缓冲的精度都是24位。

weixin_70073176的博客 1247

Skills入门学习路线

简单来说,Skills就像是给Claude准备的”插件包"或”工具箱”。它是一个集合,里面装了特定的操作指令(Instructions)、可执行脚本(Scripts)和相关素材(Resources)。2025 年 10 月中旬,Anthropic 正式发布 Claude Skills。两个月后,Agent Skills 作为开放标准被进一步发布,意在引导一个新的 AI Agent 开发生态。OpenAI、Github、VS Code、Cursor 均已跟进。为了更好的理解,你可以把。

十二测试录 1098

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

LearnOpenGL(十五)之深度测试

LearnOpenGL(十三)之深度测试

ckg3824278的博客 985

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

learnOpenGL-深度测试

提前深度测试:允许深度测试在片段着色器之前运行。使用提前深度测试时,片段着色器不可写入深度值,因为OpenGl不能提前知道深度值。深度测试:OpenGL将一个片段的深度值与深度缓冲的内容进行对比。执行一个深度测试,测试通过则深度缓冲将会更新为新的深度值。3.牺牲一些性能,使用更高精度的深度缓冲。片段着色器中内置变量gl_FragCoord的z值即为深度值。深度测试片段着色器及模版测试之后执行。

Mhypnos的博客 1213

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

LearnOpenGL12——深度测试

转载自 https://blog.youkuaiyun.com/qq_36696486/article/details/104378594 https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/01%20Depth%20testing/#_2 https://zhuanlan.zhihu.com/p/56739656 需要深度测试的原因 当我们渲染多个物体时,这多个物体之间存在互相遮挡的关系,被遮挡的物体的部分将不可见,也就是它离相机更远,为了告诉计算机被遮挡的

白小飞 500

(自用)learnOpenGL-高级OpenGL-深度测试

这一章提到了之前的深度函数,首先要开启深度测试,然后要在loop中及时清除深度通过开启深度测试,画面就会正常显示点与点的位置信息,里屏幕近的物体会覆盖远的物体。也就是z-buffer,用来确定一个片段是否在其他片段后方的。当深度测试(Depth Testing)被启用的时候,OpenGL会将一个片段的深度值与深度缓冲的内容进行对比。OpenGL会执行一个深度测试,如果这个测试通过了的话,深度缓冲将会更新为新的深度值。如果深度测试失败了,片段将会被丢弃。

SHIgaNatsuki的博客 519

learnopengl学习笔记——模板测试

片段着色器——模板测试——深度测试 和深度测试一样,模板测试(Stencil Test)也可能会舍弃片段。模板测试是根据模板缓冲来进行的。一个模板缓冲中,通常每个模板值是8位的。所以每个像素一共可以有256种不同的模板值。我们可以将这些模板值设置为我们想要的值,然后当某个片段有某个模板值的时候,我们选择舍弃或是保留这个片段。说白了模板缓冲可以自定义舍弃哪些片段、采用哪些片段。 一般的工作流如下: 启用模板缓冲的写入 渲染物体,更新模板缓冲内容 禁用模板缓冲写入 渲染物体,根据模板缓冲内容丢弃特点片段

kiss_the_rian的博客 235
上一篇: LearnOpenGL学习笔记——投光物
下一篇: LearnOpenGL学习笔记——模板测试
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值