OpenGL中glScissor多次裁剪叠加失效问题求助
多次glScissor裁剪仅最后一次生效的问题解决
项目中需要使用glScissor实现多次区域裁剪,目标仅渲染同时处于所有裁剪框内的内容,但当前遇到的问题是:第二次设置的裁剪框会直接覆盖前一个,最终仅最后一次设置的裁剪框生效。
尝试过的无效操作:
- 设置第一个裁剪框后调用
glPushMatrix(),启用裁剪、设置第二个裁剪框、禁用裁剪、glPopMatrix()再禁用裁剪 - 使用
glPushAttrib(GL_SCISSOR_BIT)替代矩阵操作
以下是测试用例(基于freeglut,编译命令:g++ .\scissor.cpp -lglu32 -lfreeglut -lopengl32):
#include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> void display(); void reshape(int, int); void timer(int); void init(){ glClearColor(0, 0, 0, 1); } int main(int argc, char **argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutInitWindowPosition(200, 100); glutInitWindowSize(500, 500); glutCreateWindow("Window 1"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutTimerFunc(0, timer, 0); init(); glutMainLoop(); } float xPos = -10; int state = 1;//1 = right, -1 = left void display(){ glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); // 原无效尝试代码 glEnable(GL_SCISSOR_TEST); glScissor(0, 0, 100, 1000); glPushMatrix(); glEnable(GL_SCISSOR_TEST); glScissor(50, 0, 1000, 1000); glBegin(GL_QUADS); glVertex2f(xPos, 1); glVertex2f(xPos, -1); glVertex2f(xPos+2, -1); glVertex2f(xPos+2, 1); glEnd(); glDisable(GL_SCISSOR_TEST); glPopMatrix(); glDisable(GL_SCISSOR_TEST); glutSwapBuffers(); } void reshape(int width, int height){ glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-10, 10, -10, 10); glMatrixMode(GL_MODELVIEW); } void timer(int a){ glutPostRedisplay(); glutTimerFunc(1000/60, timer, 0); switch(state){ case 1: if(xPos < 8) xPos += 0.15; else state = -1; break; case -1: if(xPos > -10) xPos -= 0.15; else state = 1; break; } }
解决方案:手动计算裁剪框交集
glScissor本身不支持叠加裁剪,每次调用都会直接替换当前裁剪区域。要实现多框交集的裁剪效果,最直接高效的方式是手动计算所有裁剪框的交集区域,再将该区域设置为唯一的裁剪框。
修改后的display()函数如下:
void display(){ glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); // 定义两个裁剪框(窗口像素坐标) int scissor1_x = 0, scissor1_y = 0, scissor1_w = 100, scissor1_h = 1000; int scissor2_x = 50, scissor2_y = 0, scissor2_w = 1000, scissor2_h = 1000; // 计算两个框的交集区域 int intersect_x = max(scissor1_x, scissor2_x); int intersect_y = max(scissor1_y, scissor2_y); int intersect_w = min(scissor1_x + scissor1_w, scissor2_x + scissor2_w) - intersect_x; int intersect_h = min(scissor1_y + scissor1_h, scissor2_y + scissor2_h) - intersect_y; // 仅当交集有效(宽高为正)时启用裁剪 if(intersect_w > 0 && intersect_h > 0){ glEnable(GL_SCISSOR_TEST); glScissor(intersect_x, intersect_y, intersect_w, intersect_h); } // 绘制内容 glBegin(GL_QUADS); glVertex2f(xPos, 1); glVertex2f(xPos, -1); glVertex2f(xPos+2, -1); glVertex2f(xPos+2, 1); glEnd(); // 关闭裁剪测试 glDisable(GL_SCISSOR_TEST); glutSwapBuffers(); }
多裁剪框扩展
如果需要处理3个及以上的裁剪框,只需循环计算交集:每次将当前交集与下一个裁剪框计算新的交集,直到所有框处理完毕,最终得到的交集就是所有框的共同区域。
内容的提问来源于stack exchange,提问作者InternetUser
相关产品推荐
相关产品推荐

