前言:
關於UnityShader方面的知識有很多,但真正能讓讀者讀懂並很快上手操作的少之又少,在這里我簡單介紹下關於Shader的一些入門知識,如有出入請大佬們多多指點!
圖形學的基礎知識:
1.Unity游戲物體上需掛載Mesh Filter組件,Mesh Filter中存儲一個Mesh網格(用於存儲形成圖形的所有三角面的頂點信息)。
2.Unity游戲物體上需掛載Mesh Renderer組件,Mesh Renderer為渲染組件,通俗來講就是按照Mesh網格上的頂點信息將圖形顯示出來,賦予皮膚、顏色等等。
3.Mesh Renderer中Material(材質)及我們編寫的Shader所依賴的,用於實現效果的依托。
Shader、OpenGL、DirectX之間的關系:
通俗來講,Shader是一種渲染命令,由OpenGL或者DirectX進行解析進而渲染出豐富多彩的圖形。
其中OpenGL一般用於移動平台,DirectX一般用於PC平台。
Shader的語言分類:
1.GLSL OpenGL語言
2.HLSL DirectX語言
3.CG 誇平台語言
4.ShaderLab Unity中對上述語言的通用封裝
關於Shader中的屬性代碼:
Shader"Mocha/01 myshader"{//這里制定Shader的名字,不要求與文件名保持一致 Properties{ //屬性 _Color("Color",Color)=(1,1,1,1) //顏色float4 _Vector("Vector",Vector)=(1,2,3,4) //向量float4 _Int("Int",Int)=1234 //整數float _Float("Float",Float)=4.5 //小數float _Range("Range",Range(1,11))=6 //隨機數float _2D("Texture",2D)="white"{} //圖片sampler2D(其中white代表當未指定圖片時默認其未一張白色的圖片,也可改為其他顏色) _Cube("Cube",Cube)="White"{} //立方體紋理samplerCube(其中white代表當未指定圖片時默認其未一張白色的圖片,也可改為其他顏色)用於天空盒子等 _3D("Texure",3D) = "White"{} //3D貼圖sampler3D(其中white代表當未指定圖片時默認其未一張白色的圖片,也可改為其他顏色) } //SubShader可以有很多個,顯卡運行效果的時候,從第一個SubShader開始,如果里面的效果全部可以實現,那么就使用第一個SubShader,如果不支持則進行下一個 SubShader{ //每個SubShader至少有一個Pass塊 相當於一個方法 Pass{ //在這里編寫Shader代碼 CGPROGRAM //使用CG語言編寫Shader代碼 //每次使用上面定義好的屬性時需要重新定義一下並且此處每行代碼“;”結束 //取到的值為上述默認定義好的值 float4 _Color; float4 _Vector; float _Int; float _Float; float _Range; sampler2D _2D; samplerCube _Cube; sampler3D _3D; //float half fixed 的區別 //一般小數這三個都可以聲明定義 float t1; half t2; fixed t3; half2 t4; fixed2 t5; //區別在於范圍不同 //float 32位 //half 16位 -6萬 -- +6萬 //fixed 11位 -2 -- +2 (一般顏色用fixed) ENDCG } } //當所有的SubShader都不符合的時候,則用此備胎Shader效果可自定義備胎Shader Fallback "VertexLit" }
關於Shader中的常用語義:
1.從應用程序傳遞到頂點函數的語義有哪些a2v
POSITION 頂點坐標(模型空間下的)
NORMAL 法線( 模型空間下)
TANGENT 切線(模型空間)
TEXCOORD0 ~n 紋理坐標
COLOR 頂點顏色
2.從頂點函數傳遞給片元函數的時候可以使用的語義
SV_POSITION 剪裁空間中的頂點坐標(一般是系統直接使用)
COLOR0 可以傳遞一組值 4個
COLOR1 可以傳遞一組值 4個
TEXCOORD0~7 傳遞紋理坐標
3.片元函數傳遞給系統
SV_Target 顏色值,顯示到屏幕上的顏色
Shader "Mocha/02 secondshader can run"{ SubShader{ Pass{ CGPROGRAM //頂點函數 這里只是聲明了頂點函數的函數名 //基本作用 完成頂點坐標從模型空間到剪裁空間的轉換(從游戲環境到相機視野屏幕上) #pragma vertex vert //片元函數 這里只是聲明了片元函數的函數名 //基本作用 返回模型對應的屏幕上的每一個像素的顏色值 #pragma fragment frag float4 vert(float4 v : POSITION) : SV_POSITION{//通過語義來告訴系統我這個參數是干嘛的 //比如POSITION是告訴系統我需要頂點坐標 //比如SV_POSITION用來解釋說明返回值,返回值是剪裁空間下的頂點坐標 //轉換剪裁空間坐標的算法,也可直接調用包裝好的方法 float4 pos=mul(UNITY_MATRIX_MVP,v); return pos; } fixed4 frag() : SV_Target{ return fixed4(0.5,0.5,1,1); } ENDCG } } Fallback "VertexLit" }
使用結構體進行存儲傳遞數據:
Shader "Mocha/03 Use Struct"{ SubShader{ Pass{ CGPROGRAM //頂點函數 這里只是聲明了頂點函數的函數名 //基本作用 完成頂點坐標從模型空間到剪裁空間的轉換(從游戲環境到相機視野屏幕上) #pragma vertex vert //片元函數 這里只是聲明了片元函數的函數名 //基本作用 返回模型對應的屏幕上的每一個像素的顏色值 #pragma fragment frag //使用結構體存儲 //a2v 即 application to vertex struct a2v{ float4 vertex:POSITION;//告訴Unity把模型空間下的頂點坐標填充給vertex float3 normal:NORMAL;//告訴Unity把模型空間下的法線方向填充給normal float4 texcoord:TEXCOORD0;//告訴Unity把第一套紋理坐標填充給texcoord }; //使用結構體存儲 struct v2f{ float4 position:SV_POSITION;//告訴Unity存儲剪裁空間下的頂點坐標 float3 temp:COLOR0;//臨時測試頂點到片元函數之間的數據傳遞,此處將頂點中的法線作為顏色傳遞給片元函數顯示 }; v2f vert(a2v v){ v2f f; f.position=mul(UNITY_MATRIX_MVP,v.vertex); f.temp=v.normal; return f; } fixed4 frag(v2f f) : SV_Target{ return fixed4(f.temp,1); } ENDCG } } Fallback "VertexLit" }