Search code examples
c++sdlglutfreeglut

glut cannot plot a 2D image


I am struggling with loading src/up.bmp and showing it in 2D overlaid on my 3D environment. But nothing does appear. Where is my mistake?

#define SDL_MAIN_HANDLED

#include <math.h>
#include <SDL.h>
#include <iostream>
#include <GL/freeglut.h>

using namespace std;

int w_width = 800;
int w_height = 500;
string w_title = "Model viewer";
float line_width = 2.0f;
float camera_radius = 100.0f;
float axis_size = 20.0;

SDL_Surface* button1;
GLuint TextureID;


void draw_button(SDL_Surface* button)
{

    glGenTextures(1, &TextureID);
    glBindTexture(GL_TEXTURE_2D, TextureID);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, button->w, button->h, GL_RGB, GL_UNSIGNED_BYTE, button->pixels);
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    const float ratio = (float)glutGet(GLUT_SCREEN_WIDTH) / (float)glutGet(GLUT_SCREEN_HEIGHT);
    static double t = 0.0;
    const float deg2rad = 3.1415926f / 180.0f;
    float cam_x = camera_radius*float(cos(20.0f*deg2rad))*float(cos(0.5235*deg2rad));
    float cam_y = camera_radius*float(sin(20.f*deg2rad))*float(cos(0.5235*deg2rad));
    float cam_z = camera_radius*float(sin(0.5235*deg2rad));

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90, ratio, 0.01, 10000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(cam_x, cam_y, cam_z, 0, 0, 0, 0, 0, 1);

    // sphere
    glPushMatrix();
    glColor3ub(255, 0, 0);
    glTranslated(
        0,
        0,
        0);
    glutSolidSphere(1, 20, 20);
    glPopMatrix();

    draw_button(button1);

    glFlush();
    glutSwapBuffers();
}

void timer_event(int value)
{
    glutPostRedisplay();
    glutTimerFunc(100, timer_event, value);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutSetOption(GLUT_MULTISAMPLE, 8);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);

    glutTimerFunc(30, timer_event, 1);
    glutInitWindowSize(w_width, w_height);
    glutInitWindowPosition(10, 10);
    glutCreateWindow(argv[0]);
    glutSetWindowTitle(w_title.c_str());
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);


    glutDisplayFunc(display);

    glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
        GLUT_ACTION_GLUTMAINLOOP_RETURNS);

    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_TEXTURE_2D);
    button1 = SDL_LoadBMP("src/up.bmp");
    if (button1 == NULL)
    {
        cout << "Image not found" << endl;
        exit(1);
    }
    glutMainLoop();

    SDL_FreeSurface(button1);

    return 0;
}

Solution

  • Here is a minimal example I can come up with:

    #define SDL_MAIN_HANDLED
    
    #include <math.h>
    #include <SDL.h>
    #include <iostream>
    #include <GL/gl.h>
    #include <GL/freeglut.h>
    
    using namespace std;
    
    int w_width = 800;
    int w_height = 500;
    string w_title = "Model viewer";
    float line_width = 2.0f;
    float camera_radius = 100.0f;
    float axis_size = 20.0;
    
    SDL_Surface* button1;
    GLuint TextureID;
    
    
    static void prepare_texture(SDL_Surface *button)
    {
        glGenTextures(1, &TextureID);
        glBindTexture(GL_TEXTURE_2D, TextureID);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
        // convert surface to RGB8
        SDL_Surface *rgb = SDL_CreateRGBSurface(0, button->w, button->h, 24, 0xff, 0xff00, 0xff0000, 0);
        SDL_BlitSurface(button, NULL, rgb, NULL);
    
        gluBuild2DMipmaps(GL_TEXTURE_2D, 3, button->w, button->h, GL_RGB, GL_UNSIGNED_BYTE, rgb->pixels);
    
        SDL_FreeSurface(rgb);
    }
    
    static void draw_button()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
        glBindTexture(GL_TEXTURE_2D, TextureID);
        glBegin(GL_QUADS);
            glTexCoord2f(0.0f, 1.0f);
            glVertex2f(0.1f, 0.1f);
            glTexCoord2f(0.0f, 0.0f);
            glVertex2f(0.1f, 0.2f);
            glTexCoord2f(1.0f, 0.0f);
            glVertex2f(0.2f, 0.2f);
            glTexCoord2f(1.0f, 1.0f);
            glVertex2f(0.2f, 0.1f);
        glEnd();
    }
    
    void display()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    
        const float ratio = (float)glutGet(GLUT_SCREEN_WIDTH) / (float)glutGet(GLUT_SCREEN_HEIGHT);
        static double t = 0.0;
        const float deg2rad = 3.1415926f / 180.0f;
        float cam_x = camera_radius*float(cos(20.0f*deg2rad))*float(cos(0.5235*deg2rad));
        float cam_y = camera_radius*float(sin(20.f*deg2rad))*float(cos(0.5235*deg2rad));
        float cam_z = camera_radius*float(sin(0.5235*deg2rad));
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(90, ratio, 0.01, 10000);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(cam_x, cam_y, cam_z, 0, 0, 0, 0, 0, 1);
    
        // sphere
        glPushMatrix();
        glColor3ub(255, 0, 0);
        glTranslated(
                0,
                0,
                0);
        glutSolidSphere(1, 20, 20);
        glPopMatrix();
    
        draw_button();
    
        glFlush();
        glutSwapBuffers();
    }
    
    void timer_event(int value)
    {
        glutPostRedisplay();
        glutTimerFunc(100, timer_event, value);
    }
    
    int main(int argc, char *argv[])
    {
        glutInit(&argc, argv);
        glutSetOption(GLUT_MULTISAMPLE, 8);
        glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);
    
        glutTimerFunc(30, timer_event, 1);
        glutInitWindowSize(w_width, w_height);
        glutInitWindowPosition(10, 10);
        glutCreateWindow(argv[0]);
        glutSetWindowTitle(w_title.c_str());
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
    
    
        glutDisplayFunc(display);
    
        glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
                GLUT_ACTION_GLUTMAINLOOP_RETURNS);
    
        glEnable(GL_COLOR_MATERIAL);
        glEnable(GL_TEXTURE_2D);
        button1 = SDL_LoadBMP("up.bmp");
        if (button1 == NULL)
        {
            cout << "Image not found" << endl;
            exit(1);
        }
    
        prepare_texture(button1);
        SDL_FreeSurface(button1);
    
        glutMainLoop();
    
        return 0;
    }
    

    Note identity projection, which maps screen to [-1,1] range; you may want something more like gluOrtho2D.