C ++:OpenGL:绘制多个几何

时间:2017-07-23 21:36:52

标签: c++ opengl

我正在编写一个超级超级超级大赛 - Über-3D-Game ,我正在努力一个接一个地绘制多个几何形状。

绘制单个几何图形工作正常,但是如果我尝试绘制多个几何图形,则切换它们的顶点数据和着色器程序;或者他们切换位置和旋转轴。这是我绘制一个立方体的样子: http://i.imgur.com/zmTPc0h.png 如果我在该立方体之后绘制一艘宇宙飞船,这就是它的样子: http://i.imgur.com/10HDjm9.png 以下是此应用程序的代码:

void MainLoop::loop()
{

    VisibleObject cube("cube.obj", "vertexShader.glsl", "fragmentShaderCube.glsl");
    cube.coordinates = glm::vec3(0.0f, 5.0f, -10.0f);

    VisibleObject spaceship("spaceship.obj", "vertexShader.glsl", "fragmentShader.glsl");
    spaceship.actualAxisOfRotation = glm::vec3(1.0f, 0.0f, 0.0f);

    while (gameState != GAMESTATE_EXITING)
    {
        //check for input
        while (SDL_PollEvent(&evnt))
        {
            switch (evnt.type)
            {
            case SDL_QUIT:
                gameState = GAMESTATE_EXITING;
                break;

            default:
                break;
            }
        }


        //clear depth buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        spaceship.draw();
        cube.draw();

        //display result
        SDL_GL_SwapWindow(window);

    }
}

class VisibleObject
{
public:
    VisibleObject(std::string modelPath, std::string vertexShaderPath, std::string fragmentShaderPath);
    ~VisibleObject();
    void cleanup();

    void draw();

    glm::vec3 coordinates; //1.0f = 1.0 meter
    glm::vec3 actualAxisOfRotation;
    GLfloat actualRotation; //radians off the originposition

    glm::vec3 velocity; //meters per second
    glm::vec3 axisOfRotation;
    GLfloat rotationSpeed; //radians per second
private:
    short numberOfIndices;
    std::vector<short> indices;
    short numberOfVertices;
    std::vector<glm::vec3> vertices;
    glm::mat4 fullMatrix; 
    GLuint fullMatrixUniformLocation;
    GLuint shaderProgramID;
    GLuint vertexBufferID;
    GLuint indexBufferID;
    GLuint vertexArrayObjectID;

};

VisibleObject::VisibleObject(std::string modelPath, std::string vertexShaderPath, std::string fragmentShaderPath)
{
    coordinates = glm::vec3(0.0f, 0.0f, -10.0f);
    actualAxisOfRotation = glm::vec3(0.0f, 1.0f, 0.0f);
    actualRotation = 2.0f;
    velocity = glm::vec3(0.0f, 0.0f, 0.0f);
    axisOfRotation = glm::vec3(0.0f, 1.0f, 0.0f);
    rotationSpeed = 0.0f;

    //create shader-program
    shaderProgramID = GlslUtilities::installShader(vertexShaderPath, fragmentShaderPath);
    //create transformation-matrix-uniform
    fullMatrixUniformLocation = glGetUniformLocation(shaderProgramID, "f_matrix");

    //load model data
    numberOfIndices = 0;
    numberOfVertices = 0;
    indices.clear();
    vertices.clear();

    something_that_works_and_loads_the_vertex_and_index_data_from_an_obj-file_into_the_vectors();

    //sending data to opengl
    glGenVertexArrays(1, &vertexArrayObjectID);
    glGenBuffers(1, &indexBufferID);
    glGenBuffers(1, &vertexBufferID);

    glBindVertexArray(vertexArrayObjectID);

    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(vertices[0]), &vertices[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices[0]), &indices[0], GL_STATIC_DRAW);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}


VisibleObject::~VisibleObject()
{
}

void VisibleObject::cleanup()
{
    glUseProgram(0);
    glDeleteProgram(shaderProgramID);
    glDeleteBuffers(1, &vertexBufferID);
    glDeleteBuffers(1, &indexBufferID);
    glDeleteBuffers(1, &vertexArrayObjectID);
}

void VisibleObject::draw()
{

    glBindVertexArray(vertexArrayObjectID);


    fullMatrix = glm::perspective(glm::radians(85.0f), 800.0f / 600, 0.1f, 150.0f);
    fullMatrix = glm::translate(fullMatrix, coordinates);
    fullMatrix = glm::rotate(fullMatrix, glm::radians(((float)SDL_GetTicks())/10), actualAxisOfRotation);

    glUniformMatrix4fv(fullMatrixUniformLocation, 1, GL_FALSE, &fullMatrix[0][0]);

    glUseProgram(shaderProgramID);
    glDrawElements(GL_TRIANGLES, numberOfIndices, GL_UNSIGNED_SHORT, 0);
}

1 个答案:

答案 0 :(得分:1)

在绑定着色器之前,您正在将fullMatrix上传到着色器。由于glMatrix4fv调用始终在当前绑定的着色器上运行,因此在绘制时使用了错误的矩阵。

解决方案:以正确的顺序调用函数

glUseProgram(shaderProgramID);
glUniformMatrix4fv(fullMatrixUniformLocation, 1, GL_FALSE, &fullMatrix[0][0]);

glDrawElements(GL_TRIANGLES, numberOfIndices, GL_UNSIGNED_SHORT, 0);