OpenGL, реализующий MultiPass - PullRequest
0 голосов
/ 11 октября 2018

У меня проблемы с переносом кода, который я успешно реализовал в Shadertoy , на рабочий стол OpenGL, проблема в том, что мне нужно создать FBO FrameBufferObject, чтобы я мог выполнять внеэкранные вычисления, которые позже будут переданык основному фрагментному шейдеру glsl дело в том, что этот буфер должен ссылаться на себя как на текстуру, чтобы получить предыдущие значения, чтобы он мог запускать симуляцию.

Я успешно создал FBO:

// Framebuffer configuration.
unsigned int frameBufferOne;
glGenFramebuffers(1, &frameBufferOne);
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferOne);

// Create a colour attachment texture.
unsigned int textureColourBufferOne;
glGenTextures(1, &textureColourBufferOne);
glBindTexture(GL_TEXTURE_2D, textureColourBufferOne);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColourBufferOne, 0);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);

И мне удалось вызвать его внутри моего цикла рендеринга, чтобы я мог выполнить рендеринг в FBO, а затем передать эти значения в кадровый буфер по умолчанию:

// Render Loop.
while( !glfwWindowShouldClose( window ) )
{

    // Input.
    processInput( window );

    // Render.

    // Bind to frameBuffer and draw scene as normally would to colour texture.
    glBindFramebuffer( GL_FRAMEBUFFER, frameBufferOne );

    glClearColor( 0.2f, 0.3f, 0.1f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT );

    bufferShader.use();
    float currentFrame = glfwGetTime();
    //Set the iTimeDelta uniform.
    float deltaTime = currentFrame - lastFrame;
    lastFrame = currentFrame;
    bufferShader.setFloat( "iTimeDelta", deltaTime );
    // Set the iTime uniform.
    float timeValue = currentFrame;
    bufferShader.setFloat( "iTime", timeValue );
    // Set the iResolution uniform.
    bufferShader.setVec2( "iResolution", WIDTH, HEIGHT );
    // Input iMouse.
    double xPos, yPos;
    glfwGetCursorPos( window, &xPos, &yPos );
    yPos = HEIGHT - yPos;
    bufferShader.setVec2( "iMouse", xPos, yPos );

    glBindVertexArray( VAO );
    glBindTexture( GL_TEXTURE_2D, textureColourBufferOne );
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
    glBindVertexArray( 0 );

    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
    glDisable( GL_DEPTH_TEST );

    glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT );

    ourShader.use();
    ourShader.setVec2( "iResolution", WIDTH, HEIGHT );
    // Set the iTime uniform.
    ourShader.setFloat( "iTime", timeValue );
    glBindVertexArray(VAO);
    glBindTexture( GL_TEXTURE_2D, textureColourBufferOne );
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );

    glfwSwapBuffers( window );
    glfwPollEvents();

    frameCount++;
    finalTime = time( NULL );
    if( finalTime - initialTime > 0 )
    {

        std::cout << "FPS : " << frameCount / (finalTime - initialTime) << std::endl;
        frameCount = 0;
        initialTime = finalTime;

    }

Но я не могувизуализировать буфер как текстуру, я понимаю, что он выводит неопределенное поведение и что мне следует использовать технику в качестве пинг-понга.

Может кто-нибудь указать мне правильное направление?

1 Ответ

0 голосов
/ 11 октября 2018

Но я не могу представить буфер себе как текстуру, я понимаю, что он выводит неопределенное поведение и что мне следует использовать технику в качестве пинг-понга.

Может кто-нибудь указатьменя в правильном направлении?

Вы должны создать 2 объекта кадрового буфера, как вы сделали это с одним из ваших вопросов: frameBufferOne и frameBufferTwo.
Каждый для этого 2 кадровых буферак объектам должен быть прикреплен объект текстуры: textureColourBufferOne и textureColourBufferTwo.

В основном цикле вашей программы вы должны знать, является ли номер кадра четным или нечетным.
Есличисло является четным, тогда вы должны выполнить рендеринг до textureColourBufferOne, а вход для прохода рендеринга будет textureColourBufferTwo.
Если число нечетное, тогда вам нужно сделать рендеринг до textureColourBufferTwo, а вход для прохода рендеринга будет textureColourBufferOne.
Результат рендеринга всегда сохраняется в текстуре, которая принадлежит кадровому буферу текущего кадра:

bool even = true;
while( !glfwWindowShouldClose( window ) )
{
    .....

    glBindFramebuffer( GL_FRAMEBUFFER, even ? frameBufferOne : frameBufferTwo );

    glClearColor( 0.2f, 0.3f, 0.1f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT );

    .....

    glBindVertexArray( VAO );
    glBindTexture( GL_TEXTURE_2D, even ? textureColourBufferTwo : textureColourBufferOne );
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
    glBindVertexArray( 0 );

    .....

    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
    glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT );

    .....

    glBindVertexArray(VAO);
    glBindTexture( GL_TEXTURE_2D, even ? textureColourBufferOne : textureColourBufferTwo );
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );

    glfwSwapBuffers( window );
    glfwPollEvents();

    even = !even;

    .....
}
...