Chapter8 透明效果——Shader入门精要学习笔记

一、基本概念

  • 在Unity中通常使用两种方法来实现透明效果
    • 透明度测试(无法达到真正的半透明效果)
    • 透明度混合(关闭了深度写入)

透明度测试

  • 基本原理:设置一个阈值,只要片元的透明度小于阈值,就会被舍弃(不会进行任何处理,也不会对颜色缓冲造成影响);否则,就会按照普通的不透明物体来处理(进行深度测试、深度写入等)
  • 效果极端,要么透明,要么完全不透明

透明度混合

  • 基本原理:使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色
  • 需要关闭深度写入,但没有关闭深度测试——深度缓冲是只读的
    • 为什么关闭深度写入:如果开启,半透明物体在不透明物体前面时,半透明物体会挡住不透明物体,实现不了半透明效果
  • 可以实现半透明效果

二、渲染顺序

  • 对于半透明物体和不透明物体,因为关闭了深度写入,所以应该在不透明物体渲染完后再渲染半透明物体
  • 对于两个半透明物体,应该先渲染远处的,再渲染近处的(不准确)

1.渲染引擎的方法

  • 先渲染所有不透明物体,并开启他们的深度测试和深度写入
  • 把半透明物体按他们的距离摄像机的远近进行排序,再按照从后往前的顺序渲染,开启深度测试,关闭深度写入
    • 会有更加复杂的重叠情况,排序困难

2.Unity的渲染顺序

  • 使用SubShader的 Queue 标签来决定我们的模型将归于哪个渲染队列,使用整数索引来表示每个渲染队列,号小的越早被渲染
    在这里插入图片描述
  • 如果想要通过透明度测试来实现效果,代码:
SubShader{Tags{ "Queue" = "AlphaTest"}Pass{...}}
  • 如果想使用透明度混合
SubShader{Tags{ "Queue" = "Transparent"}Pass{ZWrite Off //关闭深度写入...}}

三、透明度测试

  • 基本原理:设置一个阈值,只要片元的透明度小于阈值,就会被舍弃(不会进行任何处理,也不会对颜色缓冲造成影响);否则,就会按照普通的不透明物体来处理(进行深度测试、深度写入等)
  • 通常会在片元着色器中使用 clip函数 进行透明度测试
    • 如果给定参数的任何一个分量是负数,则会舍弃当前像素的输出颜色
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "Custom/Chapter8-AlphaTest"
{Properties{_Color ("Main Tint", Color) = (1,1,1,1)_MainTex ("Main Tex", 2D) = "white"{}_Cutoff ("Alpha Cutoff", Range(0,1)) = 0.5//用于决定我们调用clip进行透明度测试时使用的判决条件}SubShader{Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutoff"}Pass{Tags{"LightMode" = "ForwardBase"}CGPROGRAM#pragma vertex vert #pragma fragment frag#include "Lighting.cginc"fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;fixed _Cutoff;struct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float3 worldNormal : TEXCOORD0;float3 worldPos : TEXCOORD1;float2 uv : TEXCOORD2;};v2f vert(a2v v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);return o;}fixed4 frag(v2f i) : SV_Target {fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));fixed4 texColor = tex2D(_MainTex, i.uv);//透明度测试clip(texColor.a - _Cutoff);fixed3 albedo = texColor.rgb * _Color.rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal,worldLightDir));return fixed4(ambient + diffuse, 1.0);}ENDCG}}FallBack "Transparent/Cutout/VertexLit"
}
  • _Cutoff (“Alpha Cutoff”, Range(0,1)) = 0.5 用于决定我们调用clip进行透明度测试时使用的判决条件
  • clip(texColor.a - _Cutoff); 做透明度测试,判断texColor.a - _Cutoff是否为负数,负数的纹理颜色为全透明
    在这里插入图片描述

四、透明度混合

  • 基本原理:使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色
  • 需要使用Unity提供的混合命令 Blend
    在这里插入图片描述
  • 本节中使用的是Blend SrcFactor DstFactor来进行混合,将源颜色混合因子SrcFactor设为SrcAlpha,目标颜色混合因子设为OneMinusSrcAlpha
    • 即混合后的新颜色为
    • D s t C o l o r n e w DstColor_{new} DstColornew = SrcAlpha × SrcColor + (1-SrcAlpha) × D s t C o l o r o l d DstColor_{old} DstColorold
  • ZWrite Off 关闭深度写入
Shader "Custom/Chapter8-AlphaBlend"
{Properties{_Color ("Main Tint", Color) = (1,1,1,1)_MainTex ("Main Tex", 2D) = "white"{}_AlphaScale ("Alpha Scale", Range(0,1)) = 1}SubShader{Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}Pass{Tags {"LightMode" = "ForwardBase"}ZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert #pragma fragment frag #include "Lighting.cginc"fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;fixed _AlphaScale;struct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float3 worldNormal : TEXCOORD0;float3 worldPos : TEXCOORD1;float2 uv : TEXCOORD2;};v2f vert(a2v v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);return o;}fixed4 frag(v2f i) : SV_Target {fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));fixed4 texColor = tex2D(_MainTex, i.uv);//透明度混合fixed3 albedo = texColor.rgb * _Color.rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal,worldLightDir));return fixed4(ambient + diffuse, texColor.a * _AlphaScale);}ENDCG}}FallBack "Transparent/VertexLit"
}

在这里插入图片描述

五、开启深度写入的半透明效果

  • 对于复杂网格的半透明处理,避免错误排序
  • 方法:使用 两个Pass 来渲染模型
    • 第一个开启深度写入,但不输出颜色,仅仅为了把该模型的深度值写入深度缓存中
    • 第二个Pass 进行正常的透明度混合,根据第一个Pass,可以进行像素级别的深度排序
    • 缺点是 多个Pass会造成性能的影响
Shader "Custom/Chapter8-AlphaBlend"
{Properties{_Color ("Main Tint", Color) = (1,1,1,1)_MainTex ("Main Tex", 2D) = "white"{}_AlphaScale ("Alpha Scale", Range(0,1)) = 1}SubShader{Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}Pass{ZWrite On ColorMask 0}Pass{Tags {"LightMode" = "ForwardBase"}ZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert #pragma fragment frag #include "Lighting.cginc"fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;fixed _AlphaScale;struct a2v{float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;};struct v2f{float4 pos : SV_POSITION;float3 worldNormal : TEXCOORD0;float3 worldPos : TEXCOORD1;float2 uv : TEXCOORD2;};v2f vert(a2v v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);return o;}fixed4 frag(v2f i) : SV_Target {fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));fixed4 texColor = tex2D(_MainTex, i.uv);//透明度混合fixed3 albedo = texColor.rgb * _Color.rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal,worldLightDir));return fixed4(ambient + diffuse, texColor.a * _AlphaScale);}ENDCG}}FallBack "Transparent/VertexLit"
}
  • 与透明度混合代码几乎一致,只是增加了一个Pass
Pass{ZWrite On ColorMask 0}
  • ZWrite On 打开深度写入,ColorMask 0 意味着Pass不写入任何颜色通道,不会输出任何颜色
    在这里插入图片描述

六、ShaderLab的混合命令

  • 混合与两个操作数有关:源颜色(SourceColor)和目标颜色(DestinationColor)
    • 源颜色指片元着色器产生的颜色 S
    • 目标颜色指从颜色缓冲中读取到的颜色值 D
    • 混合后的颜色 O
    • 包含了 RGBA四个颜色通道

1.混合等式和参数

  • 将S和D进行混合的等式——混合等式,需要两个,一个用于混合RGB,一个用于混合A
  • 设置混合状态时,即设置等式中的 “操作” 和 “因子”
    • 一共有两个等式(分别用于混合RGB和A)
    • 一个等式里有两个因子(一个与S相乘,一个与D相乘)

在这里插入图片描述

  • 第一个命令中只有两个因子——RGB和A通道用相同的两个因子
    在这里插入图片描述
    混合因子可以是哪些值呢?
    在这里插入图片描述

2.混合操作

  • 可以使用 BlendOp BlendOperation命令
    在这里插入图片描述
    在这里插入图片描述
  • 当使用Min和Max操作时,混合因子不起作用的

3.常见的混合类型(效果)

在这里插入图片描述

七、双面渲染的透明效果

  • 观察到其内部结构
  • 可以使用Cull指令来控制需要剔除哪个面的渲染图元
    • Back:背对相机的渲染图元不会被渲染
    • Front:朝向相机的渲染图元不会被渲染
    • Off:关闭剔除功能
Cull Back | Front | Off

1.透明度测试的双面渲染

  • 在Pass中使用 Cull Off 来关闭剔除功能即可
  • 只在 AlphaTest.shader 里Pass中加一句 Cull Off
    在这里插入图片描述

2.透明度混合的双面渲染

  • 因为关闭了深度写入,如果直接加 Cull Off 的话会造成前后面混乱
  • 所以,写了两个Pass (与AlphaBlend.shader一样)
    • 只在Pass中,第一个Pass只渲染背面 ,添加了Cull Front;第二个只渲染正面 添加了Cull Back
    • SubShader是会按照顺序执行Pass
      在这里插入图片描述

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

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

相关文章

go Channel原理 (三)

Channel 设计原理 不要通过共享内存的方式进行通信,而是应该通过通信的方式共享内存。 在主流编程语言中,多个线程传递数据的方式一般都是共享内存。 Go 可以使用共享内存加互斥锁进行通信,同时也提供了一种不同的并发模型,即通…

信息系统的安全模型

1. 信息系统的安全目标 信息系统的安全目标是控制和管理主体(含用户和进程)对客体(含数据和程序)的访问。作为信息系统安全目标,就是要实现: 保护信息系统的可用性; 保护网络系统服务的…

基于Java实现图像浏览器的设计与实现

图像浏览器的设计与实现 前言一、需求分析选题意义应用意义功能需求关键技术系统用例图设计JPG系统用例图图片查看系统用例图 二、概要设计JPG.javaPicture.java 三、详细设计类图JPG.java UML类图picture.java UML类图 界面设计JPG.javapicture.java 四、源代码JPG.javapictur…

jvm性能监控常用工具

在java的/bin目录下有许多java自带的工具。 我们常用的有 基础工具 jar:创建和管理jar文件 java:java运行工具,用于运行class文件或jar文件 javac:java的编译器 javadoc:java的API文档生成工具 性能监控和故障处理 jps jstat…

Spring Boot 实现 AOP 动态热插拔功能并附DEMO源码

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…

【解锁未来:深入了解机器学习的核心技术与实际应用】

解锁未来:深入了解机器学习的核心技术与实际应用 💎1.引言💎1.1 什么是机器学习? 💎2 机器学习的分类💎3 常用的机器学习算法💎3.1 线性回归(Linear Regression)&#x1…

基础算法模板

1. 相向双指针 class Solution { // 两数之和public int[] twoSum(int[] numbers, int target) {int left 0; // 第一步初始化开头和结尾两个指针int right numbers.length - 1;while (true) { // 之后一直while循环 int s numbers[left] numbers[right]; //计算左右两个…

Flutter循序渐进==>数据结构(列表、映射和集合)和错误处理

导言 填鸭似的教育确实不行,我高中时学过集合,不知道有什么用,毫无兴趣,等到我学了一门编程语言后,才发现集合真的很有用;可以去重,可以看你有我没有的,可以看我有你没有的&#xf…

mybatis实现多表查询

mybatis高级查询【掌握】 1、准备工作 【1】包结构 创建java项目,导入jar包和log4j日志配置文件以及连接数据库的配置文件; 【2】导入SQL脚本 运行资料中的sql脚本:mybatis.sql 【3】创建实体来包,导入资料中的pojo 【4】User…

Swift宏的实现

上篇介绍了Swift宏的定义与生声明,本篇主要看看是Swift宏的具体实现。结合Swift中Codable协议,封装一个工具让类或者结构体自动实现Codable协议,并且添加一些协议中没有的功能。 关于Codable协议 Codable很好,但是有一些缺陷&…

141个图表,完美展示数据分类别关系!

本文介绍使用Python工具seaborn详细实现分类关系图表,包含8类图141个代码模版。 分类关系图表用于展示数字变量和一个或多个分类变量之间的关系,可以进一步分为:箱形图(box plot)、增强箱形图(enhanced bo…

DP:子数组问题

文章目录 引言子数组问题介绍动态规划的基本概念具体问题的解决方法动态规划解法:关于子数组问题的几个题1.最大子数组和2.环形子数组的最大和3.乘积最大子数组4.乘积为正数的最长子数组长度5.等差数列划分 总结 引言 介绍动态规划(DP)在解决…

Deep-LIBRA:一种用于可靠量化乳腺密度的人工智能方法,并在乳腺癌风险评估中进行了独立验证| 文献速递-深度学习自动化疾病检查

Title 题目 Deep-LIBRA: An artificial-intelligence method for robust quantification of breast density with independent validation in breast cancer risk assessment Deep-LIBRA:一种用于可靠量化乳腺密度的人工智能方法,并在乳腺癌风险评估中…

【内网渗透】从0到1的内网渗透基础概念笔记

目录 域 域的介绍 单域 父域和子域 域树 域森林 域名服务器 活动目录 活动目录介绍 域内权限 组 域本地组 全局组 通用组 总结 示例 A-G-DL-P策略 重要的域本地组 重要的全局组、通用组 安全域划分 域 域的介绍 Windows域是计算机网络的一种形式&#xf…

【机器学习】FFmpeg+Whisper:二阶段法视频理解(video-to-text)大模型实战

目录 一、引言 二、FFmpeg工具介绍 2.1 什么是FFmpeg 2.2 FFmpeg核心原理 2.3 FFmpeg使用示例 三、FFmpegWhisper二阶段法视频理解实战 3.1 FFmpeg安装 3.2 Whisper模型下载 3.3 FFmpeg抽取视频的音频 3.3.1 方案一:命令行方式使用ffmpeg 3.3.2 方案二&a…

[论文精读]Variational Graph Auto-Encoders

论文网址:[1611.07308] Variational Graph Auto-Encoders (arxiv.org) 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎…

Android 界面库 (二) 之 Data binding 详细介绍

1. 简介 回顾我们在前面文章《Android 界面库 (一) 之 View binding 简单使用》中学习的 View Binding,它旨在简化 View 与代码之间的绑定过程。它会在编译时期为每个 XML 布局文件生成相应的绑定类(Binding class),该类里包含了布局文件每个有 ID 的 Vi…

基于SpringBoot扶农助农政策管理系统设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,…

利用 Docker 简化 Nacos 部署:快速搭建 Nacos 服务

利用 Docker 简化 Nacos 部署:快速搭建 Nacos 服务 引言 在微服务架构中,服务注册与发现是确保服务间通信顺畅的关键组件。Nacos(Dynamic Naming and Configuration Service)作为阿里巴巴开源的一个服务发现和配置管理平台&…

【单片机毕业设计选题24039】-基于单片机的太阳能储能智能恒温外卖柜设计

系统功能: 以单片机为控制核心,综合运用传感器、物联网、太阳能等技术,设计一种基于单片机为控制核心的智能恒温外卖柜。它由恒温系统、无线模块、智能提醒系统、供电系统等组成,通过太阳能电池板独立供电,利用太阳能储能元件驱动…