OpenGL纹理在屏幕上显得很大

OpenGL texture appears to big on the screen

本文关键字:纹理 屏幕 OpenGL      更新时间:2023-10-16

好的,所以我正在开发玩具2d引擎。我最初使用常规SDL_Surfaces进行渲染和内置SDL_Renderer。但我想为什么不使用OpenGL,获得一些经验。

但是我现在被困住了。我有一个上下文,东西被渲染到屏幕上,但看起来我试图显示的纹理很大,可以适应屏幕。就像我只看到几个像素,但不是真的。

纹理类可以在这里找到:

#include "texture.h"
Texture::Texture(std::string path, bool loadNow) {
    //Initialize texture ID
    mTextureID = 0;
    //Initialize texture dimensions
    width = 0;
    height = 0;
    this->path = path;
    if(loadNow) {
        loadTexture(path);
    }
}
Texture::~Texture() {
    freeTexture();
}
bool Texture::loadTexture(std::string path) {
    //Texture loading success
    loaded = false;
    SDL_Surface *image = IMG_Load(path.c_str());
    //Image loaded successfully
    if(image != NULL) {
        if((image->w & (image->w - 1)) == 0) {
            printf("Warning: image width not power of 2 -> %sn", path.c_str());
        }
        if((image->h & (image->h - 1)) == 0) {
            printf("Warning: image height not power of 2 -> %sn", path.c_str());
        }
        loaded = loadTextureFromPixels32(image, (GLuint)image->w, (GLuint)image->h);
    }
    //Report error
    if(!loaded) {
        printf( "Unable to load %sn", path.c_str() );
    }

    return loaded;
}
bool Texture::loadTextureFromPixels32(SDL_Surface *image, GLuint width, GLuint height ) {
    //Free texture if it exists
    freeTexture();
    //Get texture dimensions
    this->width = width;
    this->height = height;
    //Generate texture ID
    glGenTextures(1, &mTextureID);
    //Bind texture ID
    glBindTexture(GL_TEXTURE_2D, mTextureID);
    //Generate texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
    //Set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //Unbind texture
    glBindTexture(GL_TEXTURE_2D, 0);
    //Check for error
    GLenum error = glGetError();
    if(error != GL_NO_ERROR) {
        printf("Error loading texture from %p pixels!n", image->pixels);
        return false;
    }
    return true;
}
void Texture::render(GLfloat x, GLfloat y) {
    if(loaded) {
        //If the texture exists
        if(mTextureID != 0) {
            GLfloat realX = x;// - (this->width / 2);
            GLfloat realY = y;// - (this->height / 2);
            //Remove any previous transformations
            glLoadIdentity();
            //Move to rendering point
            glTranslatef(realX, realY, 0.f);
            glClearDepth(1.0f); 
            //Set texture ID
            glBindTexture(GL_TEXTURE_2D, mTextureID);
            //Render textured quad
            glBegin(GL_QUADS);
                glTexCoord2f( 0.f, 0.f ); glVertex2f(0.f,   0.f);
                glTexCoord2f( 1.f, 0.f ); glVertex2f(width, 0.f);
                glTexCoord2f( 1.f, 1.f ); glVertex2f(width, height);
                glTexCoord2f( 0.f, 1.f ); glVertex2f(0.f,   height);
            glEnd();
        }
    } else {
        // do nothing
    }
}
GLuint Texture::getWidth() {
    return this->width;
}
GLuint Texture::getHeight() {
    return this->height;
}
void Texture::freeTexture() {
    //Delete texture
    if(mTextureID != 0) {
        glDeleteTextures(1, &mTextureID);
        mTextureID = 0;
    }
    width = 0;
    height = 0;
}

猜问题出在这里,但也可能是我如何初始化 OpenGL,所以这里是:

void Main::initGL() {
    /* Request opengl 3.2 context.
     * SDL doesn't have the ability to choose which profile at this time of writing,
     * but it should default to the core profile */
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    /* Turn on double buffering with a 24bit Z buffer.
     * You may need to change this to 16 or 32 for your system */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
    glContext = SDL_GL_CreateContext(this->window);
    glViewport(0.0, 0.0, SCREEN_WIDTH, SCREEN_HEIGHT);
    glOrtho( 0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, 1.0, -1.0 );
    SDL_GL_SetSwapInterval(0);
    //Initialize clear color
    glClearColor( 0.f, 0.f, 0.f, 1.f );
    //Enable texturing
    glEnable( GL_TEXTURE_2D );
    //Check for error
    GLenum error = glGetError();
    if(error != GL_NO_ERROR) {
        printf("Error initializing OpenGL!n");
    }
}

SDL 已正确初始化,否则屏幕上不会有任何内容。我是OpenGL的新手,所以任何帮助将不胜感激。

您将纵

坐标GL_TEXTURE_2D的东西与GL_TEXTURE_RECTANGLE混合在一起,并且同时启用两者是一个非常糟糕的主意。您正在使用 [0,1] 范围内的 texcoord,因此您实际上似乎想使用 GL_TEXTURE_2D .您应该重写纹理代码以使用它,并完全删除这些矩形纹理。

接下来是您的投影设置错误。您的glOrtho调用不起作用,因为您在几行后加载单位矩阵会完全覆盖它。您应该熟悉GL正在使用的stae机器方法。由于您的矩阵是当前设置的,因此您可以绘制一个巨大的四边形,其中大部分完全不在屏幕上。

现在这部分完全奇怪了:

/* Request opengl 3.2 context.
 * SDL doesn't have the ability to choose which profile at this time of writing,
 * but it should default to the core profile */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);

这段代码永远不会创建核心配置文件,因为核心配置文件在GL2.1中甚至不存在,它们是在GL3.2中引入的。目前尚不清楚您使用的是哪个 SDL 版本,但现代 SDL 能够选择配置文件。

但是,您的代码使用的是完全过时的 ande 已弃用的 OpenGL,这无法与核心配置文件一起使用。如果你在这十年里学习了OpenGL,我强烈建议你忘记所有这些,从一些关于现代GL的文档/教程开始,并实际使用核心产品。