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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 22:45:02