简体   繁体   中英

How to use GL_TEXTURE_2D_ARRAY with stb_image

I'm trying to create sprite animation with texture array. Right now I have follow code:

int width, height, depth;
stbi_set_flip_vertically_on_load(true);
byte_t* buffer = stbi_load(R"(.\fire.jpg)",
                                   &width, &height, &depth, STBI_rgb_alpha);
if (buffer == nullptr) {
    std::cerr << "Could not read texture" << std::endl;
    return EXIT_FAILURE;
}
GLuint texture_id;
const GLenum target = GL_TEXTURE_2D_ARRAY;
SAFE_CALL(glGenTextures(1, &texture_id));
SAFE_CALL(glBindTexture(target, texture_id));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 1));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
SAFE_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));

const GLsizei tile_w_count = 6, tile_h_count = 6;
const GLsizei total_tiles = tile_w_count * tile_h_count;
const GLsizei tile_w = width / tile_w_count,
              tile_h = height / tile_h_count;
std::cout << "Texture WxH: " << width << "x" << height;
std::cout << ", Tile WxH: " << tile_w << "x" << tile_h << std::endl;
SAFE_CALL(glTexStorage3D(target, 1, GL_RGBA8, tile_w, tile_h,
                         total_tiles));

SAFE_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, width));
SAFE_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, height));
for (GLsizei i = 0; i < total_tiles; ++i) {
    SAFE_CALL(glTexSubImage3D(
        GL_TEXTURE_2D_ARRAY,
        0,
        0, 0, i,
        tile_w, tile_h, 1,
        GL_RGBA,
        GL_UNSIGNED_BYTE,
        buffer + (i * tile_w * tile_h * depth)
    ));
}

Fragment shader:

#version 460 core

in vec2 tex_coords;
out vec4 frag_color;

uniform sampler2DArray texture_0;

uniform int current_frame;
uniform int total_frames;

float actual_layer() {
    return max(0, min(total_frames - 1,
                      floor(current_frame + 0.5)));
}

void main() {
    frag_color = texture(texture_0, vec3(tex_coords, actual_layer()));
}

And seems like I incorrectly crop source texture, because when I run my program in Nsight debugger I saw follow:

Texture array:

纹理数组

Original image:

原始图像

Is it issue with cropping source image, or issue with fragment shader? How to make sprite animation correctly?

You calculate the data offset incorrectly. The correct way would be:

Convert i to a 2-d index of the tile:

int ix = i % tile_w_count;
int iy = i / tile_w_count;

The x and y coordinates of its top-left pixel would be at

int x = ix*tile_w;
int y = iy*tile_h;

The offset can be calculated then by:

buffer + 4*(y*width + x)

Note that you shall use 4 instead of depth because stb returns the number of channels that was found in the file rather the number of the channels returned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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