0

我正在尝试使用 SDL 和 SOIL 在 openGL 中显示图像,但它不起作用。

全局文件

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

#include "player.h"

主文件

#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
}

播放器.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);
};

播放器.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();
}
4

1 回答 1

2

您的代码中有三个问题:

  1. GL_TEXTURE_2D使用归一化纹理坐标 ( 0.0 - 1.0 )。除非HW1.0或更低,否则您不想将它们用于纹理坐标。如果您只想在四边形上拉伸此纹理一次,请使用1.0代替Wand H

  2. 最严重的问题:您在每一帧上创建一个新纹理,您应该加载一次纹理,然后将加载的纹理句柄传递给,DisplayWithImage (...)而不是让该函数在每次调用它时加载纹理。

  3. glOrtho (...)创建一个正交投影矩阵,如果您对模型视图矩阵使用单位投影矩阵和正交投影矩阵,则任何单独使用投影矩阵(例如,不是Projection * ModelView)的GL 操作都将无法正常工作。出于同样的原因,顶点照明之类的东西将无法与用作模型视图矩阵的投影矩阵一起正常工作......

您可以通过以下方式重写部分代码来更正要点 3:

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!
于 2013-11-01T07:34:30.133 回答