使用多个VAO和VBO渲染对象

时间:2018-04-17 11:40:26

标签: c++ opengl rendering vbo vao

我正在学习OpenGL。我的任务是开发一个程序,用于渲染下载为.obj文件的大量不同对象。我的想法是创建一个类,用于在一个类对象中存储3个VBO(顶点,纹理,法线),VAO和对象类型。因此,类似的对象(用于渲染)将只使用一个具有正确VAO和VBO的类对象。我编写了它,但它不起作用:对象从文件下载,所有类对象都被创建,但屏幕上没有任何内容。

用于存储VAO和VBO的类,此类的构造函数:

modelMemory(char* typeT)
{
    this->modelType = typeT;

    if (this->modelType == "Suzanne")   loadOBJ("suzanne.obj", this->vertices, this->uvs, this->normals);

    glGenVertexArrays(1, &this->VAO_id);
    glBindVertexArray(this->VAO_id);

    glGenBuffers(1, &this->VBO_vertex);
    glBindBuffer(GL_ARRAY_BUFFER, this->VBO_vertex);
    glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(glm::vec3), &this->vertices[0], GL_STATIC_DRAW);
/**/glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glGenBuffers(1, &this->VBO_uv);
    glBindBuffer(GL_ARRAY_BUFFER, this->VBO_uv);
    glBufferData(GL_ARRAY_BUFFER, this->uvs.size() * sizeof(glm::vec2), &this->uvs[0], GL_STATIC_DRAW);
/**/glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glGenBuffers(1, &this->VBO_normal);
    glBindBuffer(GL_ARRAY_BUFFER, this->VBO_normal);
    glBufferData(GL_ARRAY_BUFFER, this->normals.size() * sizeof(glm::vec3), &this->normals[0], GL_STATIC_DRAW);
/**/glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glBindVertexArray(0);
}
/*DESTRUCTOR*/
~modelMemory()
{
/**/if (toDel)
    {
        glDeleteBuffers(1, &VBO_vertex);
        glDeleteBuffers(1, &VBO_uv);
        glDeleteBuffers(1, &VBO_normal);
        glDeleteVertexArrays(1, &VAO_id);
    }
}

用于存储模型的类,构造函数:

Model2 (char* Type, float x, float y, float z, std::vector<modelMemory>* M, GLuint programID)
{
    this->type = Type;
    this->programID = programID;

    unsigned int k = 0;

    if ((*M).size() > 0){
        while(this->type != (*M)[k].modelType && k < (*M).size()) k++;
        if (k < (*M).size()) this->mem = &((*M)[k]);
    }
    if ((*M).size() == 0 || k == (*M).size()){
        //modelMemory newModel(this->type);
        //(*M).push_back(newModel);
        /**/(*M).emplace_back(this->type);  
        this->mem = &((*M)[(*M).size()-1]);
    }

    ModelPosition[0] += x;
    ModelPosition[1] += y;
    ModelPosition[2] += z;

    MatrixID = glGetUniformLocation(programID, "MVP");
    ViewMatrixID = glGetUniformLocation(programID, "V");
    ModelMatrixID = glGetUniformLocation(programID, "M");

    TextureID  = glGetUniformLocation(programID, "myTextureSampler");
    Texture = loadDDS("uvmap.DDS");
}

绘图功能:

void Draw()
{
    glUseProgram(programID);
    computeMatricesFromInputs();
    glm::mat4 ProjectionMatrix = getProjectionMatrix();
    glm::mat4 ViewMatrix = getViewMatrix();
    glm::mat4 ModelMatrix = glm::translate(glm::mat4(1.0), ModelPosition);

    glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix; 

    glUniformMatrix4fv(this->MatrixID, 1, GL_FALSE, &MVP[0][0]);
    glUniformMatrix4fv(this->ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
    glUniformMatrix4fv(this->ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, this->Texture);
    glUniform1i(this->TextureID, 0);

    glBindVertexArray(this->mem->VAO_id);

    glDrawArrays(GL_TRIANGLES, 0, this->mem->vertices.size());

    glBindVertexArray(0);
}

我在main.cpp中创建了一个向量:

std::vector<modelMemory> Memory;
std::vector<Model2> ModelList;

并要求在main.cpp中创建和绘图:

ModelList.emplace_back((char*)"Field", 0.0f, 0.0f, -5.0f, &Memory, programID);
ModelList.emplace_back((char*)"Suzanne", 0.0f, 0.0f, 0.0f, &Memory, programID);
ModelList.emplace_back((char*)"Suzanne", 4.0f, 1.0f, 1.0f, &Memory, programID);

for (int i = 0; i < ModelList.size(); i++)
        ModelList[i].Draw();

着色器(实际上,我在着色器中不是很好,它们依赖于OpenGL课程)。 顶点着色器:

#version 330 core

layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
layout(location = 2) in vec3 vertexNormal_modelspace;

out vec2 UV;
out vec3 Position_worldspace;
out vec3 Normal_cameraspace;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_cameraspace;

uniform mat4 MVP;
uniform mat4 V;
uniform mat4 M;
uniform vec3 LightPosition_worldspace;

void main(){

    gl_Position =  MVP * vec4(vertexPosition_modelspace,1);

    Position_worldspace = (M * vec4(vertexPosition_modelspace,1)).xyz;

    vec3 vertexPosition_cameraspace = ( V * M * vec4(vertexPosition_modelspace,1)).xyz;
    EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;

    vec3 LightPosition_cameraspace = ( V * vec4(LightPosition_worldspace,1)).xyz;
    LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;

    Normal_cameraspace = ( V * M * vec4(vertexNormal_modelspace,0)).xyz; 

    UV = vertexUV;
}

片段着色器:

#version 330 core

vec2 UV;
in vec3 Position_worldspace;
in vec3 Normal_cameraspace;
in vec3 EyeDirection_cameraspace;
in vec3 LightDirection_cameraspace;

out vec3 color;

uniform sampler2D myTextureSampler;
uniform mat4 MV;
uniform vec3 LightPosition_worldspace;

void main(){

    vec3 LightColor = vec3(1,1,1);
    float LightPower = 10.0f;

    vec3 MaterialDiffuseColor = texture( myTextureSampler, UV ).rgb;
    vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * MaterialDiffuseColor;
    vec3 MaterialSpecularColor = vec3(0.3,0.3,0.3);

    float distance = length( LightPosition_worldspace - Position_worldspace );

    vec3 n = normalize( Normal_cameraspace );
    vec3 l = normalize( LightDirection_cameraspace );
    float cosTheta = clamp( dot( n,l ), 0.1,1 );

    vec3 E = normalize(EyeDirection_cameraspace);
    vec3 R = reflect(-l,n);
    float cosAlpha = clamp( dot( E,R ), 0.4,1 );

    color = 
        MaterialAmbientColor +
        MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) +
        MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,6) / (distance*distance);
}

0 个答案:

没有答案