初識Shader

HLSL

高階著色器語言(High Level Shader Language,簡稱HLSL),由微軟擁有及開發的一種語言,HLSL 獨立的工作在 Windows 平臺上,只能供微軟的Direct3D使用。 HLSL是微軟抗衡GLSL的產品,同時不能與OpenGL標準兼容。

GLSL

OpenGL著色語言(OpenGL Shading Language)是用來在OpenGL中著色編程的語言,也即開發人員寫的短小的自定義程序,他們是在圖形卡的GPU (Graphic Processor Unit圖形處理單元)上執行的,代替了固定的渲染管線的一部分,使渲染管線中不同層次具有可編程性。

圖片2.png

CG

Paste_Image.png

GPU語言

由于GPU采用不同于CPU的運行運算結構,因此需要一種適用于GPU的編程語言。
1、微軟基于Direct3D圖形庫的HLSL(High Level Shading Language)
2、OpenGL ARB定義基于OpenGL圖形庫的GLSL(OpenGL Shading Language)
3、NVIDIA(英偉達)與微軟合作研發的Cg(C for Graphics).

Cg能夠同時兼容Direct3D和OpenGL圖形接口。

Unity所有的渲染都需要shader來完成,內置的著色器超過80個,可以輕松利用其內置的著色器來完成各種畫面效果,并且還提供了自定義shader,方便擴展。Unity使用shaderLab開發語言來組織shader內容,并會針對不同的平臺進行編譯,類似微軟的FX文件或者NAIDIA的CgFX.

Shader,可以分為VertexShader 和PixelShader/FragmentShader兩部分,簡稱VS,PS。學名頂點著色器和像素著色器。一旦你使用了VS和PS,則渲染過程會將VB(頂點緩沖)的數據按照IB索引(頂點索引緩沖)將每個頂點結構值分量傳入VS,VS進行相應的計算和頂點變化,并將VS返回的結果再交由PS進行像素著色,輸出相應的圖像。概念上來說 FragmentShader會比PixelShader大很多..
這兩個東西由于DX用PixelShader的緣故,其實是一個東西

Unity中可以編寫3種不同的著色器:表面著色器(Surface Shader)、頂點和片段著色器(Vertex and Fragment Shaders)和固定功能管線著色器(Fixed Function Shaders).
Unity5.0,內建了基于物理渲染的StandardShader,同時還引入了完全延遲著色(FullDeferredRendering)和烘焙反射探頭(Baked Reflection Probes)用于以真實環境為基礎的鏡面高光

物理著色:PBS (physically Based Shading):新的工業標準,用于電影產品
遵從了Conservation of Energy(能量守恒定律),只有這樣才能夠正真讓場景里面的光源依據能量傳遞的方式,產生一種自然和諧的光照效果。


Paste_Image.png

Standard Surface Shader (Instanced):標準表面材質(實例化)
Unlit Shader:未點燃的材質
Image Effect Shader:圖像效果材質
Compute Shader:計算著色器
Shader Variant Collection:著色器變量集合

內建Shader介紹

4.X版本提供超過80個內建Shader、包括頂點光照效果到高光、發現、反射等游戲常用的材質效果。

內建Shader分類:
普通(Normal):用于不透明對象
透明(Transparent):用于半透明和全透明對象
透明鏤空效果(TransparentCutOut):用于完全透明和完全不透明部分組成(不含半透明部分)的對象,像柵欄一樣。
自發光(Self-llluminated shader Family):用于能反射環境立方體貼圖的不透明對象
反射(Reflective Shader Family):用于能反射環境立方體貼圖的不透明對象

每個類別下包含若干復雜性各異的shader


Paste_Image.png

以光照效果計算開銷從低到高排序:
Unlit : 僅使用紋理,不受光照影響
VertexLit:頂點光照
Diffuse:漫發射
Specular: 在漫反射基礎上增加高光計算
Nomal Mapped : 法線貼圖,增加了一張法線貼圖和幾個著色器指令。
Nomal Mapped Specular : 帶高光法線貼圖
Parallax Nomal Mapped : 視差法線貼圖,增加了視差貼圖計算開銷
Parallax Nomal Mapped :帶高光視差法線貼圖

5.X版本新增加了一種基于物理著色的內建著色器,即StandardShader(標準著色器)
物理著色:PBS (physically Based Shading):新的工業標準,用于電影產品
遵從了Conservation of Energy(能量守恒定律),只有這樣才能夠正真讓場景里面的光源依據能量傳遞的方式,產生一種自然和諧的光照效果。


Paste_Image.png

Paste_Image.png

StandardShader是基于物理的著色器,也就是說不管你選擇什么樣的貼圖都會與光照產生反應,這些貼圖可以是同一張圖片,Unity會使用必要的資源進行計算。

原理:
遵從了Conservation of Energy(能量守恒定律),只有這樣才能夠正真讓場景里面的光源依據能量傳遞的方式,產生一種自然和諧的光照效果。
表面反射的光線不會比它們收到的更多
光滑的表面會有更強的反射
醋糟的表面反射會更弱一些
高光強度會隨著漫反射的強度而改變
所有的表面從某一特定角度看上去會有或多或少的高光
所有的表面在掠射角會有更多的反射

圖片3.png
能量守恒:光能=漫反射+反射+折射

編寫自己的Shader(詳細解答Shader的各種屬性及用法)

Shader "Custom/firstsharder" {//這里是Shader的名字
    Properties {//著色器屬性
        _Color ("Color", Color) = (1,1,1,1)
        //在輸入貼圖時候,必須要寫一個什么都不含的{}
        //需要打開特定選項時可以把其寫在這對花括號內.
        //如果需要同時打開多個選項,可以使用空白分隔
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }

    SubShader {
    //表面著色器可以被若干的標簽(tags)所修飾
    //硬件將通過判定這些標簽來決定什么時候調用該著色器
    //標簽 可選
        Tags
        {

        "Queue" = "Opaque"http://渲染順序  
        //Background--最早被調用的渲染,用來渲染天空盒或者背景 
        //Geometry--默認值,用來渲染非透明物體(普通情況下,場景中的絕大多數物體應該是非透明的)
        //AlphaTest--用來渲染經過Alpha Test的像素,單獨為AlphaTest設定一個Queue是出于對效率的考慮
        //Overlay--用來渲染疊加的效果,是渲染的最后階段(比如鏡頭光暈等特效)
         //Transparent--以從后往前的順序渲染透明物體
          //預設的隊列本質就是定義的整數(有點像枚舉值)
        //Background=1000,Geometry=2000,AlphaTest=2450
        //Transparent=3000,最后Overlay=4000


        "RenderType" = "Transparent" //著色器替換功能  "Transparent" 渲染透明物體調用 "Opaqu"渲染非透明的物體
        "DisableBatching" = "True"http://是否進行合批
        "ForceNoShadowCasting" = "True"http://是否不投射陰影
        "IgnoreProjector" = "True"http://受不受projector的影響,通常用于透明物體,如果為true,此著色器的對象將不受Projectors的影響

        "CanUseSpriteAltas" = "False"http://是否用于圖片的Shader,通常用于UI,`CanUseSpriteAtlas`如果著色器用于Sprite則將標簽設置為“ False”

        "PreviewType" = "Plane"http://用作Shader面板預覽的類型
         }
        //預設的隊列本質就是定義的整數(有點像枚舉值)
        //Background=1000,Geometry=2000,AlphaTest=2450
        //Transparent=3000,最后Overlay=4000

        //如何自定義列表
        Tags{ "Queue"="Transparent+100" }//通過調用Queue值,確保渲染的先后順序


        //Unity的內建Diffuse著色器的設定值,這個數值決定了我們能用什么樣的Shader
        //這個數值可以在unity中的質量設定中設定

//Render設置 可選
//Cull off/back/front //選擇渲染哪個面
Cull off//默認渲染正面,設置Cull off意思是關閉裁剪, 那就是正反兩面都渲染
Cull back//只渲染背面
Cull front//只渲染前面


        //ZTest Always/Less Greater/LEqual/Gequal/Equal/NotEqual  //深度測試   默認使用小于等于
ZTest Always  //總是
ZTest Less Greater//小于
ZTest LEqual//小于等于
ZTest Gequal//大于等于
ZTest Equal//等于
ZTest NotEqual//不等于

        //Zwrite off/on   //深度寫入
Zwrite off
Zwrite on
        //Blend SrcFactor DstFactor  //混合
        LOD 200//不同情況下使用不同的LOD,達到性能提升
        //關于VertexLit及其系列 = 100
        //Decal, Reflective VertexLit = 150
        //Diffuse = 200
       //Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
      //Bumped, Specular = 300
      //Bumped Specular = 400
     //Parallax = 500
     //Parallax Specular = 600

    Pass
        {
             Name "PassName"http://Pass 通道名稱 可以在其他地方Use 該pass通道Name, Use 通道的時候名稱必須大寫

             Tags
            {
            "LightMode"="ForwardBase"http://定義該Pass通道在unity渲染流水中的角色
            //"RequireOptions"="SoftVegetation"http://用于滿足某些條件時才渲染該Pass通道
            }//可以在每個Pass通道里面進行定義
        //Shader字體:也就是將輸入轉變成輸出的代碼部分
        CGPROGRAM//開始CG語言的編寫
        // Physically based Standard lighting model, and enable shadows on all light types
        //surface:申明的是一個表面著色器
        //surf:著色器代碼的方法的名字,下方的代碼有這個函數
        //Standard:標準
        //fullforwardshadows:光照模型
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
        //在CG中,sampler2D就是和texture所綁定的一個數據容器接口
        //其實就是內存存儲的RGB通道,sampler2D:就是GLSL中的2D貼圖的類型
        //其他類型:sampler1D,sampler3D,samplerCube
        // 圖片
        sampler2D _MainTex;
        // 用來獲取MainTex的UV信息
        struct Input {
            float2 uv_MainTex;//float2:浮點數的float后面緊跟一個數字2
            vec2 coordinate;//float和vec都可以在之后加入一個2到4的數字,來表示被打包在一起的2到4個同類型數
            float4 color;
        };

        half _Glossiness;//half指的是半精度浮點數,精度最低,運算性能相對比高精度浮點數高一些
        half _Metallic;
        // 顏色屬性
        fixed4 _Color;
        // SurfaceOutputStandard 表面著色器輸出一個標準的結構體
        //著色器的工作核心,著色器就是給定了輸入,然后給出輸出進行著色的代碼,第一個參數是Input結果,第二個參數是一個inout的SurfaceOutput結構
        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            // 獲取圖片 * 我們選定的顏色
            //fixed4:定點書:整形數據類型,作用就是把所有數進行轉換,得到相應類型的整形表達
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            // 輸出的像素的顏色 = 圖像的顏色(RGB)
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            // 輸出的顏色效果(金屬方面) = 設定的金屬值
            o.Metallic = _Metallic;
            // 輸出的光滑粗糙程度 = 設置的光滑粗燥程度
            o.Smoothness = _Glossiness;
            // 輸出的透明通道 = 圖像的透明通道
            o.Alpha = c.a;
        }
}
        ENDCG//結束CG語言的編寫
    }
    FallBack "Diffuse"
}
642887-57f1485a1e706ea0.png

參考

https://docs.unity3d.com/Manual/SL-SurfaceShaderExamples.html
https://onevcat.com/2013/08/shader-tutorial-2/
http://www.tuicool.com/articles/JvYJ3em
http://www.itnose.net/detail/6143450.html

CG語言基礎知識:

內置元類型
Float : 32bit浮點類型
Half: 16bit浮點
Int : 32bit整形
Fixed : 12bit定點
Bool : 布爾值
Sampler:紋理對象的句柄
String:不是每個都支持

cg提供內置的向量數據類型(build-in vector data types)
float1、float4,
bool2, bool3,
float1x1
float2x3
類型轉換跟C是一樣的,用強制轉化。
類型定義的時候可以在常量后跟后綴,如2.0f,1.0h,3x。目前值有f,h,x(fixed)三種。

支持類型
1、數組
float a[10];
float4 b[10];
int length = a.length; //獲取長度,上面兩個返回都是10

float b[2][3] = { { }, { } };
int length1 = b.length; // length1 = 2;
int length2 = b[0].length; // length = 3;

2、結構
以struct開始,緊跟名字,內容用{};包住。不要忘記最后的分號。
結構中可以帶function,是C++中的用法。
結構不支持繼承。

3、特定關鍵字
in , out , inout,
uniform (被修飾的變量從外部傳入), const ,
4、輸入語義關鍵字
Vertex Shader的輸入:

POSITION, NORMAL, BINORMAL, BLENDINDICES, BLENDWEIGHT, TANGENT, PSIZE, TEXCOORD0 ~ TEXCOORD7

如:in float4 modelPos: POSITION

Vertex Shader的輸出, 也就是Pixel Shader的輸入
POSITION, PSIZE, FOG,COLOR0 ~ COLOR1, TEXCOORD1 ~ TEXCOORD7
Pixel Shader的輸出:

COLOR

5、入口函數
通過觀察程序的輸入輸出語義綁定,就可以區分入口函數對應到頂點程序還是片段程序。

6、內置函數庫
reflect 求發射向量
refract 求折射向量
mul 矩陣相乘
normalize 歸一化

CG語言的學習資料:

http://blog.csdn.net/liu_lin_xm?viewmode=contents
https://developer.nvidia.com/cg-toolkit

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容