glsl初步接觸

2021-06-26 03:02:53 字數 4552 閱讀 5034

在看計算機系的同學的**時,我還不知道glsl這種東西。我還以為opengl繪製就是使用glbegin和glend。我還深深地納悶:opengl這貨畫東西完全不給力,是怎麼做到跟directx相比的?然後我看到了**裡的gluseprogram,看到了程式裡完全沒有出現glbegin這種語句。後來我才知道,手裡的opengl紅寶書已經是過去時,nehe的opengl教程也已經是過去時,我離地球太遠了。

乙個glsl的程式,最常用的有兩個著色器,乙個頂點著色器(vertex shader),乙個片段著色器(fragement shader)。當然我們需要首先初始化著色器,比如用以下**(參見

gluint fragmentshader = glcreateshader(gl_fragment_shader);

glshadersource(fragmentshader, 1, &fragmentsource, null);

glcompileshader(fragmentshader);

這段**用於生成並編譯乙個fragment shader。當然這裡面可以換成vertex shader、geometry shader等,甚至最新的compute shader。這裡面有個fragmentsource,是個字串,用來存這些shader的源**。可是有一件事情顯而易見:用字串來寫shader的**實在是太麻煩了。最好是把shader都存到檔案裡,然後把這個檔案讀入乙個陣列裡。讀取檔案的方法多種多樣,就不細說了。

顯然上文中compileshader這句就是用來編譯著色器的,可是我們還想知道成功沒成功。說實在的,跟顯示卡打交道很不方便,因為其中**有什麼錯誤都不太直觀。

glint status;

glgetshaderiv(vertexshader, gl_compile_status, &status);

把所有要用到的shader都建立起來之後,就要建乙個program,將所有的shader都綁到這個程式上來,比如乙個誇張點的栗子:

gluint shaderprogram = glcreateprogram();

glattachshader(shaderprogram, vertexshader);

glattachshader(shaderprogram, fragmentshader);

glattachshader(shaderprogram, geometryshader);

glattachshader(shaderprogram, computeshader);

當然名字都是自己起的。

然後還需要連線一下,用:

gllinkprogram(shaderprogram);

最後,當需要使用或者停用這個shaderprogram時,分別對應下面兩個語句:

gluseprogram(shaderprogram);

gluseprogram(0);

shader是建完了,我們還需要往裡面傳資料。首先當然是頂點座標、顏色和紋理座標,分別對應的是glbegin之後的glvertex*、glcolor*和gltexcoord*這些命令。這次我們建三個陣列來存這些資料。比如乙個三角形總共三個頂點,對應三組座標,可以分別存為

float vertex[9]=; 

float color[9]=;

float texture[6]=;

顯然最常用的二維紋理座標乙個點只有兩個數。

然後根據這三組資料建立vbo(vertex buffer object):

gluint vbo[3];

glgenbuffers(3, vbo);

//頂點座標

glbindbuffer(gl_array_buffer, vbo[0]);

glbufferdata(gl_array_buffer, 9*sizeof(float), vertex, gl_static_draw);

//顏色

glbindbuffer(gl_array_buffer, vbo[1]);

glbufferdata(gl_array_buffer, 9*sizeof(float), color, gl_static_draw);

//紋理座標

glbindbuffer(gl_array_buffer, vbo[2]);

glbufferdata(gl_array_buffer, 6*sizeof(float), texture, gl_static_draw);

快取的大小應當與陣列的大小相等。由於這些資料只是讀取,不需要更改,因此最後乙個引數就是gl_static_draw。當然,如果不需要顏色或者紋理座標,可以相應地改動vbo陣列的大小。

為了繪製方便,我們還要建立乙個頂點陣列物件(vao,vertex array object):

gluint vao;

glgenvertexarrays(1, &vao);

glbindvertexarray(vao);

這些事情算是準備工作,已經做得差不多了。還有一些關鍵部分。這些部分需要先使用gluseprogram(shaderprogram)啟用shader。然後需要指定我們這些資料的入口。有兩種方法可以用於指定入口,一種類似open.gl教程裡所說,可以用

glbindbuffer(gl_array_buffer, vbo[0]);

glint posattrib = glgetattriblocation(shaderprogram, "invertex");

glvertexattribpointer(posattrib, 3, gl_float, gl_false, 0, 0);

glenablevertexattribarray(posattrib);

我們假設傳入的頂點座標在shader裡的名字是invertex。這兩句首先將要繫結的資料啟用,然後獲取shader裡面invertex變數的位置,然後將啟用的資料綁到對應的位置上,最後啟用這個綁好的資料。三組資料都可以類似地繫結好。

當然我們也可以很明確地指定這幾個資料的位置,比如說

glbindbuffer(gl_array_buffer, vbo[0]);

glvertexattribpointer(0, 3, gl_float, gl_false, 0, 0);

glenablevertexattribarray(0);

這就寫明了vbo[0]這個物件(這裡是頂點座標)是綁在了0號位置上的。但是這樣的話,在shader當中就需要明確指出所有傳入變數的位置。假設傳入的頂點座標、顏色和紋理座標分別繫結到0、1、2號位置,而shader裡名稱分別為invertex、incolor、intexture的話,那麼在shader裡就應該定義為:
layout (location = 0) in vec3 invertex;

layout (location = 1) in vec3 incolor;

layout (location = 2) in vec2 intexture;

這樣三個變數就能對應得上了。

由於啟用了vao,繪製只需要一句:

gldrawarrays(gl_********, 0, 3);

這裡還應該說說vertex和fragment這兩個shader裡應該寫什麼。以下是我某個vertex shader裡的內容:

#version 400 compatibility

//此處兩個location應當與程式當中繫結vbo時的引數對應

layout (location = 0) in vec2 vertexposition;

layout (location = 1) in vec2 vertextexcoord;

out vec2 vtexcoord;

void main()

第一句是指定了所用glsl的版本。有些函式只在新版本裡才能用。然後out vec2的這句是用來將vtexcoord的內容傳給fragment shader。而主函式裡除了將紋理座標傳遞了一下之外,用了乙個ftransform()函式。這個內建函式實際上是把opengl裡的glviewport、glperspective等函式生成的矩陣按照最常用的方式與頂點座標相乘了。如果不對頂點座標進行操作的話,這個函式是個不錯的選擇。

而另乙個fragment shader裡的內容為:

#version 400 compatibility

uniform sampler2d sampler0;

in vec2 vtexcoord;

out vec4 fragcolor;

void main()

這個shader也啥都沒乾,texture2d一句表示從sampler0紋理中根據vtexcoord座標獲得相應的顏色值。

看起來glsl的框架搭起來還是相當麻煩,但是一旦搭好了框架,就能發揮glsl十分強大的功能了。

VML初步接觸

什麼是vml?vml vector markup language 是乙個最初由microsoft開發的xml詞表,現在也只有ie5.0以上版本對vml提供支援。使用vml可以在ie中繪製向量圖形,所以有人認為vml就是在ie中實現了畫筆的功能。下面介紹一下vml的優點 基於xml標準 xml是公認...

初步接觸ubuntu

1 檔案部分helloworld 建立檔案 sudo vi aa.txt 由於許可權問題所以加上管理員許可權sudo 然後進入編輯介面 寫入helloworld 按esc退出 輸入 wq 寫入write並退出quit 檢視檔案 修改檔案許可權 此處還是要用sudo chmod 今天把學習到的先記錄到...

初步接觸pentaho

最近有個專案要一些生成報表的功能,技術老總要用pentaho,以前同事也接觸過pentaho,但是總體印象不太好。經過兩個星期的研究,對pentaho有點初步的認識。從總體來講pentaho還是很強大的,而且是開源的,所以不用花錢也能用。pentaho的文件還算比較多,但是就跟其他的開源專案一樣,文...