glsl用什麼編譯
① NO.15 - OpenGL ES 使用GLSL載入圖片
利用GLSL自定義的著色去載入一張圖片,效果圖如下
整體流程圖如下
流程中主要分為4個模塊
項目的創建及自定義視圖創建等,這里不作過多說明,主要說說著色器文件是如何創建的
自定義的著色器本質上其實是一個字元串,且在Xcode中編寫時,是沒有任何提示的,所以需要格外仔細!
頂點著色器
片與著色器
初始化主要分為4部分
setupLayer函數:創建圖層
layer主要是用於顯示OpenGL ES繪制內容的載體
setupContext函數:創建上下文
上下文主要是用於保存 OpenGL ES 中的狀態,是一個狀態機,不論是 GLKit 還是 GLSL ,都是需要 context 的,主要創建流程如下
deleteRenderAndFrameBuffer函數:清理緩存區
清理緩沖區的目的在於清除殘留數據,防止殘留數據對本次操作造成影響
需要清空兩個緩存區: RenderBuffer和FrameBuffer
設置RenderBUffe & FrameBuffer
首先了解一下RenderBuffer和FrameBuffer
兩者間的關系如下圖:
setupRenderBuffer函數
主要是創建 RenderBufferID 並申請標識符,將標識符綁定至 GL_RENDERBUFFER ,並且將 layer 的相關存儲綁定到 RenderBuffer 對象
setupFrameBuffer函數
主要是創建 FrameBuffer 的ID並申請標識符,將標識符綁定至 GL_FRAMEBUFFER ,然後將 RenderBuffer 通過 glFramebufferRenderbuffer 函數綁定到 FrameBuffer 中的 GL_COLOR_ATTACHMENT0 附著點上,通過 FrameBuffer 來管理 RenderBuffer , RenderBuffer 存儲相關數據到相應緩存區
繪制的整體流程圖所示:
主要包含5部分
初始化
需要注行消意的是,需要將視口的大小設置為與屏幕大小一致
GLSL自定義著色器載入
自定義著色器的載入主要分為以下幾步
讀取自定義著色器
讀取自定義著色器文件的前提是需要獲得文件的路徑,將其傳入 loadShaders 函數進行載入
loadShaders函數 & compileShader函數
loadShaders 函數沒帶尺:分別將頂點著色器和片元著色器編譯完成後,並返回著色器對應的 ID ,然後通過 glAttachShader 函數將頂點和片元的 shader 分別附著到 program 上,然後釋放不再使用的 shader ,並賦值給全局的 program
鏈接program
使用program
通過 glUseProgram 函數來使用鏈接成功的 program
頂點數據設置及處理
通過數組存儲頂點數據,並將頂點坐標和紋理坐標讀取到自定義的頂點著色器中
分為以下三步
開辟頂點緩存區
開啟頂點緩存區,這部分其實跟之前使用 GLKit 框架開啟緩存區步驟是一致的,沒什麼變化,有以下四步
打開頂點/片元的通道
在 iOS 中, attribute 通道默認是關閉的,需要手動開啟,而數據有頂點坐標和紋理坐標兩種,需要分別開啟兩次,這里的開啟與 GLKit 框架中是有所區別枯高的,
使用自定義著色器打開通道,一般有以下三步(相對於 GLKit 而言,只多了一個獲取入口的步驟,後面兩步是沒有多大變化的)
載入紋理
這部分的內容主要是將 png/jpg 圖片解壓成點陣圖,並通過自定義著色器讀取紋理每個像素點的紋素,包含兩部分
setupTexture函數
將 png/jpg 解壓成點陣圖,載入成紋理數據,其中紋理的解壓縮使用的都是 CoreGraphic ,載入紋理的流程如下圖
設置紋理采樣器
主要是獲取紋理中對應像素點的的顏色值,即紋素
繪制
開始繪制,存儲到 RenderBuffer ,從 RenderBuffer 將圖片顯示到屏幕上
*調用 glDrawArrays 函數指定圖元連接方式進行繪制
② glsl語言和c語言的區別·也就是不同的地方有哪些,明確點。謝謝嘍
變數
GLSL的變數命名方式與C語言類似。變數的名稱可以使用字母,數字以及下劃線,但變數名不能以數字開頭,還有變數名不能以gl_作為前綴,這個是GLSL保留的前綴,用於GLSL的內部變數。當然還有一些GLSL保留的名稱是不能夠作為變數的名稱的。
基本類型
除了布爾型,整型,浮點型基本類型外,GLSL還引入了一些在著色器中經常用到的類型作為基本類型。這些基本類型都可以作為結構體內部的類型。如下表:
類型 描述
void 跟C語言的void類似,表示空類型。作為函數的返回類型,表示這個函數不返回值。
bool 布爾類型,可以是true 和false,以及可以產生布爾型的表達式。
int 整型 代表至少包含16位的有符號的整數。可以是十進制的,十六進制的,八進制的。
float 浮點型
bvec2 包含2個布爾成分的向量
bvec3 包含3個布爾成分的向量
bvec4 包含4個布爾成分的向量
ivec2 包含2個整型成分的向量
ivec3 包含3個整型成分的向量
ivec4 包含4個整型成分的向量
mat2 或者 mat2x2 2×2的浮點數矩陣類型
mat3或者mat3x3 3×3的浮點數矩陣類型
mat4x4 4×4的浮點矩陣
mat2x3 2列3行的浮點矩陣(OpenGL的矩陣是列主順序的)
mat2x4 2列4行的浮點矩陣
mat3x2 3列2行的浮點矩陣
mat3x4 3列4行的浮點矩陣
mat4x2 4列2行的浮點矩陣
mat4x3 4列3行的浮點矩陣
sampler1D 用於內建的紋理函數中引用指定的1D紋理的句柄。只可以作為一致變數或者函數參數使用
sampler2D 二維紋理句柄
sampler3D 三維紋理句柄
samplerCube cube map紋理句柄
sampler1DShadow 一維深度紋理句柄
sampler2DShadow 二維深度紋理句柄
結構體
結構體
結構體可以組合基本類型和數組來形成用戶自定義的類型。在定義一個結構體的同時,你可以定義一個結構體實例。或者後面再定義。
struct surface {float indexOfRefraction;
vec3 color;float turbulence;
} mySurface;
surface secondeSurface;
你可以通過=為結構體賦值,或者使用 ==,!=來判斷兩個結構體是否相等。
mySurface = secondSurface;
mySurface == secondSurface;
只有結構體中的每個成分都相等,那麼這兩個結構體才是相等的。訪問結構體的內部成員使用. 來訪問。
vec3 color = mySurface.color + secondSurface.color;
結構體至少包含一個成員。固定大小的數組也可以被包含在結構體中。GLSL的結構體不支持嵌套定義。只有預先聲明的結構體可以嵌套其中。
struct myStruct {
vec3 points[3]; //固定大小的數組是合法的
surface surf; //可以,之前已經定義了
struct velocity { //不合法float speed;
vec3 direction;
} velo;
subSurface sub; //不合法,沒有預先聲明;};struct subSurface { int id;
};
數組
GLSL中只可以使用一維的數組。數組的類型可以是一切基本類型或者結構體。下面的幾種數組聲明是合法的:
surface mySurfaces[];
vec4 lightPositions[8];
vec4 lightPos[] = light www.hnne.com Positions;const int numSurfaces = 5;
surface myFiveSurfaces[numSurfaces];float[5] values;
指定顯示大小的數組可以作為函數的參數或者使返回值,也可以作為結構體的成員.數組類型內建了一個length()函數,可以返回數組的長度。
lightPositions.length() //返回數組的大小 8
最後,你不能定義數組的數組。
修飾符
變數的聲明可以使用如下的修飾符。
修飾符 描述
const 常量值必須在聲明是初始化。它是只讀的不可修改的。
attribute 表示只讀的頂點數據,只用在頂點著色器中。數據來自當前的頂點狀態或者頂點數組。它必須是全局范圍聲明的,不能再函數內部。一個attribute可以是浮點數類型的標量,向量,或者矩陣。不可以是數組或則結構體
uniform 一致變數。在著色器執行期間一致變數的值是不變的。與const常量不同的是,這個值在編譯時期是未知的是由著色器外部初始化的。一致變數在頂點著色器和片段著色器之間是共享的。它也只能在全局范圍進行聲明。
varying 頂點著色器的輸出。例如顏色或者紋理坐標,(插值後的數據)作為片段著色器的只讀輸入數據。必須是全局范圍聲明的全局變數。可以是浮點數類型的標量,向量,矩陣。不能是數組或者結構體。
centorid varying 在沒有多重采樣的情況下,與varying是一樣的意思。在多重采樣時,centorid varying在光柵化的圖形內部進行求值而不是在片段中心的固定位置求值。
invariant (不變數)用於表示頂點著色器的輸出和任何匹配片段著色器的輸入,在不同的著色器中計算產生的值必須是一致的。所有的數據流和控制流,寫入一個invariant變數的是一致的。編譯器為了保證結果是完全一致的,需要放棄那些可能會導致不一致值的潛在的優化。除非必要,不要使用這個修飾符。在多通道渲染中避免z-fighting可能會使用到。
in 用在函數的參數中,表示這個參數是輸入的,在函數中改變這個值,並不會影響對調用的函數產生副作用。(相當於C語言的傳值),這個是函數參數默認的修飾符
out 用在函數的參數中,表示該參數是輸出參數,值是會改變的。
inout 用在函數的參數,表示這個參數即是輸入參數也是輸出參數。
內置變數
內置變數可以與固定函數功能進行交互。在使用前不需要聲明。頂點著色器可用的內置變數如下表:
名稱 類型 描述
gl_Color vec4 輸入屬性-表示頂點的主顏色
gl_SecondaryColor vec4 輸入屬性-表示頂點的輔助顏色
gl_Normal vec3 輸入屬性-表示頂點的法線值
gl_Vertex vec4 輸入屬性-表示物體空間的頂點位置
gl_MultiTexCoordn vec4 輸入屬性-表示頂點的第n個紋理的坐標
gl_FogCoord float 輸入屬性-表示頂點的霧坐標
gl_Position vec4 輸出屬性-變換後的頂點的位置,用於後面的固定的裁剪等操作。所有的頂點著色器都必須寫這個值。
gl_ClipVertex vec4 輸出坐標,用於用戶裁剪平面的裁剪
gl_PointSize float 點的大小
gl_FrontColor vec4 正面的主顏色的varying輸出
gl_BackColor vec4 背面主顏色的varying輸出
gl_FrontSecondaryColor vec4 正面的輔助顏色的varying輸出
gl_BackSecondaryColor vec4 背面的輔助顏色的varying輸出
gl_TexCoord[] vec4 紋理坐標的數組varying輸出
gl_FogFragCoord float 霧坐標的varying輸出
片段著色器的內置變數如下表:
名稱 類型 描述
gl_Color vec4 包含主顏色的插值只讀輸入
gl_SecondaryColor vec4 包含輔助顏色的插值只讀輸入
gl_TexCoord[] vec4 包含紋理坐標數組的插值只讀輸入
gl_FogFragCoord float 包含霧坐標的插值只讀輸入
gl_FragCoord vec4 只讀輸入,窗口的x,y,z和1/w
gl_FrontFacing bool 只讀輸入,如果是窗口正面圖元的一部分,則這個值為true
gl_PointCoord vec2 點精靈的二維空間坐標范圍在(0.0, 0.0)到(1.0, 1.0)之間,僅用於點圖元和點精靈開啟的情況下。
gl_FragData[] vec4 使用glDrawBuffers輸出的數據數組。不能與gl_FragColor結合使用。
gl_FragColor vec4 輸出的顏色用於隨後的像素操作
gl_FragDepth float 輸出的深度用於隨後的像素操作,如果這個值沒有被寫,則使用固定功能管線的深度值代替
表達式
操作符
GLSL語言的操作符與C語言相似。如下表(操作符的優先順序從高到低排列)
操作符 描述
() 用於表達式組合,函數調用,構造
[] 數組下標,向量或矩陣的選擇器
. 結構體和向量的成員選擇
++ – 前綴或後綴的自增自減操作符
+ – ! 一元操作符,表示正 負 邏輯非
* / 乘 除操作符
+ - 二元操作符 表示加 減操作
<> <= >= == != 小於,大於,小於等於, 大於等於,等於,不等於 判斷符
&& || ^^ 邏輯與 ,或, 異或
?: 條件判斷符
= += –= *= /= 賦值操作符
, 表示序列
像 求地址的& 和 解引用的 * 操作符不再GLSL中出現,因為GLSL不能直接操作地址。類型轉換操作也是不允許的。 位操作符(&,|,^,~, <<, >> ,&=, |=, ^=, <<=, >>=)是GLSL保留的操作符,將來可能會被使用。還有求模操作(%,%=)也是保留的。
數組訪問
數組的下標從0開始。合理的范圍是[0, size - 1]。跟C語言一樣。如果數組訪問越界了,那行為是未定義的。如果著色器的編譯器在編譯時知道數組訪問越界了,就會提示編譯失敗。
vec4 myColor, ambient, diffuse[6], specular[6];
myColor = ambient + diffuse[4] + specular[4];
構造函數
構造函數可以用於初始化包含多個成員的變數,包括數組和結構體。構造函數也可以用在表達式中。調用方式如下:
vec3 myNormal = vec3(1.0, 1.0, 1.0);
greenTint = myColor + vec3(0.0, 1.0, 0.0);
ivec4 myColor = ivec4(255);
還可以使用混合標量和向量的方式來構造,只要你的元素足以填滿該向量。
vec4 color = vec4(1.0, vec2(0.0, 1.0), 1.0);
vec3 v = vec3(1.0, 10.0, 1.0);
vec3 v1 = vec3(v);