Question

I'm trying to display an image in openGL using SDL and SOIL but it isn't working.

Globals.h

#include <SDL.h>
#include <SDL_OpenGL.h>
#include <SOIL.h>

#include "player.h"

main.cpp

#include "Globals.h"

int main(int argc, char** argv){
    //Begin SDL initialization
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Surface* Screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE|SDL_OPENGL);
    SDL_Event Event;
    //End SDL initialization

    //Begin OpenGL initialization
    glClearColor(1, 1, 1, 1);//Set colour for empty screen
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);//Enable transparency
    glEnable(GL_TEXTURE_2D);

    glShadeModel(GL_SMOOTH);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glOrtho(-400, 400, -300, 300, -1, 1);//Set grid for display

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //End OpenGL initialization

    Player Player(0, 0, 32, 64, 1, 0, 0, 0.5);
    bool gameRunning = true;

    while(gameRunning){
        while(SDL_PollEvent(&Event)){
            if(Event.type == SDL_QUIT)
                gameRunning = false;
                //If user closed the window in any way stop gameRunning
            Player.Events(Event);
        }
        Player.Update();

        glClear(GL_COLOR_BUFFER_BIT);//Clear screen

        glPushMatrix();

        Player.DisplayWithImage("Brick.png", 32, 64);

        glPopMatrix();

        SDL_GL_SwapBuffers();//Update screen with new shit
    }

    SDL_Quit();//Quit SDL
    return 0;//End program
}

player.h

#pragma once

class Player{
public:
    GLfloat X, Y, W, H, R, G, B, A;
    bool movingUp, movingRight, movingDown, movingLeft;
    GLuint image;

    Player(GLfloat x, GLfloat y, GLfloat w, GLfloat h,
        GLfloat r, GLfloat g, GLfloat b, GLfloat a);
    void Events(SDL_Event &Event);
    void Update();
    void Display();
    void DisplayWithImage(const char* filename, GLsizei w, GLsizei h);
};

player.cpp

#include "Globals.h"

Player::Player(GLfloat x, GLfloat y, GLfloat w, GLfloat h, GLfloat r, GLfloat g, GLfloat b, GLfloat a){
    X = x;
    Y = y;
    W = w;
    H = h;
    R = r;
    G = g;
    B = b;
    A = a;

    movingUp = false;
    movingRight = false;
    movingDown = false;
    movingLeft = false;
}

void Player::Events(SDL_Event &Event){
    if(Event.type == SDL_KEYDOWN){
        if(Event.key.keysym.sym == SDLK_w)
            movingUp = true;
        if(Event.key.keysym.sym == SDLK_d)
            movingRight = true;
        if(Event.key.keysym.sym == SDLK_s)
            movingDown = true;
        if(Event.key.keysym.sym == SDLK_a)
            movingLeft = true;
    }
    if(Event.type == SDL_KEYUP){
        if(Event.key.keysym.sym == SDLK_w)
            movingUp = false;
        if(Event.key.keysym.sym == SDLK_d)
            movingRight = false;
        if(Event.key.keysym.sym == SDLK_s)
            movingDown = false;
        if(Event.key.keysym.sym == SDLK_a)
            movingLeft = false;
    }
}

void Player::Update(){
    if(movingUp)
        Y ++;
    if(movingRight)
        X ++;
    if(movingDown)
        Y --;
    if(movingLeft)
        X --;
}

void Player::Display(){
    glBegin(GL_QUADS);

        glColor4f(R, G, B, A);

        //bottom right
        glVertex2f(X+(W/2), Y-(H/2));
        //top right
        glVertex2f(X+(W/2), Y+(H/2));
        //top left
        glVertex2f(X-(W/2), Y+(H/2));
        //bottom left
        glVertex2f(X-(W/2), Y-(H/2));

    glEnd();
}

void Player::DisplayWithImage(const char* filename, GLsizei w, GLsizei h){
    image = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
    (
        filename,
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
    );

    glBindTexture(GL_TEXTURE_2D, image);

    glBegin(GL_QUADS);

        //bottom right
        glTexCoord2f(0, 0); glVertex2f(X+(W/2), Y-(H/2));
        //top right
        glTexCoord2f(0, H); glVertex2f(X+(W/2), Y+(H/2));
        //top left
        glTexCoord2f(W, H); glVertex2f(X-(W/2), Y+(H/2));
        //bottom left
        glTexCoord2f(W, 0); glVertex2f(X-(W/2), Y-(H/2));

    glEnd();
}
Was it helpful?

Solution

You have three problems in your code:

  1. GL_TEXTURE_2D uses normalized texture coordinates (0.0 - 1.0). Unless H and W are 1.0 or less you do not want to use them for your texture coordinates. If you just want to stretch this texture across your quad one time, use 1.0 in-place of W and H.

  2. Most Serious Issue: You are creating a new texture on each frame, you should load the texture one time and then pass the loaded texture handle to DisplayWithImage (...) instead of having that function load a texture each time you call it.

  3. glOrtho (...) creates an orthographic projection matrix, any GL operation that uses the projection matrix in isolation (e.g. not Projection * ModelView) is going to fail to work properly if you use an identity projection matrix and an orthographic projection matrix for your modelview matrix. By the same token, things like vertex lighting will not work properly with a projection matrix serving as your modelview matrix...

You can correct bullet point 3 by re-writing part of your code this way:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho(-400, 400, -300, 300, -1, 1);//Set grid for display
~~~~~~~ This should come AFTER you set the matrix mode to projection!
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top