画像を使って画素単位でステンシルバッファの値を定め、一部分が欠けたオブジェクトを描画する方法.
- アルファチャンネルを持つテクスチャを準備する
- 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(); }