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
相关产品推荐
相关产品推荐

