Unity3D學習筆記(三十五):Shader著色器(2)- 頂點片元著色器
阿新 • • 發佈:2019-02-12
結構體 意義 float inline 有意義 pro spa ocl rcu Alpha測試
AlphaTest Great:大於
AlphaTest Less:小於
AlphaTest Equal:等於
AlphaTest GEqual:大於等於
AlphaTest LEqual:小於等於
AlphaTest Never:全不渲染
AlphaTest Always:全部渲染
如果使用後兩項的命名的情況下,比較後的數字項沒有意義
AlphaTest 比較項 數字
AlphaTest Great 0.5 //表示只渲染alpha值大於0.5的部分 AlphaTest Less 0.5 //表示只渲染alpha值小於0.5的部分混合命令 Blend SrcFactor DstFactor SrcFactor DstFactor 可以的取值 One表示1 Zero表示0 SrcColor當前的顏色 DstColor已經存在的顏色 SrcAlpha當前的透明度 DstAlpha已經存在的顏色的透明度 OneMinusSrcColor當前的顏色取反向 1-SrcColor OneMinusSrcAlpha當前的Alpha值取反向 1-SrcAlpha OneMinusDstColor已經存在的顏色取反向 1-DstColor OneMinusDstAlpha已經存在的顏色的透明度取反向 1-DstAlpha 最終顏色 = 新顏色 * SrcFactor + 舊顏色 * DstFactor 新顏色:即將寫入到顏色緩沖區的顏色 舊顏色:已經在顏色緩沖區的顏色 顏色運算法則(不同於向量運算法則) (r,g,b) * a = (r*a,g*a,b*a) (r,g,b) * (x,y,z) = (r*x,g*y,b*z) (r,g,b) + (x,y,z) = (r+x,g+y,b+z) A - (r,g,b) = (a-x,a-y,a-z) 例如
Blend Zero One //僅僅顯示背景的顏色,自身的效果不會顯示 Blend One Zero //顯示貼圖的RGB顏色,即使有透明通道的部分也顯示原色,不會透過去 Blend One One //貼圖色與背景色疊加,沒有透明通道處理,結果可能更趨近於(1,1,1) Blend SrcAlpha Zero //沒有透明通道部分顯示的是貼圖的原色,有透明通道0的部分,顯示黑色,0.5部分更趨近於黑色 Blend SrcAlpha OneMinusSrcAlpha //最終顏色 = 新顏色 * 當前透明度 + 舊顏色 * (1 - 當前透明度),最常用的透明混合方式
Shader "Lesson/AlphaTest" { Properties { _Tex(Cg語言,詳見PPT 頂點/片元著色器 核心: 頂點函數: 片元函數: 頂點函數在幾何階段,能從應用程序獲取頂點信息。這些信息就是通過頂點函數的參數傳遞進來的。頂點函數的返回值就是傳遞到片元函數裏的,片元函數也是通過參數去接收的 Float4 vertex:頂點坐標(模型空間下) Float4 normal:頂點的法線向量 Float4 tangent:頂點的切線向量 Float4 texcoord:第一UV顏色 Float4 texcoord1:第二UV顏色 Float4 color:頂點顏色 語義:語句的含義 頂點函數的形參後跟的語義:表示該形參的是接收應用程序傳遞來的是什麽。 對於頂點函數的方法後跟的語義:修飾的返回值,代表該返回值表示的是什麽。 對於片元函數的方法後跟的語義:修飾的是片元函數的返回值,代表的是告訴應該GPU是什麽 從應用程序階段到頂點函數階段 1.POSITION:表示應用程序把頂點坐標傳遞過來並且存儲在修飾的參數 2.NORMAL:表示法線,通常是float3 3TANGENT:表示切線 4.TEXCOORD0-N:從第1套UV到第7套UV 5.COLOR:頂點顏色 從頂點函數到片元函數能表示的語義 1.SV_POSITION:代表轉換之後的齊次空間坐標 2.COLOR0:代表一組顏色 2.COLOR1:代表一組顏色 4.TEXCOORD0-N:從第1套UV到第7套UV 從片元函數輸出的語義 SV_Target:輸出的值會渲染到屏幕上"紋理", 2D) = "white"{} _Alpha("透明度", Range(0,1)) = 0 } SubShader { Pass { //表示只渲染alpha值大於0.5的部分 AlphaTest Greater 0.5 AlphaTest Greater [_Alpha] //Blend SrcAlpha OneMinusSrcAlpha Blend SrcAlpha zero SetTexture[_Tex] { Combine texture } } } FallBack"Diffuse" }
// Upgrade NOTE: replaced ‘mul(UNITY_MATRIX_MVP,*)‘ with ‘UnityObjectToClipPos(*)‘ Shader "Lesson/VFColor" { Properties { _Color("顏色", Color) = (1,0,0,1) } SubShader { //1.頂點片元程序也要寫在Pass塊裏 Pass { //2.把Cg語言的開始和結束寫出來 //表示Cg語言程序的開始 CGPROGRAM //3.定義頂點函數和片元函數的名字 //#pragma 不變 vertex 關鍵字,後跟的是頂點函數的名字,vert頂點函數的名字 #pragma vertex vert //定義函數名為vert的函數為頂點函數 //#pragma 不變 fragment 關鍵字 #pragma fragment frag //定義函數名為frag的函數為片元函數 fixed4 _Color;//如果要在Cg語言中去使用屬性面板定義的一些變量,需要在Cg語言中進行重定義 //4.實現頂點函數 //POSITION修飾的是頂點函數參數vet,證明vet是頂點坐標 //SV_POSITION修飾的是vet函數的返回值,證明返回值是轉換之後的坐標 float4 vert(float4 vet : POSITION, float3 normal : NORMAL) : SV_POSITION { //頂點函數的核心作用必須做的是空間坐標轉換 //mul是Cg語言的提供的API,計算向量與矩陣相乘 float4 position = UnityObjectToClipPos(vet); // return position; } //5.實現片元函數 fixed4 frag() : SV_Target { //最重要的必須的做到就是返回一個顏色 return _Color; } //表示Cg語言程序的結束 ENDCG } } FallBack "Diffuse" }Unity\Editor\Data\CGIncludes\UnityShaderUtilities.cginc裏的UnityObjectToClipPos()函數 UnityCG.cginc常用的API
#ifndef UNITY_SHADER_UTILITIES_INCLUDED #define UNITY_SHADER_UTILITIES_INCLUDED // This file is always included in all unity shaders. #include "UnityShaderVariables.cginc" // Tranforms position from object to homogenous space inline float4 UnityObjectToClipPos(in float3 pos) { // More efficient than computing M*VP matrix product return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0))); } inline float4 UnityObjectToClipPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders { return UnityObjectToClipPos(pos.xyz); } #endifUNITY_MATRIX_MVP的MVP是幾何階段的三次轉變 M模型到世界 V世界到觀察 P觀察到剪裁
// Upgrade NOTE: replaced ‘mul(UNITY_MATRIX_MVP,*)‘ with ‘UnityObjectToClipPos(*)‘ Shader "Lesson/VFNormal" { Properties { } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag //定義一個結構體,作為頂點函數的參數 struct m2v { float4 vex : POSITION;//告訴應用程序把模型空間下的頂點坐標放在這 float3 normal : NORMAL;//告訴應用程序把模型空間下的法線放在這 float3 tangent : TANGENT;//告訴應用程序把模型空間下的切線放在這 }; //定義一個結構體,作為頂點函數的返回值和片元函數的參數 struct v2f { float4 position : SV_POSITION;//轉換之後的頂點坐標 float3 normal : COLOR0;//法線 float3 tangent : COLOR1;//切線 }; //結構體作為參數和返回值 v2f vert(m2v v) { v2f f; f.position = UnityObjectToClipPos(v.vex); //必須變換頂點坐標 f.normal = v.normal;//法線賦值 f.normal = mul(UNITY_MATRIX_M, v.normal); //f.tangent = v.tangent;//切線賦值 return f; } fixed4 frag(v2f f) : SV_Target { return fixed4(f.normal.x, f.normal.y, f.normal.z, 1);//把法線作為顏色輸出 //return fixed4(f.tangent.x, f.tangent.y, f.tangent.z, 1);//把切線作為顏色輸出 } ENDCG } } FallBack "Diffuse" }
UV坐標,可以通過頂點的UV坐標去獲取紋理對應的顏色。對於圖片的紋理來說UV的(0,0)點在左下角,UV的(1,1)點在右上角
// Upgrade NOTE: replaced ‘mul(UNITY_MATRIX_MVP,*)‘ with ‘UnityObjectToClipPos(*)‘ Shader "Lesson/VFTexture" { Properties{ //定義一個圖片 _MainTex("紋理", 2D) = "white"{} } SubShader{ //透明的紋理處理要把渲染隊列調高 Tags{ "Queue" = "Transparent" } Pass { //Cull off //處理帶有透明通道貼圖的混合 Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag //重定義紋理 sampler2D _MainTex; //定義結構體,作為頂點函數的參數 struct m2v { float4 vex : POSITION; float2 uv : TEXCOORD0;//告訴應用程序要UV信息 }; //定義一個結構體,作為頂點函數的返回值和片元函數的參數 struct v2f { float4 position : SV_POSITION; float2 uv : TEXCOORD0; }; v2f vert(m2v v) { v2f f; //轉換頂點坐標 f.position = UnityObjectToClipPos(v.vex); f.uv = v.uv; return f; } fixed4 frag(v2f f) : SV_Target { //通過頂點的uv坐標去訪問紋理對應的顏色 fixed4 color = tex2D(_MainTex, f.uv); //return fixed4(f.uv.x,f.uv.y, 0, 1); return color; } ENDCG } } FallBack "Diffuse" }屬性面板的變量,如果想在Cg程序中去使用,必須在Cg程序中重新定義: Color - fixed4或float4 Vector - float4 Float - float Range - float 2D - sampler2D Rect - samplerRect Cube - samplerCube 裁剪可以做場景切換的幕布效果
// Upgrade NOTE: replaced ‘mul(UNITY_MATRIX_MVP,*)‘ with ‘UnityObjectToClipPos(*)‘ Shader "Lesson/VFDiscard" { Properties{ _MainTex("紋理", 2D) = "white"{} _Radius("半徑", Range(0, 0.75)) = 0 } SubShader{ Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag sampler2D _MainTex; float _Radius; struct m2v { float4 vex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 position : SV_POSITION; float2 uv : TEXCOORD0; }; v2f vert(m2v v) { v2f f; f.position = UnityObjectToClipPos(v.vex); f.uv = v.uv; return f; } fixed4 frag(v2f f) : SV_Target { //discard;//裁剪命令 fixed4 color = tex2D(_MainTex, f.uv); //0.2圓的半徑 //圓心是0.5 0.5 float2 current = f.uv; float2 center = float2(0.5, 0.5); float dis = pow((current.x - center.x), 2) + pow((current.y - center.y), 2); if (dis < pow(_Radius, 2)) { //在圓內 discard; } return color; } ENDCG } } FallBack "Diffuse" }Emission,類似RawImage的UV Rect ----Tiling:圖片的左右偏移 ----Offset:圖片的大小比例 練習 - 實現西瓜的效果
Shader "Lesson/VFWatermelon" { Properties { _LightColor("淺色條紋", Color) = (1,1,1,1) _DarkColor("深色條紋", Color) = (1,1,1,1) _Number("深色條紋數量", int) = 3 _Width("深色條紋寬度", Range(0.01, 0.2)) = 0.02 } SubShader{ Pass { CGPROGRAM fixed4 _LightColor; fixed4 _DarkColor; int _Number; float _Width; #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct m2v { float4 vex : POSITION; float3 uv : TEXCOORD0; }; struct v2f { float4 position : SV_POSITION; float3 uv : TEXCOORD0; }; v2f vert(m2v v) { v2f f; f.position = UnityObjectToClipPos(v.vex); f.uv = v.uv; return f; } fixed4 frag(v2f f) : SV_Target { //實現1 //淺色條紋的寬度 float width = 1.0 / _Number - _Width; for (int i = 0; i < _Number; i++) { if (f.uv.x > i * (width + _Width) && f.uv.x < width + i * (width + _Width)) { return _DarkColor; } } return _LightColor; /* //實現2 //每對條紋的寬度(1深1淺) float wid = 1.0 / _Number; float x = fmod(f.uv.x, wid); //對wid取模(余) if (x < _Width) { return _DarkColor; } return _LightColor; */ } ENDCG } } FallBack "Diffuse" }
Unity3D學習筆記(三十五):Shader著色器(2)- 頂點片元著色器