我有一些代码可以通过几何着色器传递点来绘制正方形。我构造了一个数组,它是3个浮点数的序列,将它绑定到我的顶点着色器的in vec3 vert
属性,一切都很好。
但是,我想添加另一个浮点数,片段着色器将使用它来计算颜色。这是在顶点着色器(通过)in float val
。尽管能够找到vert
,但glGetAttribLocation
找不到val
(get_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();
}
答案 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 (...)
导致所有输出变量在返回时变为 未定义 ,因此您必须每次都设置它。