OpenGL 編寫特效在部分應(yīng)用中可通過單個(gè)shader實(shí)現(xiàn)各拷,即通過修過修改頂點(diǎn)著色器或片元著色器實(shí)現(xiàn)疚鲤。但更多的場景是要求有多個(gè)特效組合而成,例如最終效果是圖片灰度加上下顛倒样刷,效果不復(fù)雜條件下可以通過修改片元著色器實(shí)現(xiàn)览爵,當(dāng)效果復(fù)雜特效、組合特效蜓竹、特效的模塊化開發(fā)都會(huì)通過鏈?zhǔn)綖V鏡實(shí)現(xiàn)箕母。
一俱济、鏈?zhǔn)綖V鏡概念
鏈?zhǔn)綖V鏡 通過幀緩沖離屏渲染技術(shù)實(shí)現(xiàn)特效的組合和疊加。通過多次draw最終實(shí)現(xiàn)預(yù)期效果蛛碌。
二、渲染流程中的幀緩沖
OpenGL的工作流程蔚携,輸入像素?cái)?shù)據(jù)和頂點(diǎn)數(shù)據(jù),兩種數(shù)據(jù)分別操作后酝蜒,通過光柵化誊辉,得到片段,再經(jīng)過片段處理秕硝,最后繪制到幀緩沖區(qū)芥映,最終轉(zhuǎn)化為像素?cái)?shù)據(jù)。OpenGL 管線渲染的最終目的地就是FrameBuffer(幀緩沖)远豺。下面是OpenGL渲染流程圖奈偏。
三、幀緩沖對象
在OpenGL渲染管線中躯护,幾何數(shù)據(jù)和紋理經(jīng)過多次轉(zhuǎn)化和多次測試惊来,最后以二維像素的形式顯示在屏幕上。OpenGL管線的最終渲染目的地被稱作幀緩存(framebuffer)棺滞。幀緩沖是一些二維數(shù)組和OpenG所使用的存儲(chǔ)區(qū)的集合:顏色緩存裁蚁、深度緩存、模板緩存和累計(jì)緩存继准。一般情況下枉证,幀緩存完全由window系統(tǒng)生成和管理,由OpenGL使用移必。這個(gè)默認(rèn)的幀緩存被稱作“window系統(tǒng)生成”(window-system-provided)的幀緩存室谚。OpenGL允許我們定義我們自己的幀緩沖,也就是說我們能夠定義我們自己的顏色緩沖,甚至是深度緩沖和模板緩沖秒赤。在一個(gè)幀緩存對象中有多個(gè)顏色關(guān)聯(lián)點(diǎn)猪瞬、一個(gè)深度關(guān)聯(lián)點(diǎn),和一個(gè)模板關(guān)聯(lián)入篮。每個(gè)幀緩存中至少有一個(gè)顏色關(guān)聯(lián)點(diǎn)陈瘦,其數(shù)目與實(shí)體顯卡相關(guān)〕笔郏可以通過GL_MAX_COLOR_ATTACHMENTS_EXT來查詢顏色關(guān)聯(lián)點(diǎn)的最大數(shù)目痊项。
需要注意:FBO中并沒有存儲(chǔ)圖像,只有多個(gè)關(guān)聯(lián)點(diǎn)酥诽。
四线婚、自定義幀緩沖
1:創(chuàng)建一個(gè)幀緩沖.
unsigned int fbo;
glGenFramebuffers(1, &fbo);
2:綁定幀緩沖,幀緩沖會(huì)在被綁定時(shí)隱士開啟
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3:渲染到紋理
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
五、渲染鏈條
多個(gè)特效組合結(jié)構(gòu)如下,綁定frame buffer 0 作用是再次激活默認(rèn)幀緩沖盆均,在主窗口中有視覺效果。
1:灰度 fragment shaderGray
precision highp float; uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
void main (void) {
vec4 mask = texture2D(Texture, TextureCoordsVarying);
floatluminance = dot(mask.rgb, W);
gl_FragColor = vec4(vec3(luminance), 1.0);
}
1:上下顛倒 fragment shaderReverse
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
void main (void) {
vec4 color = texture2D(Texture, vec2(TextureCoordsVarying.x, 1.0 - TextureCoordsVarying.y));
gl_FragColor = color;
}
偽代碼如下:
// Step one
unsigned int fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
DrawShaderGray(); //繪制結(jié)果在texture
//setp two
DrawWithGrayInShaderReverse(texture)