当我想绘制一个对象(例如立方体)时,这一切都很好。我为立方体创建顶点,我创建缓冲区,我创建MVP矩阵并将其发送到着色器,它工作得很好。
但是,当我想绘制2个或更多个物体时该做什么,例如立方体和三角形?我认为三角形和立方体的视图和投影矩阵应该相同,我只需要不同的模型矩阵,对吧? 那么这意味着我将拥有两个MVP?
//Example (using GLM):
glm::mat4 MVPC = Projection * View * ModelCube;
glm::mat4 MVPT = Projection * View * ModelTriangle;
那我现在该怎么办?这是适用于立方体
的顶点着色器//vertex shader
#version 330 core
layout(location = 0) in vec3 verticesCube;
uniform mat4 MVPC;
void main(){
gl_Position = MVPC * vec4(verticesCube,1);
}
我应该如何处理着色器中的MVPT(三角形),我尝试弄乱不同的东西,但我不能让它工作,我不能同时显示立方体和三角形。
答案 0 :(得分:7)
混淆来自于认为着色器一次控制多个顶点数组,而它应该被视为一个通用实体。将顶点数组传递给着色器,然后绘制对象。然后重复这个过程。
例如,假设我们将变量 matrixID 分配给统一 MVP :
// get handle for our "MVP" uniform
GLuint matrixID = glGetUniformLocation(programID, "MVP");
当我们准备绘制对象时,我们将 matrixID 设置为对象的MVP:
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &cubeMVP[0][0]);
然后绑定顶点缓冲区,设置属性指针并绘制它:
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, cubeVerteciesBuffer);
glVertexAttribPointer(
0, // shader layout location
3,
GL_FLOAT,
GL_FALSE,
0,
(void *)0
);
glDrawArrays(GL_TRIANGLES, 0, 12*3); // draw cube
现在我们转到三角形并重复该过程 - 将 matrixID 设置为对象的MVP,绑定顶点缓冲区,设置属性指针并绘制它:
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &triMVP[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, triangleVerteciesBuffer);
glVertexAttribPointer(
0, // shader layout location
3,
GL_FLOAT,
GL_FALSE,
0,
(void *)0
);
glDrawArrays(GL_TRIANGLES, 0, 3); // draw triangle
相应的顶点着色器代码:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertecies_modelspace;
uniform mat4 MVP;
void main(){
gl_Position = MVP * vec4(vertecies_modelspace, 1);
}
答案 1 :(得分:3)
OpenGL不是场景图。它根据当前状态绘制内容,然后忘记它。
因此,如果要绘制不同的几何图形,使用不同的变换只需设置相应的变换矩阵(均匀),绘制对象并对要绘制的每个对象重复此操作。绘制几何体后,除了可能透支之外,以下操作对它没有进一步的影响。
答案 2 :(得分:2)
可能也有效的替代方法是在顶点着色器中进行“ModelViewProjection”矩阵计算。您可以通过在顶点着色器中生成统一的模型,视图和投影矩阵变量来实现此目的。然后,您可以全局计算视图和投影矩阵,并将它们发送到着色器。然后,您可以单独计算立方体和三角形(或任何需要渲染的对象)的模型矩阵,并将这些模型矩阵也发送到着色器。
glm::mat4 viewMatrix = glm::lookAt(
glm::vec3(0, -5, 0), // camera location in world
glm::vec3(0, 0, 0), // point camera is looking at
glm::vec3(0, 1, 0) // orientation of camera, change 1 to -1 to flip camera upside down
);
glm::mat4 projectionMatrix = glm::perspective(35.0f, displayWidth / displayHeight, 0.1f, 100.0f);
// send view and projection matrices to the shader
glUseProgram(shaderProgram);
GLint viewMatrixId = glGetUniformLocation(shaderProgram, "view");
GLint projectionMatrixId = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(viewMatrixId, 1, GL_FALSE, &viewMatrix[0][0]);
glUniformMatrix4fv(projectionMatrixId, 1, GL_FALSE, &projectionMatrix[0][0]);
glUseProgram(0);
// this can go after where you initialize your cube or triangle vertex information
glUseProgram(shaderProgram);
modelMatrixId = glGetUniformLocation(shaderProgram, "model"); //modelMatrixId can be a global GLint
glUniformMatrix4fv(modelMatrixId, 1, GL_FALSE, &modelMatrix[0][0]); //modelMatrix can be a global glm::mat4
glUseProgram(0);
//use this for every render frame
glUseProgram(shaderProgram);
glUniformMatrix4fv(modelMatrixId, 1, GL_FALSE, &modelMatrix[0][0]);
// code to bind vertices and draw you objects goes here
glUseProgram(0);
//vertex shader
#version 330 core
layout(location = 0) in vec3 vertices;
uniform mat4 model, view, projection;
void main(){
gl_Position = projection * view * model * vec4(vertices, 1.0);
}
答案 3 :(得分:0)
有两个顶点数组。让我们说array1 for cube,array2 for circle。 创建2个vaos和2个vbos。 vao1和vbo1 for cube。圆圈的vao2和vbo2。
绑定vao1,绑定vbo1,用array1填充vbo1缓冲区。 glUserProgram(program)是着色器程序,设置vertexattripointer。
调用glDrawArray()
对其他vao和vbo做同样的事情。