简体   繁体   English

在带有SOIL的openGL中显示图像

[英]Displaying image in openGL with SOIL

I'm trying to display an image in openGL using SDL and SOIL but it isn't working. 我正在尝试使用SDL和SOIL在openGL中显示图像,但是它不起作用。

Globals.h Globals.h

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

#include "player.h"

main.cpp 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();
}

You have three problems in your code: 您的代码中存在三个问题:

  1. GL_TEXTURE_2D uses normalized texture coordinates ( 0.0 - 1.0 ). GL_TEXTURE_2D使用归一化的纹理坐标(0.0 - 1.0)。 Unless H and W are 1.0 or less you do not want to use them for your texture coordinates. 除非HW等于或小于1.0,否则您不希望将它们用于纹理坐标。 If you just want to stretch this texture across your quad one time, use 1.0 in-place of W and H . 如果只想一次在四边形上拉伸此纹理,请在WH处使用1.0

  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. 最严重的问题:您正在每个帧上创建一个新纹理,应该加载一次纹理,然后将加载的纹理句柄传递给DisplayWithImage (...)而不是让该函数每次调用时都加载纹理。

  3. glOrtho (...) creates an orthographic projection matrix, any GL operation that uses the projection matrix in isolation (eg 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. glOrtho (...)创建一个正交投影矩阵,使用单独的投影矩阵任何GL操作(例如投影*模型视图)是要失败的,如果你使用的身份投影矩阵和正交投影矩阵正常工作的模型视图矩阵。 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: 您可以通过以下方式重写部分代码来更正项目要点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!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM