Masking in OpenGL (L11)

2016-01-07_100026

今天要介紹如何將 Texture 蓋上一層面具,或實現一個特殊的遮蔽物。基本上是透過 L4 所講的 Blending 方式來實現,只是今天要前置處理得到一個 Texture 的 Mask ,再透過 Blending Function 來呈現。

● glBlendFunc()

首先細部解說 glBlendFunc() 函數,

void glBlendFunc (GLenum sfactor, GLenum dfactor) 函數裡有兩個主要變數分別為 sfactor 表示 source factor (新加入顏色的權重值);dfactor 表示 destination factor (原本在屏幕緩衝區裡的權重值),兩個 factor 數值介於[0,1]。

FinalColor = sfactor * SourceColor + dfactor * DestinationColor

factor 參數設定有多組型態可以設定,如下圖:2016-01-07_122533參數裡面的kG kR kB kA 代表像素的最大值(以 8bit 為例就是 255);而當選用 GL_CONSTANT_COLOR 時,需要透過 glBlendColor() 來決定混和顏色的數值。

 


● Masking

接下來就是本篇重頭戲了,要製造出 mask 的效果,必須先將你的 texture image 轉成二值化影像,將 image 有 texture 轉成 black,沒有 texture 的部分轉成 white,得到二值化影像後,接著透過 glBlendFunc(GL_DST_COLOR, GL_ZEOR) 來實現 masking 的效果。左下圖為 texture image,右下圖為 mask image。

aboutdada2 aboutdada_mask


void myopenGL::paintGL()
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glLoadIdentity();
 
 // @ masking
 glTranslatef(0.0f, 0.0f, -2.0f);
 glRotatef(rota_x, 1.0f, 0.0f, 0.0f);
 glRotatef(rota_y, 0.0f, 1.0f, 0.0f);
 glRotatef(rota_z, 0.0f, 0.0f, 1.0f);
 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);// set texture alpha 
 glBindTexture(GL_TEXTURE_2D, texture[0]);
 glBegin(GL_QUADS);
 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
 glEnd();

 glEnable(GL_BLEND);
 glDisable(GL_DEPTH_TEST);

if(masking)
 {
 glBlendFunc(GL_DST_COLOR, GL_ZERO);

glPushMatrix();
 glTranslatef(0.0f, 0.0f, -0.2f); // for cookie cutter 
 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);// set texture alpha
 glBindTexture(GL_TEXTURE_2D, texture[1]);
 glBegin(GL_QUADS);
 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f,-1.1f, 0.0f);
 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f,-1.1f, 0.0f);
 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f);
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f);
 glEnd();
 glPopMatrix();
 }

 glEnable(GL_DEPTH_TEST);
 glDisable(GL_BLEND);

}

注意到在 blending 之前要先 glDisable(GL_DEPTH_TEST),當繪製完成後,再 glEnable(GL_DEPTH_TEST),是為了避免錯誤的行為發生。 還有 mask image 的 size 會比 texture image 還來得大一些,主要是為了有好的遮蔽效果,透過 masking 參數來開關 mask,執行結果會有種餅乾切割器( cookie cutter )的效果,只會顯現出 texture 的輪廓,執行結果:picasion.com_8d092731cb98e2622b67517464af1da0

此外,這裡我另外加入兩個 mask,分別是以下兩個影像,這裡的 blending 方式就直接用自己的顏色數值來決定glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR)。 

aboutdada_mask2 aboutdada_mask3


if(masking2)
 {
 glPushMatrix();
 glTranslatef(0.0f, 0.0f, 0.1f); 
 glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
 glBindTexture(GL_TEXTURE_2D, texture[2]);

 glBegin(GL_QUADS);
 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f,-1.1f, 0.0f);
 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f,-1.1f, 0.0f);
 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f);
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f); 
 glEnd();
 glPopMatrix();
 }
 if(masking3)
 {
 glPushMatrix();
 glTranslatef(0.0f, 0.0f, 0.2f); 
 glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
 glBindTexture(GL_TEXTURE_2D, texture[3]);

 glBegin(GL_QUADS);
 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f,-1.1f, 0.0f);
 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f,-1.1f, 0.0f);
 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f);
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f);
 glEnd();
 glPopMatrix();
 }

透過 masking2 與 masking3 來開關 mask,執行結果如下:

picasion.com_e76d9d3f3a2b6f6b55d7cae83462d0eb

 


reference :

http://nehe.gamedev.net/tutorial/masking/15006/

https://www.opengl.org/sdk/docs/man/html/glBlendFunc.xhtml

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *