OpenGL-ES 学习(2)---- DepthTest

深度测试

OpenGL-ES 深度测试是指在片段着色器执行之后,利用深度缓冲区所保存的深度值决定当前片段是否被丢弃的过程

深度缓冲区通常和颜色缓冲区有着相同的宽度和高度,一般由窗口系统自动创建并将其深度值存储为 16、 24 或 32 位浮点数。(注意只保存深度值)

当深度测试开启的时候, OpenGL-ES 才会测试深度缓冲区中的深度值;如果此测试通过,深度缓冲内的值可以被设为新的深度值;如果深度测试失败,则丢弃该片段。

深度测试是在片段着色器运行之后(并且在模板测试运行之后)在屏幕空间 (screen space) 中执行的。

屏幕空间坐标相关的视区是由 OpenGL-ES 的视口设置函数 glViewport 函数给定,并且可以通过片段着色器中内置的 gl_FragCoord 变量访问。

gl_FragCoord 的 X 和 y 表示该片段的屏幕空间坐标 ((0,0) 在左下角),其取值范围由 glViewport 函数决定,屏幕空间坐标原点位于左下角。

gl_FragCoord 还包含一个 z 坐标,它包含了片段的实际深度值,此 z 坐标值是与深度缓冲区的内容进行比较的值。

深度缓冲区中包含深度值介于 0.0 和 1.0 之间,物体接近近平面的时候,深度值接近 0.0 ,物体接近远平面时,深度接近 1.0。

深度测试实现

开启深度测试后,如果片段通过深度测试,OpenGL-ES 自动在深度缓冲区存储片段的 gl_FragCoord.z 值,如果深度测试失败,那么相应地丢弃该片段。

如果启用深度测试,那么需要在渲染之前使用 **glClear(GL_DEPTH_BUFFER_BIT); **清除深度缓冲区,否则深度缓冲区将保留上一次进行深度测试时所写的深度值。

另外在一些场景中,我们需要进行深度测试并相应地丢弃片段,但我们不希望更新深度缓冲区,那么可以设置深度掩码**glDepthMask(GL_FALSE);**实现禁用深度缓冲区的写入(只有在深度测试开启时才有效)。

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

OpenGL-ES 深度测试是通过深度测试函数 glDepthFunc 控制深度测试是否通过和如何更新深度缓冲区。

参数作用说明
GL_ALWAYS永远通过测试
GL_NEVER永远不通过测试
GL_LESS片段值小于深度缓冲区通过测试
GL_EQUAL片段值等于深度缓冲区通过测试
GL_LEQUAL片段值小于等于深度缓冲区通过测试
GL_NOTEQUAL片段值不等于等于深度缓冲区通过测试
GL_GREATER片段值大于深度缓冲区通过测试
GL_GEQUAL片段值大于等于深度缓冲区通过测试

深度测试启用后,默认情况下深度测试函数使用 GL_LESS,这将丢弃深度值高于或等于当前深度缓冲区的值的片段。

代码实现

原理: 绘制了两张图片,并且设置投影矩阵,使其都绕着 Y 轴旋转,注意这两张图片的初始化的 Z 轴坐标是不一致的,所以会出现不同的深度,此时的深度可以理解为 Camera
系统里的景深的概念。

  • 如果开启深度测试,近端的画面会遮挡远端,出现正确的深度效果
  • 如果不开启,会出现两张图片在抢夺 Z 的现象
static int Init(ESContext *esContext)
{UserData *userData = esContext->userData;const char vShaderStr[] ="#version 300 es                             \n""uniform mat4 u_mvpMatrix;                   \n""layout(location = 0) in vec4 a_position;    \n""layout(location = 1) in vec2 a_texCoord;   \n""out vec2 v_texCoord;                       \n""void main()                                 \n""{                                           \n""   gl_Position = u_mvpMatrix * a_position;  \n""   v_texCoord = a_texCoord;                \n""}                                           \n";char fShaderStr[] ="#version 300 es                                     \n""precision mediump float;                            \n""in vec2 v_texCoord;                                 \n""layout(location = 0) out vec4 outColor;             \n""uniform sampler2D s_texture;                        \n""vec4 tempColor;                                     \n""void main()                                         \n""{                                                   \n""  tempColor = texture( s_texture, v_texCoord );    \n""  outColor = vec4(tempColor.r, tempColor.b, tempColor.g, tempColor.a); \n""}                                                   \n";userData->programObject = esLoadProgram(vShaderStr, fShaderStr);userData->samplerLoc = glGetUniformLocation(userData->programObject, "s_texture");userData->textureIdFront = loadTgaTextures("./Huskey.tga");userData->textureIdBack = loadTgaTextures("./scene.tga");userData->mvpLoc = glGetUniformLocation(userData->programObject, "u_mvpMatrix");userData->angle = 0.0f;// 启用深度测试glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);glClearColor(1.0f, 1.0f, 1.0f, 0.0f);return TRUE;
}static void Draw(ESContext *esContext)
{UserData *userData = esContext->userData;GLfloat vertices1[] = {-0.7f,  0.7f, 0.5f,  // 左上-0.7f, -0.7f, 0.5f,  // 左下0.7f, -0.7f, 0.5f,  // 右下0.7f,  0.7f, 0.5f   // 右上};GLfloat vertices2[] = {// 顶点坐标 (x, y, z)-0.5f,  0.5f, 0.1f, -0.5f, -0.5f,  0.1f, 0.5f, -0.5f,  0.1f, 0.5f,  0.5f,  0.1f, };GLfloat texCoords[] = {// 纹理坐标 (s, t)0.0f, 0.0f,  0.0f, 1.0f,  1.0f, 1.0f,   1.0f, 0.0f, };GLushort indices[] = { 0, 1, 2, 0, 2, 3 };glViewport(0, 0, esContext->width, esContext->height);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glUseProgram(userData->programObject);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), vertices1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), texCoords);glEnableVertexAttribArray(0);glEnableVertexAttribArray(1);glUniformMatrix4fv(userData->mvpLoc, 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);// Bind the textureglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, userData->textureIdFront);// Set the sampler texture unit to 0glUniform1i(userData->samplerLoc, 0);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), vertices2);glEnableVertexAttribArray(0);glActiveTexture(GL_TEXTURE0);glUniformMatrix4fv(userData->mvpLoc, 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);glBindTexture(GL_TEXTURE_2D, userData->textureIdBack);glUniform1i(userData->samplerLoc, 0);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);}static void Update(ESContext *esContext, float deltaTime)
{UserData *userData = esContext->userData;ESMatrix perspective;ESMatrix orthographic;ESMatrix modelview;float    aspect;// Compute a rotation angle based on time to rotate the cubeuserData->angle += (deltaTime * 40.0f);if (userData->angle >= 360.0f){userData->angle -= 360.0f;}aspect = (GLfloat)esContext->width / (GLfloat)esContext->height;// Generate a perspective matrix with a 60 degree FOV// 如果不需要 Perspective 可以不设置esMatrixLoadIdentity(&perspective);esPerspective(&perspective, 45.0f, aspect, 1.0f, 20.0f);//  Generate a model view matrix to rotate/translate the cube//  沿着 Z 轴负方向平移两个位置//  沿着 y 轴旋转一定的角度  x y z repsents x y z rotateesMatrixLoadIdentity(&modelview);esTranslate(&modelview, 0.0, 0.0, -2.0);esRotate(&modelview, userData->angle, 0.0, 1.0, 0.0);esMatrixMultiply(&userData->mvpMatrix, &modelview, &perspective);}
static void ShutDown(ESContext *esContext)
{UserData *userData = esContext->userData;glDeleteTextures(1, &userData->textureIdFront);glDeleteTextures(1, &userData->textureIdBack);glDeleteProgram(userData->programObject);
}

实际效果如下:
启动深度测试的效果:
正确的深度测试效果

不启用深度测试:
不正确的深度测试效果

Z-Fight 现象

深度测试中,深度冲突现象需要值得注意。深度冲突(Z-fighting)是指两个平面(或三角形)相互平行且靠近的过于紧密,深度缓冲区不具有足够的精度确定哪一个平面靠前,导致这两个平面的内容不断交替显示,看上去像平面内容争夺顶靠前的位置。

防止深度冲突的方法:

  • 不要让物体之间靠得过近,以免它们的三角形面片发生重叠; - 把近平面设置得远一些(越靠近近平面的位置精度越高);
  • 牺牲一些性能,使用更高精度的深度值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/682690.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

红队笔记Day3-->隧道上线不出网机器

昨天讲了通过代理的形式(端口转发)实现了上线不出网的机器,那么今天就来讲一下如何通过隧道上线不出网机器 目录 1.网络拓扑 2.开始做隧道?No!!! 3.icmp隧道 4.HTTP隧道 5.SSH隧道 1.什么…

HarmonyOS鸿蒙学习基础篇 - 自定义组件(一)

前言 在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离&#…

【Linux】yum软件包管理器

目录 Linux 软件包管理器 yum 什么是软件包 Linux安装软件 查看软件包 关于rzsz Linux卸载软件 查看yum源 扩展yum源下载 Linux开发工具 vim编辑器 上述vim三种模式之间的切换总结: 命令模式下,一些命令: vim配置 Linux 软件包管理…

项目访问量激增该如何应对

✨✨ 欢迎大家来到喔的嘛呀的博客✨✨ 🎈🎈希望这篇博客对大家能有帮助🎈🎈 目录 引言 一. 优化数据库 1.1 索引优化 1.2 查询优化 1.3 数据库设计优化 1.4 事务优化 1.5 硬件优化 1.6 数据库配置优化 二. 增加服务器资源…

JVM(4)原理篇

1 栈上的数据存储 在Java中有8大基本数据类型: 这里的内存占用,指的是堆上或者数组中内存分配的空间大小,栈上的实现更加复杂。 以基础篇的这段代码为例: Java中的8大数据类型在虚拟机中的实现: boolean、byte、char…

【AI视野·今日CV 计算机视觉论文速览 第300期】Tue, 30 Jan 2024

AI视野今日CS.CV 计算机视觉论文速览 Tue, 30 Jan 2024 Totally 146 papers 👉上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Computer Vision for Primate Behavior Analysis in the Wild Authors Richard Vogg, Timo L ddecke, Jonathan Henrich, …

应用进程跨越网络的通信

目录 1 系统调用和应用编程接口 应用编程接口 API 几种应用编程接口 API 套接字的作用 几种常用的系统调用 1. 连接建立阶段 2. 传送阶段 3. 连接释放阶段 1 系统调用和应用编程接口 大多数操作系统使用系统调用 (system call ) 的机制在应用程序和操作系统之间传递控制…

Java基于SpringBoot+vue的租房网站,附源码

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

【学网攻】 第(27)节 -- HSRP(热备份路由器协议)

系列文章目录 目录 系列文章目录 文章目录 前言 一、HSRP(热备份路由器协议)是什么? 二、实验 1.引入 实验目标 实验背景 技术原理 实验步骤 实验设备 实验拓扑图 实验配置 实验验证 文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交…

OpenAI ChatGPT 记忆功能怎么实现?

你的聊天助手现在能“记住”你的对话了! 2月14日凌晨,OpenAI宣布正在测试ChatGPT的新功能——记住用户提问内容,并自由控制内存。这意味着,ChatGPT能帮你记住那些重要的聊天内容,让你的对话更流畅、更自然。 想象一下…

HMI(人机界面设计)大扫盲了,UI设计的重要领域,附案例。

Hello,我是大千UI工场,开始分享HMI设计了,这个可是除了手机和电脑外的,最重要的设计领域哦,可能你觉的它很陌生,其实生活中处处可见。关注我们,学习N多UI干货,有设计需求&#xff0c…

Python算法探索:从经典到现代(二)

一、引言 Python作为一种高级编程语言,其简洁明了的语法和丰富的库资源,使得它成为算法实现的理想选择。本文将带您从经典算法出发,逐步探索到现代算法,感受Python在算法领域的魅力。 二、经典算法:贪心算法 贪心算法…

Web基础01-HTML+CSS

目录 一、HTML 1.概述 2.html结构解析 3.HTML标签分类 4.HTML标签关系 5.HTML空元素 6.HTML属性 7.常用标签 (1)HTML标签 (2)标题标签 (3)换/折行标签 (4)段落标签 &am…

华为机考入门python3--(14)牛客14-字符串排序

分类:列表、排序 知识点: 字典序排序 sorted(my_list) 题目来自【牛客】 def sort_strings_by_lex_order(strings): # 使用内置的sorted函数进行排序,默认是按照字典序排序 sorted_strings sorted(strings) # 返回排序后的字符串列…

php基础学习之运算符(重点在连接符和错误抑制符)

运算符总结 在各种编程语言中&#xff0c;常用的运算符号有这三大类&#xff1a; 算术运算符&#xff1a;&#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;%位运算符&#xff1a;&&#xff0c;|&#xff0c;^&#xff0c;<<&#xff0c;>>赋值运算符&…

洛谷C++简单题小练习day11—字母转换,分可乐两个小程序

day11--字母转换--2.14 习题概述 题目描述 输入一个小写字母&#xff0c;输出其对应的大写字母。例如输入 q[回车] 时&#xff0c;会输出 Q。 代码部分 #include<bits/stdc.h> using namespace std; int main() { char n;cin>>n;cout<<char(n-32)<…

代码+视频基于R语言进行K折交叉验证

我们在建立数据模型后通常希望在外部数据验证模型的检验能力。然而当没有外部数据可以验证的时候&#xff0c;交叉验证也不失为一种方法。交叉验验证&#xff08;交叉验证&#xff0c;&#xff23;&#xff36;&#xff09;则是一种评估模型泛化能力的方法&#xff0c;广泛应用…

尚硅谷最新Node.js 学习笔记(二)

目录 五、HTTP协议 5.1、概念 5.2、请求报文的组成 5.3、HTTP 的请求行 5.4、HTTP 的请求头 5.5、HTTP 的请求体 5.6、响应报文的组成 5.7、创建HTTP服务 操作步骤 测试 注意事项 5.8、浏览器查看 HTTP 报文 查看请求行和请求头 查看请求体 查看URL查询字符串 …

PHP脉聊交友系统网站源码,可通过广告变现社交在线聊天交友即时通讯APP源码,附带视频搭建教程

探索全新社交体验&#xff1a;一站式PHP交友网站解决方案 &#x1f310; 全球化交友&#xff0c;无界沟通 在数字化的浪潮下&#xff0c;社交已不再受地域限制。我们的PHP交友网站不仅支持多国语言&#xff0c;还配备了即时翻译功能&#xff0c;让您轻松跨越语言障碍&#xff…

编译OpenSSL时报错,Can‘t locate IPC/Cmd.pm in @INC

编译OpenSSL 3.0.1时报错&#xff0c;错误信息如下 解决方法&#xff1a; 安装perl-CPAN yum install -y perl-CPAN进入CPAN的shell模式&#xff0c;首次进入需要配置shell&#xff0c;按照提示操作即可&#xff08;本人perl小白&#xff0c;全部选择默认配置&#xff0c;高…