OpenGL 學習筆記 5

2022-08-19 06:39:07 字數 4494 閱讀 3797

什麼是幀緩衝?可以理解為gpu在渲染前預先準備的乙個區域,之後將把它渲染成螢幕上的畫素。但是,幀緩衝本身並不儲存資料,僅僅儲存指向資料的指標。所以,幀緩衝需要繫結幾個緩衝區,我們特殊地稱它們為附件:顏色附件,深度緩衝附件,模板緩衝附件。需要注意的是,乙個完整的幀緩衝必須包括乙個顏色附件。

除了這種分類之外,附件還可以分為紋理附件和渲染緩衝物件(rbo,render buffer object)。其中,紋理附件就是顏色附件,rbo分為深度緩衝附件和模板緩衝附件。讓我們來列乙個樹形圖。

幀緩衝--[紋理附件]--顏色附件

[渲染緩衝附件]--深度緩衝附件

--模板緩衝附件

為什麼要講到幀緩衝呢?因為幀緩衝是後期處理相當重要的部分。例如陰影,模糊,反相等後期處理都要依靠幀緩衝來實現。打個比方,幀緩衝就好像是拍出來的一張**,可以讓我們ps。

此處的ps便是著色器。opengl提供了可以讓我們編輯的幀緩衝,好偉大!我們可以把一張幀緩衝儲存的2d紋理或深度緩衝獲得為乙個控制代碼,在後面直接使用,塞進著色器裡。

首先生成並繫結乙個幀緩衝:

gluint framebuffername = 0

; glgenframebuffers(

1, &framebuffername);

glbindframebuffer(gl_framebuffer, framebuffername);

生成乙個紋理:

gluint renderedtexture;

glgentextures(

1, &renderedtexture);

狀態機不解釋:

glbindtexture(gl_texture_2d, renderedtexture);
由於幀緩衝必須包含乙個顏色附件,所以接下來對之前繫結的紋理填充乙個空的影象(最後乙個引數0代表空,empty):

glteximage2d(gl_texture_2d, 0,gl_rgb, windowwidth, windowheight, 0,gl_rgb, gl_unsigned_byte, 0);
可  憐  的  過  濾(效能upup),設定過濾模式:

gltexparameteri(gl_texture_2d, gl_texture_mag_filter, gl_nearest);

gltexparameteri(gl_texture_2d, gl_texture_min_filter, gl_nearest);

gltexparameteri(gl_texture_2d, gl_texture_wrap_s, gl_clamp_to_edge);

gltexparameteri(gl_texture_2d, gl_texture_wrap_t, gl_clamp_to_edge);

由於我們要渲染乙個3d模型,所以要進行深度測試,所以來生成並繫結乙個渲染緩衝區,將要作為我們的rbo:

gluint depthrenderbuffer;

glgenrenderbuffers(

1, &depthrenderbuffer);

glbindrenderbuffer(gl_renderbuffer, depthrenderbuffer);

由於opengl只知道這是個渲染緩衝區,對其中的資料格式和大小全然不知,所以我們得告訴它,使用glrenderbufferstorage來指定rbo的資料格式和大小,此處指定為深度緩衝區:

glrenderbufferstorage(gl_renderbuffer, gl_depth_component, windowwidth, windowheight);
對於此函式,第乙個引數必須填gl_renderbuffer,第二個指定了型別為深度緩衝,還可以是gl_rgb,gl_rgba,剩下的兩個引數指定了資料長寬,這裡設定為螢幕大小。

接下來開始為幀緩衝繫結附件,將此深度緩衝繫結為深度附件:

glframebufferrenderbuffer(gl_framebuffer, gl_depth_attachment, gl_renderbuffer, depthrenderbuffer);
第二個引數指定了型別為深度附件。

然後繫結紋理附件,這個比較特殊,先看**:

glframebuffertexture(gl_framebuffer, gl_color_attachment0, renderedtexture, 0);
可以看到,第二個引數並不是指定的型別,而是gl_color_attachment0,這意味著什麼呢,這意味著顏色附件可以有多個,0代表的是顏色附件的位置。同時我們也發現rbo只能有乙個,因為它直接指定了型別。

所以,我們就需要指定接下來渲染時需要渲染到哪些顏色附件上,這次我們只渲染到gl_color_attachment0上:

glenum drawbuffers[1] =;

gldrawbuffers(

1, drawbuffers);

不需要多說了吧。

終於,幀緩衝的前置操作完成了。這時需要檢查你的幀緩衝是否完整,否則會有很可怕的錯誤:

if(glcheckframebufferstatus(gl_framebuffer) !=gl_framebuffer_complete)

return

false;

經常check是好習慣呦~

由於我們要把幀緩衝的影象經過處理繪製到螢幕上,所以一會渲染的時候將要分兩個步驟:第一步,按照往常的操作渲染,但是在渲染前把渲染目標繫結到我們自定義的幀緩衝上,此為離屏渲染。然後,通過顏色附件獲得渲染得到的深度緩衝和紋理,再把它們傳到著色器裡處理,作為2d紋理渲染到乙個螢幕大小的四邊形上。

那麼,下面開始定義四邊形:

static

const glfloat g_quad_vertex_buffer_data =;

gluint quad_vertexbuffer;

glgenbuffers(

1, &quad_vertexbuffer);

glbindbuffer(gl_array_buffer, quad_vertexbuffer);

glbufferdata(gl_array_buffer,

sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, gl_static_draw);

定義頂點緩衝,裡面包括的是乙個2d充滿螢幕的四邊形的頂點,注意此時頂點依然是3維的格式,只不過z=0,相當於2d。

好了,一切都準備好了,下面進入主迴圈:

首先把渲染目標繫結到我們定義的幀緩衝裡:

glbindframebuffer(gl_framebuffer, framebuffername);
這裡是渲染操作...

gluseprogram(programid);
(這裡使用通常的著色器)

這裡是渲染操作...

然後重頭戲來了,開始渲染四邊形,先把渲染目標繫結到預設幀緩衝:這個幀緩衝將會直接被gpu提取渲染:

glbindframebuffer(gl_framebuffer, 0);
這裡是渲染操作...

gluseprogram(quad_programid);
(使用第二個著色器,這個著色器只負責渲染乙個2d紋理並稍稍處理)

這裡是渲染操作...

怎麼樣,這樣就完成了呢,小朋友們學會了嗎?(狗頭)

咳咳,說了這麼多,第二個著色器長啥樣呢,僅僅渲染乙個2d紋理的著色器,來看吧:

#version 330

core

//input vertex data, different for all executions of this shader.

layout(location = 0) in

vec3 vertexposition_modelspace;

//output data ; will be interpolated for each fragment.

outvec2 uv;

void

main()

出人意料的簡單呢......僅僅傳出乙個uv座標。不過,這裡要注意,我們的頂點座標xy的範圍是[-1,1],而uv座標uv的範圍是[0,1],所以需要(xy+(1,1))/2來轉換。

看片元著色器:

#version 330

core

invec2 uv;

outvec3 color;

uniform sampler2d renderedtexture;

uniform

float

time;

void

main()

用時間來做乙個偏移量,不多說了吧。

那麼看看結果吧:

畫素會隨著時間的變化慢慢移動喔!

OpenGL學習筆記

我是一名ios開發者,opengl是乙個比較重要的技術。所以就此開啟我的菜鳥之路。opengl open graphics library 是乙個跨程式設計語 言 跨平台的程式設計圖形程式接 它將計算機的資源抽象稱為乙個個opengl的物件,對這些資源的操作抽象為乙個的opengl指令.direct...

OpenGL學習筆記

數學基礎 叉積mv矩陣 文章內容主要來自 計算機圖形學程式設計 使用opengl和c 光柵化過程確定了用以顯示3個頂點所確定的三角形的所有畫素需要繪製的位置 光柵化過程開始時先對三角形的每對頂點進行插值 如果光柵化過程到此為止,那麼呈現出的影象將會是線框模型 使用 glpolygonmode gl ...

OpenGL學習筆記

因工作需要,這些天要研究opengl。我給自己定的目標是 1.節前能熟悉opengl基礎知識 2.確定一款以opengl為基礎的gui 3.學習如何使用該gui的控制項繪製3d選單 今天找到幾個 嵌入式系統使用的是opengl es,是桌面opengl的乙個子集,定義了一系列靈活高效的圖形加速介面。...