How to draw multiple objects in OpenGL using multiple VAO and VBO?

北战南征 提交于 2019-12-24 00:43:37

问题


I'm trying to render multiple objects in OpenGL using multiple VAO's and VBO's. To render multiple objects using the same vertices I've done it, but what I want to do is to use different vertices for each object, for example to draw a square and a circle. For a square I only need 6 vertices but for circle I need 360. I have error with reading or creating the shaders.

Here is the Vertex Shader:

#version 330 core

layout (location = 0) in vec4 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * position;
}

Fragment Shader:

#version 330 core

layout(location = 0) out vec4 color;

uniform vec4 u_Color;

void main()
{
    color = u_Color;
}

The VAO and VBO generating and binding

// Circle
std::vector<VertexFormat> vertices;

for (int i = 0; i < 360; i++)
{
    GLfloat angle = i * ((2.0f * 3.14159f) / 360);
    vertices.push_back(VertexFormat(glm::vec3(cos(angle) * 100.0f, sin(angle) * 100.0f, 0.0f)));
}

// Pipette object
std::vector<VertexFormat> pipetteVertices;
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 500.0f, 0.0f))); // 0
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 500.0f, 0.0f))); // 1
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 700.0f, 0.0f))); // 2
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 700.0f, 0.0f))); // 3
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 500.0f, 0.0f)));
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 700.0f, 0.0f)));

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * 6, &pipetteVertices[0], GL_STATIC_DRAW);

//Position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (GLvoid *)0);

GLuint vao2;
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);

GLuint vbo2;
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * 360, &vertices[0], GL_STATIC_DRAW);

//Position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (GLvoid *) 0);

glBindBuffer(GL_ARRAY_BUFFER, 0);

And the draw call in the rendering loop:

    //Get the uniform locations of model, view and projection matrices
    modelID = glGetUniformLocation(program, "model");
    viewID = glGetUniformLocation(program, "view");
    projectionID = glGetUniformLocation(program, "projection");

    //View transform
    glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 2), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
    //Projection transform
    //glm::mat4 projection = glm::perspective(45.0f, (GLfloat)screenWidth / (GLfloat)screenHeight, 0.1f, 1000.0f);
    glm::mat4 projection = glm::ortho(0.0f, (GLfloat)screenWidth, 0.0f,  (GLfloat)screenHeight, 0.1f, 10.0f);

    {
        glUniformMatrix4fv(viewID, 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(projectionID, 1, GL_FALSE, glm::value_ptr(projection));

        glm::mat4 translate = glm::translate(glm::mat4(1.0), glm::vec3(100.0f + move_x, 100.0f + move_y, 0.0f));
        glm::mat4 rotate = glm::rotate(glm::mat4(1.0), 0.0f, glm::vec3(0.0f, 0.0f, 1.0f));
        glm::mat4 scale = glm::scale(glm::mat4(1.0), glm::vec3(1.0f, 1.0f, 2.0f));

        glm::mat4 model = translate * rotate * scale;
        glUniformMatrix4fv(modelID, 1, GL_FALSE, glm::value_ptr(model));

        glUniform4f(color, 0.0f, 0.0f, 1.0f, 1.0f);

        //Render
        glDrawArrays(GL_TRIANGLE_FAN, 0, 360);
    }

    {
        glUniformMatrix4fv(viewID, 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(projectionID, 1, GL_FALSE, glm::value_ptr(projection));

        glm::mat4 translate = glm::translate(glm::mat4(1.0), glm::vec3(300.0f + injPipette.x, 300.0f + injPipette.y, 0.0f));
        glm::mat4 rotate = glm::rotate(glm::mat4(1.0), 0.0f, glm::vec3(0.0f, 0.0f, 1.0f));
        glm::mat4 scale = glm::scale(glm::mat4(1.0), glm::vec3(1.0f, 1.0f, 2.0f));

        glm::mat4 model = translate * rotate * scale;
        glUniformMatrix4fv(modelID, 1, GL_FALSE, glm::value_ptr(model));

        glUniform4f(color, 1.0f, 0.0f, 0.0f, 0.5f);

        //Render
        glDrawArrays(GL_TRIANGLES, 0, 6);
    }

I repeat, to draw multiple objects using the same vertices I've done it. I need to know how to draw multiple objects using the same vertex and fragment shader but different number of vertices. The project is small, just rendering maximum 10 objects in 2D.


回答1:


Drawing commands like glDrawArrays process and draw the arrays of generic vertex attribute data, which are stated in the Vertex Array Object which is current.

This means you have to bind the proper vertex array object before you do the draw call:

{
    // [...]

    glBindVertexArray(vao2);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 360);
}

{
    // [ ...]

    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLES, 0, 6); 
}



回答2:


@Kenny83 It's been a while since I touched OpenGL and honestly I don't remember from where I got the VertexFormat but thankfully I found the project with the code. I don't know how to add snippet to comment and I think it's not even possible so I added it as an answer:

#pragma once
#include "glm\glm.hpp"

struct VertexFormat
{

    glm::vec3 position;

    VertexFormat(const glm::vec3 &iPos)
    {
        position = iPos;
    }

    VertexFormat()
    {

    }

};

Hope it helps.



来源:https://stackoverflow.com/questions/54583368/how-to-draw-multiple-objects-in-opengl-using-multiple-vao-and-vbo

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