You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL构建2D纹理数组触发段错误,请求排查问题

问题排查与修复

核心问题分析

你的BuildTextureArray函数存在以下直接导致段错误和潜在隐患的缺陷:

1. 未检查图片加载结果

stbi_load若加载失败(如路径错误、文件损坏)会返回nullptr,直接将空指针传入glTexSubImage3D会触发内存访问错误(段错误)。

2. 未释放图片加载内存

stbi_load分配的内存未通过stbi_image_free释放,会造成内存泄漏。

3. 纹理内部格式不明确

调用glTexImage3D时使用GL_RGBA作为内部格式,应明确指定GL_RGBA8(表示每个通道8位),避免不同OpenGL驱动的默认行为差异。

4. 未验证后续图片尺寸

虽你说明两张图均为1024x1024,但函数未验证后续图片尺寸是否与第一张一致,若尺寸不符会导致OpenGL错误甚至崩溃。

修复后的BuildTextureArray函数

uint32_t BuildTextureArray(const std::vector<std::string>& paths) {
    if (paths.empty()) {
        return 0; // 空路径列表直接返回
    }

    int width, height, channels;
    stbi_set_flip_vertically_on_load(1);
    uint8_t* data_of_first = stbi_load(paths[0].c_str(), &width, &height, &channels, 4);
    
    if (!data_of_first) {
        std::cerr << "Failed to load texture: " << paths[0] << std::endl;
        return 0;
    }

    uint32_t array_id;
    glGenTextures(1, &array_id);
    glBindTexture(GL_TEXTURE_2D_ARRAY, array_id);
    
    // 使用GL_RGBA8明确内部格式
    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, width, height, paths.size(), 0, 
                 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);

    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // 添加纹理环绕参数,避免默认值可能的问题
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, 1, 
                    GL_RGBA, GL_UNSIGNED_BYTE, data_of_first);
    stbi_image_free(data_of_first); // 释放第一张图的内存

    for (size_t i = 1; i < paths.size(); ++i) {
        int curr_width, curr_height;
        uint8_t* data = stbi_load(paths[i].c_str(), &curr_width, &curr_height, nullptr, 4);
        
        if (!data) {
            std::cerr << "Failed to load texture: " << paths[i] << std::endl;
            continue; // 加载失败跳过,或根据需求处理
        }

        if (curr_width != width || curr_height != height) {
            std::cerr << "Texture size mismatch: " << paths[i] << " expected " 
                      << width << "x" << height << ", got " << curr_width << "x" << curr_height << std::endl;
            stbi_image_free(data);
            continue;
        }

        glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, static_cast<int>(i), width, height, 1, 
                        GL_RGBA, GL_UNSIGNED_BYTE, data);
        stbi_image_free(data); // 释放当前图的内存
    }

    return array_id;
}

额外需要修复的着色器问题

你的顶点着色器中,a_texindex的输入位置被错误设置为0,与a_pos的位置冲突,导致纹理索引无法正确传递:

// 错误代码
layout(location = 0) in vec3 a_pos;
layout(location = 1) in vec2 a_texcoord;
layout(location = 0) in float a_texindex; // 位置0重复,会覆盖a_pos

应修正为:

// 正确代码
layout(location = 0) in vec3 a_pos;
layout(location = 1) in vec2 a_texcoord;
layout(location = 2) in float a_texindex; // 对应C++代码中设置的位置2

内容的提问来源于stack exchange,提问作者milanHrabos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:32:00