1. 程式人生 > >ARCore之路-環境理解之Cg語言

ARCore之路-環境理解之Cg語言

  雖然Surface Shader是Unity極力推動的編寫Shader的方式,但由於Surface Shader做了大量的封裝,遮蔽了很多底層實現細節,包括光照、頂點變換、材質使用等,在提供了更簡單的使用之餘也喪失了靈活性,下面我們只對vertex shaders 和 fragment shaders進行學習,讀者可以參閱官方文件以瞭解更多Surface Shader細節。

一、vertex & fragment shaders基本結構

Shader "DavidWang/vertexAndFragment"{
    SubShader{
        pass{
                CGPROGRAM
                 #pragma vertex vert
                 #pragma fragment frag
                  void vert(in float2 objPos:POSITION, out float4 pos:POSITION)
                 {
                        pos = float4(objPos,0,1);
                  }
                 void frag(out float4 col:COLOR)
                 {
                      col = float4(1,0,0,1);
                 }
                ENDCG
        }
    }
    Fallback "Mobile/VertexLit"
}

  Vertex & Frament Shader至少有一個pass通道,一個pass就是對場景的一次渲染。在ShaderLab語法中需要使用關鍵詞“CGPROGRAM”和“ENDCG”將Cg程式碼段包含起來才能編譯使用,需要注意的是這兩個關鍵詞都是大寫的。#pragma vertex vert指令的意思是使用vert函式來做Vertex shader的處理工作, #pragma fragment fragt指令的意思是使用fragt函式來做Fragment shader的處理工作,即這是分別指定了執行頂點和片段處理的函式。

  Vertex shader會對頂點做一系列的處理,最主要的是把頂點座標從物體Local空間轉換成齊次裁減空間的齊次座標,同時進行必要的光照處理,把處理後的資料傳遞給Fragment shader程式,Fragment shader拿到頂點程式處理後的資料繼續進行最終的計算。Fragment shader最主要的工作是對紋理進行取樣、對顏色進行最終的合成,其輸出是顏色值。

  在上例中,“void vert(in float2 objPos:POSITION, out float4 pos:POSITION)” 中有兩個引數,其中第一個引數中的“in”表示引擎提供的輸入,“float2”表示資料的型別為二階的向量,引數名“objPos”冒號後需要帶上語義,語義指的是頂點程式和片段程式能夠被識別的變數,這裡使用“POSITION”。第二個引數中“out”表示輸出,資料型別為“float4”,語義也是“POSITION”。如果頂點程式要輸出一個“POSITION”語義的變數,這個變數必須要以“float4”四階向量的形式。“void frag(out float4 col:COLOR)”使用語義為“COLOR”的變數作為輸出,這裡使用“out float4 col:COLOR”作為顏色變數的輸出,語義“COLOR”就是指“COLOR0”。

  語義詞“POSITION”,“COLOR”不僅僅是表示資料型別,更重要的是指示出資料存放的位置,這些語義詞都有特定的含義。   Cg 語言所有 vertex profile 支援的輸入語義關鍵詞有: POSITION、BLENDWEIGHT、NORMAL、 TANGENT、 BINORMAL、 PSIZE、BLENDINDICES、TEXCOORD0—TEXCOORD7。   Cg 語言所有 vertex profile 支援的輸出和 fragment profile 輸入語義關鍵詞有:POSITION 、PSIZE 、FOG,COLOR0-COLOR1、TEXCOORD0-TEXCOORD7 。    Cg 語言所有 fragment profile 支援的輸出語義關鍵詞有:COLOR 。

  示例shader是最簡單但又是結構完整的vertex shaders 和 fragment shaders,讀者務必瞭解。關於輸入輸出語義更詳細的說明超出了本章的內容,請讀者查閱相關資料。

這裡寫圖片描述

二、profile

  一個Cg profile定義了一個“被特定圖形硬體或API所支援的Cg語言子集”,任意一種shader language都是基於可程式設計圖形硬體的(暫存器、指令集等),這也就意味著,不同的圖形硬體對應著不同的功能子集。這些可選的語言功能包括某些控制結構和標準庫函式。profile還定義了資料型別的精度,並且指定資料型別是否全部支援或僅部分支援。profile按照功能可以劃分為vertex profile和fragment profile,而vertex profile和fragment profile又基於OpenGL和DirectX的不同版本或擴充套件,劃分為各種版本。

  profile是語言的一種特性,在不同的處理方法中會擁有不同的特性。在特殊情況下,語言profile就是關於一個使用for或者while迴圈的限制,意思就是有些情況下它不支援for或者while迴圈,有些profile僅僅loop迴圈。Cg不支援goto、switch、case、default等保留關鍵字;也不支援指標和指標相關的運算能力;Cg支援陣列,但是有尺寸和維度的限制;Cg沒有列舉和聯合;Cg在結構體當中沒有位成員;Cg中所有的整型都是有符號,沒有signed關鍵字。

  Cg有繫結語義,比如POSITON、COLOR0等;Cg內建有swizzle操作;對於一個值來說,swizzle操作可以允許進行拼湊一個向量或矩陣;swizzle操作可以去訪問所有的分量;資料有不同的有限的型別,主要的型別有float、half、fixed,片段profile必須支援這三種資料型別,但是可以選擇使用half或fixed去實現float,頂點profile要求實現half和float,但是可以選擇實現halp和float,頂點profile可以忽略支援fixed,Cg允許profile去忽略支援執行時的int,實際上會把int轉換成float;Cg中的操作很多都是對於向量的操作,可以對向量的基本元素進行操作,Cg中也有?問號表示式,沒有全域性的非靜態變數;Cg有新的sampler*集合;函式擁有預設引數;函式和它們的操作可以被過載;變數可以定義在任何地方,但要在使用之前定義就行等等。

三、Cg基本資料型別

  Cg支援7種基本的資料型別

資料型別 說明
float 32 位浮點資料,一個符號位。浮點資料型別被所有的 profile 支援。
half 16 位浮點資料。
int 32 位整形資料,有些 profile 會將 int 型別作為 float 型別使用。
fixed 12 位定點數,被所有的 fragment profiles 所支援。
bool 布林資料,通常用於 if 和條件操作符( ?: ) ,布林資料型別被所有的profiles 支援。
simpler* 紋理物件的控制代碼( the handle to a texture object ) ,分為 6 類: sampler, sampler1D, sampler2D, sampler3D, samplerCUBE, 和 samplerRECT 。

  Cg還提供了內建的向量資料型別 (built-in vector data types) ,內建的向量資料型別基於基礎資料型別。 例如: float4, 表示 float 型別的 4 元向量; bool4, 表示 bool型別 4 元向量。 注意: 向量最長不能超過 4 元, 即在 Cg 程式中可以宣告 float1 、 float2 、 float3 、float4 型別的陣列變數,但是不能宣告超過 4 元的向量。

參考文獻