Issues with render to texture.

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
Jae686
Insane DCEmu
Insane DCEmu
Posts: 112
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Sat Sep 22, 2007 9:43 pm
Location: Braga - Portugal
Has thanked: 0
Been thanked: 0

Issues with render to texture.

Post by Jae686 »

Good afternoon.
I've been having a odd issue while using the render the texture feature.
I've copied the code from the examples (the radial blur example) that came with libgl and I'm rendering the texture into a quad (using ortho projection).
I'm initializing the texture just like the example and, if I comment out the call to

Code: Select all

glutCopyBufferToTexture(RENDER_TEXTURE, &RENDER_TEXTURE_W, &RENDER_TEXTURE_H);
A black quad is rendered trough all the scene, as expected.
I must note that the function above is only called AFTER i send all the geometry out (via direct mode or vertex arrays)

When the code above is uncommented, well, odd behavior is observed.
(Is there some form of flushing that I'm not aware of ?)

The quad only appears mid scene, and sometimes it just vanishes and reappears some seconds later.
This is the expected behavior :
Image

This occurs mid scene :
Image

This is the following (relevant) code :
Spoiler!

Code: Select all

#include <kos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <sys/time.h>
#include <time.h>
#include <sys/time.h>
//#include <arch/time.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <pcx/pcx.h>


#include <math.h>

#include "data_estructures.h"

//to be removed as soon as the scene and asset loader are put into order
//#include "obj_loader.h"
//#include "pcx_loader.h"



void pmesh_draw_array();
void pmesh_draw(pmesh p); 
void pmesh_draw_test();
void draw_p(pmesh m);
extern pDemoAssetList demo_content;

//pvr_stats_t stats;

// RENDER TO TEXTURE TEST

static pvr_ptr_t *RENDER_TEXTURE = NULL;   /* PVR Memory Pointer for Render-To-Texture result */
static GLuint      RENDER_TEXTURE_ID;      /* Render-To-Texture GL Texture ID */
static long unsigned int RENDER_TEXTURE_W; /* Render-To-Texture width */
static long unsigned int RENDER_TEXTURE_H; /* Render-To-Texture height */

extern GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap);

void InitRenderTexture(long unsigned int width, long unsigned int height) {
    /* 1.) Allcoate PVR Texture Memory for Render-To-Texture */
    RENDER_TEXTURE_W = width;
    RENDER_TEXTURE_H = height;
    RENDER_TEXTURE = pvr_mem_malloc(RENDER_TEXTURE_W * RENDER_TEXTURE_H * 2);

    /* 2.) Generate a texture for Open GL, and bind that texxture */
    glGenTextures(1, &RENDER_TEXTURE_ID);
    glBindTexture(GL_TEXTURE_2D, RENDER_TEXTURE_ID);

    /* 3.) Use glKosTexImage2D() to bind the texture address for the Render-To-Texture */
    glKosTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
                    RENDER_TEXTURE_W, RENDER_TEXTURE_H, 0,
                    PVR_TXRFMT_NONTWIDDLED, PVR_TXRFMT_RGB565, RENDER_TEXTURE);

    /* 4.) Enable GL_LINEAR Texture Filter to enable the PVR's bilinear filtering */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FILTER, GL_LINEAR);
}


//void RTT_test(pDemoAssetList d, char* font_name) //Render to Texture Test
void RTT_test(GLuint a, pDemoAssetList d) //Render to Texture Test
{
   // int curr_texture_pos = getTexturePos(d->t, "checkerboard");
   // int curr_texture = retrieveTextureHandle(d->t, curr_texture_pos);
    
   // glBindTexture(GL_TEXTURE_2D, curr_texture);
    
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, a);
    
   


    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    //glLoadIdentity();
    glOrtho(0,640,0,480, -1,1);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
   // glLoadIdentity();
    
   // glEnable(GL_BLEND);                     // Enable Blending

   // glBlendFunc(GL_SRC_ALPHA, GL_ONE);      // Set Blending Mode
  
    glBegin(GL_QUADS);                      // Draw A Quad
        
        glTexCoord2f(0,0);
        glVertex2f(0,0);              // Top Left
        glTexCoord2f(1,0);
        glVertex2f( 256, 0);
        glTexCoord2f(1,1);              // Top Right
        glVertex2f( 256,256);
        glTexCoord2f(0,1);              // Bottom Right
        glVertex2f(0,256); 
                                        // Bottom Left
    glEnd();                            // Done Drawing The Quad

    
     glBegin(GL_QUADS);                      // Draw A Quad
        
        glTexCoord2f(1,0);
        glVertex2f(512,0);              // Top Left
        glTexCoord2f(0,0);
        glVertex2f( 256, 0);
        glTexCoord2f(0,1);              // Top Right
        glVertex2f( 256,256);
        glTexCoord2f(1,1);              // Bottom Right
        glVertex2f(512,256); 
                     // Bottom Left
    glEnd();                      


    glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
    glPopMatrix();                              // Restore The Old Projection Matrix

    glMatrixMode(GL_MODELVIEW);                     // Select The Modelview Matrix
    glPopMatrix();                              // Restore The Old Projection Matrix

   // glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);   

}


//

void gridDraw(pmesh mesh, pmesh grid, pDemoAssetList asl)
{
    

    int i = 0 ;

    vec3* iter_ptr = grid->vertex_data ; // to make the syntax more tolerable

    float z_value = 0.0f ;

    int x_iter = 0;
    int y_iter = 0;

    for( x_iter = 0 ; x_iter < grid->indices_count ; x_iter++)
    {
        for (y_iter = 0 ; y_iter < grid->uv_count ; y_iter++ )
        {
            z_value = 7 * fsin(asl->milisec_elapsed * 0.0009 + (iter_ptr[i].x / 5) ) ;
            //z_value = fsin(asl->milisec_elapsed * 0.0005 + iter_ptr[i].x) + fcos(asl->milisec_elapsed * 0.0005 + iter_ptr[i].y) ; 
           //z_value = fsin(iter_ptr[i].x * iter_ptr[i].y * i) ;
            glPushMatrix();
          //  glScalef(0.5, 0.5, 0.5);
            glTranslatef(iter_ptr[i].x, iter_ptr[i].y , z_value);
            //printf("t : x : %f, y: %f  i : %d \n ", iter_ptr[i].x, iter_ptr[i].y, i);
            draw_p(mesh);
            glPopMatrix();
            i++;
        }
        

    }

}

inline float new_width(const float fwsize,const float fhsize,const float req_size_w)
{
    if(fwsize == 0)
    {
        return 0 ;
    }
    if(fhsize == 0)
    {
        return 0 ;
    }

    return (float) (req_size_w * fwsize) / fhsize ; 
}

inline float new_height(const float f_old_wsize,const float f_new_wsize,const float f_height)
{
    if(f_old_wsize == 0)
    {
        return 0 ;
    }
    if(f_new_wsize == 0)
    {
        return 0 ;
    }

    return (float) (f_height * f_new_wsize) / f_old_wsize ; 
}

pTexFontList getTexFont(pTexFontList p, char* a)
{
    pTexFontList curr = p ;
    for (curr = p ; curr != NULL ; curr = curr->next)
    {
        if ( strcmp(curr->name, a) == 0 )
        {
           // printf("\n seeking : %s ; %s found \n",curr->name, a);
            return curr ;
        }
        
    }   
   
    return p ; // if nothing was found......
}



void print_text(pDemoAssetList d, char* font_name,  char* txt, int xpos, int ypos, const float scale)
{
    int curr_texture_pos = getTexturePos(d->t, font_name);

    int curr_texture = retrieveTextureHandle(d->t, curr_texture_pos);

    int tex_w = retrieveTextureWidth(d->t, curr_texture_pos);
    int tex_h = retrieveTextureHeight(d->t, curr_texture_pos);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, curr_texture);
    
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(0,640,0,480, -1,1);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    int txt_len = strlen(txt);
    int i = 0 ;

    unsigned int c ;

    float cursor = 0;

    float n_width = 0 ;
    float n_height = 0.5 ;
    float spacing = 5 ;

    float uv_x, uv_y, uv_wx, uv_wy;
    vec2 uv_up_l, uv_up_r;
    vec2 uv_bottom_r, uv_bottom_l;

    vec2 quad_up_l, quad_up_r;
    vec2 quad_down_l, quad_down_r;

    pTexFontList f = getTexFont(d->f, font_name);
    
    glBegin(GL_QUADS); 

    for(i = 0; i < txt_len ; i++)
    {
        
        c = txt[i];

        n_width = new_width(f->charCoord[c].width, f->charCoord[c].height, scale) ;

        uv_x =  (f->charCoord[c].x / (float) tex_w);
        uv_y = (f->charCoord[c].y / (float)tex_h);

        uv_wx =  ((f->charCoord[c].x + f->charCoord[c].width) / (float) tex_w) ; 
        uv_wy = ((f->charCoord[c].y + f->charCoord[c].height) / (float) tex_h) ;


        uv_bottom_l.u = uv_x ;
        uv_bottom_l.v = uv_y ;

        uv_bottom_r.u = uv_wx ; 
        uv_bottom_r.v = uv_y ;
        
        uv_up_r.u = uv_wx ;
        uv_up_r.v = uv_wy ;

        uv_up_l.u = uv_x ;
        uv_up_l.v = uv_wy ;

        //old uv coords
        /*
        uv_bottom_l.u = uv_x ;
        uv_bottom_l.v = uv_wy ;

        uv_bottom_r.u = uv_wx ;
        uv_bottom_r.v = uv_wy ;
        
        uv_up_r.u = uv_wx ;
        uv_up_r.v = uv_y ;

        uv_up_l.u = uv_x ;
        uv_up_l.v = uv_y ;
        */

        // quad old coords
        /*
        quad_up_l.u = xpos + cursor;
        quad_up_l.v = ypos + (f->charCoord[c].height * scale) ;
        
        quad_up_r.u = xpos + cursor + (f->charCoord[c].width * scale) ;
        quad_up_r.v = ypos + (f->charCoord[c].height * scale);

        quad_down_r.u = xpos + cursor + (f->charCoord[c].width * scale);
        quad_down_r.v = ypos ;

        quad_down_l.u = xpos + cursor;
        quad_down_l.v = ypos;
        */
        //quad new coords


        quad_up_l.u = xpos + cursor;
        quad_up_l.v = ypos  ;
        
        quad_up_r.u = xpos + cursor + (f->charCoord[c].width * scale) ;
        quad_up_r.v = ypos  ;

        quad_down_r.u = xpos + cursor + (f->charCoord[c].width * scale);
        quad_down_r.v = ypos - (f->charCoord[c].height * scale) ;

        quad_down_l.u = xpos + cursor;
        quad_down_l.v = ypos - (f->charCoord[c].height * scale) ;





        // Draw A Quad
       
        glTexCoord2f(uv_up_l.u , uv_up_l.v);
        glVertex2f(quad_up_l.u , quad_up_l.v);             
        glTexCoord2f(uv_up_r.u , uv_up_r.v); 
        glVertex2f( quad_up_r.u , quad_up_r.v);
        glTexCoord2f(uv_bottom_r.u , uv_bottom_r.v);
        glVertex2f( quad_down_r.u , quad_down_r.v );
        glTexCoord2f(uv_bottom_l.u , uv_bottom_l.v);
        glVertex2f(quad_down_l.u , quad_down_l.v ); 
                     

   

    cursor = cursor + (f->charCoord[c].width * scale) + spacing;


    }

   glEnd();


    glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
    glPopMatrix();                              // Restore The Old Projection Matrix


    glMatrixMode(GL_MODELVIEW);                     // Select The Modelview Matrix
    glPopMatrix();                              // Restore The Old Projection Matrix

    glDisable(GL_BLEND);

    glDisable(GL_TEXTURE_2D);

    glEnable(GL_DEPTH_TEST);   

}


// timming functions - 


inline unsigned long diff_msec(uint64 start,uint64 end)
{
    if(end > start)
    {
        return (unsigned long) (end - start);    
    }
    else
    {
        return (unsigned long) (start - end);
    }
    
}




void draw_p(pmesh p)
{
    
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, p->vertex_data);

   if(p->uv_data != NULL)
   {
       //glEnable(GL_TEXTURE_2D);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(2, GL_FLOAT, 0, p->uv_data);
        
    }
    

    glDrawArrays(GL_TRIANGLES,0, p->vertex_count);
    glDisableClientState(GL_VERTEX_ARRAY);
    
    if(p->uv_data != NULL)
    {
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       // glDisable(GL_TEXTURE_2D);
    }
    
}

void new_draw(pDemoAssetList a)
{
    // measures the time it took to render in order to keep the animation time dependent instead of frame rate dependent.
    // the scene descriptor WILL get modified during the demo execution
        
    uint64 ms_start;
    uint64 ms_end;
    uint64 ms_elapsed ;


   // unsigned long total_render_time_ms ;
    pDemoAssetList iter ;
    p3DModelList m;
    pTextureList t;
    pSceneDescription d;
    pCameraList c ;
    pTransformList tr;

    pmesh curr_model ;
    pmesh aux_model ;
    int curr_texture ;
    int curr_texture_pos ;

    iter = a ;

    m = iter->m ; // model list
    t = iter->t ; // texture list
    d = iter->d ; // scene descriptor
    c = iter->c ; // camera descriptor

   
    
    ms_start = timer_ms_gettime64();

    while(isCameraInTime(c, iter->milisec_elapsed) == 0)
    {
        c = c->next ; // seeks the camera in the current time frame
        
    }
    // glKosBeginFrame(); // REMOVED DUE TO PH3N0N's API
    glLoadIdentity();
    gluLookAt( c->start_pos.x,
               c->start_pos.y,
               c->start_pos.z,
               c->start_looking_direction.x,
               c->start_looking_direction.y,
               c->start_looking_direction.z,
               0.0,
               0.0,
               1.0 );

   
    while (d != NULL) // goes trough all the meshes on the asset list
    {
        
        glPushMatrix();
    
        if(d->render_effects & DRAW_WIREFRAME)
        {
            // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        }

        if(d->render_effects & DRAW_FLAT)
        {
            //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        }

    
        for ( tr = d->transforms ; tr != NULL ; tr = tr->next)
        {
          
            printf("CURRENT MESH \n \n");
        
            if(tr->transformType == ROTATION)
            {
                printf("ROTATION APPLIED : %f %f %f %f\n", tr->scalar_val , tr->transformData.x, tr->transformData.y, tr->transformData.z);
                glRotatef(tr->scalar_val , tr->transformData.x, tr->transformData.y, tr->transformData.z);
                
            }
            if(tr->transformType == TRANSLATION)
            {
                printf("TRANSLATION APPLIED : %f %f %f\n",  tr->transformData.x, tr->transformData.y, tr->transformData.z);
                glTranslatef(tr->transformData.x *1.5 , tr->transformData.y*1.5, tr->transformData.z*1.5);
                
            }
            if(tr->transformType == SCALE)
            {
                printf("SCALE APPLIED : %f %f %f\n", tr->transformData.x, tr->transformData.y, tr->transformData.z);
                glScalef(tr->transformData.x, tr->transformData.y, tr->transformData.z);
               
            }
          
            
        }
        printf("END TRANSFORMS \n");

        if( !(d->render_effects & DRAW_GRID)) // regular model drawing
        {
           
            curr_texture_pos = getTexturePos(t, d->texture_name);
            curr_texture = retrieveTextureHandle(t, curr_texture_pos);
    
            glBindTexture(GL_TEXTURE_2D, curr_texture);

            curr_model = retrieveMesh (m, getMeshPos(m, d->mesh_name) );

            draw_p(curr_model) ;    
        }
        else // renders a given mesh multiple times on a grid mesh
        {
          
            curr_texture_pos = getTexturePos(t, d->texture_name);
            curr_texture = retrieveTextureHandle(t, curr_texture_pos);

            glBindTexture(GL_TEXTURE_2D, curr_texture);
           
           // printf("d->name : %s (%d) ; d->mesh_name %s (%d)\n",d->name, getMeshPos(m, d->name) , d->mesh_name, getMeshPos(m, d->mesh_name) );

            curr_model = retrieveMesh (m, (getMeshPos(m, d->name)) ); // the grid mesh. Cant figure out WHY I must -1 on the position.
            aux_model = retrieveMesh (m, getMeshPos(m, d->mesh_name) ); // the mesh to be rendered on the grid
           // printf(" get_curr_model 1st arg : %s (pos : %d) \n get_aux_model 2nd arg : %s (pos : %d) \n",  d->name , getMeshPos(m, d->name),  d->mesh_name, getMeshPos(m, d->mesh_name) );
            

           // printf(" curr_model 1st arg : %d\n aux_model 2nd arg : %d \n", curr_model->vertex_count, aux_model->vertex_count);
            gridDraw(aux_model, curr_model, a);

        }
        

       d = d -> next ; // goes to the next element
       glPopMatrix();

    }
    

    ms_end = timer_ms_gettime64();

    ms_elapsed = diff_msec(ms_start, ms_end);
    
    

    // HACKJOB

    char hackjob[512];
    hackjob[511] = 0 ;

    sprintf(hackjob, "Render Time : %d ms", ms_elapsed );

    
    print_text(a, "font_2" ,"Vollumetric Illusions Demo Framework v0.0.1", 0, 440, 0.4);
    print_text(a, "font" ,hackjob, 0,400, 0.8);

    
    glutCopyBufferToTexture(RENDER_TEXTURE, &RENDER_TEXTURE_W, &RENDER_TEXTURE_H);
    

    
    RTT_test(RENDER_TEXTURE_ID, a);
    
    glutSwapBuffers();
    
   // glutCopyBufferToTexture(RENDER_TEXTURE, &RENDER_TEXTURE_W, &RENDER_TEXTURE_H);
    


    iter->milisec_elapsed += ms_elapsed;
   
    CameraListPosUpdate(iter->c, (iter->milisec_elapsed));

}

void demo_render(pDemoAssetList a)
{
    InitRenderTexture(1024, 512);

    while(1)
    {
        new_draw(a);
    }
}
Attachments
main.elf.zip
The .elf with the example executable. The main difference is that this one displays 2 quads instead of one.
(1.19 MiB) Downloaded 47 times
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Issues with render to texture.

Post by PH3NOM »

The function "glutCopyBufferToTexture(...)" will render to texture, and it will leave the vertex data in main ram to be submitted on the next frame. I wrote that function for use with the radial blur effect, because when using radial blur, you need to submit the same geometry twice. By leaving the vertex buffer in main ram, this saves the need to transform all of the geometry two times; it only needs to be done once.

The function "glutSwapBuffersToTexture(...)" will render to texture, then it will clear the vertex data in main ram. This is probably what you are expecting in your code there....

Also, I did document the fact at the function declaration in glut.h
http://sourceforge.net/p/cadcdev/libgl/ ... glut.h#l21
User avatar
bogglez
Moderator
Moderator
Posts: 578
Joined: Sun Apr 20, 2014 9:45 am
Has thanked: 0
Been thanked: 0

Re: Issues with render to texture.

Post by bogglez »

PH3NOM, When you say vertex buffer you mean frame buffer, right?
Wiki & tutorials: http://dcemulation.org/?title=Development
Wiki feedback: viewtopic.php?f=29&t=103940
My libgl playground (not for production): https://bitbucket.org/bogglez/libgl15
My lxdream fork (with small fixes): https://bitbucket.org/bogglez/lxdream
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Issues with render to texture.

Post by PH3NOM »

Hi bogglez!

Nope, I meant Vertex Buffer, not Frame Buffer.

The Frame Buffer is on the PVR, not in main RAM.

One of the things I do differently than the old KGL is I buffer the vertex data in main RAM before blasting the data off to the PVR using the Store-Queues.

There are many advantages to my solution.

Because the old KGL uses Direct Rendering to submit vertex data on the fly to the PVR, one could not mix the submission of Opaque and Translucent polygons.

Another elegant feature of my solution is that the PVR polygon headers are actually stored in line in the Vertex Buffer, along with the actual vertex data. This means an entire list can be submitted in one "draw call", without having to make multiple calls to submit each header and each vertex individually.

Take a look at the code here:
http://sourceforge.net/p/cadcdev/libgl/ ... e/gl-pvr.c
Post Reply