Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Loading a bitmap image to use it as a texture / background on canvas for drawing

  1. #1
    Junior Member Newbie
    Join Date
    Mar 2014
    Posts
    26

    Loading a bitmap image to use it as a texture / background on canvas for drawing

    Greetings all !

    I intended to write some code that would load a bitmap image of Earth surface ( of size 1024x512 ) into a texture, and that texture would be displayed in a 1024x512 size FreeGLUT initialized window. I would then use this image to draw simple primitives on it. I am using SOIL image loading library to load the bitmap image. Instead of getting a window with the Earth surface image I get a 1024x512 black background window.

    Code :
    #include "SOIL.h"
     
    #include "GL/glew.h" 
    #include "GL/glut.h"
     
    GLuint texture; 
     
     
    void display (void) 
    {
        glClearColor (0.0,0.0,0.0,1.0);
        glClear (GL_COLOR_BUFFER_BIT);
        glLoadIdentity();
     
        glEnable( GL_TEXTURE_2D );
     
        glBindTexture(GL_TEXTURE_2D, texture);
     
        glBegin (GL_QUADS);
        glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
        glTexCoord2d(1.0,0.0); glVertex2d(1024.0,0.0);
        glTexCoord2d(1.0,1.0); glVertex2d(1024.0,512.0);
        glTexCoord2d(0.0,1.0); glVertex2d(0.0,512.0);
        glEnd();
     
        glutSwapBuffers();
    }
     
     
    void reshape (int w, int h) 
    {
        glViewport (0, 0, (GLsizei)w, (GLsizei)h);
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();
        gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
        glMatrixMode (GL_MODELVIEW);
    }
     
     
    int main (int argc, char **argv) 
    {
        glutInit (&argc, argv);
        glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize (1024, 512);
        glutInitWindowPosition (100, 100);
        glutCreateWindow ("A basic OpenGL Window");
        glutDisplayFunc (display);
        glutIdleFunc (display);
        glutReshapeFunc (reshape);
     
        glEnable( GL_TEXTURE_2D );
     
        texture = SOIL_load_OGL_texture
    	(
    		"earth.bmp",
    		SOIL_LOAD_AUTO,
    		SOIL_CREATE_NEW_ID,
    		SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
    	);
     
        glutMainLoop ();
     
        return 0;
    }

    What did I do wrong or miss to include in the program ? And also... since you know what I intend to do and use the image for, please let me know if my approach to the problem is not right, or if there is a more optimal way of doing it. Thank you very much.

    Kind regards,
    T

    Note : I have edited my question to include the new code that I tried. I will leave the old code here just to serve as "topic history".

    -----------------------------------------------------------------

    Code :
    #include <vector>
    #include <fstream>
     
    #include "GL/glew.h" // Include the GLEW header file
    #include "GL/glut.h" // Include the GLUT header file
     
    #include <cstdint>
     
     
    using namespace std;
     
     
    GLuint texture; //the array for our texture
     
    GLfloat angle = 0.0;
     
    int width = 0;
    int height = 0;
    short BitsPerPixel = 0;
    std::vector<unsigned char> Pixels;
     
    GLuint LoadTexture( const char * filename );
     
     
    void FreeTexture( GLuint texture )
    {
      glDeleteTextures( 1, &texture );
    }
     
     
    void display (void) {
     
        glClearColor (0.0,0.0,0.0,1.0);
        glClear (GL_COLOR_BUFFER_BIT);
        glLoadIdentity();
        glEnable( GL_TEXTURE_2D );
     
        glBindTexture( GL_TEXTURE_2D, texture );
     
        glBegin (GL_QUADS);
        glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
        glTexCoord2d(1.0,0.0); glVertex2d(1024.0,0.0);
        glTexCoord2d(1.0,1.0); glVertex2d(1024.0,512.0);
        glTexCoord2d(0.0,1.0); glVertex2d(0.0,512.0);
        glEnd();
     
        glutSwapBuffers();
     
    }
    void reshape (int w, int h) {
        glViewport (0, 0, (GLsizei)w, (GLsizei)h);
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();
        gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
        glMatrixMode (GL_MODELVIEW);
    }
     
    int main (int argc, char **argv) {
        glutInit (&argc, argv);
        glutInitDisplayMode (GLUT_DOUBLE);
        glutInitWindowSize (1024, 512);
        glutInitWindowPosition (100, 100);
        glutCreateWindow ("A basic OpenGL Window");
        glutDisplayFunc (display);
        glutIdleFunc (display);
        glutReshapeFunc (reshape);
     
     
        //Load our texture
        GLuint texture;
        texture= LoadTexture( "earth.bmp" );
     
        glutMainLoop ();
     
        //Free our texture
        FreeTexture( texture );
     
        return 0;
    }
    Last edited by thor36; 08-17-2014 at 08:27 PM. Reason: I am trying new code with SOIL library

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    894
    You need to render your background with an orthographic projection matrix instead of the perspective one you are currently using. glVertex2d has very little to do with 2 dimensional rendering, it just implicitly means the z coordinate is 0 and the w coordinate is 1 and that you want to pass in double precision floating point values, but otherwise the vertex data still goes through the normal transformation steps and that includes applying the projection matrix.
    You also probably want to clear the depth buffer when clearing the color buffer.
    As far as doing things more optimal: You may want to read up on 'modern' OpenGL (see the tutorials at wiki) where buffer objects are used to avoid the CPU intensive immediate mode drawing. However, for your program this is not really going to matter much, since there is not a lot happening so far

  3. #3
    Junior Member Newbie
    Join Date
    Mar 2014
    Posts
    26
    Thank you for reply. Some more questions follow up, since I didn't manage to make it work :/
    Where should I put an orthographic projection matrix instead of the perspective one ? There is only one perspective matrix, and it's in reshape() function, that may not be used at all if window size isn't changing.
    And I have changed "glClear (GL_COLOR_BUFFER_BIT);" to "glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);" .

    Can you please write the corrected code about the part with projection matrix that I am not doing right ? Thank you.
    Regrads, T

  4. #4
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    894
    Look at it like this: there are some parts of your scene that you want to render using an ortho projection and some that you want rendered with perspective projection. You'll have to switch from one to the other in your display function:

    Code :
    float aspect = 1.f;
     
    void display()
    {
        // set up ortho projection
        // render background
     
        // set up perspective projection, making use of the stored aspect ratio
        // render foreground
    }
     
    void reshape(int w, int h)
    {
        aspect = static_cast<float>(w) / h;
     
        // set viewport
    }

    Glut calls the reshape function at least once before calling display for the first time.

  5. #5
    Junior Member Newbie
    Join Date
    Mar 2014
    Posts
    26
    Thank you. I have managed to make the texture appear on the background properly. Now I would like to render a blue square on it ( just for demonstration to learn how to draw on the background ). I tried to follow the simple example from primitives rendering sample code, but it doesn't function properly. I understand the problems must be in perspectives, but I have no idea how to solve it. My present display function now looks like this :

    Code :
    void display (void) {
     
        glClearColor (0.0,0.0,0.0,1.0);
        glClear (GL_COLOR_BUFFER_BIT);
     
        // background render
     
        glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f);
     
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
     
        glEnable( GL_TEXTURE_2D );
     
        glBindTexture( GL_TEXTURE_2D, texture );
     
        glBegin (GL_QUADS);
        glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
        glTexCoord2d(1.0,0.0); glVertex2d(1024.0,0.0);
        glTexCoord2d(1.0,1.0); glVertex2d(1024.0,512.0);
        glTexCoord2d(0.0,1.0); glVertex2d(0.0,512.0);
        glEnd();
     
        // foreground render - added code, not working
     
        glMatrixMode(GL_MODELVIEW); 
        glLoadIdentity(); 
     
        glColor3f(0.0f, 0.0f, 1.0f);
     
        glBegin (GL_QUADS);
        glVertex2d(500.0,400.0);
        glVertex2d(500.0,500.0);
        glVertex2d(600.0,400.0);
        glVertex2d(600.0,500.0);
        glEnd();
     
        glutSwapBuffers();
    }

    I also understand now why you pointed out the reshape function, since reshaping doesn't function, and on a window resize I get a black window.
    What did you have in mind when you wrote "static_cast<float>(w) / h;", isn't that equivalent to "(GLfloat)w / (GLfloat)h" that I have in gluPerspective ? I am not sure what you mean by it , and how I should modify reshape =/

  6. #6
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    894
    You should be more careful to put projection related matrices on the projection matrix stack, e.g. enable glMatrixMode(GL_PROJECTION) before calling glOrtho() - currently this all just works by accident, because you put the ortho projection on the modelview matrix stack and have an identity projection. In this case that happens to result in the same modelviewprojection matrix being used for rendering, but is very fragile.

    Code :
    int winWidth  = 0;
    int winHeight = 0;
     
    void display()
    {
        // clear
     
        // orthographic projection for background
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f);
     
        // draw background
     
        // perspective projection for foreground
        glLoadIdentity();
        gluPerspective (60, (GLfloat)winWidth / (GLfloat)winHeight, 1.0, 100.0);
     
        glMatrixMode(GL_MODELVIEW);
     
        // draw foreground
    }

    The variables winWidth, winHeight are assigned in the reshape function, because you need those sizes to calculate the aspect ratio for the perspective projection - alternatively you can just calculate the aspect ratio in reshape an store that, but usually as a program grows there's few additional places where you need the window size.
    I would suggest you read a tutorial on how the various transformations of the OpenGL pipeline work to get a better understanding what the various steps are good for.

  7. #7
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    894
    Actually, I forgot one other important aspect: you need to disable depth buffer writes when rendering the background (or clear the depth buffer afterwards), otherwise the background might obscure foreground objects.

    Code :
    void display()
    {
        // clear color/depth buffer
     
        // orthographic projection for background
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f);
     
        // disable depth writes
        glDepthMask(GL_FALSE);
     
        // draw background
     
        // re-enable depth writes
        glDepthMask(GL_TRUE);
     
        // perspective projection for foreground
        glLoadIdentity();
        gluPerspective (60, (GLfloat)winWidth / (GLfloat)winHeight, 1.0, 100.0);
     
        glMatrixMode(GL_MODELVIEW);
     
        // draw foreground
    }

  8. #8
    Junior Member Newbie
    Join Date
    Mar 2014
    Posts
    26
    Carsten Neumann - yes , I was searching the internet and found out that I should pay attention to clearing depth buffer. And about what you said earlier, that I should read a text on transformation and pipeline.. you are absolutely right and I know very well that I should. It just so happens that right now I am in a situation when I need to produce a result. But certainly, if I want to know the subject well and do more work in the future I will have to read about it when I get the chance.

    My current state of the code is :

    Code :
    void display (void) {
     
    //    if these lines were still there, i get a black screen
    //    glClearColor (0.0,0.0,0.0,1.0); 
    //    glClear (GL_COLOR_BUFFER_BIT);
     
        // background render
     
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f);
     
        glEnable( GL_TEXTURE_2D ); 
        glBindTexture( GL_TEXTURE_2D, texture );
     
        glBegin (GL_QUADS);
        glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
        glTexCoord2d(1.0,0.0); glVertex2d(1024.0,0.0);
        glTexCoord2d(1.0,1.0); glVertex2d(1024.0,512.0);
        glTexCoord2d(0.0,1.0); glVertex2d(0.0,512.0);
        glEnd();
     
        glDisable(GL_TEXTURE_2D);
     
     
        // foreground render
     
        // re-enable depth writes
        glDepthMask(GL_TRUE);
     
        glLoadIdentity();
        //gluPerspective (60, (GLfloat)winWidth / (GLfloat)winHeight, 0.0, 1.0);
        glMatrixMode(GL_MODELVIEW);
     
        glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f);
     
        glColor3f(0.0, 0.0, 1.0);
     
        glBegin (GL_QUADS);
        glVertex2d(400.0,100.0);
        glVertex2d(400.0,300.0);
        glVertex2d(700.0,100.0);
        glVertex2d(700.0,300.0);
        glEnd();
     
        glutSwapBuffers();
    }

    What I get now is flashing image on the screen. And the quad actually looks like this : more like a ribbon, Click image for larger version. 

Name:	kOC1B.jpg 
Views:	334 
Size:	5.9 KB 
ID:	1399. The background seems to be displayed in proper colours though. Why do I get the flashing screen and incorrectly drawn quad ? Thank you.
    Regards, T

    Edit : I also tried to add your new code that wasn't present here before, and result is same. =/
    Also, if I include this line ( gluPerspective (60, (GLfloat)winWidth / (GLfloat)winHeight, 0.0, 1.0); ), the "quad" isn't going to be drawn at all.
    Last edited by thor36; 08-19-2014 at 03:51 PM.

  9. #9
    Intern Newbie
    Join Date
    Apr 2014
    Posts
    47
    Your "ribbon" quad is not wound counterclockwise which is why it displays as a ribbon.
    Code :
    glBegin (GL_QUADS);
    glVertex2d(400.0,100.0);
    glVertex2d(700.0,100.0);
    glVertex2d(700.0,300.0);
    glVertex2d(400.0,300.0);
    glEnd();

    I'm still working on the flashing aspect.

    EDIT: You are disabling depth writes for the background, but you are still testing the background against the depth buffer, and the depth buffer is never cleared. That's why you get a black screen since you are clearing the screen to black and nothing else is passing the depth test. By default the depth test used is GL_LESS, so if you render once, you will not see anything for subsequent writes.

    I'd try:
    Code :
    void display (void) {
     
    //    if these lines were still there, i get a black screen
        glClearColor (0.0,0.0,0.0,1.0); 
        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
     
        // background render
     
        glDisable( GL_DEPTH_TEST ) ///!!!!
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f);
     
        glEnable( GL_TEXTURE_2D ); // se ugotovi kam dat
        glBindTexture( GL_TEXTURE_2D, texture );
     
        glBegin (GL_QUADS);
        glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
        glTexCoord2d(1.0,0.0); glVertex2d(1024.0,0.0);
        glTexCoord2d(1.0,1.0); glVertex2d(1024.0,512.0);
        glTexCoord2d(0.0,1.0); glVertex2d(0.0,512.0);
        glEnd();
     
        glDisable(GL_TEXTURE_2D);
     
     
        // foreground render
     
        // re-enable depth writes and testing
        glEnable( GL_DEPTH_TEST );
        glDepthMask(GL_TRUE);
     
        glLoadIdentity();
        //gluPerspective (60, (GLfloat)winWidth / (GLfloat)winHeight, 0.0, 1.0);
        glMatrixMode(GL_PROJECTION); // changed this here to be consistent w/ conventions
     
        glOrtho(0.0f, 1024.0, 512.0, 0.0, 0.0, 1.f);
     
        glColor3f(0.0, 0.0, 1.0);
     
        glBegin (GL_QUADS);
        glVertex2d(400.0,100.0);
        glVertex2d(400.0,300.0);
        glVertex2d(700.0,100.0);
        glVertex2d(700.0,300.0);
        glEnd();
     
        glutSwapBuffers();
    }
    Last edited by MtRoad; 08-19-2014 at 03:30 PM.

  10. #10
    Junior Member Newbie
    Join Date
    Mar 2014
    Posts
    26
    MtRoad - thank you for your explanations and code. I have tried your code and I still get the "ribbon". Also now it's back to the problem I had in the beginning, where whole image consisted only of black and blue(hues) colours. Flashing is gone however.
    Last edited by thor36; 08-19-2014 at 05:16 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •