OpenGL glTextureStorage2D报错 地面纹理缺失错位显示异常求助
问题排查&修复方案
核心问题1:纹理加载逻辑错误
你的代码写了两层嵌套循环:外层遍历2个纹理文件名,内层又遍历2个纹理ID。这会导致每一张加载的图片都会覆盖两个纹理对象的所有数据,最终两个纹理都存的是最后加载的wood.jpg内容,根本拿不到地面用的Green.jpg纹理。
核心问题2:像素格式不匹配导致纹理错位
你没有判断stbi_load返回的图片通道数,硬编码GL_RGB作为上传格式:如果加载的图片是带透明通道的4通道(RGBA)图片,像素对齐错误会直接导致纹理显示错位、颜色异常。
核心问题3:API调用冲突&参数错误
- 调用
glTextureStorage2D时指定了mipmap层级为1(只有基础层),后续又调用glGenerateMipmap生成mipmap属于无效操作 - 纹理参数重复设置了两次
GL_TEXTURE_MIN_FILTER,遗漏了GL_TEXTURE_MAG_FILTER的配置 - stbi_load加载的纹理数据没有释放,存在内存泄漏
核心问题4:着色器和CPU侧uniform配置不匹配
- CPU侧代码要获取的uniform名是
texture[i],但片元着色器里的采样器命名是tex,根本找不到对应uniform,采样器配置无效 - 片元着色器只定义了1个绑定到0点的采样器,CPU侧绑了两个纹理也不会生效,且多模型渲染时没有在绘制前切换对应纹理
- 你写的
glGetUniformLocation(program, "texture[i]")是错误写法,字符串里的i不会被自动替换成数字,永远返回-1
修正后的代码
1. 纹理加载部分
Ground.LoadModel("O_Ground.obj"); Fence.LoadModel("O_Fence.obj"); string names[] = {"Green.jpg", "wood.jpg"}; glGenTextures(2, texture); stbi_set_flip_vertically_on_load(true); // 全局设置只需要调用一次,不用放循环里 for (int i = 0; i < 2; i++) { int iWidth, iHeight, iChannels; unsigned char* iData = stbi_load(names[i].c_str(), &iWidth, &iHeight, &iChannels, 0); if (!iData) { cout << "纹理加载失败:" << names[i] << endl; continue; } GLenum format = (iChannels == 4) ? GL_RGBA : GL_RGB; GLenum internalFormat = (iChannels == 4) ? GL_RGBA8 : GL_RGB8; glBindTexture(GL_TEXTURE_2D, texture[i]); // 如果要生成mipmap,levels参数改成对应层级数即可,比如4级就写4 glTextureStorage2D(texture[i], 1, internalFormat, iWidth, iHeight); glTextureSubImage2D(texture[i], 0, 0, 0, iWidth, iHeight, format, GL_UNSIGNED_BYTE, iData); cout << "生成纹理ID:" << texture[i] << endl; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 如果glTextureStorage2D的levels设为1,不需要调用glGenerateMipmap,否则levels要填对应层级数 // glGenerateMipmap(GL_TEXTURE_2D); stbi_image_free(iData); // 释放加载的图片内存 }
2. 渲染部分
当前片元着色器只有一个采样器,无需提前绑定两个纹理,绘制哪个模型就绑定对应纹理即可:
// 绘制地面,绑定第一个纹理 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture[0]); GLint tex_loc = glGetUniformLocation(program, "tex"); glUniform1i(tex_loc, 0); Ground.Draw(); // 绘制栅栏,绑定第二个纹理 glBindTexture(GL_TEXTURE_2D, texture[1]); Fence.Draw();
3. 片元着色器保持原样即可,若需要同时用两个纹理再改成采样器数组:
out vec4 color; in VS_OUT { vec2 tc; vec3 normals; } fs_in; // 单采样器保持当前配置即可 layout(binding=0)uniform sampler2D tex; void main(void) { color = texture(tex, fs_in.tc); }
内容的提问来源于stack exchange,提问作者Sara
相关产品推荐
相关产品推荐

