OpenGL纹理渲染颠倒和模糊

Posted

技术标签:

【中文标题】OpenGL纹理渲染颠倒和模糊【英文标题】:OpenGL Textures rendering upside down, and blurred 【发布时间】:2013-07-22 03:25:15 【问题描述】:

我之前在开发游戏,遇到了一点问题!我从单张图片开始游戏。每个纹理都有自己的文件。我意识到我这样做是多么的白痴,并试图切换到使用包含所有纹理的一张图片(无论如何它们都很小),这让我有点投入。现在,问题出现了。当加载比我的原始纹理 ( 10 x 10 ) 更大的图像时,几乎就像它没有使用最近邻大小算法显示一样。我得到的是一个模糊的图像。它也被翻转了......为什么会发生这些问题?

代码和图片如下。

这是第一个显示包含文本和符号的精灵表。 (它很小, 100 x 100 ) http://imgur.com/HU5zEAO.jpg

这是我在程序运行时得到的。 http://i.imgur.com/HeVPdPy.jpg

这里是main.cpp文件

#include <GL/glew.h>
#include <GL/glut.h>

#include "spritesheet_class.h"
#include "load_img.h"

GLuint TextSheet;
Spritesheet Test;

void LoadFiles()


    GLuint TextSheet = LoadTexture( "davetica.png", 100, 100, 0 );

    Test.SetTex( TextSheet, 100, 100, 10, 10 );



void Reshape( int width, int height )


    glViewport( 0, 0, (GLsizei)width, (GLsizei)height );
    glMatrixMode( GL_PROJECTION );

    glLoadIdentity();
    glOrtho( 0.0f, width, 0.0f, height, 1.0f, 100.0f );

    glMatrixMode( GL_MODELVIEW );



void Display()


    glClear( GL_COLOR_BUFFER_BIT );
    glLoadIdentity();

    glTranslatef( 0.0f, 0.0f, -1.0f );

    Test.DrawSprite( 1, 0, 0, 400, 400 );

    glutSwapBuffers();



int main( int argc, char **argv )


    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE );

    glutInitWindowPosition( 200, 100 );
    glutInitWindowSize( 512, 512 );

    glutCreateWindow( "Sprite Sheets" );

    glutDisplayFunc( Display );
    glutIdleFunc( Display );
    glutReshapeFunc( Reshape );

    LoadFiles();

    glutMainLoop();


现在这是我编写 Spritesheet 类的类头。

#ifndef SPRITESHEET_CLASS_H_INCLUDED
#define SPRITESHEET_CLASS_H_INCLUDED

#include "load_img.h"

class Spritesheet


    public:
        void SetTex( GLuint Tex, int ImgW, int ImgH, int HorzAm, int VertAm );

        void DrawSprite( int spriteNum, int xLoc, int yLoc, int width, int height );

    private:
        GLuint Texture;
        int imageWidth, imageHeight, horiAm, vertAm;

;

void Spritesheet::SetTex( GLuint Tex, int ImgW, int ImgH, int HorzAm, int VertAm )


    imageWidth = ImgW;
    imageHeight = ImgH;
    horiAm = HorzAm;
    vertAm = VertAm;

    Texture = Tex;



void Spritesheet::DrawSprite( int spriteNum, int xLoc, int yLoc, int width, int height )


    glEnable( GL_TEXTURE_2D );

    glBindTexture( GL_TEXTURE_2D, Texture );

    glBegin( GL_QUADS );

        glTexCoord2f( 1.0f, 0.0f );
        glVertex2f( xLoc, yLoc );

        glTexCoord2f( 1.0f, 1.0f );
        glVertex2f( xLoc, yLoc+height );

        glTexCoord2f( 0.0f, 1.0f );
        glVertex2f( xLoc+width, yLoc+height );

        glTexCoord2f( 0.0f, 0.0f );
        glVertex2f( xLoc+width, yLoc );

    glEnd();

    glDisable( GL_TEXTURE_2D );



#endif // SPRITESHEET_CLASS_H_INCLUDED

最后,如果你需要这个,这里是处理 LoadImage 函数的文件,我用它来加载和格式化纹理。

#ifndef LOAD_IMG_H_INCLUDED
#define LOAD_IMG_H_INCLUDED

#include <iostream>
#include <stbimg.h>
#include <string>

bool loadCorrectly = true;

using namespace std;

GLuint LoadTexture( const char *filename, int w, int h, int n )


    unsigned char *data = stbi_load( filename, &w, &h, &n, 4 );
    GLuint texture;

    if( data == NULL )
    

        cout << "ERROR: '"<< filename << "' HAS BEEN MODIFIED OR IS MISSING." << endl;
        return 0;

    else
    

        cout << "Loaded: '" << filename << "' successfully." << endl;

    

    glGenTextures( 1, &texture );
    glBindTexture( GL_TEXTURE_2D, texture );
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT );

    gluBuild2DMipmaps( GL_TEXTURE_2D, 3, w, h,GL_RGBA, GL_UNSIGNED_BYTE, data );

    free( data );

    return texture;

编辑:我发现了问题。我的图像不是两个正方形,因此无法正常显示。

【问题讨论】:

我几天前遇到了这个问题。我通过将图像上下颠倒解决了这个问题,但我想知道它为什么会发生...... 是的,我在考虑走那条路。不过说实话好像有点草率哈哈。 【参考方案1】:

您的图像被翻转是因为您没有翻转它们以正确定位。这听起来是重言式,但是 OpenGL 的坐标系统将纹理向下映射到左下角的 (0,0) 和右上角的 (1,1)。解决这个问题是教科书式的练习。

您需要调用glActiveTexture(GL_TEXTURE0) 以使后续的gl* 调用知道他们正在修改哪个纹理(即激活该纹理)。初始值是GL_TEXTURE0,但我还是把它放进去,这样你就不会遇到潜在的问题。

我知道这不是您的问题的一部分,但您使用的 OpenGL 代码已被弃用 7 年。作为一般建议,您应该切换到可编程管道。 Here's a link to ogldev 现代 OpenGL 的基础知识,或者至少其中一些是 4.0+。有些在 3 中,但着色器比 FFP 更好。 Here's another short few from Swiftless。基本上搜索 OpenGL 4.0 或更高版本,Google 会指导您。这是一个更陡峭的学习曲线,但它是值得的。

【讨论】:

关于最后一件事,您能详细说明一下吗?我意识到我使用的东西可能已经过时了,但老实说,这是我能找到的唯一有好的入门教程的东西。你能给我一些正确方向的指示吗?非常感谢! 旧评论,但对于那些可能也在搜索的人来说,以下网站有我见过的最好的现代 opengl 教程,没有之一:learnopengl.com,阅读这些后,现代 opengl 似乎要容易得多比以前看起来更强大。 老实说,我必须先学习 webgl,然后将这些知识移植到 opengl。信息更好。强烈推荐 Webgl2fundamentals.com。如果您对任何事情感到困惑,请查看“状态图”。它显示了示例程序和 gl 状态机内部发生的事情的可视化。即使用 C 编程,也能节省宝贵的时间!【参考方案2】:

我只在 DDS (DXT) 文件中遇到过这种情况,其中需要翻转块以防止它们倒置。我必须在代码中执行此操作,但另一种方法是在图像程序中简单地翻转图像。

老实说,我在 OpenGL 中不使用 PNG 文件,而且我认为我上次使用 PNG 是在不久前的 XNA 中。

我在这里找到了这个:Flipping OpenGL texture 这是一种不同的语言,但你们似乎都有同样的问题。

我也会研究一下这个函数,看看它是否能够翻转数据

stbi_load( filename, &w, &h, &n, 4 );

要么这样,要么你必须自己做或使用其他东西来导入 PNG 图像。

我确实注意到该链接上的答案表明您可以在渲染期间使用 glMatrixMode(GL_TEXTURE) 翻转矩阵,但我想这不是您想要做的事情。

祝你好运。

【讨论】:

以上是关于OpenGL纹理渲染颠倒和模糊的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL:只模糊纹理的一部分;可以使用顶点着色器加速吗?

◮OpenGL-帧缓冲

◮OpenGL-帧缓冲

OpenGL渲染白色纹理错误

使用现代 OpenGL 渲染纹理

opengl 纹理无法正确渲染