【发布时间】:2016-09-29 22:20:18
【问题描述】:
我创建了两个着色器程序 shaderProgram0 和 shaderProgram1。我已将所有相关的着色器和变量附加为 0 或 1,以显示它们与 shaderProgram0 或 shaderProgram1 的关系。 两个着色器程序都按设计工作。 shaderProgram0 使用 SimpleVertexShader0.vert 作为顶点着色器:
#version 330
in vec3 vertexPosition0;
void main()
{
gl_Position = vec4(vertexPosition0, 1);
}
shaderProgram0的输出是这样的:
shaderProgram1 使用 SimpleVertexShader1.vert 作为顶点着色器:
#version 330
in vec3 vertexPosition1;
void main()
{
gl_Position = vec4(vertexPosition1, 1);
}
shaderProgram1的输出是这样的:
现在有趣的部分是这个;在使用shaderProgram1时,我不小心注释了顶点属性数组vao1的绑定,没有注释vao0的绑定,导致输出如下图,实际上是(我认为)只能由shaderProgram0生成的输出!:
代码经过简化,是在 Windows 中使用 Qt Creator 编写的:
void OpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
shaderProgram0.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/SimpleVertexShader0.vert");
shaderProgram0.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/SimpleFragmentShader0.frag");
shaderProgram0.link();
shaderProgram1.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/SimpleVertexShader1.vert");
shaderProgram1.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/SimpleFragmentShader1.frag");
shaderProgram1.link();
}
void OpenGLWidget::resizeGL(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
}
void OpenGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat vertexBufferData0[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
GLuint vbo0;
glGenBuffers(1, &vbo0);
glBindBuffer(GL_ARRAY_BUFFER, vbo0);
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertexBufferData0),
vertexBufferData0,
GL_STATIC_DRAW);
GLuint vao0;
glGenVertexArrays(1, &vao0);
glBindVertexArray(vao0);
glBindBuffer(GL_ARRAY_BUFFER, vbo0);
glVertexAttribPointer(glGetAttribLocation(shaderProgram0.programId(),"vertexPosition0"), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
GLfloat vertexBufferData1[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
GLuint vbo1;
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertexBufferData1),
vertexBufferData1,
GL_STATIC_DRAW);
GLuint vao1;
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glVertexAttribPointer(glGetAttribLocation(shaderProgram1.programId(),"vertexPosition1"), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// Now Rendering-----------------------------------------------------
glBindVertexArray(vao0);
glEnableVertexAttribArray(glGetAttribLocation(shaderProgram0.programId(),"vertexPosition0"));
// glBindVertexArray(vao1);
// glEnableVertexAttribArray(glGetAttribLocation(shaderProgram1.programId(),"vertexPosition1"));
shaderProgram1.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);
}
shaderProgram1 的顶点着色器访问与 shaderProgram0 属性绑定的缓冲区数据是不是很奇怪?我认为它不应该生成任何输出,因为未启用有效的顶点属性数组! 如果有人知道这是如何工作的,请解释这种情况。如果您不明白我在问什么,请仔细查看代码,您会明白这一点,否则我会进一步解释。
编辑:
// Now Rendering-----------------------------------------------------
glBindVertexArray(vao0);
glEnableVertexAttribArray(glGetAttribLocation(shaderProgram0.programId(),"vertexPosition0"));
shaderProgram0.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(vao1);
glEnableVertexAttribArray(glGetAttribLocation(shaderProgram1.programId(),"vertexPosition1"));
shaderProgram1.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);
编辑后的代码输出为:
如果两个程序都对唯一属性使用相同的位置,那么就会出现一个问题,那么它们应该生成一个三角形或另一个三角形,而不是同时覆盖!? 请多多包涵,我刚开始学习。
【问题讨论】:
-
当前绑定的程序完全独立于存储在VAO中的管道输入配置。如果当前绑定的 VAO 从某些缓冲区获取数据到某些属性中。您可以不断更改程序并仍然从相同的输入为管道提供数据,这看起来就像您正在(不小心?)在做的事情。
-
另请注意,启用顶点属性是 VAO 的设置,而不是程序的设置。 VAO 和程序“相遇”的地方是在建立这些属性的位置时,这是您没有在代码中明确执行的操作——在您的系统上,偶然地,两个程序都使用相同的位置唯一的属性,因此它们都可以使用相同的 VAO。
-
@peppe 我已经编辑了我的问题,你能看一下吗?你的回答很有道理,但我想消除我的疑虑。
标签: qt opengl glsl shader vertex-shader