shader入门精要第八章

透明效果

透明是游戏中经常要使用的一种效果。在实时渲染中要实现透明效果,通常会在渲染模型时 控制它的透明通道 (Alpha Channel) 。当开启透明混合后,当一个物体被渲染到屏幕上时,每个 片元除了颜色值和深度值之外,它还有另 个属性一透明度 。当透明度为1 时,表示该像素是 完全不透明的,而当其为 0时,则表示该像素完全不会显示。 Unity 中,我们通常使用两种方法来实现透明效果:第一种是使用透明度测试(Alpha Test), 这种方法其实无法得到真正的半透明效果;另一种是透明度混合 (Alpha Blending )

对 于不透明 (opaque) 物体,不考虑它们的渲染顺序也能得到正确的排序效果,这是由于强大的深度 缓冲 depth buffer, 也被称为 z-buffer) 的存在。在实时渲染中 ,深度缓冲是用千解决可见性 visibility 问题的,它可以决定哪个物体的哪些部分会被渲染在前面,而哪些部分会被其他物体遮挡 。它的基本思想是 根据深度缓存中的值来判断该片元距离摄像机的距离,当渲染 一个片元时, 需要把它的 深度值和已经存在千深度缓冲中的值进行比较(如果开启了深度测试),如果它的值距离摄像机更 远,那么说明这个片元不应该被渲染到屏幕上(有物体挡住了它);否则,这个片元应该覆盖掉此 时颜色缓冲中的像素值,并把它的深度值更新到深度缓冲中(如果开启了深度写入)

简单来说,透明度测试和透明度混合的基本原理如下。

透明度测试:

只要 一个片元的透明度不满足条件(通常 是小于某个阙值),那么它对应的片元就会被舍弃。被舍弃的片元将不会再进行任何处理, 也不会对颜色缓冲产生任何影响;否则,就会按照普通的不透明物体的处理方式来处理它, 即进行深度测试、深度写入等。也就是说,透明度测试是不需要关闭深度写入的,它和其 他不透明物体最大的不同就是它会根据透明度来舍弃 些片元。虽然简单,但是它产生的 效果也很极端,要么完全透明,即看不到,要么完全不透明,就像不透明物体那样。

透明度混合:

这种方法可以得到真正的半透明效果。它会使用当前片元的透明度作为混合 因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。但是,透明度混合需 要关闭深度写入(我们下面会讲为什么需要关闭),这使得我们要非常小心物体的渲染顺 序。需要注意的是,透明度混合只关闭了深度写入,但没有关闭深度测试。这意味着,当 使用透明度混合渲染一个片元时,还是会比较它的深度值与当前深度缓冲中的深度值,如 果它的深度值距离摄像机更远,那么就不会再进行混合操作。这一点决定了,当 个不透 明物体出现在 个透明物体的前面,而我们先渲染了不透明物体,它仍然可以正常地遮挡 住透明物体。也就是说,对千透明度混合来说,深度缓冲是只读的。

渲染顺序

假设场景里有两个物体A和B, 如图8.1所示, 其中A是半透明 物体, 而B是不透明物体

我们来考虑不同的渲染顺序会有什么结果。

第一种情况

我们先渲染B, 再渲染A。那么由于不透明物体开启了深度测试和深度写入, 而此时深度缓冲中没有任何有效数据, 因此B首先会写入颜色缓冲和深度缓冲。 随后我 们渲染A, 透明物体仍然会进行深度测试, 因此我们发现和B相比,A距离摄像机更近, 因此, 我们会使用A的透明度来和颜色缓冲中的B的颜色进行混合, 得到正确的半透明 效果。

第二种情况

我们先渲染A, 再渲染B。 渲染A时, 深度缓冲区中没有任何有效数据, 因此A直接写入颜色缓冲, 但由于对半透明物体关闭了深度写入, 因此A不会修改深度 缓冲。 等到渲染B时,B会进行深度测试, 它发现,“咦, 深度缓存中还没有人来过, 那 我就放心地写入颜色缓冲了! "' 结果就是B会直接覆盖A的颜色。 从视觉上来看, B就 出现在了A的前面, 而这是错误的。

从这个例子可以看出, 当关闭了深度写入后, 渲染顺序是多么重要。 由此我们知道, 我们应 该在不透明物体渲染完之后再渲染半透明物体。那么,如果都是半透明物体,渲染顺序还重要吗? 答案是肯定的。还是假设场景里有两个物体A和B, 如图8.2所示,其中A和B都是半透明物体。

我们还是考虑不同的渲染顺序有什么不同的结果

第一种情况

我们先渲染B, 再渲染A。 那么B会正常写入颜色缓冲, 然后A会和颜色 缓冲中的B颜色进行混合, 得到正确的半透明效果。

第二种情况

我们先渲染A, 再渲染B。 那么A会先写入颜色缓冲, 随后B会和颜色缓 冲中的A进行混合, 这样混合结果会完全反过来, 看起来就好像B在A的前面, 得到的 就是错误的半透明结构。 从这个例子可以看出, 半透明物体之间也是要符合一定的渲染顺序的

渲染引擎一般都会先对物体进行排序,再渲染。常用的方法是。

先渲染所有不透明物体,并开启它们的深度测试和深度写入。

把半透明物体按它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半 透明物体,并开启它们的深度测试,但关闭深度写入。

UnityShader的渲染顺序

Unity使用渲染队列(render queue)解决渲染顺序问题。通过使用SubShader的Queue标签决定渲染的模型属于哪一个渲染队列。Unity内部使用一系列索引号表示渲染顺序,索引号越小渲染越早。

若是使用透明度测试实现透明效果:

SubShader{
	Tags{"Queue"="AlphaTest"}
	Pass{
	}
}  

若是使用透明度混合实现透明效果:

SubShader{
	Tags{"Queue"="Transparent"}
	Pass{
		Zwrite Off//用于关闭深度写入
	}
}

使用透明度混合是需要关闭深度写入的。

透明度测试(Alpha Test)实例

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

透明剪切常用于复杂轮廓,明确边缘的物体表现 ,如:镂空金属,裙摆边缘,特定风格下的头发啊啊,树叶等等。

也常用于卡通渲染的特效表现。

透明剪切有 没有排序的问题,但是边缘效果太实,移动端性能较差。

AlphaBlend中,树叶的边缘比较柔和透明,并且中心部位的排序比较混乱。而AlphaCutout中,边缘清晰并且镇中心排序整正确。

AlphaCutout的边缘类似于1和0,1是开,0是关。而AlphaBlend则是边缘是1-0。是从0到1的一个范围,有类似于渐变的效果。

通常在片元着色器中使用clip函数进行透明度测试。函数定义:

void clip(float x){
	if(any(x<0))
		discard;
}

代码

Shader "Unlit/VS_Shader_AlphaTest"{
    Properties{
        _Color("Color",Color) = (1,1,1,1)
        _MainTex("MainTex", 2d) = "white"{}
        _Cutoff("Cutoff", range(0.0, 1.0)) = 0.5
    }
        SubShader{                                 //SubSgader是可以有多个的,你可以在一个Sahder里面写多个SubShader
            Tags {
                "Queue" = "AlphaTest"
                "RenderType" = "TransparentCutout"    //unity内置专门的透明裁剪AC渲染类型。             
                "IgnoreProjector" = "True"            //把投射器的相应关闭
           //通常,使用透明度测试的Shader都应该在SubShader中设置这几个标签
        }
            Pass {
                Name "FORWARD"
                Tags {
                    "LightMode" = "ForwardBase"
                }


                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
               
                #include "Lighting.cginc"
                

            // 输入参数
           uniform sampler2D _MainTex; 
           uniform float4 _MainTex_ST;//声明一个贴图的_XXX_ST来让贴图支持缩放与位移TilingOffset
           uniform half _Cutoff;
           uniform fixed4 _Color;
           //输入结构
           struct VertexInput {
               float4 vertex : POSITION;  //顶点信息
               float2 uv : TEXCOORD0;     // UV信息 采样贴图用
               float3 normal:NORMAL;
             
           };

           //输出结构
           struct VertexOutput {
               float4 pos : SV_POSITION;  //顶点信息
               float3 nDirWS:TEXCOORD0;
               float3 posWS:TEXCOORD1;
               float2 uv0:TEXCOORD2;

                   };

           //顶点Shader
           VertexOutput vert(VertexInput v) {
               VertexOutput o = (VertexOutput)0;
               o.pos = UnityObjectToClipPos(v.vertex);
               o.nDirWS = UnityObjectToWorldNormal(v.normal);
               o.posWS = mul(unity_ObjectToWorld, v.vertex).xyz;
               o.uv0 = TRANSFORM_TEX(v.uv, _MainTex);        
               return o;
           }

           //像素Shader
           float4 frag(VertexOutput i) : COLOR {
            fixed3 nDirWS = normalize(i.nDirWS);
            fixed3 lDirWS = normalize(UnityWorldSpaceLightDir(i.posWS));

            fixed4 texColor = tex2D(_MainTex, i.uv0);// 采样贴图 RGB颜色 A透贴
               
                          // 透明贴图就是输入颜色贴图的A通道
               clip(texColor.a - _Cutoff);                        // 透明剪切就是透明贴图减去输入可控制的透明裁切阈值
               fixed3 albedo = texColor.rgb * _Color;
            
               fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
               fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(nDirWS, lDirWS));
               return fixed4(ambient+ diffuse, 1.0);             //输出 返回,返回一个值输出
           }
           ENDCG
       }
        }
            FallBack "Diffuse"
}

 

采样贴图

 

自上到下,CutOff值分别为0.65,0.75

漫反射贴图自带透明通道a,使用clip函数根据传入的透明度与阈值的插值判断片元舍弃还是按照不透明处理,可以看出透明度测试效果要么为全透明,要么为完全不透明。

透明度混合

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

透明混合常用于复杂的轮廓,无明显边缘的物体表现,常用于半透明的物体表现。也用于一般的特效表现。

透明混合的移动端性能较好,边缘过度效果比较好。但是透明混合有透明排序问题,会有后方物体渲染在前列的缺点,需要手动设置透明排序。

Shader "Unlit/AlphaBlender"
{
    Properties{
        _MainTex("_MainTex", 2d) = "white"{}
    _AlphaScale("AlphaScale",Range(0,1)) = 1
    }
        SubShader{                                 //SubSgader是可以有多个的,你可以在一个Sahder里面写多个SubShader
            Tags {
                "Queue" = "Transparent"               //调整渲染顺序,设置到透明的渲染队列
                "RenderType" = "Transparent"          //"RenderType"="Transparent"指明该shader为使用了透明度混合的shader               
                "IgnoreProjector" = "True"            //把投射器的相应关闭
            }
            Pass {
                Name "FORWARD"
                Tags {
                    "LightMode" = "ForwardBase"
                }
                Zwrite Off  //关闭深度写入
                Blend One OneMinusSrcAlpha          //修改混合方式One/SrcAlpha OneMinusSrcAlpha

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                #include "Lighting.cginc"
                #pragma multi_compile_fwdbase_fullshadows
                #pragma target 3.0

        // 输入参数
       uniform sampler2D _MainTex; uniform float4 _MainTex_ST;//声明一个贴图的_XXX_ST来让贴图支持缩放与位移TilingOffset
        fixed   _AlphaScale;
       //输入结构
       struct VertexInput {
           float4 vertex : POSITION;  //顶点信息
           float2 uv : TEXCOORD0;     // UV信息 采样贴图用
       };

       //输出结构
       struct VertexOutput {
           float4 pos : SV_POSITION;  //顶点信息
           float2 uv : TEXCOORD0;     // UV信息 采样贴图用
       };

       //顶点Shader
       VertexOutput vert(VertexInput v) {
           VertexOutput o = (VertexOutput)0;
               o.pos = UnityObjectToClipPos(v.vertex);   // 顶点位置 OS>CS
               o.uv = TRANSFORM_TEX(v.uv, _MainTex);       // UV信息 支持面板上的缩放与位移(TilingOffset)
           return o;
       }

       //像素Shader
       float4 frag(VertexOutput i) : COLOR {
           half4 var_MainTex = tex2D(_MainTex, i.uv);      // 采样贴图 RGB颜色 A透贴
           return (var_MainTex* _AlphaScale);             //输出 返回,返回一个值输出
       }
       ENDCG
   }
    }
        FallBack "Diffuse"
}

 

只是移除了透明度测试的 代码,并设置了该片元着色 器返回值中的透明通道 它是纹理像素的透明通道和 质参数 AlphaScale 的乘积

Alpha Scale 不同数值下的效果

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

当模型本身具有复杂的遮挡关系或者包含复杂非凸网格时,未开启深度写入,会有因为排序错误产生的错误透明效果。一种解决办法是使用两个Pass来对模型进行渲染,第一个Pass开启深度写入,不输出颜色,第二个进行正常透明度混合。

Shader "AlphaBlendZwrite" {
	Properties{
	
		_MainTex("MainTex",2D) = "white"{}
		_AlphaScale("AlphaScale",Range(0,1)) = 1
	}
		SubShader{
			Tags{"Queue" = "Transparent"
			"IgnoreProjector" = "True" 
			"RenderType" = "Transparent"}//"RenderType"="Transparent"指明该shader为使用了透明度混合的shader
			

			//开启深度写入的Pass是为了将模型的深度信息写入深度缓冲中,从而剔除模型中被自身遮挡的片元
			Pass{
				ZWrite On
				ColorMask 0//ColorMask  RGB | A | 0  ,设置为0时,表示该Pass不写入任何颜色通道,不会输出任何颜色。
			}
			Pass{
				Tags{"LightMode" = "ForwardBase"}

				Zwrite Off  //关闭深度写入
				Blend SrcAlpha OneMinusSrcAlpha  //设置混合因子为源的透明度 

				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "Lighting.cginc"

	
				sampler2D _MainTex;
				float4 _MainTex_ST;
				fixed   _AlphaScale;

				struct VertexInput {
					float4 vertex:POSITION;				
					float4 uv:TEXCOORD0;
				};

				struct VertexOutput {
					float4 pos:SV_POSITION;
					float3 posWS:TEXCOORD0;					
					float2 uv:TEXCOORD2;
				};

				VertexOutput vert(VertexInput v) {
					VertexOutput o = (VertexOutput)0;
					o.pos = UnityObjectToClipPos(v.vertex);
					o.posWS = mul(unity_ObjectToWorld,v.vertex).xyz;				
					o.uv = TRANSFORM_TEX(v.uv,_MainTex);

					return o;
				}

				float4 frag(VertexOutput i) : COLOR{		

					fixed4 var_MainTex = tex2D(_MainTex,i.uv);

				

					return fixed4(var_MainTex * _AlphaScale);
				}
				ENDCG
			}
		}
			FallBack "Transparent/VertexLit"
}

 

右侧为添加深度写入的Pass后,模型内部的遮挡效果正常。

透明重叠Addtive·AD

透明重叠常用于发光体,做辉光的表现,一般是特效使用,用作提亮道具等等。

透明重叠也有排序问题,多层叠加会容易堆爆性能(OverDraw),作为辉光效果但是可以用后处理来做代替。

Shader "AlphaBlendZwrite" {
	Properties{
	
		_MainTex("MainTex",2D) = "white"{}
		_AlphaScale("AlphaScale",Range(0,1)) = 1
	}
		SubShader{
			Tags{"Queue" = "Transparent"
			"IgnoreProjector" = "True" 
			"RenderType" = "Transparent"}//"RenderType"="Transparent"指明该shader为使用了透明度混合的shader
			

			//开启深度写入的Pass是为了将模型的深度信息写入深度缓冲中,从而剔除模型中被自身遮挡的片元
			Pass{
				ZWrite On
				ColorMask 0
			}
			Pass{
				Tags{"LightMode" = "ForwardBase"}

				Zwrite Off  //关闭深度写入
				Blend SrcAlpha OneMinusSrcAlpha  //设置混合因子为源的透明度 

				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "Lighting.cginc"

	
				sampler2D _MainTex;
				float4 _MainTex_ST;
				fixed   _AlphaScale;

				struct VertexInput {
					float4 vertex:POSITION;				
					float4 uv:TEXCOORD0;
				};

				struct VertexOutput {
					float4 pos:SV_POSITION;
					float3 posWS:TEXCOORD0;					
					float2 uv:TEXCOORD2;
				};

				VertexOutput vert(VertexInput v) {
					VertexOutput o = (VertexOutput)0;
					o.pos = UnityObjectToClipPos(v.vertex);
					o.posWS = mul(unity_ObjectToWorld,v.vertex).xyz;				
					o.uv = TRANSFORM_TEX(v.uv,_MainTex);

					return o;
				}

				float4 frag(VertexOutput i) : COLOR{		

					fixed4 var_MainTex = tex2D(_MainTex,i.uv);

				

					return fixed4(var_MainTex * _AlphaScale);
				}
				ENDCG
			}
		}
			FallBack "Transparent/VertexLit"
}

 

 

shaderlab 的混合命令

混合如何实现

混合原理

常见的混合类型

Shader "Unlit/VS_Shader_Alpha"
{
    Properties {       
        _MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}
        _Opacity ("透明度", range(0, 1)) = 0.5
        [Enum(UnityEngine.Rendering.BlendMode)]             //unity自带的源乘子
        _BlendSrc ("混合源乘子", int) = 0
        [Enum(UnityEngine.Rendering.BlendMode)]             //unity自带的目标乘子
        _BlendDst ("混合目标乘子", int) = 0
        [Enum(UnityEngine.Rendering.BlendOp)]               //unity自带的运算符
        _BlendOp ("混合算符", int) = 0
    }
    SubShader {                                 //SubSgader是可以有多个的,你可以在一个Sahder里面写多个SubShader
        Tags {
            "Queue"="Transparent"               //调整渲染顺序,设置到透明的渲染队列
            "RenderType"="Transparent"          //unity内置的渲染类型。
            "ForceNoShadowCasting"="True"       //强制关闭阴影投射(特效一般不用投影,如果特殊可以打开)
            "IgnoreProjector"="True"            //把投射器的相应关闭
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            BlendOp [_BlendOp]                  // 可自定义混合算符
            Blend [_BlendSrc] [_BlendDst]       // 可自定义混合模式

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma target 3.0

             // 输入参数
            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;//声明一个贴图的_XXX_ST来让贴图支持缩放与位移TilingOffset

            //输入结构
            struct VertexInput {
                float4 vertex : POSITION;  //顶点信息
                float2 uv : TEXCOORD0;     // UV信息 采样贴图用
            };

            //输出结构
            struct VertexOutput {
                float4 pos : SV_POSITION;  //顶点信息
                float2 uv : TEXCOORD0;     // UV信息 采样贴图用
            };

            //顶点Shader
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                    o.pos = UnityObjectToClipPos( v.vertex );   // 顶点位置 OS>CS
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);       // UV信息 支持面板上的缩放与位移(TilingOffset)
                return o;
            }

            //像素Shader
            float4 frag(VertexOutput i) : COLOR {
                half4 var_MainTex = tex2D(_MainTex, i.uv);      // 采样贴图 RGB颜色 A透贴
                return var_MainTex;             //输出 返回,返回一个值输出
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

 

 

双面渲染的透明效果

默认情况下渲染引擎剔除了物体背面(相对于摄像机的方向)的渲染图元,而只渲染了物体的 面。如果我们想要得到双面渲染的效果,可以使用 Cull 指令来控制需要剔除哪个面的渲染图元。

Cull | Back | Front | Off     

设置为Back 背对摄像机的图元不会被渲染,设置为Front朝向摄像机的图元不会被渲染,设置为Off,双面渲染。

透明度测试双面渲染

Pass{
  	Tags{"LightMode"="ForwardBase"}

  	Cull Off   //开启双面渲染效果     
  	}   

这行代码的作用是关闭剔除功能 使得该物体的所有的渲染图元都会被渲染。

透明度混合的双面渲染

Shader "Unlit/AlphaBlender"
{
    Properties{
        _MainTex("_MainTex", 2d) = "white"{}
        _AlphaScale("AlphaScale",Range(0,1)) = 1
    }
        SubShader{                                 //SubSgader是可以有多个的,你可以在一个Sahder里面写多个SubShader
            Tags {
                "Queue" = "Transparent"               //调整渲染顺序,设置到透明的渲染队列
                "RenderType" = "Transparent"          //"RenderType"="Transparent"指明该shader为使用了透明度混合的shader               
                "IgnoreProjector" = "True"            //把投射器的相应关闭
            }
            Pass {
                Name "FORWARD"
                Tags {
                    "LightMode" = "ForwardBase"
                }
                Zwrite Off  //关闭深度写入
                Cull Front  //先渲染背面
                Blend SrcAlpha OneMinusSrcAlpha  //设置混合因子为源的透明度 
               
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag        
                #include "Lighting.cginc"
              

        // 输入参数
       uniform sampler2D _MainTex; uniform float4 _MainTex_ST;//声明一个贴图的_XXX_ST来让贴图支持缩放与位移TilingOffset
        fixed   _AlphaScale;
        //输入结构
        struct VertexInput {
            float4 vertex : POSITION;  //顶点信息
            float2 uv : TEXCOORD0;     // UV信息 采样贴图用
        };

        //输出结构
        struct VertexOutput {
            float4 pos : SV_POSITION;  //顶点信息
            float2 uv : TEXCOORD0;     // UV信息 采样贴图用
        };

        //顶点Shader
        VertexOutput vert(VertexInput v) {
            VertexOutput o = (VertexOutput)0;
                o.pos = UnityObjectToClipPos(v.vertex);   // 顶点位置 OS>CS
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);       // UV信息 支持面板上的缩放与位移(TilingOffset)
            return o;
        }

        //像素Shader
        float4 frag(VertexOutput i) : COLOR {
            half4 var_MainTex = tex2D(_MainTex, i.uv);      // 采样贴图 RGB颜色 A透贴
            return (var_MainTex * _AlphaScale);             //输出 返回,返回一个值输出
        }
        ENDCG
    }

            Pass{
                Name "FORWARD"
                 Tags {"LightMode" = "ForwardBase"}
             Zwrite Off  //关闭深度写入
             Cull Back  //先渲染背面
            Blend SrcAlpha OneMinusSrcAlpha  //设置混合因子为源的透明度 
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag        
            #include "Lighting.cginc"


            // 输入参数
           uniform sampler2D _MainTex; uniform float4 _MainTex_ST;//声明一个贴图的_XXX_ST来让贴图支持缩放与位移TilingOffset
            fixed   _AlphaScale;
            //输入结构
            struct VertexInput {
                float4 vertex : POSITION;  //顶点信息
                float2 uv : TEXCOORD0;     // UV信息 采样贴图用
            };

            //输出结构
            struct VertexOutput {
                float4 pos : SV_POSITION;  //顶点信息
                float2 uv : TEXCOORD0;     // UV信息 采样贴图用
            };

            //顶点Shader
            VertexOutput vert(VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                    o.pos = UnityObjectToClipPos(v.vertex);   // 顶点位置 OS>CS
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);       // UV信息 支持面板上的缩放与位移(TilingOffset)
                return o;
            }

            //像素Shader
            float4 frag(VertexOutput i) : COLOR {
                half4 var_MainTex = tex2D(_MainTex, i.uv);      // 采样贴图 RGB颜色 A透贴
                return (var_MainTex * _AlphaScale);             //输出 返回,返回一个值输出
            }
            ENDCG
        }
}
        FallBack "Transparent/VertexLit"
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要理解shader入门精要,首先需要了解shader是指令代码,需要关联材质才能赋予游戏对象以特定的效果。材质按照关联的shader的规则,处理贴图等输入信息,达到特定的画面效果。 在Unity中,有几种类型的shader可供选择。一种是表面着色器(Surface Shader),它是对顶点/片断着色器的封装,更符合人类的思维模式,可以以极少的代码来实现不同的光照模型和不同平台下的需求。在表面着色器的开发中,我们直接在Subshader层次上编写代码,系统会将代码编译成适当的Pass。而顶点/片断着色器是更基础的shader类型,能够实现更多的效果,但表面着色器不一定能实现这些效果。还有一种被淘汰的固定管线着色器(Fixed Function Shaders),它在硬件上执行基本的命令,速度很快,但功能有限,不再推荐使用。 不同图形API都有各自的shader语言。在DirectX中,顶点shader叫做Vertex Shader,像素shader叫做Pixel Shader。而在OpenGL中,顶点shader也叫做Vertex Shader,但像素shader叫做Fragment Shader或者片断Shader。这些shader语言有不同的语法和特性,需要根据使用的图形API选择适当的语言来编写shader。 总结起来,要入门shader,首先需要了解shader是指令代码,需要关联材质才能实现效果。在Unity中,可以选择使用表面着色器、顶点/片断着色器或固定管线着色器来实现不同的效果。此外,不同图形API有不同的shader语言,需要根据使用的API选择合适的语言来编写shader
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值