1. 程式人生 > >Unity3D學習筆記(三十四):Shader著色器(1)

Unity3D學習筆記(三十四):Shader著色器(1)

mission inf 向量 投影 rim tags 系統 依賴 什麽是

一、GPU:圖形處理器,Graphics Processing Unit 顯卡的處理器就是圖形處理器。與CPU類似。 GPU和CPU的區別? 1.CPU主要是為了串行指令設計,GPU則是為了大規模的秉性的計算而設計。 2.從並行的角度來看,CPU並行針對於指令集並行,而GPU的並行是針對大規模運算的。 3.同樣面積的芯片:CPU上更多的放置緩存和控制部件,而GPU上放置的是更多的運算單元。 二、渲染管線 渲染管線也叫渲染流水線,就是告訴GPU一堆數據,然後得到一個二維的圖像。 渲染管線主要分三個階段:應用程序階段、幾何階段、光柵化階段 1.應用程序階段(CPU) 主要是CPU將模型身上的頂點信息(頂點坐標、紋理坐標、法線等),組成一個圖元,告訴GPU。 2.幾何階段(GPU)(頂點函數在這個階段) 幾何階段的主要工作是“變換三維頂點坐標”。主要是將圖元信息的頂點坐標變化到屏幕坐標中,傳給光柵化階段。 幾何階段涉及的幾個空間: Object Space(模型坐標空間),以模型原點為參考 World Space(世界坐標空間),三維 Eye Space(觀察坐標空間) Clip anf Project Space(剪裁和屏幕坐標空間),二維 1)從Object Space到World Space 模型在導入到場景中,只有一些模型身上的頂點信息。需要把頂點坐標轉換到世界坐標空間下,我們才知道模型在世界中的哪一個位置。 2)從World Space到Eye Space 我們模型顯示到屏幕是需要攝像機的,所有的觀察坐標空間,就是以攝像機為原點, 攝像機的右方為觀察坐標系的+X軸的方向, 攝像機的上方為觀察坐標系的+Y軸的方向, 攝像機的正前方為觀察坐標系的-Z軸的方向。 Unity的觀察坐標系是右手坐標系。 3)從Eye Space到Clip anf Project Space 就是一個裁剪(視錐體以外的部分)和投影的過程 3.光柵化階段(GPU)(片元函數在這個階段) 使用上一個階段生成的數據渲染出最終的圖像。 三、Shader著色器:GPU上運行實現圖像渲染的程序 技術分享圖片
圖像編程接口 OpenGL,蘋果 DirectX,微軟 技術分享圖片 著色器的語言: 按照3D渲染的圖像編程接口來區分 GLSL:OpenGL Shading Language(支持OpenGL API) HLSL:High Level Shader Language(支持DX API) Cg語言:C for Graphics(支持兩種編程接口) 技術分享圖片 著色器的分類: 固定管線著色器:效果差,難度小,適用各種硬件,老舊顯卡,手機顯卡 頂點/片段著色器(可編程頂點/片段處理器):Cg語言,效果好,新型顯卡,可編程,更靈活 表面著色器(固定功能著色器):Unity自己的,對Cg語言的封裝,較頂點/片段著色器復雜,包括光影的運算 著色器的結構: 1.需要一個定義 Shader"著色器的名字"{ },這個名字是可以帶有層級化結構的,並且名字可以與Shader的名字不一致。 2.向引擎公布一些自己的公共的屬性(可以存在,也可以不存在) Properties{ //屬性的集合},Properties向下融合 3.至少包括一個計算過程 SubShader{ //計算過程} 計算過程可以是多個,也可以是一個,SubShader多個的情況下,機器會從上至下往下找,只有一個會執行,這個可以執行的SubShader是機器可以容忍的著色器代碼,從上至下找到一個自己可以容忍可以執行的SubShader,那麽就執行這個。 表面著色器的代碼不需要寫在Pass塊裏,但固定管線著色器和頂點/片段著色器的代碼都需要寫在pass塊裏 一個SubShader可以有多個Pass塊,Pass塊效果會疊加。 4.最後是在所有的SubShader都失效的情況下執行的一個方案 FallBack"最好寫默認的著色器代碼",編寫時最好把FallBack註釋掉,避免系統默認調用,無法顯示粉色錯誤
FallBack "
Diffuse"//Unity自帶的LegacyShaders的Diffuse
5.對於多個Pass塊的情況,機器會依次向下執行每一個Pass,一般情況下最後一個Pass的效果會覆蓋前面的Pass,但是也有特殊的情況。 ShaderLab結構 技術分享圖片 技術分享圖片 註意: shader依賴材質球,材質球依賴物體身上的Mesh Render 材質球的粉色:是報錯的顏色 著色器的屬性: 定義:<屬性的變量名>("Inspactor顯示的名字", 數據類型) = <必須初始化> 類型: Color:顏色
_Color ("顏色", Color) = (1,1,1,1)

Float:數字

_Float ("數字", float) = 0.1//不用加f

Vector:四維向量

_Vector ("向量", Vector) = (0,0,0,0)

Range:區間

_Range ("區間", Range(0, 10)) = 0//註意區間裏要設置最大值和最小值

2D:2D紋理

_2D ("2D紋理", 2D) = "white"{}//紋理使用字符串加花括號形式賦初值

Rect:矩形紋理(少用)

_Rect ("矩形紋理", Rect) = "white"{}
Cube:立方體紋理(一般用於天空盒)
_Cube ("立方體紋理", Cube) = "white"{}
對於紋理來說,沒辦法對其進行指定的紋理作為默認值,可以使用{}表示空紋理,{}前的字符串表示的是當使用空紋理時,使用的顏色,"white"、"red"、"gray"。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SetMat : MonoBehaviour {
    public Texture tex;
    //如果要修改Shader屬性面板的值
    //首先需要獲取使用這個Shader材質
    private Material mat;
    private MeshRenderer mr;
       // Use this for initialization
       void Start () {
        mr = GetComponent<MeshRenderer>();
        //獲取MeshRenderer裏的材質
        mat = mr.material;
        //修改顏色,第一個參數是屬性面板的變量名,第二個參數是想要設置的值
        mat.SetColor("_Color", Color.blue);
        //修改數字、區間
        mat.SetFloat("_Float", 100);
        mat.SetFloat("_Range", 5);
        //修改向量
        mat.SetVector("_Vector", Vector4.one);
        //修改紋理
        mat.SetTexture("_2D", tex);
        //修改紋理的Tiling和Offset
        mat.SetTextureScale("_2D", Vector2.zero);//Tiling
        mat.SetTextureOffset("_2D", Vector2.one);//Offset
    }
}
SubShader Unity提供的一些渲染的控制命令 註意: 1.所有的命令後都不可以帶分號結尾 2.所有的命令必須給值,值分為常量值和變量值。如果想要使用屬性面板的變量,命令[變量名]。使用常量值,命令 (1,1,1,1)或數字 燈光命令 Lighting off/on on表示支持燈光,off表示不理會燈光 固定顏色 Color(r,g,b,a)或Color[變量名] r,g,b,a的取值範圍0-1 註意:如果開啟的燈光控制,該命令無效,如果想要命令有效,那麽必須關閉燈光控制。
Shader "Lesson/FixedColor" {
    Properties{
        _Color("Color", Color) = (1,1,1,1)
    }
    SubShader{
      //固定管線著色器要寫在Pass裏
      Pass
      {
         //關閉燈光
         Lighting off
         //固定顏色
         //Color (1,0,0,1)//使用常量值的顏色
         Color[_Color]//使用變量值的顏色
      }
   //FallBack "Diffuse"
}
燈光處理塊 Material{//處理各種燈光} Diffuse:Color控制基本的漫反射的顏色:Diffuse(r,g,b,a)或Diffuse[顏色變量名] Specular:Color控制鏡面反射的顏色:Specular(r,g,b,a)或Specular[顏色變量名] Shininess:Number控制高光的銳利度,一般取值範圍在0-1之間,0高光最大,1高光最小。Shininess 數字或Shininess[區間或float變量名] Emisson:Color控制物體自發光顏色。Emisson(r,g,b,a)或Emisson[顏色變量名] Ambient:Color控制環境光顏色。Ambient(r,g,b,a)或Ambient[顏色變量名] SeparateSpecular on/off 開啟獨立的鏡面反射,只有開啟了這個命令,Specular高光命令才有效。 最終顏色 = Ambient 控制的顏色 * 引擎設置的環境光顏色 + 光照顏色 * Diffuse + 光照顏色 * Specular + Emisson
Shader "Lesson/FixedDiffuse" {
    Properties {
      _Diffuse("漫反射顏色", Color) = (1,1,1,1)
      _Specular("高光顏色", Color) = (1,1,1,1)
      _Shininess("高光系數", Range(0, 1)) = 0.2
      _Emission("自發光顏色", Color) = (1,1,1,1)
      _Ambient("環境光顏色", Color) = (1,1,1,1)
   }
   SubShader {
      Pass
      {
         //先把燈光打開
         Lighting on
         //開啟獨立的鏡面反射
         SeparateSpecular on
                 
         //在這個裏去寫一些燈光處理控制的命令
         Material
         {
            //燈光產生的漫反射的影響
            //漫反射光照命令
            Diffuse [_Diffuse]
            //高光顏色的命令
            Specular [_Specular]
            //高光系數 數字0~1
            Shininess [_Shininess]
            //自發光 相加
            Emission [_Emission]
            //環境光 相乘,乘以Environment Light的數值,一般情況下設置為(1,1,1,1)
            Ambient [_Ambient]
         }
      }
   }
   //FallBack "Diffuse"
}

環境光設置

技術分享圖片

紋理顯示: SetTexture[紋理的屬性變量名]{//紋理計算命令} Combine:告訴引擎開始進行顏色混合 texture:紋理貼圖的原始顏色 constantColor:定義一個常量的顏色 constant:使用這個常量的顏色 primary:使用燈光的顏色 double:使燈光的顏色變成二倍 quad:使燈光的顏色變成四倍 previous:代表顏色緩沖區(幀緩存)當前的顏色 Combine texture:顯示圖片的原始色 Combine texture * constant:使用一個常量顏色與紋理的原始顏色混合 Combine texture * primary:使用燈光顏色與紋理的原始顏色混合
Shader "Lesson/FixedDiffuse" {
   Properties {
      _Tex("紋理", 2D) = "white"{}
   }
   SubShader {
      Pass

      {
         SetTexture[_Tex]//可以有多個,效果疊加
         {
               //計算命令的選項
               Combine texture//顯示紋理的原始顏色
               //如果想與原始顏色進行混合
               //定義一個常量色
               constantColor[_Color]
               //常量色與紋理的原始顏色
               Combine texture * constant
               //燈光顏色與紋理的原始顏色混合
               //double代表雙倍的意思
               Combine texture * primary double
               Combine texture * previous + constant
         }
      }
   }
   //FallBack "Diffuse"
}

技術分享圖片

Shader "Custom/FixedSetTexture" {
   Properties {
      _MainTex("主紋理貼圖", 2D) = ""{}
      _SecTex("主紋理貼圖", 2D) = ""{}
      _Color("顏色", Color) = (1,1,1,1)
   }
   SubShader {
      Pass
      {
         SetTexture[_MainTex]
         SetTexture[_SecTex]
         {
            //語法:Combine src1 lerp (scr2)scr3
            //使用scr2的alpha值進行顏色插值,當scr2的alpha值為1的時候,顯示scr1的顏色,當scr2的alpha值為0的時候,顯示scr3的顏色
            //如果scr2的某個像素的alpha值為0.5的時候,那麽就是scr1的顏色和scr3的顏色進行1:1的混合
            Combine texture lerp (texture)previous
         }
         SetTexture[_SecTex]
         SetTexture[_MainTex]
         {
            ConstantColor[_Color]
            //語法:Combine src1 * scr2 + scr3 用scr1的顏色 * scr2的 alpha 值 + scr3
            Combine texture * previous + constant
         }
      }
   }
   FallBack "Diffuse"
}
網格面的裁剪 Cull off/back/front Cull off:關閉網格面的裁剪:雙面顯示 Cull back:裁剪掉背面網格,默認開啟的是裁剪掉背面網格 Cull front:裁剪掉正面網格,可以用作天空盒 渲染隊列命令,這個命令與Pass是同級的 控制誰先渲染誰後渲染!渲染隊列值,值越大越後渲染,最終顯示在屏幕上的顏色是由渲染隊列深度深度比較等同時決定的。 "Queue"="BackGround",代表的渲染隊列值1000,一般用於背景層,第一批渲染 "Queue"="Geometry",代表的渲染隊列值2000,一般用於不透明的遊戲物體 "Queue"="AlphaTest",代表的渲染隊列值2450 "Queue"="Transparent",代表的渲染隊列值3000 "Queue"="Overlay",代表的渲染隊列值4000,一般用於鏡頭的處理 如果想設置3200的渲染隊列 "Queue"="Transparent+200",註意加號左右不允許有空格
Shader "Lesson/FixedCull" {
   Properties {
      _MainTex("Albedo (RGB)", 2D) = "white" {}
   }
   SubShader {
      //設置渲染隊列的值
      Tags{ "Queue" = "BackGround" }
      Tags{ "Queue" = "Geometry" }
      Tags{ "Queue" = "AlphaTest" }
      Tags{ "Queue" = "Transparent" }
      Tags{ "Queue" = "Overlay" }
              
      Pass
      {
         //網格面的裁剪
         Cull off
                 
         SetTexture[_MainTex]
         {
            Combine texture
         }
      }
   }
   //FallBack "Diffuse"
}
什麽是深度? 遊戲物體距離攝像機的距離我們叫做深度。 深度測試:當前物體的對應像素顏色的深度與深度緩沖區裏的深度做比價的過程就是深度測試 深度緩沖:開啟了深度緩沖,證明當比較成功之後,要把新的深度寫入到深度緩沖區裏去 ZTest深度測試 ZTest Less:小於,默認就是小於比較 Greater:大於 Equal:等於 LEqual:小於等於 GEqual:大於等於 NotEqual:不等於 off:關閉,深度測試關閉時,當跟深度緩沖區裏做比較時,直接通過。 深度寫入 ZWrite off/on:關閉或者開啟深度寫入 如果深度寫入關閉,即使比較成功了,深度不會寫入深度緩沖區,但是顏色會寫入到深度緩沖區。 1.深度測試通過,深度寫入開啟,深度寫入深度緩沖區,顏色寫入顏色緩沖區 2.深度測試通過,深度寫入關閉,深度不寫入深度緩沖區,顏色寫入顏色緩沖區 3.深度測試失敗,深度寫入開啟,深度不寫入深度緩沖區,顏色不寫入顏色緩沖區 4.深度測試失敗,深度寫入關閉,深度不寫入深度緩沖區,顏色不寫入顏色緩沖區 5.深度測試關閉,深度寫入開啟,深度寫入深度緩沖區,顏色寫入顏色緩沖區
Shader "Lesson/ZTestR" {
   Properties {
   }
   SubShader {
      //紅色 3000
      Tags{ "Queue" = "Transparent" }
              
      Pass
      {
         //深度測試變為小於比較
          ZTest Less



         //深度寫入關閉
          ZWrite off
              
         Color(1,0,0,1)
      }
   }
   //FallBack "Diffuse"
}

技術分享圖片

補充內容 快速添加材質球的方法:在Shader腳本上右鍵新建Material,會自動根據Shader腳本的路徑命名 技術分享圖片

Unity3D學習筆記(三十四):Shader著色器(1)