openGL - Save Complex Rendering in Memory for Future Restore

Asked

Viewed 172 times

1

I am developing a c++ application using opengl, but my knowledge in c++ and opengl is limited, especially in the latter.

I need to create a board similar to the chess board, however for each execution of the program the size of the board will probably be different, for example to 1000x1000 houses (it is not always quadricular, it can also be rectangular 1000x600). Each of these houses that I re-screen using GL_QUADS is texturing with an image .PNG (some with alpha channel). The board is different for each execution of the program, but STATIC after created, that is, its appearance does not change in the course of the execution, but on it there are objects in the order of 10% of the amount of houses that are dynamic. So if the board has 1000x1000 houses, there are 100 dynamic elements moving on it.

Consider that the function "Designer (int W, short H){}" works perfectly, and is able to render the board completely on screen. In this function, to render the board I use the for command. I need to change the dynamic elements at least 24 times a second, at least similar to a video. For this I am using glutTimerFunc and glutPostRedisplay. That is, update at a rate of 41 Millis (at least).

The problem is that from an 82x82 tray, the program is unfit to run 24 screen updates per second.

What I need is beginning of the program, render the board once, and save it in memory. Thus, draw function provided in glutDisplayFunc(draw); would not create the board every time, but would only restore its original (initial) state, drawing only the dynamic elements on it, significantly reducing the need for processing, and improving the PERFORMANCE. I believe this would guarantee the updating capacity every 41 Mlillis().

Example:

bool background = false;

void desenhar(){
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);                   // Black and opaque    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear the color buffer (background)           

    glMatrixMode(GL_MODELVIEW);                             // To operate on Model-View matrix
    glLoadIdentity();  

    // SE AINDA NAO CRIOU O TABULEIRO CRIE
    if (!background){
        DesenharTabuleiro(qtdW(), qtdH());

        // AGORA SALVE A IMAGEM DO TABULEIRO NA MEMÓRIA
        // ISSO QUE NAO SEI COMO FAZER
        SalvarRenderizacaoNaMemoria();

        background = true;
    }else
        // ESTA FUNCÃO DEVERIA PEGAR A IMAGEM JÁ CRIADA 
        // E ARMAZENADA NA MEMÓRIA, E EXIBIR NA TELA
        // SEM A NECESSIDADE DE RECRIAR CADA UM DOS QUADS
        RestarurasBackground();

    /*
     * AGORA REDESENHA TODOS OBJETOS DINAMICOS
     */
}


// DEVERIA SER EXECUTADO A CADA 41 MILLIS, SEM ATRAZO
void Timer(int value) {
    glutPostRedisplay();          //REDESENHA O CENARIO
    glutTimerFunc( 41, Timer, 0); // PROGRAMA A PROXIMA ATUALIZACAO DE TELA
}


int main(int argc, char** argv) {
    glutInit(&argc, argv);                                                                              // Initialize GLUT  
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );  // Set double buffered mode
    glutCreateWindow("OpenGL Setup Test");                                              // Create a window with the given title

    glewInit();

    glutInitWindowSize(Tela.width, Tela.height);        // Set the window's initial width & height          
    glutInitWindowPosition(0, 0);                       // Position the window's initial top-left corner
    glutFullScreen();                                   // Exibe em tela cheia      

    glutDisplayFunc(desenhar);                          // Register display callback handler for window re-paint        
    glutTimerFunc( 41, Timer, 0);             // First timer call immediately   

    glEnable(GL_DEPTH_TEST);  
    glEnable(GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);             

    glutMainLoop();                 // LOOP PROCESSADOR DE EVENTOS  
}

Possible Solution - Framebuffer - Not working!

I tried to perform the save of the board in memory through Framebuffer, but I confess that I could not understand its functioning, and not even how to restore the image after saved.

The code below is real, and has no effect (the screen is black):

GLuint  fBuffer, // FRAME BUFFER
        tBuffer, // TEXTURE BUFFER
        rBuffer; // RENDER BUFFER

GLenum dBuffer[1];  

// ESTA FUNCÃO DEVERIA CRIAR O TABULEIRO E SALVÁ-LO NA MEMÓRIA
// ISSO PARECE NÃO FUNCIONAR        
bool gerarESalvarPlanta(){
    bool retorno = false;

    printf("\r\nRenderizando planta... ");  

    // ##########################################################################
    // CRIA OBJETOS PARA BUFFER
    fBuffer = 0;
    glGenFramebuffers(1, &fBuffer);     

    rBuffer = 0;
    glGenRenderbuffers(1, &rBuffer);        

    tBuffer = 0;
    glGenTextures(1,      &tBuffer);        

    dBuffer[0] = GL_COLOR_ATTACHMENT0;
    glDrawBuffers (1, &fBuffer);        

    // ATIVA O OBJETOS CRIADOS
    glBindFramebuffer(  GL_FRAMEBUFFER,   fBuffer);          
    glBindTexture(      GL_TEXTURE_2D,    tBuffer);    
    glBindRenderbuffer( GL_RENDERBUFFER,  rBuffer);  


    // ##########################################################################      
    // CRIA A IMAGEM EM BRANCO DO TAMANHO DO MAPA
    glTexImage2D(
        GL_TEXTURE_2D, 
        0,
        GL_RGB, 
        W(), 
        H(), 
        0,
        GL_RGB, 
        GL_UNSIGNED_BYTE, 
        NULL
    );

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //GL_NEAREST

    // VINCULA A TEXTURA AO BUFFER  
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, tBuffer);  
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tBuffer, 0);  


    // ##########################################################################      
    // DIMENCIONA O RENDER
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, W(), H());  

    // VINCULA O RENDER AO BUFFER
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rBuffer);  


    // VERIFICA POR ERROS
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);  

    if (status == GL_FRAMEBUFFER_COMPLETE){
        // PRINTA OK
        printf("[OK]\r\n");  

        retorno = true; 
    }else{  
        std::cout << "[FALHA : " << status ;
        std::cout << " | GlError : " << glGetError() << "]" << std::endl;  
        return false;
    }    


    // AQUI EH ONDE EU RENDERIZO AS CENTENAS DE GL_QUADS
    // DO TABULEIRO, ESSA FUNCAO ESTA FUNCIONANDO PERFEITAMENTE
    // POR ISSO EU NÃO A REPRODUZO AQUI
    DesenharTabuleiro(qtdW(), qtdH());

    // DESATIVA
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);  
    glBindFramebuffer(GL_FRAMEBUFFER, 0);  

    return retorno;
}

/*
 * DESENHA UM QUADRADO/RETÂNGULO
 * O OBJETIVO DESTA FUNÇÃO E REDESENHAR NA TELA A IMAGEM DO
 * TABULEIRO DESENHADO NO INICIO DO PROGRAMA E ARMAZENADA
 * NO BUFFER
 * >> ISSO NAO FUNCIONA
 */
void buildQuadradoBufferText(float x, float y, float w, float h, float qW = 2, float qH = 2){
    glEnable(GL_TEXTURE_2D);      

    glBindTexture(GL_TEXTURE_2D, tBuffer);         
    glBindFramebuffer(GL_FRAMEBUFFER, fBuffer);        

    glBegin(GL_QUADS);

        glTexCoord2f(0, qH);
        glVertex2f( x   , y   );

        glTexCoord2f(qW, qH);    
        glVertex2f( x+w , y   );    

        glTexCoord2f(qW, 0);    
        glVertex2f( x+w , y-h );     

        glTexCoord2f(0  , 0);    
        glVertex2f( x   , y-h );

    glEnd();

    glDisable(GL_TEXTURE_2D);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);  
    glBindTexture(GL_TEXTURE_2D, 0);
}   

I would be so kind as to provide practical example.

Thanks in advance for all your help.

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.