OpenGL在顶点着色器中查找`在vec3 vert`中但不在`float val`中

时间:2014-06-13 18:53:58

标签: c opengl shader fragment-shader vertex-shader

我有一些代码可以通过几何着色器传递点来绘制正方形。我构造了一个数组,它是3个浮点数的序列,将它绑定到我的顶点着色器的in vec3 vert属性,一切都很好。

但是,我想添加另一个浮点数,片段着色器将使用它来计算颜色。这是在顶点着色器(通过)in float val。尽管能够找到vert,但glGetAttribLocation找不到valget_program_attrib(): Atrrib val not found (-1))。

代码:

void load_model(GLuint* vao, GLuint* vbo) {
    glGenVertexArrays(1, vao);
    glBindVertexArray(*vao);
    glGenBuffers(1, vbo);
    glBindBuffer(GL_ARRAY_BUFFER, *vbo);

    float data[SQUARES_PER_AXIS_SQ * 4] = {0};
    squares_count = 0;

    for (int i = 0; i < SQUARES_PER_AXIS_SQ; i++) {
        int x_pos = i % SQUARES_PER_AXIS;
        int y_pos = i / SQUARES_PER_AXIS;
        if (fabs(squares[i]) > 0.0) {
            data[squares_count * 4 + 0] = x_pos / ((float)SQUARES_PER_AXIS) * 2 - 1;
            data[squares_count * 4 + 1] = (SQUARES_PER_AXIS - y_pos) / ((float)SQUARES_PER_AXIS) * 2 - 1;
            data[squares_count * 4 + 2] = 0.5f;
            data[squares_count * 4 + 3] = (float)squares[i];
            squares_count++;
        }
    }
    DPRINT("Loaded %d squares\n", squares_count);

    glBufferData(GL_ARRAY_BUFFER, squares_count * 4 * sizeof(float), data, GL_STATIC_DRAW);

    glEnableVertexAttribArray(get_program_attrib(main_shader, "vert"));
    glEnableVertexAttribArray(get_program_attrib(main_shader, "val"));
    glVertexAttribPointer(get_program_attrib(main_shader, "vert"), 3, GL_FLOAT, GL_FALSE, 4, NULL);
    glVertexAttribPointer(get_program_attrib(main_shader, "val"), 1, GL_FLOAT, GL_FALSE, 4, (float*)(3 * sizeof(float)));

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

GLuint get_program_attrib(program_t* prog, GLchar* name) {
    if (!name) {
        DPRINT("ERROR: name == NULL\n");
        return -1;
    }
    GLint attrib = glGetAttribLocation(prog->id, name);
    if (attrib < 0)
        DPRINT("Atrrib %s not found (%d)\n", name, attrib);
    return attrib;
}

顶点着色器:

#version 150

in vec3 vert;
in float val;
out float value;

void main() {
    gl_Position = vec4(vert, 1);
    value = val;
}

片段着色器:

#version 150

in float value;
out vec4 color;

void main() {
    color = vec4(value, 0, 0, 1);
}

几何着色器:

#version 150

layout (points) in;
layout (triangle_strip, max_vertices=4) out;

uniform float square_size;

void main() {
    vec4 position = gl_in[0].gl_Position;

    gl_Position = vec4(position.x, position.y, position.zw);
    EmitVertex();
    gl_Position = vec4(position.x,  position.y + square_size, position.zw);
    EmitVertex();
    gl_Position = vec4(position.x + square_size, position.y, position.zw);
    EmitVertex();
    gl_Position = vec4(position.x + square_size,  position.y + square_size, position.zw);
    EmitVertex();

    EndPrimitive();
}

1 个答案:

答案 0 :(得分:3)

具有几何着色器时,顶点着色器输出不会直接传递到片段着色器。

这就是造成你所有问题的原因。要使顶点属性处于活动状态,它必须为程序的最终输出做出贡献。基本上这意味着在片段着色器中计算的东西必须基于它。

不幸的是,现在没有发生这种情况。您有一个名为value的变量,它从您的顶点着色器输出,还有一个名为value的变量,由您的片段着色器输入。由于几何着色器位于其中两个之间,因此片段着色器仅在几何着色器中查找名为value的输出 - 不存在此类输出

当然,您可能认为解决方案是在几何着色器中创建一个名为value的变量,用作输入和输出。但是,这不起作用,你必须声明它inout value,这是无效的。


以下是必要的更正:

顶点着色器:

#version 150

in vec3 vert;
in float val;
out float value_vtx; // Output is fed to the Geometry Shader

void main() {
    gl_Position = vec4(vert, 1);
    value_vtx = val;
}

片段着色器:

#version 150

in float value_geo; // Takes its input from the Geometry Shader
out vec4 color;

void main() {
    color = vec4(value_geo, 0, 0, 1);
}

几何着色器:

#version 150

layout (points) in;
layout (triangle_strip, max_vertices=4) out;

uniform float square_size;

in  float value_vtx []; // This was output by the vertex shader
out float value_geo;    // This will be the input to the fragment shader

void main() {
    vec4 position = gl_in[0].gl_Position;

    gl_Position = vec4(position.x, position.y, position.zw);
    value_geo   = value_vtx[0];
    EmitVertex();

    gl_Position = vec4(position.x,  position.y + square_size, position.zw);
    value_geo   = value_vtx[0];
    EmitVertex();

    gl_Position = vec4(position.x + square_size, position.y, position.zw);
    value_geo   = value_vtx[0];
    EmitVertex();

    gl_Position = vec4(position.x + square_size,  position.y + square_size, position.zw);
    value_geo   = value_vtx[0];
    EmitVertex();

    EndPrimitive();
}

你可能会问我为什么在它不变时分配value_geo 4次。这是因为EmitVertex (...)导致所有输出变量在返回时变为 未定义 ,因此您必须每次都设置它。