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 texture
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, userData->textureIdFront);

	// Set the sampler texture unit to 0
	glUniform1i(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 cube
	userData->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 rotate
	esMatrixLoadIdentity(&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)是指两个平面(或三角形)相互平行且靠近的过于紧密,深度缓冲区不具有足够的精度确定哪一个平面靠前,导致这两个平面的内容不断交替显示,看上去像平面内容争夺顶靠前的位置。

防止深度冲突的方法:

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

函数求导法则【高数笔记】

【分类】 1. 四则运算求导 2. 复合运算求导 3. 整体思想求导 #整体思想求导本质是运用复合运算求导,只不过是对复合运算求导的一种精炼 #无论是具体函数还是抽象函数求导,方法是一致的 【四则运算求导】 加,减,乘,除&a…

Javaweb基础-tomcat,servlet

一.配置文件基础: properties配置文件: 由键值对组成 键和值之间的符号是等号 每一行都必须顶格写,前面不能有空格之类的其他符号 xml配置文件:(xml语法HTML语法HTML约束)xml约束-DTD / Schema DOM4…

代码随想录算法训练营第三十一天 |基础知识,455.分发饼干,376.摆动序列,53.最大子序和(已补充)

基础知识: 题目分类大纲如下: #算法公开课 《代码随想录》算法视频公开课(opens new window):贪心算法理论基础!(opens new window),相信结合视频再看本篇题解,更有助于大家对本题的理解。 #什么是贪心 贪心的本质…

MySQL什么情况下会死锁,发生了死锁怎么处理呢?

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师…

Springboot加载bootstrap和application原理

Springboot加载bootstrap和application原理 bootstrap.yml能被springboot加载导入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.6</version><rel…

Web 目录爆破神器:Dirsearch 保姆级教程

一、介绍 dirsearch 是一款用于目录扫描的开源工具&#xff0c;旨在帮助渗透测试人员和安全研究人员发现目标网站上的隐藏目录和文件。与 dirb 类似&#xff0c;它使用字典文件中的单词构建 URL 路径&#xff0c;然后发送 HTTP 请求来检查这些路径是否存在。 以下是 dirsearc…

开店必知:如何在社区开一家最受欢迎的店

在社区开一家受欢迎的店需要综合考虑多个因素。以下是一些关键要点&#xff0c;以帮助你实现这一目标。 1、了解社区需求&#xff1a; 在选择经营项目之前&#xff0c;深入了解社区的特点和需求。研究社区人口结构、消费习惯以及竞争对手情况。这将有助于你确定适合该社区的产…

基于AI Agent探讨:安全领域下的AI应用范式

先说观点&#xff1a;关于AI应用&#xff0c;通常都会聊准召。但在安全等模糊标准的场景下&#xff0c;事实上不存在准召的定义。因此&#xff0c;AI的目标应该是尽可能的“像人”。而想要评价有多“像人”&#xff0c;就先需要将人的工作数字化。而AI Agent是能够将数字化、自…

数据结构.图的存储

一、邻接矩阵法 二、邻列表法 三、十字链表法

SpringCloud第一天

1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.1.单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打…

鸿蒙开发系列教程(十八)--页面内动画(1)

页面内的动画 显示动画 语法&#xff1a;animateTo(value: AnimateParam, event: () > void): void 第一个参数指定动画参数 第二个参数为动画的闭包函数。 如&#xff1a;animateTo({ duration: 1000, curve: Curve.EaseInOut }, () > {动画代码}&#xff09; dura…

面试经典150题——最小覆盖子串(困难)

"The greatest glory in living lies not in never falling, but in rising every time we fall." - Nelson Mandela​ 1. 题目描述 2. 题目分析与解析 2.1 思路一——暴力求解 还是和之前讲的一样&#xff0c;看见题目没思路&#xff0c;先试试普通情况下人的解法…

计算机毕业设计分享-SpringBoot宿舍管理平台app13023(赠送源码数据库)JAVA、PHP,node.js,C++、python,大屏数据可视化等

SpringBoot宿舍管理平台app 摘 要 近年来&#xff0c;校园内出现了越来越多的信息管理系统&#xff0c;逐渐覆盖了校园内的各种教学和管理业务。在各种制度的帮助下&#xff0c;校园的管理水平和效率都有了很大的提高。在学生管理方面&#xff0c;已经涌现了众多的信息管理系统…

每日OJ题_递归①_力扣面试题 08.06. 汉诺塔问题

目录 递归算法原理 力扣面试题 08.06. 汉诺塔问题 解析代码 递归算法原理 递归算法个人经验&#xff1a;给定一个任务&#xff0c;相信递归函数一定能解决这个任务&#xff0c;根据任务所需的东西&#xff0c;给出函数参数&#xff0c;然后实现函数内容&#xff0c;最后找出…

Editing While Playing 使用 Easyx 开发的 RPG 地图编辑器 tilemap eaitor

AWSD移动画布 鼠标右键长按拖拽 鼠标左键长按绘制 可以边拖拽边移动画布边绘制。 F1 导出 DLC F2 导入DLC author: 民用级脑的研发记录 1309602336qq.com 开发环境&#xff1a; 内置 easyx 的 devc 5.11 或者 VS 2022 TDM GCC 4.9.2 64-bit c11及以上都可运行 windows 环境运行…

机器学习3----决策树

这是前期准备 import numpy as np import pandas as pd import matplotlib.pyplot as plt #ID3算法 #每个特征的信息熵 # target : 账号是否真实&#xff0c;共2种情况 # yes 7个 p0.7 # no 3个 p0.3 info_D-(0.7*np.log2(0.7)0.3*np.log2(0.3)) info_D #日志密度…

华为23年9月笔试原题,巨详细题解,附有LeetCode测试链接

文章目录 前言思路主要思路关于f函数的剖析Code就到这&#xff0c;铁子们下期见&#xff01;&#xff01;&#xff01;&#xff01; 前言 铁子们好啊&#xff01;今天阿辉又给大家来更新新一道好题&#xff0c;下面链接是23年9月27的华为笔试原题&#xff0c;LeetCode上面的ha…

- 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》

本文属于专栏《构建工业级QPS百万级服务》​​​​​ 1、前置知识 c的内存管理&#xff0c;主要说的是堆内存管理。现代计算机系统中&#xff0c;用户进程的堆内存&#xff0c;由内核映射。 堆内存的来源 主要是通过mmap()函数&#xff0c;在进程的虚拟地址空…

【Linux技术宝典】深入理解Linux基本指令:命令行新手指南

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅Linux技术宝典 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、Linux下基本指令1. ls 指令2. pwd指令3. clear指令4. cd指令什么是家目录&#xf…

【AI视野·今日Robot 机器人论文速览 第七十八期】Wed, 17 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Wed, 17 Jan 2024 Totally 49 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Safe Mission-Level Path Planning for Exploration of Lunar Shadowed Regions by a Solar-Powered Rover Authors Olivier L…