You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 23:00:56