GLSL 1.5 无法获得颜色输入

Posted

技术标签:

【中文标题】GLSL 1.5 无法获得颜色输入【英文标题】:GLSL 1.5 can't get color input 【发布时间】:2014-01-23 10:26:28 【问题描述】:

我只想在我的对象上使用一些不同的颜色做一个简单的 Gouraud 着色。基本上我的问题是,我无法将颜色值输入着色器,它只会呈现黑色。如果我在着色器中定义一个向量作为整个对象的颜色,它可以正常工作。

主程序:

protected void initOpenGL() 
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    startTime = Sys.getTime();

    m = new Matrix4f();
    m.m00 = 1;
    m.m11 = 1;
    m.m22 = -(101.0f / 99);
    m.m32 = -(200.0f / 99);
    m.m23 = -1;
    m.m33 = 0;

    makeCube();

    sp = new ShaderProgram("gouraud");
    glBindAttribLocation(sp.getId(), 0, "corners");
    glBindAttribLocation(sp.getId(), 1, "colors");



@Override
protected void render() 

    gamma = gamma + 1;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    Matrix4f newMat = new Matrix4f(m);
    Matrix4f.translate(new Vector3f(0, 0, -5), newMat, newMat);
    newMat.rotate(gamma/100, new Vector3f(0, 1, 0));
    newMat.rotate(gamma/200, new Vector3f(1, 0, 0));

    FloatBuffer fb = BufferUtils.createFloatBuffer(16);
    newMat.store(fb);
    fb.flip();
    GL20.glUniformMatrix4(GL20.glGetUniformLocation(sp.getId(), "matrix"),
            false, fb);

    GL20.glUseProgram(sp.getId());


    glBindVertexArray(vaoId);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glDrawArrays(GL_QUADS, 0, corners.length/3);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);
    glBindVertexArray(0);



private void makeCube()
    corners = new float[] 
            // cube
            // front
            -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1,
            // left
            -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1,
            // bottom
            -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1,
            // right
            1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1,
            // top
            -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1,
            // back
            -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,

    ;

    FloatBuffer eckenBuffer = BufferUtils.createFloatBuffer(corners.length);
    eckenBuffer.put(corners);
    eckenBuffer.flip();

    vaoId = glGenVertexArrays();
    glBindVertexArray(vaoId);
    int vboId = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glBufferData(GL_ARRAY_BUFFER, eckenBuffer, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);


    colors = new float[] 
            // front
            1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,

            // right
            1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,

            // back
            1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,

            // left
            0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,

            // top
            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,

            // bottom
            1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f ;

    FloatBuffer colorBuffer = BufferUtils.createFloatBuffer(colors.length);
    colorBuffer.put(colors);
    colorBuffer.flip();

    int vboIdB = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboIdB);
    glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

着色器:

顶点

#version 150
in vec4 corners;
in vec4 colors;

vec4 colorTest = vec4(1.0,0.0,0.0,1.0);

out vec4 colorToFrag;

uniform mat4 matrix;

void main(void) 
colorToFrag = colors ;
gl_Position = matrix * corners;


片段

#version 150
in vec4 colorToFrag;

out vec4 colorOut;

void main(void) 
colorOut = colorToFrag;

【问题讨论】:

不要在使用 VAO 绘制之前和之后启用/禁用属性数组。这实际上是 VAO 的全部意义所在。最初,当您创建 VAO 时,它会禁用所有阵列,您可以在创建 VAO 时启用您需要的阵列。然后,您所要做的就是在绘图之前立即更改绑定的 VAO。启用的数组集直接与绘制时绑定的任何 VAO 相关联。 这不会解决您的问题,但您应该注意这一点。 另外,你打电话给GL20.glUniformMatrix4(GL20.glGetUniformLocation(sp.getId(), "matrix"), 太早了。您需要在调用glUseProgram (...) 之后执行此操作。并且glGetUniformLocation (...) 不是你应该在每一帧都做的事情,在你链接你的程序之后计算这个索引,然后将值存储在你的类中,因为通过名称搜索一个统一的位置是非常低效的——它们不会改变。 【参考方案1】:

您没有发布着色器编译/链接的代码,但由于您在其余代码中调用了glBindAttribLocation,但没有调用glLinkProgram,我做出有根据的猜测,链接仅发生在ShaderProgram 构造函数。

glBindAttribLocation 调用只会影响它之后的任何链接操作(显然)。因此,您的位置绑定根本无效 - GL 分配它们。

现在如果你不在着色器中使用colors 属性,它会被优化掉并且该属性不会被激活——所以它根本不会得到任何位置,corners 很可能会得到索引0,正如你所料。请注意,GL 不需要按顺序分配属性位置,从零开始,但大多数都这样做。 如果您实际上使用“颜色”,它可能会以位置 0 结束,从而完全破坏您的渲染。

作为另一个旁注:在 nvidia 上,我观察到由 GL 分配的属性位置实际上似乎是按着色器中的变量名称按字典顺序排列的 - 所以“颜色”会出现在“角落”之前。我不确定这是否只是巧合或其他实现如何处理。

【讨论】:

以上是关于GLSL 1.5 无法获得颜色输入的主要内容,如果未能解决你的问题,请参考以下文章

glsl 着色器 - 颜色混合,正常模式(如在 Photoshop 中)

OpenGL/GLSL 颜色附件范围

如何使用 OpenGL 和 GLSL 改变颜色(C++)?

如何在 OpenGL/GLSL 中对特定颜色进行阈值处理

Qt GLSL 纹理只出现一种颜色

GLSL MRT 将相同的数据写入所有颜色附件