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

采样3D纹理生成2D图像无输出,请求问题排查

3D纹理平面采样无渲染输出问题排查

问题背景

我需要将标量场的值映射为3D纹理(image_texture),并沿给定平面gPlaneParams渲染该纹理。实现思路是向着色器传递覆盖窗口的4个顶点(构成两个三角形),在片段着色器中通过采样器绑定3D纹理,计算平面上的采样坐标并完成采样。但目前没有任何渲染输出,请求帮忙排查问题。

实现代码

片段着色器代码

#version 330 core
uniform sampler3D text_sampler;
uniform vec4 gPlaneParams;

in vec4 inPos;

void main()
{
    vec4 Pos = inPos;
    // 输入位置是[-1,1]^2的正方形
    // 需要映射到平面ax+by+cz=d,a,b,c,d为平面参数
    // x,y,z属于[0,1]^3
    if (gPlaneParams.z!=0){
        Pos.z = (gPlaneParams.w - gPlaneParams.x*Pos.x - gPlaneParams.y*Pos.y)/gPlaneParams.z;
    }
    else{
        if (gPlaneParams.x!=0){
            Pos.z=Pos.x;
            Pos.x = (gPlaneParams.w - gPlaneParams.y*Pos.y - gPlaneParams.z*Pos.z)/gPlaneParams.x;
        }
        else if (gPlaneParams.y!=0){
            Pos.z=Pos.y;
            Pos.y = (gPlaneParams.w - gPlaneParams.x*Pos.x - gPlaneParams.z*Pos.z)/gPlaneParams.y;
        }
    }

    gl_FragColor=vec4(1.0,0,0,0)*texture3D(text_sampler,(Pos.xyz+1)/2);

}

C++纹理绑定代码

glGenTextures(1,textureID);
glBindTexture(GL_TEXTURE_3D,textureID[0]);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB,object_size[0],object_size[1],object_size[2], 0, GL_RGB, GL_UNSIGNED_INT, image_texture1);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D,textureID[0]);
bool err=glIsTexture(textureID[0]);
cout<<"Texture bound?"<<err<<endl;

Uniform绑定代码

gSamplerLocation = glGetUniformLocation(ShaderProgram, "text_sampler");
gPLaneLoc = glGetUniformLocation(ShaderProgram, "gPlaneParams");
glUniform1i(gSamplerLocation, 0);    
glUniform4f(gPLaneLoc,plane_params[0],plane_params[1],plane_params[2],plane_params[3]);

已确认正常项

  • 4个顶点和两个三角形已正确绑定(可通过纯色渲染验证)
  • 图像纹理内存连续:image_texture = (unsigned int*) malloc(object_size[0] *object_size[1] *object_size[2]*3* sizeof(unsigned int));
  • 所有着色器输入已成功绑定

排查方向

  1. Alpha通道完全透明:当前gl_FragColor的alpha值设为0,会导致片段完全透明无法显示。需将alpha改为1.0,比如vec4(1.0,0,0,1.0),或根据纹理数据设置合理的alpha值。
  2. 纹理数据格式不匹配:glTexImage3D中指定类型为GL_UNSIGNED_INT,但如果你的纹理数据是0-255的常规颜色值,应该用GL_UNSIGNED_BYTE。使用GL_UNSIGNED_INT会让采样得到远大于1的数值,最终采样结果为0。
  3. 采样坐标超出有效范围:计算得到的(Pos.xyz+1)/2可能不在3D纹理的[0,1]^3采样区间内。可以在着色器中添加坐标校验,比如坐标越界时输出红色,验证坐标有效性:
    vec3 uv = (Pos.xyz + 1)/2;
    if(uv.x < 0.0 || uv.x > 1.0 || uv.y <0.0 || uv.y>1.0 || uv.z<0.0 || uv.z>1.0){
        gl_FragColor = vec4(1,0,0,1);
        return;
    }
    gl_FragColor=vec4(1.0,1.0,1.0,1.0)*texture3D(text_sampler, uv);
    
  4. 平面映射逻辑错误:当平面法向量z分量为0时,强行将Pos.z替换为Pos.x或Pos.y不符合平面方程逻辑。此时平面平行于z轴,需明确3D纹理空间中z坐标的取值规则(比如固定值或映射关系),否则会生成错误的采样坐标。
  5. OpenGL错误检查:在纹理创建、绑定、着色器操作后调用glGetError(),排查是否有未捕获的OpenGL错误,比如纹理维度非法、数据指针为空等。
  6. 着色器编译链接校验:打印着色器编译日志和程序链接日志,确认没有语法或链接错误,避免因着色器失效导致无输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:10:32