Рендеринг объектов с несколькими VAO и VBO

Я изучаю 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 ответов

Другие вопросы по тегам