如何使用OpenGL阵列纹理? [英] How to use OpenGL Array Texture?

查看:89
本文介绍了如何使用OpenGL阵列纹理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在OpenGL中使用精灵表,通过数组纹理实现它.
这就是我加载纹理的方式:

I am trying to use sprite sheet in OpenGL, implementing it through Array Texture
This is how I load my texture:

QImage image;
image.load("C:\\QtProjects\\project\\images\\spritesheet.png", "png");
const unsigned char* data = image.bits();
int twidth = image.width(), theight = image.height();
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, twidth / 3, theight / 4, 12);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, twidth / 3, theight / 4, 12, GL_BGRA, GL_UNSIGNED_BYTE, data);
glUseProgram(scene_program);

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

这是我的片段着色器:

#version 330 core

in vec3 Color;
in vec2 Texture_coord;

out vec4 outColor;

uniform sampler2DArray tex;

void main()
{
    vec2 coord;
    coord.x = Texture_coord.x;
    coord.y = Texture_coord.y;

    vec4 color = texture(tex, vec3(coord, 0));

    outColor = color;
}

我正在将其绘制到一个角上纹理坐标为(0.0, 0.0)且另一个角为(1.0, 1.0)的四边形上,因此我希望从四边形的第一行获得第一个精灵.
但是我得到了这张损坏的图像: http://i.stack.imgur.com/bfXgr. jpg
这是整个Sprite工作表: http://i.stack.imgur.com/LaZKP.png

I am drawing it to the quad with texture coordinates (0.0, 0.0) in one corner and (1.0, 1.0) in other, so I expect to get a first sprite from first row on my quad.
But I get this corrupted piece of image: http://i.stack.imgur.com/bfXgr.jpg
This is whole sprite sheet: http://i.stack.imgur.com/LaZKP.png

P.S .:整个图像已正确加载,我可以显示它,或者它是传统GL_TEXTURE_2D

P.S.: whole image is loaded correctly, I can display it or it's part through traditional GL_TEXTURE_2D

推荐答案

我不认为问题与数组纹理直接相关.真正的问题在于您如何尝试将部分输入图像加载到纹理中:

I don't believe the problem is directly related to array textures. The real issue is in how you are trying to load part of your input image into a texture:

glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, twidth / 3, theight / 4, 12);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, twidth / 3, theight / 4, 12,
                GL_BGRA, GL_UNSIGNED_BYTE, data);

glTexSubImage3D()调用不知道您输入的图像有多大.它将简单地根据您作为参数传入的大小顺序读取图像数据.如果将其宽度设置为原始图像宽度的1/3,它将从输入图像的第一行读取3个纹理行,然后从图像的第二行读取另外3个纹理行,等等.

The glTexSubImage3D() call does not know how large your input image is. it will simply read your image data sequentially based on the sizes you pass in as parameters. If you give it width that is 1/3 of your original image width, it will read 3 texture rows from the first row of your input image, then another 3 texture rows from the second row of your image, etc.

您可以使用GL_UNPACK_ROW_LENGTH像素存储值指定输入行的大小(以像素为单位).对于您的情况,以下调用指定了输入图像的宽度:

You can specify the size of your input rows (in pixels) with the GL_UNPACK_ROW_LENGTH pixel storage value. For your case, the following call specifies the width of your input image:

glPixelStorei(GL_UNPACK_ROW_LENGTH, twidth);

我认为没有一种合理的方法可以通过一次glTexSubImage3D()调用将整个精灵表加载到数组纹理中.如果为每个图像分别调用,这可能是最简单的.整个过程将如下所示:

I don't think there's a reasonable way of loading your whole sprite sheet into the array texture with a single glTexSubImage3D() call. It's probably easiest if you make a separate call for each image. The whole thing will then look like this:

GLuint texId = 0;
glGenTextures(1, &texId);

glBindTexture(GL_TEXTURE_2D_ARRAY, texId);

glTexParameteri(GL_TEXTURE_2D_ARRAY, ...);

int subWidth = twidth / 3;
int subHeight = theight / 4;

glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, subWidth, subHeight, 12);

glPixelStorei(GL_UNPACK_ROW_LENGTH, twidth);

for (int iRow = 0; iRow < 4; ++iRow) {
    for (int iCol = 0; iCol < 3; ++iCol) {
        glTexSubImage3D(
            GL_TEXTURE_2D_ARRAY, 0,
            0, 0, 3 * iRow + iCol,
            subWidth, subHeight, 1,
            GL_BGRA, GL_UNSIGNED_BYTE,
            data + (iRow * subHeight * twidth + iCol * subWidth) * 4);
    }
}

您可以尝试通过使用其他解包参数(例如GL_UNPACK_IMAGE_HEIGHT)来避免单独调用,但是我不相信有适合这种情况的设置.

You could try to avoid the separate calls by using other unpack parameters like GL_UNPACK_IMAGE_HEIGHT, but I'm not convinced that there are settings that would work for this case.

这篇关于如何使用OpenGL阵列纹理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆