OpenGL利用模板测试实现不规则裁剪

时间:2022-08-22 21:09:42

本文是原创文章,如需转载,请注明文章出处

在游戏开发中,经常会有这样的需求:给定一张64x64的卡牌素材,要求只显示以图片中心为圆点、直径为64的圆形区域,这就要用到模板测试来进行不规则裁剪。

实现不规则裁剪的主要思路如下:

1.准备好素材:要显示的64x64图片一张OpenGL利用模板测试实现不规则裁剪,不规则形状的遮罩图一张(本例中为圆形图)。OpenGL利用模板测试实现不规则裁剪

2.打开alpha测试,将测试通过条件设置成>0.5,使遮罩图中心的圆形区域可以通过测试,周围的透明像素无法通过测试。

3.打开模板测试,将测试通过条件设置成GL_NEVER,并将测试失败的模板值设置成参考值。

4.清除模板缓冲区,设置成0。

5.绘制遮罩图,首先alpha测试只允许遮罩图中心的圆形区域通过,随后进行模板测试,全部失败后,圆形区域的模板缓冲区的值被替换成参考值。

6.关闭alpha测试,重新设置模板测试通过条件成GL_EQUAL,值为之前替换的参考值。

7.绘制64x64的原图,此时只有圆形区域的模板缓冲区的值是参考值能通过模板测试,其他的都是0无法通过测试,实现了裁剪。

最终效果:OpenGL利用模板测试实现不规则裁剪

以下代码使用以上思路实现了矩形裁剪:

#include "stdafx.h"
#include <glut.h> #define viewWidth 800
#define viewHeight 800
GLubyte quad[viewWidth][viewHeight][];
GLuint quadTexName;
const GLint stencilRef = 0x01;
const GLint stencilClear = 0x00; void createQuad(void)
{
int i, j;
for (i = ; i < viewWidth; ++i){
for (j = ; j < viewHeight; ++j){
quad[i][j][] = (GLubyte);
quad[i][j][] = (GLubyte);
quad[i][j][] = (GLubyte);
if (i < (viewWidth / + ) && i >(viewWidth / - ) && j < (viewHeight / + ) && j >(viewHeight / - )){
quad[i][j][] = (GLubyte);
}
else{
quad[i][j][] = (GLubyte);
}
}
}
} void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearStencil(stencilClear);
glShadeModel(GL_FLAT); createQuad(); glPixelStorei(GL_UNPACK_ALIGNMENT, ); glGenTextures(, &quadTexName);
glBindTexture(GL_TEXTURE_2D, quadTexName); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, (GLsizei)viewWidth, (GLsizei)viewHeight, , GL_RGBA, GL_UNSIGNED_BYTE, quad);
} void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glStencilFunc(GL_NEVER, stencilRef, 0xFF);
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
glAlphaFunc(GL_GREATER, 0.5); glEnable(GL_STENCIL_TEST);
glEnable(GL_ALPHA_TEST);
glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, quadTexName); glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(-10.0, -10.0);
glTexCoord2f(0.0, 1.0); glVertex2f(-10.0, 10.0);
glTexCoord2f(1.0, 1.0); glVertex2f(10.0, 10.0);
glTexCoord2f(1.0, 0.0); glVertex2f(10.0, -10.0);
glEnd(); glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST); glStencilFunc(GL_EQUAL, stencilRef, 0xFF);
glBegin(GL_QUADS);
glColor3f(0.5, 0.5, 0.5);
glVertex2f(-10.0, -10.0);
glVertex2f(-10.0, 10.0);
glVertex2f(10.0, 10.0);
glVertex2f(10.0, -10.0);
glEnd();
glFlush();
} void reshape(int w, int h)
{
glViewport(, , (GLsizei)w, (GLsizei)h);
gluOrtho2D(-, , -, );
} int _tmain(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(, );
glutInitWindowSize(viewWidth, viewHeight);
glutCreateWindow("Stencil Test");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return ;
}

最终效果:OpenGL利用模板测试实现不规则裁剪