GLSL 1.5和OpenGL 3.3:将颜色传递给顶点着色器似乎失败
将顶点属性传递给正在运行的着色器程序时出现问题。我想通过两个属性,位置和一个RGBA颜色。绑定属性位置适用于该位置。但是,它不适用于颜色。因此,所有的几何图形最终都会呈现黑色。GLSL 1.5和OpenGL 3.3:将颜色传递给顶点着色器似乎失败
这是我做的:
GLuint programHandler;
// create program
// compile & attach vertex shader
// compile & attach fragment shader
glBindAttribLocation(programHandler, 0, "InPosition");
glBindAttribLocation(programHandler, 1, "InColor");
glBindFragDataLocation(programHandler, 1, "FragColor");
glLinkProgram(programHandler);
glUseProgram(programHandler);
// initialize uniform variables
// I'm trying to get the attribute locations now.
// I expect location "0" for InPosition and location "1" for InColor.
// In fact, it gets me a "-1" for InColor. I simply cannot see the reason for that behaviour
GLint positionLocation = glGetAttribLocation(programHandler, "InPosition"); // returns 0
GLint colorLocation = glGetAttribLocation(programHandler, "InColor"); // returns -1
glEnableVertexAttribArray(positionLocation);
glEnableVertexAttribArray(colorLocation); // fails!
我的顶点着色器是非常基本的。我真正要做的是转变顶点并通过颜色的片段着色器:
#version 150 core
// input
uniform mat4 ModelviewMatrix;
uniform mat4 ProjectionMatrix;
in vec3 InPosition;
in vec4 InColor;
// output
out vec4 PassColor;
void main(void) {
// passing color through to fragment shader
PassColor = InColor;
// transformation
gl_Position = ProjectionMatrix * ModelviewMatrix * vec4(InPosition, 1.0);
}
我的片段着色器应该简单地返回颜色:
#version 150 core
precision highp float;
// input
in vec4 PassColor;
// output
out vec4 FragColor;
void main(void) {
FragColor = PassColor;
}
为什么绑定“器就位”工作和“InColor”才不是?我知道GLSL编译器会优化着色器代码,以便不能绑定未使用的变量。但是,我不明白为什么这里应该优化颜色。毕竟,我通过将它传递给片段着色器来使用它。
盲拍,我认为这是错误的:
glBindFragDataLocation(programHandler, 1, "FragColor");
它应该是:
glBindFragDataLocation(programHandler, 0, "FragColor");
我明白了。但是如果我想渲染到多个渲染目标。我目前渲染到附加到帧缓冲区对象的纹理。我原本打算不仅仅将那个纹理附加到颜色缓冲区中。这就是“1”作为第二个参数的原因。我相信gl_FragData []数组已被弃用。我如何正确地绑定它并在片段着色器中声明? – Walter 2010-12-07 04:19:42
如果片段着色器应写入多个颜色平面,然后帧缓冲区必须是已创建,其中已附加了多个颜色平面,其中可以写入片段。
彩色平面既可以使缓冲区,
GLuint renderbuffer[2];
glGenRenderbuffers(2, &renderbuffer[0]);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[0]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[1]);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
,也可以是纹理。
GLuint colorTexture[2];
glGenTextures(2, &colorTexture[0]);
glBindTexture(GL_TEXTURE_2D, colorTexture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, colorTexture[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
纹理或渲染缓冲区必须附加到帧缓冲区。
渲染缓冲器
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[0]);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[1]);
纹理
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture[0], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, colorTexture[1], 0);
注意,当然渲染缓冲器和纹理可以被混合,并且可以附连到一个不同的色彩平面,并且在同一帧缓冲。
如果需要深度缓冲区或模板缓冲区,则必须将GL_DEPTH_ATTACHMENT
,GL_STENCIL_ATTACHMENT
或GL_DEPTH_STENCIL_ATTACHMENT
附加到帧缓冲区。
如果farme缓冲器已经成功完成可以与glCheckFramebufferStatus
进行评估:
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
// error
}
其可以连接到单个帧缓冲器颜色缓冲器的最大数量可以通过OGL功能glGetIntegerv
来确定,通过使用参数GL_MAX_COLOR_ATTACHMENTS
:
GLint maxColAttchemnts = 0;
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColAttchemnts);
并非所有的颜色附件必须在同一时间被激活。可以用glDrawBuffers
来定义片段着色器数据的输出写入其中的缓冲器阵列。
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT1 };
glDrawBuffers(1, &drawBuffers[0]);
在片段着色器都将被声明为每个激活的颜色附着一个out
变量。
out fragColor0;
out fragColor1;
void main()
{
....
fragColor0 = ....;
....
fragColor1 = ....;
}
一个out
变量到帧缓冲器颜色附着的指数可以通过glBindFragDataLocation
明确指定的结合。这必须在着色器程序被链接之前完成。
GLuint prog = ....;
glBindFragDataLocation(prog, 0, "fragColor0");
glBindFragDataLocation(prog, 1, "fragColor1");
glLinkProgram(prog);
在特定输出写入的现代OpenGL缓冲区索引中,可以通过布局位置明确指定。这允许放弃使用glBindFragDataLocation
。
layout(location = 0) out fragColor0;
layout(location = 1) out fragColor1;
任何`glGetError()`在那里?另外,你的GPU和驱动程序版本是什么? – Kos 2010-12-07 12:00:38