如何使用OpenGL阵列纹理?

时间:2014-08-17 14:09:49

标签: opengl textures texture2d

我正在尝试在OpenGL中使用精灵表,通过数组纹理实现它 这是我加载纹理的方法:

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
这是整个精灵表:http://i.stack.imgur.com/LaZKP.png

P.S。:正确加载整个图像,我可以通过传统的GL_TEXTURE_2D显示它或它的一部分

1 个答案:

答案 0 :(得分:3)

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

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个纹理行,等等。

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

glPixelStorei(GL_UNPACK_ROW_LENGTH, twidth);

我不认为通过一次glTexSubImage3D()调用将整个精灵表加载到数组纹理中是一种合理的方式。如果您为每张图片单独调用,这可能是最简单的。整件事情看起来像这样:

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)来避免单独调用,但我不相信有适用于此情况的设置。