首页 > 其他分享 >UnityShader透明效果

UnityShader透明效果

时间:2023-01-13 22:58:43浏览次数:57  
标签:透明 效果 渲染 深度 透明度 fixed3 UnityShader 片元 Pass

透明效果

在实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道。

当开启透明混合后,当一个物体被渲染到屏幕上时,每个片元除了颜色和深度值之外,它还有另一个属性——透明度。

当透明度为1时,表示该像素是完全不透明的,而当其为0时,则表示该像素完全不会显示。

实现:使用透明度测试,这种方法其实无法得到真正的半透明效果

另一种方法是透明度混合

对于不透明(Opaque)物体,不考虑他们的渲染顺序也能得到正确的排序效果,这是由于强大的深度缓冲(depth buffer,z-buffer)的存在。

在实时渲染中,深度缓冲是用于解决可见性(visibility)问题的,它可以决定哪个物体的哪些部分会被渲染在前面,而哪些部分会被其他物体遮挡。

基本思想:根据深度缓冲中的值来判断该片元距离摄像机的距离,当渲染一个片元时,需要把它的深度值和已经存在与深度缓冲中的值进行比较(开启了深度测试),如果它的值距离摄像机更远,那么说明这个片元不应该被渲染到屏幕上(有物体挡住了它)。否则,这个片元应该覆盖掉此时颜色缓冲中的像素值,并把它的深度值更新到深度缓冲中(开启了深度写入)。

使用透明度混合时,关闭了深度写入(ZWrite)


透明度测试

只要一个片元的透明度不满足条件(通常是小于某个阈值),那么它对应的片元就会被舍弃。被舍弃的片元将不会再进行任何处理,也不会对颜色缓冲区产生任何影响;否则就会按照普通的不透明物体的处理方式来处理它,即进行深度测试、深度写入等。

透明度混合

得到真正的半透明效果。它会使用片元的透明度作为混合因子,与已经存储在颜色缓冲区中的颜色值进行混合,得到新的颜色。但是,透明度混合需要关闭深度写入,这使得我们需要非常小心物体的渲染顺序。

UnityShader中的渲染顺序

Unity提供了渲染队列这一解决方案来解决渲染顺序的问题。

可以使用SubShader的Queue标签来决定我们的模型将归于哪个渲染队列。

Background 1000

Geometry 2000

AlphaTest 2450

Transparent 3000

Overlay 4000

ZWrite Off用于关闭深度写入。

透明度测试

工作原理:

只要一个片元的透明度不满足条件,那么它对应的片元就会被舍弃。被舍弃的片元将不会再进行任何处理,也不会对颜色缓冲残产生任何影响;否则,就会按照普通不透明物体的处理方式来处理它。

使用clip函数进行深度测试。

Properties
  {
       _Color("Color",Color)=(1,1,1,1)
       _MainTex ("Texture", 2D) = "white" {}
       _Cutoff("Alpha Cutoff",Range(0,1))=0.5
  }
   SubShader
  {
       Tags{"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCoutout"}
       Pass
      {
           Tags{"LightMode"="ForwardBase"}
           CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
           
           #include "Lighting.cginc"
           #include "UnityCG.cginc"

           fixed4 _Color;
           sampler2D _MainTex;
           float4 _MainTex_ST;
           fixed _Cutoff;

           struct v2f
          {
               float4 pos : SV_POSITION;
               float2 uv : TEXCOORD0;
               fixed3 worldNormal :TEXCOORD1;
               fixed3 worldPos :TEXCOORD2;
          };

           v2f vert (appdata_base v)
          {
               v2f o;
               o.pos = UnityObjectToClipPos(v.vertex);
               o.uv = TRANSFORM_TEX(v.texcoord ,_MainTex);
               o.worldNormal = UnityObjectToWorldNormal(v.normal);
               o.worldPos = UnityObjectToWorldDir(v.vertex);
               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);
               // if((texColor.a - _Cutoff)<0.0){
               //     discard;
               // }
               fixed3 albedo  = texColor.rgb  * _Color.rgb;
               fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
               fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(worldNormal,worldLightDir));
               return fixed4(ambient+diffuse,1.0);
          }
           ENDCG
      }
  }
   Fallback "Transparent/Cutoff/VertexLit"

RenderType标签可以让Unity把这个Shader归入到提前定义的组中,以指明该Shader是一个使用了透明度测试的Shader。

RenderType标签通常被用于着色器替换功能。

IgnoreProjector设置为True,意味着该Shader不会受到投影器的影响。

Discard指令显示剔除该片元

使用内置的Transparent/Cutoff/VertexLit来作为回调Shader,这不仅能够保证在我们编写的SubShader无法在当前显卡上工作时可以有适合的代替Shader,还可以保证使用透明度测试的物体可以正确地向其他物体投射阴影。

 

透明度混合

原理:

这种方法可以得到真正的半透明效果。他会使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。但是,透明度混合需要关闭深度写入,这使得要非常小心物体的渲染顺序。

Unity的混合命令——Blend。想要实现半透明效果就需要把当前自身的颜色和已经存在与颜色缓冲中的颜色值进行混合,混合时使用的函数就是由该指令决定的。

使用Blend SrcFactor DstFactor来进行混合。需要注意的是,这个命令在设置混合因子的同时也开启了混合模式。只有开启混合之后,设置片元的透明通道才有意义,而Unity在我们使用Blend命令的时候就自动帮我们打开了。

Properties
  {
       _Color("Color",Color)=(1,1,1,1)
       _MainTex ("Texture", 2D) = "white" {}
       _AlphaScale("Alpha Scale",Range(0,1))=1
  }
   SubShader
  {
       Tags {"Queue"="Transparent" "IgnoreProject"="True" "RenderType"="Transparent" }
       Pass
      {
           Tags{"LigheMode"="ForwardBase"}
           ZWrite off
           Blend SrcAlpha OneMinusSrcAlpha
           CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag

           #include "UnityCG.cginc"
           #include "Lighting.cginc"

           fixed4 _Color;
           sampler2D _MainTex;
           float4 _MainTex_ST;
           fixed _AlphaScale;

           struct v2f
          {
               float4 pos : SV_POSITION;
               float2 uv : TEXCOORD0;
               fixed3 worldNormal :TEXCOORD1;
               fixed3 worldPos :TEXCOORD2;
          };

           v2f vert (appdata_base v)
          {
               v2f o;
               o.pos = UnityObjectToClipPos(v.vertex);
               o.uv = TRANSFORM_TEX(v.texcoord ,_MainTex);
               o.worldNormal = UnityObjectToWorldNormal(v.normal);
               o.worldPos = UnityObjectToWorldDir(v.vertex);
               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 * saturate(dot(worldNormal,worldLightDir));
               return fixed4(ambient+diffuse,texColor.a * _AlphaScale);
          }
           ENDCG
      }
  }

透明度混合使用的渲染队列是Transparent的队列。RenterType标签可以让Unity把这个Shader归入到提前定义的组(Transparent组)中,用来指明该Shader是一个使用了透明度混合的Shader。

Zwrite Off 关闭深度写入

Blend SrcAlpha OneMinusSrcAlpha开启并设置该Pass的混合模式。

设置了该片元着色器返回值中的透明通道,它是纹理像素的透明通道和材质参数_AlphaScale的乘积。

关闭深度写入的问题:

当模型本身有复杂的遮挡关系或者是包含了复杂的非凸网格的时候,就会有各种各样因为排序错误而产生的错误的透明效果。

这都是因为关闭深度写入造成的,因为这样我们就无法对模型进行像素级别的深度排序。

我们可以重新利用深度写入,让模型可以像半透明物体一样进行导入淡出。

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

解决方法:使用两个Pass来渲染模型:

第一个Pass开启深度写入,但不输出颜色,它的目的仅仅是为了把该模型的深度值写入深度缓冲中;第二个Pass进行正常的透明度混合,由于上一个Pass已经得到了逐像素的正确的深度信息,该Pass就可以按照像素级别的深度排序结果进行透明渲染。

缺点:多使用一个Pass会对性能造成影响。

pass{
           ZWrite On
           ColorMask 0
      }

这个新Pass的目的仅仅是为了把模型的深度信息写入深度缓冲中,从而剔除模型中被自身遮挡的片元。

渲染命令ColorMask :用于设置颜色通道的写掩码。

ColorMask RGB |A|0|

当ColorMask设为0时,意味着该Pass不写入任何颜色通道,即不会输出任何颜色。

双面透明的渲染效果

透明度测试

Tags{"LightMode"="ForwardBase"}
           Cull off

透明度混合

把双面渲染的工作分成两个Pass­——第一个Pass只渲染背面,第二个Pass只渲染正面,由于Unity会顺序执行SubShader中的各个Pass因此我们可以保证背面总是在正面被渲染之前渲染,从而保证正确的深度渲染关系。

只需要将AlphaBlend的代码改动一下即可

(1) 复制原Pass的代码得到另一个Pass

(2) 在两个Pass中分别使用Cull指令突出不同朝向的渲染图元

先Front 再Back

TRANSLATE with x English
Arabic Hebrew Polish
Bulgarian Hindi Portuguese
Catalan Hmong Daw Romanian
Chinese Simplified Hungarian Russian
Chinese Traditional Indonesian Slovak
Czech Italian Slovenian
Danish Japanese Spanish
Dutch Klingon Swedish
English Korean Thai
Estonian Latvian Turkish
Finnish Lithuanian Ukrainian
French Malay Urdu
German Maltese Vietnamese
Greek Norwegian Welsh
Haitian Creole Persian  
  TRANSLATE with COPY THE URL BELOW Back EMBED THE SNIPPET BELOW IN YOUR SITE Enable collaborative features and customize widget: Bing Webmaster Portal Back     此页面的语言为加泰罗尼亚语   翻译为        
  • 中文(简体)
  • 中文(繁体)
  • 丹麦语
  • 乌克兰语
  • 乌尔都语
  • 亚美尼亚语
  • 俄语
  • 保加利亚语
  • 克罗地亚语
  • 冰岛语
  • 加泰罗尼亚语
  • 匈牙利语
  • 卡纳达语
  • 印地语
  • 印尼语
  • 古吉拉特语
  • 哈萨克语
  • 土耳其语
  • 威尔士语
  • 孟加拉语
  • 尼泊尔语
  • 布尔语(南非荷兰语)
  • 希伯来语
  • 希腊语
  • 库尔德语
  • 德语
  • 意大利语
  • 拉脱维亚语
  • 挪威语
  • 捷克语
  • 斯洛伐克语
  • 斯洛文尼亚语
  • 旁遮普语
  • 日语
  • 普什图语
  • 毛利语
  • 法语
  • 波兰语
  • 波斯语
  • 泰卢固语
  • 泰米尔语
  • 泰语
  • 海地克里奥尔语
  • 爱沙尼亚语
  • 瑞典语
  • 立陶宛语
  • 缅甸语
  • 罗马尼亚语
  • 老挝语
  • 芬兰语
  • 英语
  • 荷兰语
  • 萨摩亚语
  • 葡萄牙语
  • 西班牙语
  • 越南语
  • 阿塞拜疆语
  • 阿姆哈拉语
  • 阿尔巴尼亚语
  • 阿拉伯语
  • 韩语
  • 马尔加什语
  • 马拉地语
  • 马拉雅拉姆语
  • 马来语
  • 马耳他语
  • 高棉语
 

标签:透明,效果,渲染,深度,透明度,fixed3,UnityShader,片元,Pass
From: https://www.cnblogs.com/ApolloniaLKX/p/17050914.html

相关文章

  • React中实现keepalive组件缓存效果
    背景:由于react官方并没有提供缓存组件相关的api(类似vue中的keepalive),在某些场景,会使得页面交互性变的很差,比如在有搜索条件的表格页面,点击某一条数据跳转到详情页面,再返回......
  • 攀爬效果2
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><linkrel="stylesheet"href="try.css"><title>Document</title></head><body><......
  • css常规样式效果
    <!DOCTYPEhtml><html><style>p.dashed{border-style:dashed;border-width:5px;}.solid{border-style:solid;border-width:10px;border-color:red;text-al......
  • UnityShader光照基础
    光照基础环境光和自发光环境光:只需通过Unity的内置变量UNITY_LIGHTMODEL_AMBIENT就可以得到环境光的颜色和强度。自发光:把材质的自发光颜色添加到输出颜色上即可。漫......
  • jquery.liMarquee.js-文字滚动效果
    jquery.liMarquee.js插件:jquery多风格多功能滚动特效代码插件说明:须引入3个文件jquery.js、liMarquee的js和css文件代码:<!DOCTYPEhtml><htmllang="en"><head>......
  • 直播平台搭建,uni-app 实现搜索关键词高亮效果
    直播平台搭建,uni-app实现搜索关键词高亮效果1.封装搜索关键词方法  //搜索关键词exportfunctionsearchKeyword(keyword,city){ returnnewPromise((resove......
  • 视频直播APP源码,通过css控制div内容展开更多/收起效果
    视频直播APP源码,通过css控制div内容展开更多/收起效果一.实现思路1.需要设置一个变量控制展开/收起效果2.提前写好最高高度的class样式,超出这个高度多余内容会隐藏......
  • VUE 回车换行提交表单 跑马灯效果 只允许文本框中输入0-9数字
    导入vue.js<scriptsrc="vue-2.5.17.js"></script>1.回车换行提交表单方法一<divid="app"> <inputtype="text"v-model="name"@keydown.13="mouse(0)">{{name}}<......
  • flutter 效果实现 —— 下拉滑动面板
    效果:代码:classHomePageextendsStatefulWidget{constHomePage({Key?key}):super(key:key);finaldoublemaxHeight=200;finaldoubleminHeight=......
  • 增强现实AR互动方式营造震撼的视觉效果
    虽然疫情的爆发带来了许多负面影响,但不可否认的是,增强现实AR和虚拟现实VR技术在很大程度上借着疫情加速了发展,帮助人们减轻了疫情为生活带来的一些困扰。AR互动作为AR技术......