什麼是幀緩衝?可以理解為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);由於我們要渲染乙個3d模型,所以要進行深度測試,所以來生成並繫結乙個渲染緩衝區,將要作為我們的rbo: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);
gluint depthrenderbuffer;由於opengl只知道這是個渲染緩衝區,對其中的資料格式和大小全然不知,所以我們得告訴它,使用glrenderbufferstorage來指定rbo的資料格式和大小,此處指定為深度緩衝區:glgenrenderbuffers(
1, &depthrenderbuffer);
glbindrenderbuffer(gl_renderbuffer, depthrenderbuffer);
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)經常check是好習慣呦~return
false;
由於我們要把幀緩衝的影象經過處理繪製到螢幕上,所以一會渲染的時候將要分兩個步驟:第一步,按照往常的操作渲染,但是在渲染前把渲染目標繫結到我們自定義的幀緩衝上,此為離屏渲染。然後,通過顏色附件獲得渲染得到的深度緩衝和紋理,再把它們傳到著色器裡處理,作為2d紋理渲染到乙個螢幕大小的四邊形上。
那麼,下面開始定義四邊形:
static定義頂點緩衝,裡面包括的是乙個2d充滿螢幕的四邊形的頂點,注意此時頂點依然是3維的格式,只不過z=0,相當於2d。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);
好了,一切都準備好了,下面進入主迴圈:
首先把渲染目標繫結到我們定義的幀緩衝裡:
glbindframebuffer(gl_framebuffer, framebuffername);這裡是渲染操作...
gluseprogram(programid);(這裡使用通常的著色器)
這裡是渲染操作...
然後重頭戲來了,開始渲染四邊形,先把渲染目標繫結到預設幀緩衝:這個幀緩衝將會直接被gpu提取渲染:
glbindframebuffer(gl_framebuffer, 0);這裡是渲染操作...
gluseprogram(quad_programid);(使用第二個著色器,這個著色器只負責渲染乙個2d紋理並稍稍處理)
這裡是渲染操作...
怎麼樣,這樣就完成了呢,小朋友們學會了嗎?(狗頭)
咳咳,說了這麼多,第二個著色器長啥樣呢,僅僅渲染乙個2d紋理的著色器,來看吧:
#version 330出人意料的簡單呢......僅僅傳出乙個uv座標。不過,這裡要注意,我們的頂點座標xy的範圍是[-1,1],而uv座標uv的範圍是[0,1],所以需要(xy+(1,1))/2來轉換。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()
看片元著色器:
#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的乙個子集,定義了一系列靈活高效的圖形加速介面。...