1. 程式人生 > >OpenGL GLSL 語法和函式詳解

OpenGL GLSL 語法和函式詳解

變數和資料型別

可用的資料型別只有4種:有符號整數,無符號整數,浮點數,布林值。 
OpenGL著色語言中沒有指標和字串或字元。返回值可以為void。

向量型別

所有4種基本資料型別都可以儲存在二維、三維或者四維向量中: 
OpenGL著色語言向量資料型別

型別 描述
vec2,vec3,vec4 2分量、3分量和4分量浮點向量
ivec2,ivec3,ivec4 2分量、3分量和4分量整數向量
uvec2,uvec3,uvec4 2分量、3分量和4分量無符號整數向量
bvec2,vbec3,bvec4 2分量、3分量和4分量布林向量
vec4 v1;
vec4 v2=vec4(1.0f,1.0f,1.0f,1.0f);
vec4 v3=vec4(1.0f,1.0f,1.0f,1.0f);
v1=v2+v3;
v1+= vec4(1.0f,1.0f,1.0f,1.0f);
v2*=4.0f;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我們用點號來確定多大4個向量元素的地址,但是可以使用下列3組識別符號中的任意一組:xyzw、rgba和stpq。但不能混合到一個向量中使用。

v3.x=3.0f;
v3.rg=vec2(3.0f,5.0f);
v3.stpq= vec4(1.0f,1.0f,1.0f,1.0f);
  • 1
  • 2
  • 3

向量資料型別還支援swizzle(調換)操作。例如,將顏色資料從RGB順序轉換到BGR順序:

vColor.bgra=vColor.rgba;
  • 1

矩陣型別

矩陣型別只支援浮點數。 
OpenGL著色語言矩陣資料型別

型別 描述
mat2,mat2x2 兩行兩列
mat3,mat3x3 三行三列
mat4,mat4x4 四行四列
mat2x3 三行兩列
mat2x4 四行兩列
mat3x2 兩行三列
mat3x4 四行三列
mat4x2 兩行四列
mat4x3 三行四列

實際上在OpenGL著色語言中,矩陣就是一個由向量組成的陣列。可以對單獨一列應用向量操作:

vec3 vec=mModelView[3].xyz;
  • 1

矩陣也可以乘以向量,通常用在通過模型檢視投影矩陣來對一個向量進行變換時。 
矩陣建構函式:

mat4 vTransform=mat4(
1.0f,1.0f,1.0f,1.0f, 
1.0f,1.0f,1.0f,1.0f, 
1.0f,1.0f,1.0f,1.0f,
 1.0f,1.0f,1.0f,1.0f);
  • 1
  • 2
  • 3
  • 4
  • 5

也可以如下方式構造單位矩陣:

mat4 v=mat4(1.0f);
  • 1

儲存限定符

限定符用於將變數標記為輸入變數、輸出變數或常量。 
變數儲存限定符

限定符 描述
只是普通的本地變數,外部不可見,外部不可訪問
const 一個編譯時常量,或者說是一個隊函式來說為只讀的引數
in 一個從以前的截斷傳遞過來的變數
in centroid 一個從以前的截斷傳遞過來的變數,使用質心插值
out 傳遞到下一個處理階段或者在一個函式中指定一個返回值
out centroid 傳遞到下一個處理階段,使用質心插值
inout 一個讀/寫變數,只能用於區域性函式引數
uniform 一個從客戶端程式碼傳遞過來的變數,在頂點之間不做改變

inout只能在一個函式中宣告一個引數時使用,這是將一個值傳遞到一個函式並且允許這個函式修改並返回同一個變數值的唯一方法。 
除非正在對一個多重取樣緩衝區進行渲染,否則centroid限定符不會起任何作用。 
預設情況下,引數將在兩個著色器截斷之間以一種透視正確的方法進行插補。我們可以通過noperspective關鍵詞來指定一個非透視插值,或者甚至可以通過flat關鍵詞二不進行插值。我們還可以選擇使用smooth關鍵詞來宣告,這個變數時以一種透視正確的方法進行插補的,實際上是預設設定:

smooth out vec3 vSmoothValue;
flat out vec3 vFlatColor;
noperspective float vLinearlySmoothed;
  • 1
  • 2
  • 3

真正的著色器

Shadedldentity著色器頂點程式

// The ShadedIdentity Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

in vec4 vColor;
in vec4 vVertex;

out vec4 vVaryingColor;

void main(void) 
    { 
    vVaryingColor = vColor;
    gl_Position = vVertex;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Shadedldentity著色器片段程式

// The ShadedIdentity Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130

out vec4 vFragColor;
in vec4 vVaryingColor;

void main(void)
   { 
   vFragColor = vVaryingColor;
   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

OpenGL著色語言版本 
每個著色器的第一行非命令列都是指定這個著色器要求的OpenGL著色語言的最低版本版本,如果OpenGL驅動不支援,那麼著色器將不會編譯:

#version 330
  • 1

OpenGL3.3版本 
屬性宣告 
屬性是由OpenGL程式碼逐個頂點進行指定的,在頂點著色器中,這些屬性指示簡單地宣告為

in;
in vec4 vVertex;
in vec4 vColor;
  • 1
  • 2
  • 3

在GLSL中每個頂點程式都罪過可以有16個屬性。 
每個屬性總是一個4分量向量,即使不適用所有的4汾江時也是如此。例如,我們指示指定了一個float值作為引數,那麼在內部仍將佔據4個浮點值的空間。 
標記為in的變數時只讀的。 
宣告輸出 
頂點程式的輸出變數將成為要傳送到片段著色器的頂點的顏色值,這個變數必須為片段朱搜而起宣告一個in變數,否則在我們試圖將著色器編譯和連線到一起時,就會得到一個連線錯誤。 
頂點動作 
頂點程式的主體在批次中將為每個頂點執行一次:

void main(void){
vVaryingColor=vColor;
gl_Position=vVertex;
}
  • 1
  • 2
  • 3
  • 4

變數gl_Position是一個預定義的內建4分量向量,它包含頂點著色器要求的一個輸出。 
片段三角形 
在渲染一個圖元(例如一個三角形)時,一旦3個頂點由頂點程式進行了處理,那麼它們將組裝成一個三角形,而這個三角形將由硬體進行光柵化。圖形硬體確定獨立片段屬於螢幕上(或者更精確地,在顏色緩衝區中)的什麼位置,並且為三角形中的每個片段(如果不進行任何多重取樣的話則只是一個點)指定片段程式的一個例項。 
片段程式的最終輸出顏色是一個4分量浮點向量,我們如下宣告這個向量:

out vec4 vFragColor;
  • 1

輸入片段著色器時經過平滑插值的顏色值,由頂點程式上游傳入:

in vec4 vVaryingColor;
  • 1

片段著色器只是將平滑插值的顏色分配給片段顏色:

void main(void){
vFragColor=vVaryingColor;
}
  • 1
  • 2
  • 3

編譯、繫結和連線

指定屬性

Gluint gltLoadShaderPairWithAttributes(const char *szVertexProg,const char *szFragmentProg,……);
  • 1

我們可能像下面這樣呼叫該函式:

hShader=gltLoadShaderPairWithAttributes(“vertexProg.vp”,”fragmentProg.fp”,2,0,”vVertexPos”,1,”vNormal”);
  • 1

對於為兩個屬性位置進行0和1的選擇視任意性的,只要這個值在0~15範圍之內。我們也可以選擇7和13。不過,GLTools類GLBatch和GLTriangleBatch則使用一系列一致的屬性位置,由typedef指定:

typedef enum GLT_SHADER_ATTRIBUTE{
GLT_ATTRIBUTE_VERTEX=0,GLT_ATTRIBUTE_COLOR,GLT_ATTRIBUTE_NORMAL,GLT_ATTRIBUTE_TEXTURE0,GLT_ATTRIBUTE_TEXTURE1,GLT_ATTRIBUTE_TEXTURE2,GLT_ATTRIBUTE_TEXTURE3,GLT_ATTRIBUTE_LAST
};
  • 1
  • 2
  • 3

如果使用了這些屬性位置識別符號,我們就可以開始和GLShaderManager類中支援的儲存著色器一起使用自己的著色器了。 
設定原始碼 
我們的首要任務是建立兩個著色器物件,分別對應頂點著色器和片段著色器:

hVertexShader=glCreateShader(GL_VERTEX_SHADER);
hFragmentShader=glCreateShader(GL_FRAGMENT_SHADER);
  • 1
  • 2

然後使用gltLoadShaderFile載入著色器文字。 
接著對頂點著色器和片段著色器應用下面幾項操作:

GLchar *fsStringPtr[1];
fsStringPtr[0]=(GLchar*)szShaderSrc;
glShaderSource(shader,1,(const GLchar **)fsStringPtr,NULL);
  • 1
  • 2
  • 3

編譯著色器 
編譯著色器時一項簡單的一次性工作:

glcompileShader(hVertexShader);
glCompileShader(hFragmentShader);
  • 1
  • 2

為了檢查失敗,我們使用以GL_COMPILE_STATUS標記為引數的glGetShader函式:

glGetShaderiv(hVertexShader,GL_COMPILE_STATUS,&testVal);
  • 1

如果返回的testVal值為GL_FALSE,那就說明原始碼編譯失敗了。也可以打印出編譯資訊來查看出問題的原因。 
進行連線和繫結 
首先,我們要建立最終的著色器程式物件,並將頂點著色器和片段著色器與它繫結到一起:

hReturn=glCreateProgram();
glAttachShader(hReturn,hVertexShader);
glAttachShader(hReturn,hFragmentShader);
  • 1
  • 2
  • 3

接著,將屬性變數名繫結到指定的數字屬性位置:

void glBindAttriblocation(Gluint shaderProg,GLuint attribLocation,const GLchar *szAttributeName);
  • 1

它接受我們正在討論的著色器的識別符號,將要進行繫結的屬性位置和屬性變數的名稱。我們常採用一個約定:位置屬性變數名用vVertex,屬性位置用GLT_ATTRIBUTE_VERTEX值(值0) 
連線著色器

glLinkProgram(hReturn);
  • 1

連線之後可以丟棄頂點著色器物件和片段著色器物件:

glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
  • 1
  • 2

最後,當不再使用這個著色器程式時,需要刪除它:

void glDeleteProgram(GLuint program);
  • 相關推薦

    OpenGL GLSL 語法函式

    變數和資料型別 可用的資料型別只有4種:有符號整數,無符號整數,浮點數,布林值。  OpenGL著色語言中沒有指標和字串或字元。返回值可以為void。 向量型別 所有4種基本資料型別都可以儲存在二維、三維或者四維向量中:  OpenGL著色語言向量資料型別 型別

    robots.txt的語法寫法

    html txt 訪問 isa 字符 包含 all 屏蔽 有道 robots.txt是一個純文本文件,是搜索引擎蜘蛛爬行網站的時候要訪問的第一個文件,當蜘蛛訪問一個站點時,它會首先檢查該站點根目錄下是否存在robots.txt,如果存在,搜索機器人就會按照該文件中的內容來確

    Socket通訊過程函式

    from:http://blog.csdn.net/tianmo2010/article/details/6542063 ①什麼是Socket    Socket介面是TCP/IP網路的API,Socket介面定義了許多函式或例程,程式設計師可以用它們來開發TCP/IP網路上的應用程式。要學

    Python基礎學習資料(語法函式

    目錄 目錄 1 常用函式 5 input() 5 int() 6 len() 7 list() 與tuple相對 8 tuple() 與list相對 9 sum() 10 max() 11 min() 12 print() 13 range() 14 set() 15 sorted() 16

    android平臺下OpenGL ES 3.0例項頂點緩衝區物件(VBO)頂點陣列物件(VAO)

    OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

    mallocfree函式(轉載只是為了查閱方便,若侵權立刪)

    malloc和free函式詳解   本文介紹malloc和free函式的內容。   在C中,對記憶體的管理是相當重要。下面開始介紹這兩個函式:     一、malloc()和free()的基本概念以及基本用法: 1、函式原型及說明: void *malloc(lon

    linux中alarm函式pause函式例項

    轉載原文:https://www.cnblogs.com/yxk529188712/p/4982401.html alarm(time);執行之後告訴核心,讓核心在time秒時間之後向該程序傳送一個定時訊號,然後該程序捕獲該訊號並處理; pause()函式使該程序暫停讓出CPU,但是該函式的暫停

    PL/SQL單行函式函式

    分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

    Linux 多工程式設計——多程序建立:fork() vfork() 函式

    一、fork() 函式詳解 需要的標頭檔案: #include <sys/types.h> #include <unistd.h> pid_t fork(void); 功能: 用於從一個已存在的程序中建立一個新程序,新程序稱為子程序,原程序稱為父程序。

    初夏小談:函式 strchr strcmp

    實現和strchr(查詢字元首次出現的位置) #include<Aventador_SQ.h> int Strchr(char arr[], char Char,int* location) { int i = 0; int ArrLen = strlen(arr); int

    setjmp()longjmp()函式

    今天看《unix環境高階程式設計》發現這兩個函式,還挺有用的,在c異常處理、協程等作用很大。 使用方法 我們知道,想要實現函式內的跳轉可以使用goto語句,但如果需要從一個函式跳轉到另一個函式,goto是不能完成的,那該如何實現呢? 函式間跳轉原理 示例程式碼: void

    C語言itoa()函式atoi()函式(整數轉字元)

    轉自:http://c.biancheng.net/cpp/html/792.html C語言提供了幾個標準庫函式,可以將任意型別(整型、長整型、浮點型等)的數字轉換為字串。 以下是用itoa()函式將整數轉換為字串的一個例子:# include <stdio.h># include

    物件-中(6個預設函式

    本文主要是對類的6個預設函式進行講解 類的預設成員函式有6個:建構函式                                                解構函式                                                

    OpenGL gluLookAt函式

    第三組就是頭頂朝向的方向(因為你可以歪著頭看同一個物體)。#include <stdlib.h>#include <GL/glut.h>#pragma comment(lib, "glut32.lib")void init(void) {   glClearColor (0.0, 0.

    Android NDK——必知必會之JNI的C++操作函式小結(三)

    引言 上一篇講解了一些關於JNI和NDK的必知必會的理論知識和機制,由於篇幅問題把關於JNI的重要的函式放到這篇,具體使用留到下一篇,此係列文章基連結: 一、JNI中的函式概述 在JNI層我們基本上都是通過env指標來呼叫jni.h標頭檔案裡定義的函式,JNI

    oracle之percent_rank() over()函式PERCENTILE_CONT() within group()over()函式

    建立一個臨時表 create table EMP ( EMPNO NUMBER(4) not null, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL

    vue2.0專案實戰(4)生命週期鉤子函式

    最近的專案都使用vue2.0來開發,不得不說,vue真的非常好用,大大減少了專案的開發週期。在踩坑的過程中,因為對vue的生命週期不是特別瞭解,所以有時候會在幾個鉤子函式裡做一些事情,什麼時候做,在哪個函式裡做,我們不清楚。 下面來總結一下vue的生命週期。 vue生命週期簡介 咱們從上圖可以很明顯的看出

    C++函式呼叫過程內建函式

           上圖表示 函式呼叫過程:①程式先執行函式呼叫之前的語句;②流程的控制轉移到被呼叫函式入口處,同時進行引數傳遞;③執行被呼叫函式中函式體的語句;④流程返回呼叫函式的下一條指令處,將函式返回值帶回;⑤接著執行主調函式未執

    程式設計師必備知識——forkexec函式

            在學習UNIX程式設計時,必須要學習的一個函式為fork函式。fork函式也為面試中必定要問的一個問題,尤其是在BAT的面試中,fork函式相關問題更為面試筆試必考知識點。究其原因:

    malloc函式以及new的區別

    今天偶然看到一個面試經驗中提到malloc和new的區別,突然發現自己雖然兩個都用過,但是至於區別,真的不是很明白 ,所以就仔細查了一些資料,算是對這個點徹底地瞭解一下,現在把我所學到的記錄下來。 malloc與free是C++/C語言的標準庫函式,new/d