webgl渲染优化——深度缓冲区、多边形缓冲机制

news2024/11/18 9:43:48

文章目录

  • 前言
  • 深度缓冲区
  • 多边形缓冲机制
  • 总结


前言

webgl在渲染三维场景时,按照Z坐标的值决定前后关系,但是在默认状态下它并未开启深度检测,而是将后绘制的物体放在前面;当两个物体Z坐标相差无几时,会产生深度冲突,两个物体颜色互相影响,使得表面看上去斑斑驳驳,需要开启多边形缓冲来避免此类问题。


深度缓冲区

我们知道webgl着色器中的内置变量gl_Position是按照左手坐标系。也就是说Z轴指向屏幕内侧,z坐标大的像素将会被绘制在后方,遮挡z坐标比它大的像素(暂不考虑乘以MVP矩阵)。但是,这是在开启深度检测的前提下,如果没有开启这一设置,后绘制的会遮挡先前绘制的
这样子使用:

	/** @type {HTMLCanvasElement} */
		//------------------------------------------------------创建画布
		// 获取canvas元素对象
		let canvas = document.getElementById('canvas');
		// 获取webgl绘图上下文
		const gl = canvas.getContext('webgl');
		if (!gl) {
			throw new Error('WebGL not supported');
		}
		gl.viewport(0, 0, canvas.width, canvas.height)
		// 设置背景色
		gl.clearColor(0.0, 0.0, 0.0, 1.0)
		// 清空缓冲区
		gl.clear(gl.COLOR_BUFFER_BIT)

		const vertex = `
			attribute vec4 aPosition;
			attribute vec4 aColor;
			varying vec4 v_Color;
			void main() {
				gl_Position =  aPosition;
				gl_PointSize = 10.0;
				v_Color = aColor;
			}
		`
		const fragment = `
			precision highp float;
			varying vec4 v_Color;
			void main(){
				gl_FragColor = v_Color;
			}
		`

		// 创建program
		const program = initShader(gl, vertex, fragment)
		// 获取attribute变量的数据存储位置
		const aPosition = gl.getAttribLocation(program, 'aPosition');
		const aColor = gl.getAttribLocation(program, 'aColor');
		// 获取uniform变量的数据存储位置

		// 创建缓冲区对象
		const buffer = gl.createBuffer();
		// 绑定缓冲区对象
		gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
		// 传入的数据
		const vertices = new Float32Array([
			// Z 为 0.0的蓝色三角形
			-0.3, 0.6, 0.0, 0.4, 0.4, 1.0, 
			-0.8, -0.6, 0.0, 0.4, 0.4, 1.0,
			0.2, -0.6, 0.0, 1.0, 0.4, 0.4,
			// Z 为 -0.5的黄色三角形
			0.0, 1.0, -0.5, 1.0, 1.0, 0.4, 
			-0.5, -1.0, -0.5, 1.0, 1.0, 0.4,
			0.5, -1.0, -0.5, 1.0, 0.4, 0.4,
			// Z 为 0.5 的绿色三角形
			0.3, 0.8, 0.5, 0.4, 1.0, 0.4, 
			-0.2, -0.8, 0.5, 0.4, 1.0, 0.4,
			0.8, -0.8, 0.5, 1.0, 0.4, 0.4,
		])

		const BYTES = vertices.BYTES_PER_ELEMENT;
		// 开辟空间并写入数据
		gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
		// 缓冲区对象分配给attribute变量
		gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 6 * BYTES, 0)
		gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 6 * BYTES, 3 * BYTES)
		// 开启attribue变量
		gl.enableVertexAttribArray(aPosition)
		gl.enableVertexAttribArray(aColor)

		// 开始绘制
		gl.drawArrays(gl.TRIANGLES, 0, 18)

在上述代码中,向vertices依次传入缓冲区数据,实际效果如下:

在这里插入图片描述

webgl默认按照缓冲区中的顺序绘制图形,后绘制的图形覆盖先绘制的图形,因为这样做很高效。但是当传入顺序与z坐标大小不一致,或者视点不断移动更改视角时,将无法保证绘制顺序。

  • 开启深度检测
  • 1.开启隐藏面消除功能:gl.enable(gl.DEPTH_TEST)
  • 2.在执行绘制函数之前,清除深度缓冲区:gl.clear(gl.DEPTH_BUFFER_BIT),gl.clear支持使用 | 添加多个参数。
		// 设置背景色
		gl.clearColor(0.0, 0.0, 0.0, 1.0)
		// 开启深度检测
		gl.enable(gl.DEPTH_TEST);
		// 清空颜色缓冲区和深度缓冲区
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT )

如下黄色就到了最前面
在这里插入图片描述
为了方便观察蓝色三角形与绿色三角形的关系,将黄色三角形尺寸调整的小一些:

		const vertices = new Float32Array([
			// Z 为 0.0的蓝色三角形
			-0.3, 0.6, 0.0, 0.4, 0.4, 1.0, 
			-0.8, -0.6, 0.0, 0.4, 0.4, 1.0,
			0.2, -0.6, 0.0, 1.0, 0.4, 0.4,
			// Z 为 -0.5的黄色三角形
			0.0, 0.2, -0.5, 1.0, 1.0, 0.4, 
			-0.5, -0.2, -0.5, 1.0, 1.0, 0.4,
			0.5, -0.2, -0.5, 1.0, 0.4, 0.4,
			// Z 为 0.5 的绿色三角形
			0.3, 0.8, 0.5, 0.4, 1.0, 0.4, 
			-0.2, -0.8, 0.5, 0.4, 1.0, 0.4,
			0.8, -0.8, 0.5, 1.0, 0.4, 0.4,
		])

效果如下,与预计中一样,Z坐标:Z黄 < Z蓝 < Z绿。前后顺序:黄 > 蓝 > 绿。

在这里插入图片描述

多边形缓冲机制

当两个表面过于接近,深度缓冲区有限的精度已经不能区分先后关系,当场景中有多个运动着的物体时,很难保证它们的深度值不会在某刻相同,这种情况会导致两个物体颜色互相影响,使得表面看上去斑斑驳驳。

在这里插入图片描述

webgl提供一种名为 多边形偏移 的机制来解决这个问题。该机制将自动在 Z 值加上一个偏移量,偏移量的值由物体表面相对于观察者视线的角度来确定。

  • 1.开启多边形偏移:gl.enable(gl.POLYGON_OFFSET_FILL)
  • 2.设置偏移参数:gl.polygonOffset(1.0, 1.0)
  gl.enable(gl.POLYGON_OFFSET_FILL);
  gl.polygonOffset(1.0, 1.0);  

目的达成,可以重新编辑了。

总结

  • 深度缓冲区

  • 多边形缓冲机制

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

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

相关文章

【Redis】线程模型:Redis是单线程还是多线程?

【Redis】线程模型&#xff1a;Redis是单线程还是多线程&#xff1f; 文章目录【Redis】线程模型&#xff1a;Redis是单线程还是多线程&#xff1f;Redis 是单线程吗&#xff1f;Redis 单线程模式是怎样的&#xff1f;Redis 采用单线程为什么还这么快&#xff1f;Redis 6.0 之前…

高端装备的AC主轴头结构

加工机器人的AC主轴头和位置相关动力学特性1. 位置依赖动态特性及其复杂性2. AC主轴头2.1 常见主轴头摆角结构2.2 摆动机构3. 加装AC主轴头的作用和局限性4. 切削机器人的减速器类型5. 其他并联结构形式参考文献资料1. 位置依赖动态特性及其复杂性 However, FRF measurements …

JS学习第3天——Web APIs之DOM(什么是DOM,相关API)

目录一、Web APIs介绍1、API2、Web API二、DOM1、DOM树2、获取元素3、事件基础4、操作元素属性5、节点&#xff08;node&#xff09;操作三、以上内容总结四、小案例一、Web APIs介绍 JS的组成&#xff1a;ECMAScript&#xff08;基础语法&#xff09;、DOM&#xff08;页面文…

CTFer成长之路之反序列化漏洞

反序列化漏洞CTF 1.访问url&#xff1a; http://91a5ef16-ff14-4e0d-a687-32bdb4f61ecf.node3.buuoj.cn/ 点击下载源码 本地搭建环境并访问url&#xff1a; http://127.0.0.1/www/public/ 构造payload&#xff1a; ?sindex/index/hello&ethanwhoamiPOST的参数&#…

【渗透测试学习】—记录一次自测试渗透实战

写在前面 本文是作者入门web安全后的第一次完整的授权渗透测试实战&#xff0c;因为最近在总结自己学习与挖掘到的漏&#xff0c;无意中翻到了这篇渗透测试报告&#xff0c;想当初我的这篇渗透测试报告是被评为优秀渗透测试报告的&#xff0c;故在此重新整了一下&#xff0c;分…

创客匠人直播:构建公域到私域的用户增长模型

进入知识付费直播带货时代&#xff0c;很多拥有知识技能经验的老师和培训机构吃到了流量红利。通过知识付费直播&#xff0c;老师们可以轻松实现引流、变现&#xff0c;还可以突破时间、地域的限制&#xff0c;为全国各地的学员带来优质的教学服务&#xff0c;因此越来越受到教…

【Linux】-- 多线程安全

目录 进程互斥 计算 -> 时序问题 加锁保护 pthread_mutex_lock pthread_mutex_unlock 使用init与destory pthread_mutex_init phtread_mutex_destory 锁的实现原理 图 可重入VS线程安全 死锁 Linux线程同步 条件变量 系统调用 进程互斥 进程线程间的互斥相关…

【C语言经典例题】打印菱形

目录 一、题目要求 二、解题思路 上半部分三角形 打印空格 打印星号* 下半部分三角形 打印空格 打印星号* 三、完整代码 代码 运行截图&#xff1a; 一、题目要求 输入一个整数n&#xff08;n为奇数&#xff09;&#xff0c;n为菱形的高&#xff0c;打印出该菱形 例&a…

【模拟集成电路】鉴频鉴相器设计(Phase Frequency Detector,PFD)

鉴频鉴相器设计&#xff08;Phase Frequency Detector&#xff0c;PFD&#xff09;前言一、 PFD的工作原理二、 PFD电路设计&#xff08;1&#xff09;PFD电路图&#xff08;2&#xff09;D触发器电路图&#xff08;3&#xff09;与非门&#xff08;NAND&#xff09;电路图&…

【死磕数据库专栏】MySQL对数据库增删改查的基本操作

前言 本文是专栏【死磕数据库专栏】的第二篇文章&#xff0c;主要讲解MySQL语句最常用的增删改查操作。我一直觉得这个世界就是个程序&#xff0c;每天都在执行增删改查。 MySQL 中我们最常用的增删改查&#xff0c;对应SQL语句就是 insert 、delete、update、select&#xf…

亚马逊侵权了怎么办?不要恐慌,这套申诉方法教你解决

侵权&#xff0c;在亚马逊可是大忌&#xff01;在亚马逊平台上&#xff0c;卖家侵权行为被认为是极为严重的违规行为。亚马逊采取的对待侵权的措施通常相当严厉&#xff0c;从轻者的产品下架到重者直接被禁售。所以如果你的产品涉嫌侵犯知识产权&#xff0c;那么想要在亚马逊上…

软件质量保证与测试(测试部分)

第九章、软件测试过程 9.1 计算机软件的可靠性要素 9.2 软件测试的目的和原则 9.3 软件测试过程 9.4 软件测试与软件开发的关系 9.7 测试工具选择 9.7.1 白盒测试工具 9.7.2 黑盒测试工具 第十章、黑盒测试 10.1 黑盒测试的基本概念 10.2 等价类划分 10.2.2 划分等价类的方法…

MinGW编译log4cpp

log4cpp的官网和下载地址 https://log4cpp.sourceforge.net/ https://sourceforge.net/projects/log4cpp/files/ 使用MinGW编译log4cpp 进入到log4cpp的源码目录 cd F:\3rdParty\Log\log4cpp\log4cpp-1.1.3\log4cpp 创建文件夹 mkdir build && mkdir outcd build …

死磕Spring,什么是SPI机制,对SpringBoot自动装配有什么帮助

文章目录如果没时间看的话&#xff0c;在这里直接看总结一、Java SPI的概念和术语二、看看Java SPI是如何诞生的三、Java SPI应该如何应用四、从0开始&#xff0c;手撸一个SPI的应用实例五、SpringBoot自动装配六、Spring SPI机制与Spring Factories机制做对比七、这里是给我自…

软件测试5年,历经3轮面试成功拿下华为Offer,24K/16薪不过分吧

前言 转眼过去&#xff0c;距离读书的时候已经这么久了吗&#xff1f;&#xff0c;从18年5月本科毕业入职了一家小公司&#xff0c;到现在快5年了&#xff0c;前段时间社招想着找一个新的工作&#xff0c;前前后后花了一个多月的时间复习以及面试&#xff0c;前几天拿到了华为的…

redis(4)String字符串

前言 Redis中有5大数据类型&#xff0c;分别是字符串String、列表List、集合Set、哈希Hash、有序集合Zset&#xff0c;本篇介绍Redis的字符串String Redis字符串 String是Redis最基本的类型&#xff0c;你可以理解成与Memcached一模一样的类型&#xff0c;一个key对应一个value…

Python使用百度通用API进行翻译

想汉化StarUML这个软件&#xff0c;感觉工作量太大&#xff0c;想要用Python自动翻译。 结果网上找的一个个用不了&#xff0c;或者用一会儿就断。 于是自己手写了一个简单的&#xff0c;只有两个类&#xff1a;APIConfig和Translater 使用 demo my_api_config APIConfig(…

指针的进阶——(1)

本次讲解重点&#xff1a; 1、字符指针 2、数组指针 3、指针数组 4、数组传参和指针传参 5、函数指针 关于指针这个知识点的主题&#xff0c;我们在前面已经初级阶段已经对指针有了大致的理解和应用了。我们知道了指针的概念&#xff1a; 1、指针就是地址&#xff0c;但口…

PHP基础(3)

PHP基础表单提交文件处理PHP连接数据库异常抛出表单提交 PHP通过全局变量 $_GET和 $_POST来收集表单数据。 接下来改用post方式进行提交&#xff0c;再次查看是否隐藏了提交的内容&#xff1a; 发现提交的信息已经不在链接之中进行显示了。 GET与POST区别在于一个会在连接…

番外9:使用ADS对射频功率放大器进行非线性测试1(以IMD3测试为例)

番外9&#xff1a;使用ADS对射频功率放大器进行非线性测试1&#xff08;以IMD3测试为例&#xff09; 一般可以有多种方式对射频功率放大器的非线性性能进行测试&#xff0c;包括IMD3、ACPR、ACLR等等&#xff0c;其中IMD3的实际测试较为简单方便不需要太多的仪器。那么在ADS中…