OpenGL在渲染多个对象时出现闪烁问题

6

我对opengl还不是很熟悉,不太明白这里发生了什么。我正在尝试使用两个VAO创建多个对象,并使用自定义矩阵来旋转/平移它们。当我加载一个时,图像很好,但当我加载两个时,它们都会闪烁。我的初始化如下,其中每个缓冲区都有不同的数组,包括顶点位置、顶点索引和顶点颜色。

void init()
{
 readFile();
 //glEnable(GL_DEPTH);
 glEnable( GL_DEPTH_TEST );
 //make background yerpul in colour
 glClearColor( 0.235,  0.194,  0.314, 1.0 );


    // Load shaders and use the resulting shader program
    program = InitShader( "aVertexShader61.glsl", "aFragShader61.glsl" );
    glUseProgram( program );

    // Create a vertex array object
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    // Create and initialize two buffer objects
    glGenBuffers( 2, buffers);

    //one buffer for the vertexPositions and colours
    glBindBuffer( GL_ARRAY_BUFFER, buffers[0]);
    glBufferData( GL_ARRAY_BUFFER, numVertexPositionBytes + numVertexColourBytes,NULL, GL_STATIC_DRAW );
    glBufferSubData( GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions );
    glBufferSubData( GL_ARRAY_BUFFER, numVertexPositionBytes, numVertexColourBytes, vertexColours);

    //one buffer for the indices
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, numVertexIndexBytes,vertexIndicies, GL_STATIC_DRAW );

    // set up vertex arrays
    GLuint vPosition = glGetAttribLocation( program, "vPosition" );
    glEnableVertexAttribArray( vPosition );
    glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );

    GLuint vColor = glGetAttribLocation( program, "vColor" );
    glEnableVertexAttribArray( vColor );
    glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertexPositionBytes) );

    // Second object

    glGenVertexArrays( 1, &vao2 );
    glBindVertexArray( vao2 );

    glGenBuffers( 2, buffers2);

    //one buffer for the vertexPositions and colours
    glBindBuffer( GL_ARRAY_BUFFER, buffers2[0]);
    glBufferData( GL_ARRAY_BUFFER, numVertexPositionBytes + numVertexColourBytes,NULL, GL_STATIC_DRAW );
    glBufferSubData( GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions2 );
    glBufferSubData( GL_ARRAY_BUFFER, numVertexPositionBytes, numVertexColourBytes, vertexColours2);

    //one buffer for the indices
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers2[1]);
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, numVertexIndexBytes,vertexIndicies2, GL_STATIC_DRAW );

    // set up vertex arrays
    GLuint vPosition2 = glGetAttribLocation( program, "vPosition" );
    glEnableVertexAttribArray( vPosition2 );
    glVertexAttribPointer( vPosition2, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );

    GLuint vColor2 = glGetAttribLocation( program, "vColor" );
    glEnableVertexAttribArray( vColor2 );
    glVertexAttribPointer( vColor2, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertexPositionBytes) );


    glBindVertexArray(0);
}

这是我的显示,它在我的空闲函数中被 glutPostRedisplay() 调用,没有其他调用从空闲中进行。mStack 是从外部文件创建的矩阵栈对象。
    void
    display( void )
{

    //clear for first object, generate matrix and apply to object
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    mStack.loadIdentity();
    mStack.translatef(0,yDisplace,0);
    mStack.rotatef(Theta[Yaxis], 0.0,1.0,0.0);
    for (unsigned char i=0; i<NumVertices; i++){
        mStack.transformf(&vertexPositionsInit[i*4],&vertexPositions[i*4]);

    }

    //Apply to second object
    for (unsigned char i=0; i<NumVertices; i++){
        mStack.transformf(&vertexPositionsInit2[i*4],&vertexPositions2[i*4]);

    }


    //Draw first object
    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
    glBufferSubData(GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions );
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
    //Indexing into vertices we need to use glDrawElements
    glDrawElements(GL_TRIANGLES, NumIndicies, GL_UNSIGNED_BYTE, 0);
    glutSwapBuffers();


    //Clear and draw second object
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glutSwapBuffers();
    glBindVertexArray(vao2);
    glBindBuffer(GL_ARRAY_BUFFER, buffers2[0]);
    glBufferSubData(GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions2 );
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers2[1]);
    //Indexing into vertices we need to use glDrawElements
    glDrawElements(GL_TRIANGLES, NumIndicies, GL_UNSIGNED_BYTE, 0);
    glutSwapBuffers();


}

我是一个有用的助手,可以为您进行文本翻译。

我正在使用简单的顶点和片段着色器。 顶点着色器,

in  vec4 vPosition;
in  vec4 vColor;
out vec4 color;

void main() 
{
  gl_Position = vPosition;
  color = vColor;
} 

和片段着色器相关的内容:

in  vec4  color;
out vec4  fColor;

void main() 
{ 
    fColor = color;
} 

任何帮助都将不胜感激,如果需要,我可以发布矩阵文件。 谢谢


顺便提一下,你正在使用的着色器被称为“直通”着色器,这意味着如果你根本不使用着色器,你将得到相同的输出。大部分矩阵代码可以放在着色器中,当然你需要一次解决一个问题。 :) - Steve Howard
这可能是由矩阵计算引起的问题吗?我原以为这必须是缓冲区问题,所以我没有包括矩阵代码,但我真的不知道。 - user2755996
矩阵代码将决定您的对象的位置。如果您看到一个物体,但它在闪烁或留下轨迹,那很可能不是矩阵问题。 - Steve Howard
1个回答

6

不要在对象之间调用glutSwapBuffers()glClear()。交换缓冲区是告诉GLUT“好的,我完成了这一帧,让我们开始下一帧”的一种方式。

通常,你会想把每个帧设置和完成的代码(如glClear()glutSwapBuffers()的调用)与渲染每个对象的代码分开,因为OpenGL基本上是一个巨大的全局变量盒,如果不将方法分解成小块,很难编写出良好的OpenGL代码。


谢谢回复,我已经注释掉了清除和交换缓冲区的代码,现在第二个对象留下了一串帧并且背景也闪烁 :s - user2755996
你是把它们全部注释掉了,还是只是在对象之间的那些注释掉了?你仍然需要在开头加上一个glClear(),并在结尾处加上一个glutSwapBuffers()。看起来你已经让代码针对一个对象工作,并将所有内容复制到第二个对象中,但有些调用是每帧一次,而其他调用是每个对象一次。 - Steve Howard
搞定啦 :),我之前在每个物体的末尾而不是绘制部分的末尾放置了交换缓冲区。非常感谢你的帮助 Steve。 - user2755996

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接