使用OpenGL 4.x中的1D纹理进行纹理映射

4

我想使用一维纹理(颜色坡度)来给一个简单的三角形贴图。

enter image description here

我的片元着色器代码如下:

#version 420

uniform sampler1D           colorRamp;
in float height;

out vec4 FragColor;

void main()
{
   FragColor = texture(colorRamp, height).rgba;
}

我的顶点着色器如下:

#version 420

layout(location = 0) in vec3 position;

out float height;

void main()
{
    height = (position.y + 0.75f) / (2 * 0.75f);
    gl_Position = vec4( position, 1.0);
}

绘制三角形时,我按照以下方式进行操作(为了更好的可读性,我从代码中删除了错误检查):

glUseProgram(program_);

GLuint samplerLocation = glGetUniformLocation(program_, name.toCString());
glUniform1i(samplerLocation, currentTextureUnit_);

glActiveTexture( GL_TEXTURE0 + currentTextureUnit_ );
glBindTexture(GL_TEXTURE_1D, textureId);

很遗憾,我的三角形只是黑色的。有什么解决办法吗?

我非常确定所分配的纹理填充了正确的数据,因为我使用glGetTexImage读取并检查了它。我需要调用其他函数来绑定和激活纹理吗?我几乎有着相同的2D纹理代码,那个可以工作。

当我按照这种方式更改着色器代码时:

#version 420

uniform sampler1D           colorRamp;
in float height;

out vec4 FragColor;

void main()
{
   FragColor = vec4(height, height, height, 1.0); // change!
}

我得到了这个输出: 在此输入图片描述 我准备了一些演示源代码以重现错误。 源代码可以在这里找到。 它生成以下输出: 在此输入图片描述 这是创建1D纹理的方法,只有红色像素:
static GLuint Create1DTexture()
{
    GLuint textureId_;

    // generate the specified number of texture objects 
    glGenTextures(1, &textureId_);
    assert(glGetError() == GL_NO_ERROR);

    // bind texture
    glBindTexture(GL_TEXTURE_1D, textureId_);
    assert(glGetError() == GL_NO_ERROR);

    // tells OpenGL how the data that is going to be uploaded is aligned
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    assert(glGetError() == GL_NO_ERROR);

    float data[] =
    {
        1.0f, 0.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 0.0f, 1.0f
    };

    glTexImage1D(
        GL_TEXTURE_1D,      // Specifies the target texture. Must be GL_TEXTURE_1D or GL_PROXY_TEXTURE_1D.
        0,                  // Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.
        GL_RGBA32F,
        3*sizeof(float)*4,
        0,                  // border: This value must be 0.
        GL_RGBA,
        GL_FLOAT,
        data
    );
    assert(glGetError() == GL_NO_ERROR);

    // texture sampling/filtering operation.
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    assert(glGetError() == GL_NO_ERROR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    assert(glGetError() == GL_NO_ERROR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    assert(glGetError() == GL_NO_ERROR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    assert(glGetError() == GL_NO_ERROR);

    glBindTexture(GL_TEXTURE_1D, 0);
    assert(glGetError() == GL_NO_ERROR);

    return textureId_;
}

纹理绑定是这样进行的:
GLuint samplerLocation = glGetUniformLocation(rc.ToonHandle, "ColorRamp");
glUniform1i(samplerLocation, 0);
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_1D, rc.texure1d);

1
同时显示顶点着色器。它是否正确设置了“height”?你确定你传递的是标准化高度吗?此外,我建议使用.rgba,这样更清楚地表明你正在谈论纹理/颜色。 - Bartek Banachewicz
2
你可能会做错太多事情。纹理是否完整?坐标确定无误吗?你尝试过通过“绘制高度”来解决问题吗?例如,在0和1之间分配不同的红色阴影,而在该范围之外使用绿色。GL_KHR_debug报告了什么? - peppe
@BartekBanachewicz 我已根据您的建议更改了发布位置! - Vertexwahn
@peppe GL_KHR_debug 只报告了一个通知,似乎与这个问题无关(它报告说一个顶点缓冲区被创建在视频内存中)。 - Vertexwahn
我提供了一个“最小化”的演示,以重现错误。该演示使用GL 3.x,但我认为与GL 4.x没有太大区别。 - Vertexwahn
1个回答

2

发现了一个bug:

glTexImage1D(
  GL_TEXTURE_1D,    // Specifies the target texture. Must be GL_TEXTURE_1D or GL_PROXY_TEXTURE_1D.
  0,          // Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.
  GL_RGBA32F,
  3/*3*sizeof(float)*4*/,  // bug fix!!!!
  0,          // border: This value must be 0.
  GL_RGBA,
  GL_FLOAT,
  data
);

1
是的,第四个参数是纹理的像素宽度。看起来您将其与字节大小混淆了。 - glampert
在我的实际应用中,这个错误并没有发生 - 我在真实应用中使用采样器对象,似乎1D纹理不适用于所有类型的采样器对象。 - Vertexwahn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接