0

所以我一直在为 openGL 类玩 SOIL,我的项目遇到了一个奇怪的问题。我将显示两个窗口,每个窗口包含三个视口,我在其中绘制一个带纹理的立方体或椭圆体,以展示我对深度和面剔除的理解。现在所有形状都正确绘制,并且在单独测试时看起来与预期完全一样,但是一旦我同时启用两个窗口,纹理就会在第一个窗口中禁用。我之前发布了一个类似的问题,所以为了澄清,如果我禁用窗口二,或者如果我在窗口二中使用窗口一的绘制功能,纹理将起作用。只有当两个窗口同时显示时才会出现问题。我还能够更改渲染形状的颜色,

这是我的主要代码 w/ Initialisation void main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

    glutInitWindowSize(750, 250);

    #pragma region WINDOW ONE INITIALISATION
    glutInitWindowPosition(0, 50);

    windowID[1] = glutCreateWindow("cubes");

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-400, 400, -400, 400, -500, 500);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glutDisplayFunc(DrawWindowOne);
    #pragma endregion 

    #pragma region WINDOW TWO INITIALISATION
    glutInitWindowPosition(0, 450);
    windowID[1] = glutCreateWindow("ellipsoids");

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-60, 60, -60, 60, 60, 200);
    gluLookAt(0, 0, 120, 0, 0, 0, 0, 1, 0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glutDisplayFunc(DrawWindowTwo);
    #pragma endregion

    LoadTextures(); // Handles the SOIL_load_OGL_Texture() lines. Works 100%

    gluQuadricTexture(quad, GL_TRUE);
}

这些是两个窗口绘制函数

void DrawWindowOne()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

#pragma region Viewport One 

    glViewport(0, 0, 250, 250);                     

    glMatrixMode(GL_MODELVIEW);         

    DrawCubes();

#pragma endregion
#pragma region Viewport Two 

    glViewport(250, 0, 250, 250);   

    glMatrixMode(GL_MODELVIEW);     

    glEnable(GL_CULL_FACE);
    DrawCubes();
    glDisable(GL_CULL_FACE);

#pragma endregion
#pragma region Viewport Three   

    glViewport(500, 0, 250, 250);

    glMatrixMode(GL_MODELVIEW);

    glEnable(GL_DEPTH_TEST);
    DrawCubes();
    glDisable(GL_DEPTH_TEST);

#pragma endregion

    glFlush();
    glutSwapBuffers();
}

void DrawWindowTwo()
{
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     

    #pragma region Viewport One 

    glViewport(0, 0, 250, 250); 

    glMatrixMode(GL_MODELVIEW); 
    DrawEllipsoids();

    #pragma endregion
    #pragma region Viewport Two 

    glViewport(250, 0, 250, 250);   

    glMatrixMode(GL_MODELVIEW); 

    glEnable(GL_CULL_FACE);
    DrawEllipsoids();
    glDisable(GL_CULL_FACE);

    #pragma endregion
    #pragma region Viewport Three   

    glViewport(500, 0, 250, 250);   

    glMatrixMode(GL_MODELVIEW);     

    glEnable(GL_DEPTH_TEST);
    DrawEllipsoids();
    glDisable(GL_DEPTH_TEST);

    #pragma endregion

    glFlush();
    glutSwapBuffers();
}

这是我的对象绘制代码的一点点。我已经把它剥离了一点;它只为立方体绘制一个面(我已经确认如果所有视口都绘制一个面,也会出现同样的问题)。

void DrawCubes()
{
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
    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_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, textureID[0]);

    glBegin(GL_QUADS);
    glNormal3f(0.0, 0.0, -1.0); // front face
    glTexCoord2f(0.0, 0.0); glVertex3f(-a,-a,-a);
    glTexCoord2f(0.0, 1.0); glVertex3f(-a, a,-a);
    glTexCoord2f(1.0, 1.0); glVertex3f( a, a,-a);
    glTexCoord2f(1.0, 0.0); glVertex3f( a,-a,-a);
    glEnd()
    glDisable(GL_TEXTURE_2D);
}
4

1 回答 1

0

GLUT 为每个窗口创建一个 OpenGL 上下文。这些上下文不共享。在 GL 中,最多可以将一个 GL 上下文“设为当前”线程,因此您调用的任何 GL 函数都将与当前活动的 GL 上下文一起工作。

如果您的代码处于WINDOW TWO INITIALISATION活动状态,GLUT 将创建一个新窗口并将其上下文设为当前。因此,您的LoadTextures()调用将仅影响第二个上下文,并且您的第一个上下文不会加载任何纹理。

一种解决方案是调用LoadTextures()两次。但是,该函数可能使用一些变量来存储纹理名称 - 并且两个相同上下文之间的变量名称可能不相同,因此从概念上讲,您必须扩展代码。

另一种解决方案是使用共享上下文。它们共享任何对象,如纹理、缓冲区等。但是,GLUT 不支持这一点。

另一个解决方案是依靠 freeglut 对“官方” GLUT 规范的扩展(无论如何这已经完全过时了):

glutSetOption(GLUT_RENDERING_CONTEXT, GLUT_USE_CURRENT_CONTEXT);

将告诉 freeglut 不要为它创建的下一个窗口创建新的上下文,而是重新使用现有的。然后,您的代码基本上可以按照您的预期工作。

于 2015-05-17T12:50:27.140 回答