当前位置:   article > 正文

[Unity]透明材质_unity透明材质

unity透明材质

学习目标:

Unity Shader的渲染渲染顺序中的透明材质


学习内容:

1、透明度测试

2、透明度混合

3、渲染队列

4、透明模型


缘由:一般渲染的话会根据深度缓冲来确定渲染顺序的,但是由于透明材质需要关闭深度写入,因为透明材质会混合队列中其他材质的颜色,不能用普通材质的方法来渲染,1和2分别讲两种实现透明的方式

1、透明度测试

        比较极端的测试,如果片元的透明度不满足某个阈值,那么会被直接舍弃,否则会跟不透明片元一样进行深度测试、深度写入等,不考虑关闭深度写入的问题,结果只会是完全透明或者不透明

2、透明度混合

        该方法可得到真正的半透明效果,核心理念是与将自身的透明度与已经存在颜色缓冲中的颜色进行混合,该方法要点是要记住如果是以  透明->不透明  物体的顺序进行渲染,那就先渲染不透明物体,再将颜色缓冲中的颜色与透明片元进行混合,如果反过来,是不透明->透明的话那么就不会渲染透明片元,所以渲染队列十分重要。

3、渲染队列

        渲染队列可以理解为多个火车车厢,分别为多个组,会根据队列索引号来渲染,每个队列都有特定功能 

我们上面讲过因为不能使用深度环存因此,渲染顺序十分重要,就有了渲染队列

4、透明模型

        本项目为书籍自带的模型,实际效果如下

        透明的部分为贴图特定的颜色分布,上面展示的是使用透明度测试的方法制作的,显示出来的两种极端要么完全消失,要么可见。

        代码如下

  1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  3. Shader "Unity Shaders Book/Chapter 8/Alpha Test" {
  4. Properties {
  5. _Color ("Color Tint", Color) = (1, 1, 1, 1)
  6. _MainTex ("Main Tex", 2D) = "white" {}
  7. _Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
  8. }
  9. SubShader {
  10. Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}//渲染队列名为AlphaTest,忽略投影器影响,规划到TransparentCutout这个组
  11. Pass {
  12. Tags { "LightMode"="ForwardBase" }//渲染模式是用前向渲染->还有一种叫延迟渲染
  13. CGPROGRAM
  14. #pragma vertex vert//顶点着色器
  15. #pragma fragment frag//片元着色器
  16. #include "Lighting.cginc"//添加内置变量
  17. fixed4 _Color;
  18. sampler2D _MainTex;
  19. float4 _MainTex_ST;
  20. fixed _Cutoff;
  21. struct a2v {//顶点着色器输入结构
  22. float4 vertex : POSITION;
  23. float3 normal : NORMAL;
  24. float4 texcoord : TEXCOORD0;
  25. };
  26. struct v2f {//顶点着色器输出结构
  27. float4 pos : SV_POSITION;
  28. float3 worldNormal : TEXCOORD0;
  29. float3 worldPos : TEXCOORD1;
  30. float2 uv : TEXCOORD2;
  31. };
  32. v2f vert(a2v v) {//顶点着色器
  33. v2f o;//顺序分别为切线空间、世界空间、世界坐标、纹理坐标进行变换最后返回
  34. o.pos = UnityObjectToClipPos(v.vertex);
  35. o.worldNormal = UnityObjectToWorldNormal(v.normal);
  36. o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  37. o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
  38. return o;
  39. }
  40. fixed4 frag(v2f i) : SV_Target {
  41. fixed3 worldNormal = normalize(i.worldNormal);
  42. fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  43. fixed4 texColor = tex2D(_MainTex, i.uv);//获取贴图坐标
  44. // Alpha test
  45. clip (texColor.a - _Cutoff);//如果不为负数则采用该片元,意义在于texColor为目标材质,Cutoff为材质参数,如果低于则表明为为透明材质
  46. // Equal to
  47. // if ((texColor.a - _Cutoff) < 0.0) {
  48. // discard;//意义跟clip一样剔除掉该片元
  49. // }
  50. //计算环境光和漫反射将其计算后输出
  51. fixed3 albedo = texColor.rgb * _Color.rgb;
  52. fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
  53. fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
  54. return fixed4(ambient + diffuse, 1.0);
  55. }
  56. ENDCG
  57. }
  58. }
  59. FallBack "Transparent/Cutout/VertexLit"
  60. }

 另一种方法透明度混合,核心理念是要与颜色缓冲中的颜色混合得出透明片元的颜色,结果如下,透明则选择了整个材质

代码如下

  1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  3. Shader "Unity Shaders Book/Chapter 8/Alpha Blend" {
  4. Properties {
  5. _Color ("Color Tint", Color) = (1, 1, 1, 1)
  6. _MainTex ("Main Tex", 2D) = "white" {}
  7. _AlphaScale ("Alpha Scale", Range(0, 1)) = 1
  8. }
  9. SubShader {
  10. Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
  11. Pass {
  12. Tags { "LightMode"="ForwardBase" }
  13. ZWrite Off
  14. Blend SrcAlpha OneMinusSrcAlpha
  15. CGPROGRAM
  16. #pragma vertex vert
  17. #pragma fragment frag
  18. #include "Lighting.cginc"
  19. fixed4 _Color;
  20. sampler2D _MainTex;
  21. float4 _MainTex_ST;
  22. fixed _AlphaScale;
  23. struct a2v {
  24. float4 vertex : POSITION;
  25. float3 normal : NORMAL;
  26. float4 texcoord : TEXCOORD0;
  27. };
  28. struct v2f {
  29. float4 pos : SV_POSITION;
  30. float3 worldNormal : TEXCOORD0;
  31. float3 worldPos : TEXCOORD1;
  32. float2 uv : TEXCOORD2;
  33. };
  34. v2f vert(a2v v) {
  35. v2f o;
  36. o.pos = UnityObjectToClipPos(v.vertex);
  37. o.worldNormal = UnityObjectToWorldNormal(v.normal);
  38. o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  39. o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
  40. return o;
  41. }
  42. fixed4 frag(v2f i) : SV_Target {
  43. fixed3 worldNormal = normalize(i.worldNormal);
  44. fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  45. fixed4 texColor = tex2D(_MainTex, i.uv);
  46. fixed3 albedo = texColor.rgb * _Color.rgb;
  47. fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
  48. fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
  49. return fixed4(ambient + diffuse, texColor.a * _AlphaScale);
  50. }
  51. ENDCG
  52. }
  53. }
  54. FallBack "Transparent/VertexLit"
  55. }

 


总结:

        想要实现透明有两种方法,分别为透明度测试和透明度混合、核心表达出来的是1、如果不是透明就不显示 2、先渲染后面不透明物体再将颜色缓冲区中的数据混合得出透明物体的颜色,总体两者都需要注意渲染顺序

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/126988
推荐阅读
相关标签
  

闽ICP备14008679号