0

I need to have an image as output of my code (dimension: 3507x3281) composed by two triangles (upper-left corner and lower-right corner), each triangle will give me one different color/image on my output.

I read both images and bound them with 2 textures (texture_1 and texture_2). Afterwards I created both triangles related to their respective image. I created and bound the Framebuffer Object and attached the textures. Finally, I saved the content to a image file (.ppm).

PROBLEM:

My result (output image) is coherent and geometrically correct. However, only part of my output image is visible. The part that it is visible has 1366x768 as dimension, which is exactely my screen resolution. Am I missing something on the code?

Is there anything related to the options "GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER and GL_FRAMEBUFFER"? Only "GL_DRAW_FRAMEBUFFER" gives the coherent result.

Am I really using the Framebuffer? Because, I read that since you use the FBO this kind of problem does not appear.

CODE:

#include <windows.h>
#define  GLEW_STATIC

#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/freeglut.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cstdio>
#include <string>

/// Definitions
#define checkImageWidth    500 /// for image - texture 1
#define checkImageHeight   500
#define width   2464           /// for image - texture 2
#define height  1648

static  GLuint texture_1, texture_2;
static  GLubyte checkImage[checkImageHeight][checkImageWidth][3];
GLuint  fb = 1; ///Frame-buffer Object

/// Headers
GLuint  raw_texture_load();
void    FBO_2_PPM_file(int output_width, int output_height);

/// Functions
GLuint raw_texture_load()
{
    /// image used for texture 1
    unsigned char *data;
    FILE *file;

    // open texture data
    file = fopen("C:\\Dataset\\image_1.raw", "rb");
    if (file == NULL) return 0;

    // allocate buffer
    data = (unsigned char*) malloc(width * height * 3);

    // read texture data
    fread(data, width * height * 3, 1, file);
    fclose(file);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    /// Texture 1
    // allocate a texture name
    glGenTextures(1, &texture_1);
    // select our current texture
    glBindTexture(GL_TEXTURE_2D, texture_1);
    // select modulate to mix texture with color for shading
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
    // when texture area is small, bilinear filter the closest mipmap
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    // when texture area is large, bilinear filter the first mipmap
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // texture should tile
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // build our texture mipmaps
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
    // free buffer
    free(data);

    /// image used for texture 2
    FILE *image_4tx2;
    if( (image_4tx2 = fopen("C:\\dataset\\image2.ppm","r")) == NULL )
    {
        printf("\n Problem with input for texture 2\n");
        system("pause");
        exit(1);
    }

    int i, j, max_ND, n_col, n_lin, Red, G, B;
    char s1[20];

    /// Read header
    fscanf(image_4tx2,"%s",&s1);
    fscanf(image_4tx2,"%s %s %s %s",&s1, &s1, &s1, &s1);
    fscanf(image_4tx2,"%d %d",&n_col, &n_lin);
    fscanf(image_4tx2,"%d",&max_ND);

    for (i = 0; i < checkImageWidth; i++)
    {
        for (j = 0; j < checkImageHeight; j++)
        {
            fscanf(image_4tx2,"%d %d %d ",&Red, &G, &B);
            checkImage[i][j][0] = (GLubyte) Red;
            checkImage[i][j][1] = (GLubyte) G;
            checkImage[i][j][2] = (GLubyte) B;
        }
    }
    fclose(image_4tx2);

    /// Texture 2
    glGenTextures(2, &texture_2);
    glBindTexture(GL_TEXTURE_2D, texture_2);
    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_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, checkImageWidth, checkImageHeight,
                 0, GL_RGB, GL_UNSIGNED_BYTE, checkImage);

    return texture_1;
}

void render()
{
    GLdouble    COORD_1[3], COORD_2[3], COORD_3[3], COORD[3];

    /// Output image size
    double col_siz_double = 3507.0;
    double row_siz_double = 3281.0;

    int col_siz_output_image = 3507;
    int row_siz_output_image = 3281;

    /// Aspect ratio
    double ratio_col_row = col_siz_double/row_siz_double;

    double aspect_E, aspect_N;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    if(ratio_col_row>=0.0)
    {
        aspect_E = 1.0;
        aspect_N = 1.0/ratio_col_row;
        glOrtho(0.0, 1.0*aspect_E, 0.0, 1.0*aspect_N, 0.0, 1.0);
    }
    else
    {
        aspect_E = 1.0/ratio_col_row;
        aspect_N = 1.0;
       glOrtho(0.0, 1.0*aspect_E, 0.0, 1.0*aspect_N, 0.0, 1.0);
    }

    gluLookAt(  0.0, 0.0, 1.0,  /* eye    */
                0.0, 0.0, 0.0,  /* center */
                0, 1, 0);       /* up     */

    /// Viewport
    glViewport(0,0,col_siz_output_image,row_siz_output_image);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    /// Triangle 1 (upper-left half of the output)
    glBindTexture(GL_TEXTURE_2D, texture_1);

    glBegin(GL_TRIANGLES);
        glTexCoord2d(0.0, 0.0);
                    COORD[0]= 0.0*aspect_E;
                    COORD[1]= 0.0*aspect_N;
                    COORD[2]= 1.0;
        glVertex3d(COORD[0], COORD[1], COORD[2]);

        glTexCoord2d(1.0, 1.0);
                    COORD[0]= 1.0*aspect_E;
                    COORD[1]= 1.0*aspect_N;
                    COORD[2]= 1.0;
        glVertex3d(COORD[0], COORD[1], COORD[2]);

        glTexCoord2d(0.0, 1.0);
                    COORD[0]= 0.0*aspect_E;
                    COORD[1]= 1.0*aspect_N;
                    COORD[2]= 1.0;
        glVertex3d(COORD[0], COORD[1], COORD[2]);
    glEnd();

    /// Triangle 2 (low-right half of the output)
    glBindTexture(GL_TEXTURE_2D, texture_2);

    glBegin(GL_TRIANGLES);
        glTexCoord2d(0.0, 0.0);
                    COORD[0]= 0.0*aspect_E;
                    COORD[1]= 0.0*aspect_N;
                    COORD[2]= 1.0;
        glVertex3d(COORD[0], COORD[1], COORD[2]);

        glTexCoord2d(1.0, 1.0);
                    COORD[0]= 1.0*aspect_E;
                    COORD[1]= 1.0*aspect_N;
                    COORD[2]= 1.0;
        glVertex3d(COORD[0], COORD[1], COORD[2]);

        glTexCoord2d(1.0, 0.0);
                    COORD[0]= 1.0*aspect_E;
                    COORD[1]= 0.0*aspect_N;
                    COORD[2]= 1.0;
        glVertex3d(COORD[0], COORD[1], COORD[2]);
    glEnd();

    glFlush();
    glDisable(GL_TEXTURE_2D);

    static const GLenum draw_buffers[] =
    {
        GL_COLOR_ATTACHMENT0,
        GL_COLOR_ATTACHMENT1
    };

    /// Generating and Biding the Framebuffer Object (FBO)
    glGenFramebuffers(1, &fb);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);

    ///Attaching both 2D texture to the FBO as color attachments
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, draw_buffers[0], GL_TEXTURE_2D, texture_2, 0);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, draw_buffers[1], GL_TEXTURE_2D, texture_1, 0);

    /// Specifying a list of color buffers to be drawn into
    glDrawBuffers(2, draw_buffers);

    /// Checking the FBO status
    GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if( status != GL_FRAMEBUFFER_COMPLETE)
    {
        printf("\n\nFramebuffer status: %s\n\n",status);
        system("pause");
    }

    /// Saving the results from the FBO (fb) to a PPM image file
    FBO_2_PPM_file(col_siz_output_image,row_siz_output_image);
 }

void init()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);

    texture_1 = raw_texture_load();

    render();
}

void FBO_2_PPM_file(int output_width, int output_height)
{
    FILE    *output_image;

    /// READ THE PIXELS VALUES from FBO AND SAVE TO A .PPM FILE
    int             i, j, k;
    unsigned char   *pixels = (unsigned char*)malloc(output_width*output_height*4);

    /// READ THE CONTENT FROM THE FBO
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glReadBuffer(GL_COLOR_ATTACHMENT1);

    glReadPixels(0, 0, output_width, output_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

    output_image = fopen("C:\\Dataset\\output.ppm", "wt");
    if(output_image == NULL)
    {
        printf("Problem @ output file!\n\n");
        system("pause");
    }
    fprintf(output_image,"P3\n");
    fprintf(output_image,"# Created by Ricao\n");
    fprintf(output_image,"%d %d\n",output_width,output_height);
    fprintf(output_image,"255\n");

    k = 0;
    for(i=output_height-1; i>-1; i--)
    {
        for(j=0; j<output_width; j++)
        {
            k = (i*output_width)+j;
            /// saving only RGB
            fprintf(output_image,"%u %u %u ",(unsigned int)pixels[4*k],(unsigned int)pixels[(4*k)+1],
                                             (unsigned int)pixels[(4*k)+2]);
        }
        fprintf(output_image,"\n");
    }
    free(pixels);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(3507, 3281);
    glutCreateWindow("Do not close this window!");
    glutHideWindow();

    /// Checking GLEW library
    glewExperimental=TRUE;
    GLenum err=glewInit();

    if(err!=GLEW_OK)
    {
        printf("glewInit failed, aborting.");
        printf("\tError: %s\n\n",glewGetErrorString(err));
        system("pause");
    }

    if (GLEW_EXT_framebuffer_object != GL_TRUE)
    {
        printf("\n\n\t ** Error! GLEW_EXT_framebuffer_object != GL_TRUE \n\n");
        system("pause");
    }

    /// To check the max size of the Framebuffer
    int dims[2];
    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &dims[0]);

    ///Executing the rendering process
    init();

    return 0;
Community
  • 1
  • 1
ricãO
  • 61
  • 1
  • 10
  • 2
    You need to create and bind your framebuffer before rendering. – dari Aug 03 '15 at 15:11
  • I changed the position of the "create and bind - FBO" to the beginning of render() function, but I got an empty result. One thing strange that I noticed now is that if I run without creating and biding the FBO I get the same partial result as before (only part of the output has color). – ricãO Aug 03 '15 at 15:32
  • You use an FBO which has a 2464x1648 texture as color attachment 0, and a 500x500 texture as color attachment1. YOu also read back only the second texture. So you shouldn't be surprised if only part of your image is visible. – derhass Aug 03 '15 at 20:03
  • @derhass, This environment is quiet new for me. Do you know how can I solve my problem? Any tip will be noble! – ricãO Aug 03 '15 at 20:17
  • 1
    Well, if you want a 3507x3281 image, you need a framebuffer of that size. There is lots of stuff in the code which doesn't really make sense. Why are you using multiple render targets? Why are you rendering into the textures you try to sample from. I think you should take yourself the time for a thorough opengl introduction, something which can't be provided here on SO. – derhass Aug 03 '15 at 20:22
  • I will do that, thank you! – ricãO Aug 03 '15 at 20:25
  • I've read some opengl material and I decided to create a simple example to understand the workflow better. Can you guys say if I am in the right flow? Sequence: (1) Texture: generate, bind, set parameters, and save the memory space for it, using glTexImage2D; This will be my output, at first it is empty. (2) FBO: generate, bind and attach the texture (step 1); (3) Draw both triangles, after biding the FBO and the texture; (4) Select the buffer (glReadBuffer - my fbo); (5) Read the textute (glReadPixels - array with the same size as my texture); (6) Save as an image file. – ricãO Aug 05 '15 at 18:06

0 Answers0