Unity半透明特效原理讲解(为什么半透明设置渲染顺序和深度写入这么重要

  • 写在前面
    • 实验场景
    • 实验1:红(不透明)+蓝(不透明)+默认渲染顺序(先渲染蓝Cube)
    • 实验2:红(不透明+优先渲染)+蓝(不透明)
    • 实验3:红(透明+关闭深度写入)+蓝(不透明)+默认渲染顺序(先渲染蓝Cube)
    • 实验4:红(透明+关闭深度写入+优先渲染)+蓝(不透明)
    • 实验5:红(透明+开启深度写入)+蓝(不透明)+默认渲染顺序(先渲染蓝Cube)
    • 实验5.5:红(透明+开启深度写入+优先渲染)+蓝(不透明)
    • 实验6:红(透明+开启深度写入)+蓝(透明+开启深度写入)+默认渲染顺序(先渲染蓝Cube)
    • 实验7:红(透明+关闭深度写入)+蓝(透明+关闭深度写入)+默认渲染顺序(先渲染蓝Cube)
    • 总结
  • 写在后面

写在前面

最近要实现一个透明的特效,所以更仔细的去学了一下。但是网上更多的是用文字讲解,实验做的相对较少,因此我在这里会更多的附上实验效果展示和结论。若有理解错误的地方,欢迎讨论。

实验场景

摄像头看向两个Cube,红Cube在前,蓝Cube在后

实验1:红(不透明)+蓝(不透明)+默认渲染顺序(先渲染蓝Cube)

效果:

解析: 红蓝Cube使用相同的Shader,只是颜色不一样。可以看到红色挡住了颜色。这很好理解。因为Unity默认从离摄像机原的地方开始渲染。那蓝Cube会先进行深度测试,发现深度缓冲区里面是空的,所以将蓝Cube的深度写入深度缓冲区,并将自己的颜色Blue写入颜色缓冲区。之后红Cube深度测试,发现自己的深度值比深度缓冲区里的蓝Cube值要小,所以通过了深度测试,于是将自己的深度值写入深度缓冲区中覆盖掉以前蓝Cube的深度缓冲区,并将自己的颜色Red写入颜色颜色缓冲区。从而实现覆盖效果。
结论:
1、Unity的默认渲染顺序是从离摄像机远的地方开始渲染。
2、通过深度测试,进行深度写入时,颜色写入颜色缓冲区也会同时进行。

Shader代码:

Shader "My/Blue"
{Properties{_Color("Color", Color) = (0,0,1,1)}SubShader{Tags { "Queue"="Geometry" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment fragfixed4 _Color; struct appdata{float4 vertex : POSITION;};struct v2f{float4 vertex : SV_POSITION;};v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);return o;}fixed4 frag (v2f i) : SV_Target{return fixed4(_Color.r,_Color.g,_Color.b,_Color.a);}ENDCG}}
}

实验2:红(不透明+优先渲染)+蓝(不透明)

效果:

解析:
把蓝色Cube的渲染队列值调到2001大于红色Cube的渲染队列值。从而使得红色Cube优先渲染。但是结果并没有发生改变。这是因为先渲染红色时,红色的深度值被写入深度缓冲区,再渲染蓝色时,蓝色深度值比红色大,因此不会写入深度缓冲区,所以效果不变。


结论:
1、改变渲染队列值能改变Unity对物体的渲染顺序。
2、对于不透明物体来说,因为深度测试的存在,所以不用关心渲染顺序。

实验3:红(透明+关闭深度写入)+蓝(不透明)+默认渲染顺序(先渲染蓝Cube)

效果:

解析:
我们仅在红Cube的Shader中加入透明度混合代码、把红色Cube的渲染队列改为3000、关闭深度写入,并且把红Cube的透明度改为150。此时可以看到红色Cube呈现透明效果。原因也很简单。因为先渲染蓝色,所以当红色Cube进行深度测试通过时本应该把深度值写入深度缓冲区但是由于我们关闭了深度写入,所以深度值还是蓝色Cube的深度值。但是混合的颜色依然写入颜色缓冲区。
在本场景Blend SrcAlpha OneMinusSrcAlpha表示红色红色透明度+蓝色(1-红色透明度)

//红CubeShaer加
Tags {"Queue"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha


结论:
1、关闭深度写入,只是代表如果深度测试通过时不会将深度值写入深度缓冲,但是颜色写入依然会进行。

实验4:红(透明+关闭深度写入+优先渲染)+蓝(不透明)

效果:

解析:
我们将蓝色Cube的渲染队列值调到3001大于红色的300。因此先渲染红色Cube,但是由于红色Cube关闭了深度写入,所以深度值不会写入深度缓冲区,所以深度缓冲区依然为空,但是颜色依然会写入颜色缓冲区。然后渲染蓝Cube时,发现深度缓冲区为空,这时就会误以为蓝Cube是第一个渲染的,所以将蓝Cube深度值写入深度缓冲区,颜色值写入颜色缓冲区,从而导致了蓝Cube在红Cube前的效果。

结论:
1、对于半透明物体来说,渲染顺序是相当重要的,不同的渲染顺序会出现不同的效果。

实验5:红(透明+开启深度写入)+蓝(不透明)+默认渲染顺序(先渲染蓝Cube)

效果:

解析:
将蓝Cube渲染队列值调回2000,使得蓝Cube优先渲染,但开启红Shader的深度写入。所以在渲染红Cube时,深度测试通过后会将红色Cube的深度值写入深度缓冲区,混合颜色会写入颜色缓冲区。

结论:
1、显示结果和实验3红色Cube关闭深度写入是一样的,有人会觉得,开不开启深度写入好像效果都一样,只是最终存到深度缓冲区里面的值不一样罢了,实验3中深度缓冲区离得值是蓝Cube得深度值,而实验5深度缓冲区里得值是红Cube的值。那为什么还要关闭红Shader的深度写入呢?这不多此一举吗?这是因为此时还没考虑当蓝色Cube也是透明的情况,请看实验6、7

实验5.5:红(透明+开启深度写入+优先渲染)+蓝(不透明)

效果:

解析: 调大蓝色的渲染队列值(3001)使其大于红色的渲染队列值(3000),让红色先渲染。红色深度值和颜色被写入。然后渲染蓝色,因为蓝色在后面,深度值小于红色所以不写入深度缓冲区,因此即便红色半透明,也看不到蓝色。

实验6:红(透明+开启深度写入)+蓝(透明+开启深度写入)+默认渲染顺序(先渲染蓝Cube)

效果:

解析:
把蓝色也变为透明,可以看到红蓝重叠的地方,完全看不到红色。为什么呢?见https://blog.csdn.net/a1047120490/article/details/106744930/
写得很详细,解释了为什么。
结论:
当两个透明物体发生重叠时如果开启深度写入,那么重叠的部分显示会出错。

实验7:红(透明+关闭深度写入)+蓝(透明+关闭深度写入)+默认渲染顺序(先渲染蓝Cube)


解析:
可以看到红蓝重叠的地方,得出了透明的效果,但感觉红色是在蓝色前面的。为什么呢?同样见
https://blog.csdn.net/a1047120490/article/details/106744930/
结论:
当两个透明物体发生重叠时如果不开启深度写入,那么重叠的部分显示照样会出错,但总比开启深度写入强。

总结

1、对于不透明物体的,因为深度缓冲区的原因,渲染顺序不太重要(实验1、2)。
2、对于透明物体,渲染顺序会直接影响渲染结果,所以要设置渲染队列 Tags { "Queue"="Transparent" }(实验3、4)
3、对于透明物体,如果开启深度写入,当两个透明物体重合时,会出现渲染错误,如果关闭深度写入,也会出现渲染错误,但比开启时错误要少。所以还是关闭深度写入的好。
4、因此对于半透明物体的默认写法为设置渲染队列为"Queue"="Transparent",设置透明混合Blend SrcAlpha OneMinusSrcAlpha,关闭深度写入ZWrite Off

//设置渲染队列和渲染类型
Tags {"Queue"="Transparent"  "RenderType"="Transparent" }
//设置透明混合
Blend SrcAlpha OneMinusSrcAlpha
//关闭深度写入
ZWrite Off

5、Unity在进行渲染时一般会对物体进行排序,再渲染,渲染顺序为:
(1)先渲染所以不透明物体("Queue"="Geometry"的物体),从到相机的距离,由远到近渲染,并且开启深度测试和深度写入。
(2)再渲染半透明物体("Queue"="Transparent"的物体),从到相机的距离,由远到近渲染,并且开启深度测试但关闭深度写入。
(3)但由于Unity对物体距离相机距离排序是基于object level的(基于物体中心的排序),所以当两个透明物体出现重合时,会出现渲染的错误,这是应该以像素为单位排序渲染(用顺序无关透明(order independent transparency, OIT)技术)。

写在后面

今天2023/02/21是出考研成绩的日子,虽然博主已经走过了考研的独木桥,但回望过去考研的经历还是不禁感叹,考研这条路注定是孤独的,注定是几家欢喜几家愁。愿,星光不问赶路人,时光不负有心人。

Unity半透明特效原理讲解(为什么半透明设置渲染顺序和深度写入这么重要)相关推荐

  1. Unity性能优化要点分析(二) 渲染优化技术

    本章摘录自UnityShader入门精要的第16章内容. 移动平台的特点 移动平台的GPU架构有很大不同,由于芯片架构的不同,一些游戏往往需要针对不同的芯片发布不同的版本,以便对每种芯片进行更有针对性 ...

  2. Unity中的物体渲染顺序

    big seven 文章目录 前言 一.摄像机渲染 二.划分渲染队列 三.不透明物体的渲染 四.透明物体的渲染 五.UGUI元素的渲染 总结 前言 Unity中物体的渲染顺序 提示:以下是本篇文章正文 ...

  3. unity shader 入门 全透明与半透明效果实现

    片元函数的fixed4类型的返回值的第4位即为阿尔法值,0代表完全不显示(透明),1代表完全显示.中间的数值代表半透明.但只修改这个值是不能直接修改透明度的,因为还要对队列等进行修改. 本文介绍透明度 ...

  4. unity 2d摄像机类型_Unity透明效果-开启深度写入的半透明效果实现

    上一部分中提到了由于关闭深度写入而产生的遮挡问题,本小节将进行一种解决上述问题的实践--开启深度写入的两个Pass的透明效果实现. 基本思想 使用两个Pass进行渲染: 第一个Pass开启深度写入,但 ...

  5. flash特效原理:图片滑动放大效果(2)

    flash特效原理:图片滑动放大效果(1) http://blog.csdn.net/hero82748274/archive/2009/10/22/4715312.aspx 最近看了一些关于动态注册 ...

  6. flash特效原理 图片滑动放大效果 2

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! flas ...

  7. php 伪静态 page-18.html,PHP 伪静态实现技术原理讲解

    PHP 伪静态实现技术原理讲解 发布于 2015-01-18 23:52:58 | 129 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext Pre ...

  8. nginx反向代理原理讲解

    一 .概述                  反向代理(Reverse Proxy)方式是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器:并将从服务器上得到的结果 ...

  9. 微信小游戏开发教程-2D游戏原理讲解

    微信小游戏开发教程-2D游戏原理讲解 原理 为了更加形象的描述,这里先上一张图: 背景 a. 首先,我们看到背景好像是一张无限长的图片在向下移动.实际则不然,这是一张顶部和底部刚好重叠的图片.这是一种 ...

最新文章

  1. boost::mp11::mp_rotate_right相关用法的测试程序
  2. 季枫老师java全集_PHP冒泡排序,摘取季枫老师视频的冒泡排序内容!
  3. mysql倒叙varchar类型的数字_MySql遇到varchar字段数字字符串排序问题
  4. redis 之 ae 模型测试
  5. Python入门篇之字符串使用
  6. 【BP回归预测】基于matlab改进的鲸鱼算法优化BP神经网络回归预测(多输入单输出)【含Matlab源码 2184期】
  7. 1bit等于多少字节,换算方法?
  8. LM4890功放电路的分析
  9. Android实现即时聊天
  10. canvas初体验-图片上画方框
  11. 威斯康星大学-机器学习导论2020
  12. I2C、Arduino、ADXL345、
  13. Hibernate第三讲:Hibernate主键策略和Hibernate的查询方案
  14. 舆情指数在哪里可以查到?具体平台与工具参考
  15. UML测试题(用例图基础a)
  16. Cisco 路由器Telnet,Console配置
  17. 菜鸟学C语言-环境搭建
  18. GB28181-2016标准
  19. BZOJ 5395--[Ynoi2016]谁的梦(STL容斥)
  20. 牛客刷题和本地调试结果不一样--解决思路

热门文章

  1. 怎么离线安装matlab的工具箱,如何安装matlab工具箱
  2. Linux rootfs挂载过程
  3. lisp调用布置天正的图块_操作太慢?那是你没有正确使用AutoCAD图块!
  4. InterSystems IRIS 和 IRIS for Health 2021.2 预览版发布
  5. 树中的叶子结点的个数 计算方法
  6. 【网络科普】Wi-Fi 安全接入方法 - WEP, WPA, WPS
  7. IMPERVA - WAF 如何配置Imperva SNMP
  8. 用C语言实现控制台播放音乐的功能
  9. 前端-html 点击 跳转页面
  10. js去除字符串中的所有空格(包括前后,中间存在的所有空格),清除前后空格(手机输入框实用),es6新方法