简体   繁体   English

使用SOILs OGL函数和OpenGL加载纹理

[英]Loading texture using SOILs OGL function and OpenGL

I have a function to load a texture from a JPEG image using SOIL. 我有一个使用SOIL从JPEG图像加载纹理的功能。

So far I have been loading the texture with the SOIL_load_image() function and then supplying the image to OpenGL using glTexImage2D (see code below). 到目前为止,我一直在使用SOIL_load_image()函数加载纹理,然后使用glTexImage2D将图像提供给OpenGL(参见下面的代码)。 However! 然而! My textures is upside down, so I wanted to use the SOIL_load_OGL_texture() instead and supply the SOIL_FLAG_INVERT_Y in order to flip the images. 我的纹理是颠倒的,所以我想使用SOIL_load_OGL_texture()代替并提供SOIL_FLAG_INVERT_Y以翻转图像。 My problem is though, that I get an unhandled exception at the SOIL_load_OGL_texture() function. 我的问题是,我在SOIL_load_OGL_texture()函数中得到一个未处理的异常。

The code is almost a copy paste from the documentation, so I don't understand why this error occurs? 代码几乎是文档中的复制粘贴,所以我不明白为什么会出现这个错误?

(NOTE: I could invert the textures in my vertex shader, but I would like to use SOIL.) (注意:我可以在顶点着色器中反转纹理,但我想使用SOIL。)

The old way 旧的方式

int width;
int height;

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);

image = SOIL_load_image(filename, &width, &height, 0, SOIL_LOAD_RGB);

if (image == NULL) {
    std::cout << "An error occurred while loading image." << std::endl;
    exit(EXIT_FAILURE);
}
std::cout << "Loaded first texture image" << std::endl;

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);

What I am trying now 我现在在尝试什么

GLuint image;

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);

image = SOIL_load_OGL_texture(
        filename,
        SOIL_LOAD_RGB,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_INVERT_Y
    );

if (image == 0)
    cerr << "SOIL loading error: '" << SOIL_last_result() << "' (" << "res_texture.png" << ")" << endl;

And the error 而错误

Unhandled exception at 0x0F5427FF (msvcr110d.dll) in AnotherTutorial.exe: 0xC0000005: Access violation reading location 0x00000000.

Seems like there is no answer to using SOIL, so i'll post my solution: 似乎没有使用SOIL的答案,所以我将发布我的解决方案:

In the vertex shader I do: 在顶点着色器中我做:

Texcoord = vec2(texcoord.x, 1.0-texcoord.y);
gl_Position = proj * view * model * vec4( position, 1.0 );

The 1.0-texcoord.y inverts the y-axis of the image. 1.0-texcoord.y反转图像的y轴。 Not as clean a solution, but it works. 不是一个干净的解决方案,但它的工作原理。

void loadTexture(GLuint* texture, char* path){
    *texture = SOIL_load_OGL_texture(filename,
                                     SOIL_LOAD_AUTO,
                                     SOIL_CREATE_NEW_ID,
                                     SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_MULTIPLY_ALPHA
                                    );
    if(*textre == NULL){
        printf("[Texture loader] \"%s\" failed to load!\n", filename);
    }
}

void drawTexturedRect(int x, int y, int w, int h, GLuint texture){
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDepthMask(GL_FALSE);
    glDisable(GL_DEPTH_TEST);
    glBegin(GL_QUADS);
        glColor3f(255,255,255);
        glTexCoord2f(0,0);
        glVertex2f(x,y);
        glTexCoord2f(1,0);
        glVertex2f(x+w,y);
        glTexCoord2f(0,1);
        glVertex2f(x,y+h);
        glTexCoord2f(1,1);
        glVertex2f(x+w,y+h);
        glTexCoord2f(0,1);
        glVertex2f(x,y+h);
    glEnd();
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glDisable(GL_BLEND);
}

And then you can do: 然后你可以这样做:

// At initialization
GLuint texture;
loadTexture(&texture, "filename.png");

// Drawing part
drawTexturedRect(25,25,256,256,texture);

This is what I personally use, and it works perfectly. 这是我个人使用的,它完美无缺。 I'm using Visual Studio 2012 combined with SDL and SOIL. 我正在使用Visual Studio 2012结合SDL和SOIL。

SOIL_load_image will return unsigned char* yes, array holding your image data. SOIL_load_image将返回unsigned char* yes,包含图像数据的数组。

Then you will normally feed this data to gl using glGenerateTextures , assign texture IDs, calling glTexImage2D . 然后你通常会使用glGenerateTextures将这些数据提供给gl ,分配纹理ID,调用glTexImage2D

SOIL_load_OGL_texture returns a texture id, so you could do this instead: SOIL_load_OGL_texture返回纹理ID,因此您可以这样做:

texture[0] = SOIL_load_OGL_texture(...)

if your goal is to load textures 0,1,2. 如果你的目标是加载纹理0,1,2。

As for invert y, the easiest and weight free solution is to flip the texture coordinates in glTexCoord , but it depends on what you are doing. 对于反转y,最简单且无重量的解决方案是在glTexCoord翻转纹理坐标,但这取决于你在做什么。 If you are loading resources as a one time only operation or like, it can't hurt, except some startup time probably not worth mentioning. 如果您只是将资源作为一次性操作或类似操作,那么它不会受到伤害,除非一些启动时间可能不值得一提。 But if you're loading resources dynamically through the main loop when needed, then invert y flag (and about any flag), can hurt performance because of additional processing throughout your entire program. 但是如果你在需要时通过主循环动态加载资源,那么反转y标志(以及任何标志)会因为整个程序中的额外处理而损害性能。

One big advantage to using SOIL_load_image is that you can retrieve width, height and channel number from the original image which SOIL_load_OGL_texture doesn't provide. 使用SOIL_load_image一大优点是,您可以从SOIL_load_OGL_texture未提供的原始图像中检索宽度,高度和通道编号。

If it helps, SOIL_load_OGL_texture would crash after a while when loading RGB images as RGB but worked fine all the way with SOIL_LOAD_RGBA , that could be a fix to your problem. 如果它有帮助, SOIL_load_OGL_texture会在一段时间后将RGB图像加载为RGB但在使用SOIL_LOAD_RGBA一直正常工作时会崩溃,这可能会解决您的问题。

I still find it easier with SOIL_load_image . 我仍然觉得使用SOIL_load_image更容易。 I hope any of this helps. 我希望这有助于此。 Also check the SOIL source code that ships with soil to see what's going on. 还要检查土壤附带的SOIL源代码,看看发生了什么。

Basically, in the command 基本上,在命令中

SOIL_load_image(filename, &width, &height, 0, SOIL_LOAD_RGB);

the 0 (NULL) you are passing is a pointer to the channels set by the library, so, of course, when the library tries to access it you have: 您传递的0(NULL)是指向库设置的通道的指针,因此,当库试图访问它时,您有:

Unhandled exception at 0x0F5427FF (msvcr110d.dll) in AnotherTutorial.exe: 0xC0000005: Access violation reading location 0x00000000 AnotherTutorial.exe中0x0F5427FF(msvcr110d.dll)的未处理异常:0xC0000005:访问冲突读取位置0x00000000

Try declaring a variable and using it: 尝试声明变量并使用它:

int channels;
SOIL_load_image(filename, &width, &height, &channels, SOIL_LOAD_RGB);

None of the solution above works for me. 以上解决方案都不适合我。 I have same problem just now, like the following one: 我刚才遇到同样的问题,如下所示:

SOIL_load_OGL_texture Unhandled exception at xxxxxx (msvcr120d.dll)

After reading solution at http://www.idevgames.com/forums/thread-10281.html , i changed my path from "relative path" to "absolute path". http://www.idevgames.com/forums/thread-10281.html上阅读解决方案后,我将路径从“相对路径”改为“绝对路径”。

BTW, And since I am Chinese, i need to make sure that the path is ALL ENGLISH without non-ascii characters. 顺便说一句,既然我是中国人,我需要确保路径是全英文,没有非ascii字符。

For example: 例如:

I change my code from 我改变了我的代码

SOIL_load_OGL_texture("my_texture.bmp",
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_MULTIPLY_ALPHA
        );

to

SOIL_load_OGL_texture("D:\temp_20160926\ConsoleApplication20\ConsoleApplication19\my_texture.bmp",
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_MULTIPLY_ALPHA
        );

And it solve my problem perfectly. 它完美地解决了我的问题。

I think this is a bug/restriction in SOIL. 我认为这是SOIL中的错误/限制。 But you can avoid this by specific the absolute path like i do here. 但是你可以通过像我这里所做的具体绝对路径来避免这种情况。

Hope it can help you too. 希望它也可以帮到你。

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

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