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

OpenGL C++中混用glOrtho与gluPerspective的黑屏渲染问题

解决从glOrtho切换到gluPerspective后黑屏的问题

刚看了你的问题,切换到游戏场景后黑屏、只有调窗口才正常显示,直接进场景却没问题——其实问题不是glVertex3f参数的锅,核心是矩阵状态没及时更新,导致物体被裁剪了。

问题根源分析

  1. 投影矩阵未更新:你切换场景时改了key1的值,但myReshape只有窗口大小变化时才会触发。这意味着切换后,OpenGL用的还是欢迎页的正交投影设置(glOrtho(0.0, 100.0, 0.0, 100.0, -5.0 , 10.0)),这个投影的z轴可见范围是-5到10。
  2. 物体被裁剪:游戏场景的Drawkey1/2里,你用glTranslatef(0.0, 0.0, -22.0)把物体移到了z=-22的位置,这个值远小于正交投影的近裁剪面(-5),所以直接被OpenGL裁掉了,自然黑屏。
  3. 调窗口才正常的原因:调整窗口会触发myReshape,此时才会把投影矩阵改成透视模式(gluPerspective),它的z可见范围是0.1到200,物体的位置刚好在这个范围内,所以能显示。

另外,你的myReshape还有个小错误:在投影矩阵模式下调用了gluLookAt,这是不对的——gluLookAt是用来设置相机(模型视图矩阵)的,应该放在模型视图矩阵模式里。

解决方案

1. 修正myReshape函数,分离投影与模型视图设置

把gluLookAt从投影矩阵分支里移除,确保投影矩阵只负责投影方式,模型视图矩阵的设置放到Draw函数里:

void myReshape(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity(); // 先重置投影矩阵

    if (key1 == 3){
        // 欢迎页正交投影
        glOrtho(0.0, 100.0, 0.0, 100.0, -5.0 , 10.0);
    } else if (key1 == 1 || key1 == 2){
        // 游戏场景透视投影
        gluPerspective(45.0, (float)w/(float)h, 0.1f, 200.0);
    }

    // 切回模型视图矩阵并重置
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

2. 切换场景时手动更新矩阵并触发重绘

在你修改key1的地方(比如键盘响应函数),手动调用myReshape和glutPostRedisplay(),强制更新矩阵并刷新画面:

void keyboard(unsigned char key, int x, int y) {
    switch(key) {
        case '1':
            key1 = 1;
            // 用当前窗口尺寸触发矩阵更新
            myReshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
            glutPostRedisplay(); // 通知GLUT重绘
            break;
        case '2':
            key1 = 2;
            myReshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
            glutPostRedisplay();
            break;
        case '3':
            key1 = 3;
            myReshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
            glutPostRedisplay();
            break;
        // 其他按键处理逻辑...
    }
}

3. 在游戏场景的Draw函数里添加相机设置

把原来的gluLookAt移到Drawkey1/2里,确保模型视图矩阵正确设置相机:

void Drawkey1_2(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity ();

    // 设置相机位置和朝向(原来在myReshape里的代码移到这)
    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    // 平移物体到合适位置
    glTranslatef(0.0, 0.0, -22.0);

    int i;
    par(-8.7, 9.2, 9.0, 9.2, 0.0, 0.0);
    par(-8.7, 9.2, -8.5, -8.7, 0.0, 0.0);
    par(-8.5, -8.7, -8.7, 9.2, 0.0, 0.0);
    par( 9.2, 9.0, -8.7, 9.2, 0.0, 0.0);
    
    while(p != NULL){
        par((p -> x)/2.0,(p -> x)/2.0 + 0.4,(p -> y)/2.0,(p -> y)/2.0 + 0.4, 0.0, 0.0);
        p = p -> next; // 原代码的nexploration_ratet应该是笔误,改成next
    }
    
    par(food_x/2.0, food_x/2.0 + 0.4 , food_y/2.0 , food_y/2.0 + 0.4, 0.0 , 0.0);
    
    glutSwapBuffers(); // 如果用了双缓冲,记得加这个
}

验证效果

这样修改后,切换场景时会立刻更新投影矩阵,游戏场景的物体不会再被正交投影裁剪,不用调窗口就能正常渲染了。

内容的提问来源于stack exchange,提问作者Sunim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:55:39