How do i display 2 or more objects in openGL (model - view - projection matrices and shaders)

泪湿孤枕 提交于 2019-12-05 07:03:48

The confusion comes from thinking that the shader controls multiple vertex arrays at once, when it should be thought of as a universal entity. A vertex array is passed to the shader, then the object is drawn. And the process is repeated.

For example, let's say we assign the variable matrixID to the uniform MVP:

    // get handle for our "MVP" uniform
    GLuint matrixID = glGetUniformLocation(programID, "MVP");

When we're ready to draw an object, we set matrixID to the object's MVP:

    glUniformMatrix4fv(matrixID, 1, GL_FALSE, &cubeMVP[0][0]);

Then bind the vertex buffer, set the attribute pointer, and draw it:

    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

Now we move on to the triangle and repeat the process - set matrixID to the object's MVP, bind the vertex buffer, set the attribute pointer, and draw it:

    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

The corresponding vertex shader code:

#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);
}

OpenGL is not a scene graph. It draws things according to the current state and then forgets about it.

So if you want to draw different geometries, with different transformations just set the corresponding transformation matrix (uniform), draw the object and repeat this for each object you want to draw. After geometry has been drawn, the following operations will have no further effect on it, other than it might be overdrawn.

An alternative that may also work, would be to do the 'ModelViewProjection' matrix calculation in the vertex shader. You can do this by making uniform model, view, and projection matrix variables in the vertex shader. You can then globally calcluate view and projection matrices, and send them to the shader. You can then just calculate the model matrix for your cube and triangle (or whatever objects you need to render) individually, and send those model matrices to the shader as well.


View and projection matrix calculations; this could be in a separate 'camera' class:

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);

Model matrix calculation; this code can go in a separate class, and you can instantiate it for each object that you want to render:

// 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);

New vertex shader:

//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);

}

Have two arrays of vertices. Lets say array1 for cube, array2 for circle. Create 2 vaos and 2 vbos. vao1 and vbo1 for cube. vao2 and vbo2 for circle.

Bind vao1, bind vbo1, fill up vbo1 buffer with array1. glUserProgram(program) which is a program for shaders, set up vertexattripointer.

call glDrawArray()

Do the same thing for other vao and vbo.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!