使用 SOIL 的 OpenGL 纹理

Posted

技术标签:

【中文标题】使用 SOIL 的 OpenGL 纹理【英文标题】:OpenGL Texturing with SOIL 【发布时间】:2016-05-22 06:26:03 【问题描述】:

我正在使用 openGL 构建一个篮球游戏,但是我正在采取婴儿步骤并将我的工作分成几个部分。我目前专注于纹理,尝试使用 SOIL 库建造房屋。

我对所有这一切都非常陌生,所以我可能设置错误,但我的主要问题是纹理的行为就像它们被夹在我所看到的边缘一样。

目前该项目是一堵用砖块纹理的奇异墙,这是我得到的输出图像: Texture Fail

这里是源代码:

#include <stdlib.h>
#include <GL/glut.h>
#include <SOIL.h>
#include <stdio.h>

float _angle = 0.0;
GLuint _textureBrick;

static void resize(int width, int height)

    const float ar = (float) width / (float) height;
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-ar, ar, -1.0, 1.0, 1.0, 100.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


void renderScene(void)


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);

    // Front side brick wall
    glPushMatrix();
        glBindTexture(GL_TEXTURE_2D, _textureBrick);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTranslatef(0,0,-6);
        glRotatef(_angle, 0.0, 1.0, 0.0);
        glBegin(GL_QUADS);  // Wall
            glTexCoord3f(-50.0,2.0,0.1);  glVertex3f(-50,0,1);
            glTexCoord3f(50.0,2.0,0.1);  glVertex3f(50,0,1);
            glTexCoord3f(50.0,0.0,0.1);  glVertex3f(50,-1.5,1);
            glTexCoord3f(-50.0,0.0,0.1);  glVertex3f(-50,-1.5,1);
        glEnd();
    glPopMatrix();

    glutSwapBuffers();


void mySpecialFunc(int key, int x, int y)
    switch (key) 
    case GLUT_KEY_RIGHT:
        _angle += 1;
        if (_angle > 360) _angle = 0.0;
        break;
    case GLUT_KEY_LEFT:
        _angle -= 1;
        if (_angle > 360) _angle = 0.0;
        break;
    
    glutPostRedisplay();


GLuint loadTex(const char* texname)

    GLuint texture = SOIL_load_OGL_texture
                    (
                        texname,
                        SOIL_LOAD_AUTO,
                        SOIL_CREATE_NEW_ID,
                        SOIL_FLAG_INVERT_Y

                    );

    if( 0 == texture )
    
        printf( "SOIL loading error: '%s'\n", SOIL_last_result() );
    

    //glBindTexture(GL_TEXTURE_2D, texture);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    return texture;


void Initialize() 
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-100.0, 100.0, -100.0, 100.0, -100.0, 100.0);

    //_textureFloor = loadTex("C:\\Users\\Mikle\\OneDrive\\Uni work\\Second Year\\Projects\\3D-House-using-OpenGL-and-C--master\\court.png");

    _textureBrick = loadTex("C:\\Users\\Mikle\\OneDrive\\Uni work\\Second Year\\Projects\\3D-House-using-OpenGL-and-C--master\\bricks.bmp");


int main(int argc, char **argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowPosition(0,0);
    glutInitWindowSize(600,600);
    glutCreateWindow("Textured House");
    glEnable(GL_DEPTH_TEST);

    glutReshapeFunc(resize);
    glutSpecialFunc(mySpecialFunc);
    glutDisplayFunc(renderScene);
    Initialize();

    glutMainLoop();

    return 0;

任何帮助将不胜感激,谢谢!

【问题讨论】:

如果您刚开始使用 OpenGL,使用旧的已弃用 API 并不是最好的方法 ;) 去学习现代可编程 OpenGL。 很遗憾,我的大学课程不允许这样做。 图像看起来需要添加 GL_TEXTURE_WRAP 参数以及 MIN/MAG 过滤器。我一直在关注Learn Opengl,他们对我很有帮助。 @Jere 我尝试将我的 renderScene 函数中的 TexParameters 更改为具有 TEXTURE_WRAP 以及尝试 GL_REPEAT 但没有任何变化。 我没有使用你用来加载和创建纹理的 SOIL 函数,我用它来加载数据然后我做了创建纹理的工作。也许该函数中的某些东西正在影响正在发生的事情? 【参考方案1】:

迈克尔。为了生成 mipmap 并可能修复纹理,您应该将土壤加载函数的参数更改为

GLuint texture = SOIL_load_OGL_texture
                (
                    texname,
                    SOIL_LOAD_AUTO,
                    SOIL_CREATE_NEW_ID,
                    SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT

                );

这将自动从 OpenGL 库生成 mipmap,因为您之后没有调用 glGenerateMipmaps()。它还节省了存储纹理所需的内存。纹理钳位和包裹的另一个建议是使用

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

使用加载功能后。祝您的 OpenGL 学习体验好运。我希望这对您有所帮助。

编辑:

您也不应该在每一帧都重复 glTexParameteri。这会给您(或用户)的 CPU 带来过多和不必要的压力。

【讨论】:

以上是关于使用 SOIL 的 OpenGL 纹理的主要内容,如果未能解决你的问题,请参考以下文章

opengl-soil 第一次尝试放置纹理

OpenGL纹理弯曲[重复]

如何使用 FreeImage 库将纹理加载到 OpenGL?

OpenGL纹理不会绘制

使用现代 OpenGL 渲染纹理

GLUT OpenGL Cube 拉伸错误