画像を使って画素単位でステンシルバッファの値を定め、一部分が欠けたオブジェクトを描画する方法.
- アルファチャンネルを持つテクスチャを準備する
- GL_ALPHA_TESTを有効化
- glDrawBuffer(GL_NONE)にしてテクスチャマッピング
- glDrawBuffer(GL_BACK)にして描画したいものを描く
コード例
#include <gl/glut.h>
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable( GL_STENCIL_TEST );
glDrawBuffer(GL_NONE);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
glEnable(GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glAlphaFunc( GL_NOTEQUAL, 0.0 );
glColor4d(1.0, 1.0, 1.0, 0.5);
glBegin( GL_QUADS );
glTexCoord2d(0, 0); glVertex2d(-0.8, -0.8);
glTexCoord2d(1, 0); glVertex2d(+0.8, -0.8);
glTexCoord2d(1, 1); glVertex2d(+0.8, +0.8);
glTexCoord2d(0, 1); glVertex2d(-0.8, +0.8);
glEnd();
glStencilFunc(GL_NOTEQUAL, 1, 1);
glDrawBuffer(GL_BACK);
glDisable(GL_TEXTURE_2D);
glColor4d(1.0, 0.0, 1.0, 1.0);
glBegin( GL_QUADS );
glVertex2d(+0.0, -0.4);
glVertex2d(+0.9, -0.4);
glVertex2d(+0.9, +0.4);
glVertex2d(-0.0, +0.4);
glEnd();
glutSwapBuffers();
}
void main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
//ウィンドウ(camera)の作成
glutInitWindowPosition(256, 256);
glutInitWindowSize(256, 256);
glutCreateWindow("write texture in stencil buf");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glClearColor(0.0, 0.5, 0.0, 1.0);
//ATI-RADEONでは指定すると正しく動作しない
//glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
const int size = 256*256;
unsigned char image[size];
for(int i=0; i<size/2; i++)
{
image[i] = 0;
}
for(int i=size/2; i<size; i++)
{
image[i] = 255;
}
//テクスチャが確保できているかどうかチェックする
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, 256, 256, 0, GL_ALPHA, GL_UNSIGNED_BYTE, image );
glutMainLoop();
}