Qt 顶点着色器如何访问与另一个着色器程序属性绑定的顶点缓冲区数据?
我已经创建了两个着色器程序shaderProgram0和shaderProgram1。我已将所有相关着色器和变量附加为0或1,以显示它们与shaderProgram0或shaderProgram1的关系。 两个着色器程序都按设计工作。shaderProgram0使用SimpleVertexShader0.vert作为顶点着色器:Qt 顶点着色器如何访问与另一个着色器程序属性绑定的顶点缓冲区数据?,qt,opengl,glsl,shader,vertex-shader,Qt,Opengl,Glsl,Shader,Vertex Shader,我已经创建了两个着色器程序shaderProgram0和shaderProgram1。我已将所有相关着色器和变量附加为0或1,以显示它们与shaderProgram0或shaderProgram1的关系。 两个着色器程序都按设计工作。shaderProgram0使用SimpleVertexShader0.vert作为顶点着色器: #version 330 in vec3 vertexPosition0; void main() { gl_Position = vec4(vertexPos
#version 330
in vec3 vertexPosition0;
void main()
{
gl_Position = vec4(vertexPosition0, 1);
}
#version 330
in vec3 vertexPosition1;
void main()
{
gl_Position = vec4(vertexPosition1, 1);
}
shaderProgram0的输出如下所示:
shaderProgram1使用SimpleVertexShader1.vert作为顶点着色器:
#version 330
in vec3 vertexPosition0;
void main()
{
gl_Position = vec4(vertexPosition0, 1);
}
#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);
编辑代码的输出为:
这里出现了一个问题,如果两个程序对唯一属性使用相同的位置,那么它们应该生成一个或另一个三角形,而不是由于覆盖!?
请容忍我,我刚开始学
shaderProgram1的顶点着色器访问与shaderProgram0属性绑定的缓冲区数据不是很奇怪吗
没有
如果在链接程序之前未从着色器显式指定属性位置,或未使用glBindAttribLocation
,则实现将为您任意指定顶点属性位置。不要求单独的程序使用单独的属性位置。实际上,通常建议您尽可能使属性位置接口在程序之间兼容
在您的例子中,实现碰巧将它们都分配到同一个位置。因此,任一VAO将与任一程序一起工作
shaderProgram1的顶点着色器访问与shaderProgram0属性绑定的缓冲区数据不是很奇怪吗
没有
如果在链接程序之前未从着色器显式指定属性位置,或未使用glBindAttribLocation
,则实现将为您任意指定顶点属性位置。不要求单独的程序使用单独的属性位置。实际上,通常建议您尽可能使属性位置接口在程序之间兼容
在您的例子中,实现碰巧将它们都分配到同一个位置。因此,任一VAO将与任一程序一起工作。当前绑定的程序完全独立于存储在VAO中的管道输入的配置。如果当前绑定的VAO将数据从某些缓冲区提取到某些属性中。您可以不断更改程序,但仍然可以从相同的输入输入输入管道,这看起来像您(意外地)正在做的事情。还要注意,启用顶点属性是VAO的设置,而不是程序的设置。VAO和程序“相遇”的地方是在建立这些属性的位置时,这是您在代码中没有明确做的事情——在您的系统上,碰巧两个程序对唯一属性使用相同的位置,因此它们都将使用相同的VAO。@peppe我编辑了我的问题,你能看一下吗?你的回答有道理,但我想澄清我的疑问。当前绑定的程序完全独立于管道输入的配置,管道输入存储在VAO中。如果当前绑定的VAO将数据从某些缓冲区提取到某些属性中。您可以不断更改程序,但仍然可以从相同的输入输入输入管道,这看起来像您(意外地)正在做的事情。还要注意,启用顶点属性是VAO的设置,而不是程序的设置。VAO和程序“相遇”的地方是在建立这些属性的位置时,这是您在代码中没有明确做的事情——在您的系统上,碰巧两个程序对唯一属性使用相同的位置,因此它们都将使用相同的VAO。@peppe我编辑了我的问题,你能看一下吗?你的回答有道理,但我想澄清我的疑虑。@ShujaatAliKhan:。。。特别是你的编辑怎么样?基于之前的工作方式,这种行为没有什么令人惊讶或意外的。我不明白的是,每个着色器程序都有不同的id,并且GLDrawArray在启用的VAO上工作,所以当我启用shaderProgram0的属性时,像这样:glEnableVertexAttribArray(glGetAttribLocation(shaderProgram0.programId(),“vertexPosition0”);那么shaderProgram1如何访问为shaderProgram0初始化的数据块?我知道我想问什么,但我无法将我的想法转换为文字,因为我对opengl相关术语的接触较少:'(@ShujaatAliKhan:因为,正如我所说,顶点属性位置不是程序特定的。或者说,它们不是程序唯一的。不同的程序可以而且经常使用相同的属性位置。请你看看我的另一个问题。@ShujaatAliKhan:…你的编辑特别怎么样?没有什么令人惊讶或意外的关于这种行为,基于以前的情况。我不明白的是