OpenGL - 添加第二个网格后,第一个网格消失

时间:2017-08-11 08:01:14

标签: opengl glfw glm-math

我正在尝试在我的程序中加载2个不同的网格(金牛座和猴子头)。两者都使用相同的load_mesh函数。

我在load_mesh函数中使用init作为金牛座。此网格的顶点数据存储在g_pMeshVertices中。它看起来像这样。

Taurus mesh added

然后我加载了第二个,它看起来像这样(下图)。第二个网格(猴头)成功出现,但之前网格的一半消失了。 我做的是我再次使用load_mesh函数,但是init内的“猴头”。新网格的顶点也存储在g_pMeshVertices中。但是,我创建了一个新的VBO和VAO来存储g_pMeshVertices的新顶点,但它似乎正在影响我以前的网格。有人可以告诉我为什么吗?

Monkey head added but half of taurus missing

这是我的代码

#define MAX_CUBES 6
#define MAX_PLANES 6

// struct for lighting properties
struct LightProperties
{
    vec4 position;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
    vec3 attenuation;
    float cutoffAngle;
    vec3 direction;
};

// struct for material properties
struct MaterialProperties
{
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
};

LightProperties g_lightProperties;
MaterialProperties g_materialProperties;

// struct for vertex attributes
struct Vertex
{
    GLfloat position[3];
    GLfloat normal[3];
};

// Wall Vertices
Vertex g_vertices_plane[] = {
    -5.0f, -1.0f, 5.0f, // position
    0.0f, 1.0f, 0.0f,   // normal
    5.0f, -1.0f, 5.0f,  // position
    0.0f, 1.0f, 0.0f,   // normal
    -5.0f, -1.0f, -5.0f,// position
    0.0f, 1.0f, 0.0f,   // normal
    -5.0f, -1.0f, -5.0f,// position
    0.0f, 1.0f, 0.0f,   // normal
    5.0f, -1.0f, 5.0f,  // position
    0.0f, 1.0f, 0.0f,   // normal
    5.0f, -1.0f, -5.0f, // position
    0.0f, 1.0f, 0.0f,   // normal
};

Vertex g_vertices_cube[] = {
    // vertex 1
    -0.5f, 0.5f, 0.5f,  // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 2
    -0.5f, -0.5f, 0.5f, // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 3
    0.5f, 0.5f, 0.5f,   // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 4
    0.5f, -0.5f, 0.5f,  // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 5
    -0.5f, 0.5f, -0.5f, // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 6
    -0.5f, -0.5f, -0.5f,// position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 7
    0.5f, 0.5f, -0.5f,  // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 8
    0.5f, -0.5f, -0.5f, // position
    1.0f, 1.0f, 1.0f,   // normal
};

GLuint g_indices_cube[] = {
    0, 1, 2,    // triangle 1
    2, 1, 3,    // triangle 2
    4, 5, 0,    // triangle 3
    0, 5, 1,    // ...
    2, 3, 6,
    6, 3, 7,
    4, 0, 6,
    6, 0, 2,
    1, 5, 3,
    3, 5, 7,
    5, 4, 7,
    7, 4, 6,    // triangle 12
};

// Meshes
Vertex* g_pMeshVertices = NULL; // pointer to mesh vertices
GLint g_numberOfVertices = 0;   // number of vertices in the mesh
GLint* g_pMeshIndices = NULL;   // pointer to mesh indices
GLint g_numberOfFaces = 0;      // number of faces in the mesh

/*
    g_VBO[0] - Planes ie. walls, ceiling
    g_VBO[1] - Cubes ie. table, stools
    g_VBO[2] - Meshes (Taurus)
*/
GLuint g_IBO[3];                // index buffer object identifier
GLuint g_VBO[4];                // vertex buffer object identifier
GLuint g_VAO[4];                // vertex array object identifier
GLuint g_shaderProgramID = 0;   // shader program identifier

// locations in shader
GLuint g_MVP_Index;
GLuint g_M_Index = 0;
GLuint g_viewPointIndex = 0;
GLuint g_lightPositionIndex = 0;
GLuint g_lightAmbientIndex = 0;
GLuint g_lightDiffuseIndex = 0;
GLuint g_lightSpecularIndex = 0;
GLuint g_lightShininessIndex = 0;
GLuint g_lightAttenuationIndex = 0;
GLuint g_lightCutoffAngleIndex = 0;
GLuint g_lightDirectionIndex = 0;
GLuint g_materialAmbientIndex = 0;
GLuint g_materialDiffuseIndex = 0;
GLuint g_materialSpecularIndex = 0;

glm::mat4 g_modelMatrix_plane[MAX_PLANES];  // object's model matrix (4 walls + 1 ceiling + 1 floor)
glm::mat4 g_modelMatrix_cube[MAX_CUBES];// cube for table
glm::mat4 g_modelMatrix_mesh[2];        // for meshes
glm::mat4 g_viewMatrix;             // view matrix
glm::mat4 g_projectionMatrix;       // projection matrix
glm::vec3 g_viewPoint;              // view point

Camera g_camera;            // camera

GLuint g_windowWidth = 1600;        // window dimensions
GLuint g_windowHeight = 1000;
bool g_wireFrame = false;       // wireframe on or off

bool load_mesh(const char* fileName)
{
    // load file with assimp 
    const aiScene* pScene = aiImportFile(fileName, aiProcess_Triangulate
        | aiProcess_GenSmoothNormals | aiProcess_JoinIdenticalVertices);

    // check whether scene was loaded
    if (!pScene)
    {
        cout << "Could not load mesh." << endl;
        return false;
    }

    // get pointer to mesh 0
    const aiMesh* pMesh = pScene->mMeshes[0];

    // store number of mesh vertices
    g_numberOfVertices = pMesh->mNumVertices;

    // if mesh contains vertex coordinates
    if (pMesh->HasPositions())
    {
        // allocate memory for vertices
        g_pMeshVertices = new Vertex[pMesh->mNumVertices];

        // read vertex coordinates and store in the array
        for (int i = 0; i < pMesh->mNumVertices; i++)
        {
            const aiVector3D* pVertexPos = &(pMesh->mVertices[i]);

            g_pMeshVertices[i].position[0] = (GLfloat)pVertexPos->x;
            g_pMeshVertices[i].position[1] = (GLfloat)pVertexPos->y;
            g_pMeshVertices[i].position[2] = (GLfloat)pVertexPos->z;
        }
    }

    // if mesh contains normals
    if (pMesh->HasNormals())
    {
        // read normals and store in the array
        for (int i = 0; i < pMesh->mNumVertices; i++)
        {
            const aiVector3D* pVertexNormal = &(pMesh->mNormals[i]);

            g_pMeshVertices[i].normal[0] = (GLfloat)pVertexNormal->x;
            g_pMeshVertices[i].normal[1] = (GLfloat)pVertexNormal->y;
            g_pMeshVertices[i].normal[2] = (GLfloat)pVertexNormal->z;
        }
    }

    // if mesh contains faces
    if (pMesh->HasFaces())
    {
        // store number of mesh faces
        g_numberOfFaces = pMesh->mNumFaces;

        // allocate memory for vertices
        g_pMeshIndices = new GLint[pMesh->mNumFaces * 3];

        // read normals and store in the array
        for (int i = 0; i < pMesh->mNumFaces; i++)
        {
            const aiFace* pFace = &(pMesh->mFaces[i]);

            g_pMeshIndices[i * 3] = (GLint)pFace->mIndices[0];
            g_pMeshIndices[i * 3 + 1] = (GLint)pFace->mIndices[1];
            g_pMeshIndices[i * 3 + 2] = (GLint)pFace->mIndices[2];
        }
    }

    // release the scene
    aiReleaseImport(pScene);

    return true;
}

static void init(GLFWwindow* window)
{
    glEnable(GL_DEPTH_TEST);    // enable depth buffer test

    // create and compile our GLSL program from the shader files
    g_shaderProgramID = loadShaders("PerFragLightingVS.vert", "PerFragLightingFS.frag");

    // find the location of shader variables
    GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
    GLuint normalIndex = glGetAttribLocation(g_shaderProgramID, "aNormal");
    g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
    g_M_Index = glGetUniformLocation(g_shaderProgramID, "uModelMatrix");
    g_viewPointIndex = glGetUniformLocation(g_shaderProgramID, "uViewPoint");

    g_lightPositionIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.position");
    g_lightAmbientIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.ambient");
    g_lightDiffuseIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.diffuse");
    g_lightSpecularIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.specular");
    g_lightShininessIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.shininess");
    g_lightAttenuationIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.attenuation");
    g_lightCutoffAngleIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.cutoffAngle");
    g_lightDirectionIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.direction");

    g_materialAmbientIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.ambient");
    g_materialDiffuseIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.diffuse");
    g_materialSpecularIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.specular");

    // initialise model matrix to the identity matrix
    for (int i = 0; i < MAX_PLANES; i++) { g_modelMatrix_plane[i] = glm::mat4(1.0f); }
    for (int i = 0; i < MAX_CUBES; i++) { g_modelMatrix_cube[i] = glm::mat4(1.0f); }
    for (int i = 0; i < 2; i++) { g_modelMatrix_mesh[i] = glm::mat4(1.0f); }

...

// Model Matrices - Mesh
    g_modelMatrix_mesh[0] = glm::scale(glm::vec3(0.3f, 0.3f, 0.3f));
    g_modelMatrix_mesh[1] = glm::translate(glm::vec3(0.0f, 1.0f, 0.0f)) * glm::scale(glm::vec3(0.3f, 0.3f, 0.3f));

    // set camera's view matrix
    g_camera.setViewMatrix(glm::vec3(0, 0, 3), glm::vec3(0, 0, 2), glm::vec3(0, 1, 0));

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    float aspectRatio = static_cast<float>(width) / height;

    // set camera's projection matrix
    g_camera.setProjectionMatrix(glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f));

    // load mesh
    load_mesh("models/WusonOBJ.obj");

// initialise light and material properties
    g_lightProperties.position = glm::vec4(0.0f, 2.0f, 0.0f, 1.0f);
    g_lightProperties.ambient = glm::vec4(0.2f, 0.2f, 0.2f, 1.0f);
    g_lightProperties.diffuse = glm::vec4(0.0f, 0.5f, 1.0f, 1.0f);
    g_lightProperties.specular = glm::vec4(0.0f, 0.5f, 1.0f, 1.0f);
    g_lightProperties.shininess = 10.0f;
    g_lightProperties.attenuation = glm::vec3(1.0f, 0.0f, 0.0f);
    //g_lightProperties.cutoffAngle = 45.0f;
    g_lightProperties.cutoffAngle = 180.0f;
    g_lightProperties.direction = glm::vec3(0.0f, -1.0f, 0.0f);

// Material Properties - Planes
    // Floor
    g_materialProperties.ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
    g_materialProperties.diffuse = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
    g_materialProperties.specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);

    // generate identifier for VBOs and copy data to GPU
// Planes
    glGenBuffers(1, &g_VBO[0]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices_plane), g_vertices_plane, GL_STATIC_DRAW);

    // generate identifiers for VAO
    glGenVertexArrays(1, &g_VAO[0]);

    // create VAO and specify VBO data
    glBindVertexArray(g_VAO[0]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
    glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
    glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));

    glEnableVertexAttribArray(positionIndex);   // enable vertex attributes
    glEnableVertexAttribArray(normalIndex);

// Cube
    // generate identifier for VBOs and copy data to GPU
    glGenBuffers(1, &g_VBO[1]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices_cube), g_vertices_cube, GL_STATIC_DRAW);

    // generate identifier for IBO and copy data to GPU
    glGenBuffers(1, &g_IBO[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices_cube), g_indices_cube, GL_STATIC_DRAW);

    // generate identifiers for VAO
    glGenVertexArrays(1, &g_VAO[1]);

    // create VAO and specify VBO data
    glBindVertexArray(g_VAO[1]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[0]);
    glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
    glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));

    glEnableVertexAttribArray(positionIndex);   // enable vertex attributes
    glEnableVertexAttribArray(normalIndex);

// Meshes
    // Taurus Mesh
    // generate identifier for VBOs and copy data to GPU
    glGenBuffers(1, &g_VBO[2]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*g_numberOfVertices, g_pMeshVertices, GL_STATIC_DRAW);

    // generate identifier for IBO and copy data to GPU
    glGenBuffers(1, &g_IBO[1]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 3 * g_numberOfFaces, g_pMeshIndices, GL_STATIC_DRAW);

    // generate identifiers for VAO
    glGenVertexArrays(1, &g_VAO[2]);

    // create VAO and specify VBO data
    glBindVertexArray(g_VAO[2]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[1]);
    glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
    glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));

    glEnableVertexAttribArray(positionIndex);   // enable vertex attributes
    glEnableVertexAttribArray(normalIndex);

    // Suzanne Mesh
    load_mesh("models/suzanne.obj");

    // generate identifier for VBOs and copy data to GPU
    glGenBuffers(1, &g_VBO[3]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[3]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*g_numberOfVertices, g_pMeshVertices, GL_STATIC_DRAW);

    // generate identifier for IBO and copy data to GPU
    glGenBuffers(1, &g_IBO[2]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[2]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 3 * g_numberOfFaces, g_pMeshIndices, GL_STATIC_DRAW);

    // generate identifiers for VAO
    glGenVertexArrays(1, &g_VAO[3]);

    // create VAO and specify VBO data
    glBindVertexArray(g_VAO[3]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[3]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[2]);
    glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
    glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));

    glEnableVertexAttribArray(positionIndex);   // enable vertex attributes
    glEnableVertexAttribArray(normalIndex);
}

// function used to render the scene
static void render_scene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer

    glUseProgram(g_shaderProgramID);    // use the shaders associated with the shader program

    glBindVertexArray(g_VAO[0]);        // make VAO active

// Material Properties - Planes
    glUniform4fv(g_materialAmbientIndex, 1, &g_materialProperties.ambient[0]);
    glUniform4fv(g_materialDiffuseIndex, 1, &g_materialProperties.diffuse[0]);
    glUniform4fv(g_materialSpecularIndex, 1, &g_materialProperties.specular[0]);

    glUniform4fv(g_lightPositionIndex, 1, &g_lightProperties.position[0]);
    glUniform4fv(g_lightAmbientIndex, 1, &g_lightProperties.ambient[0]);
    glUniform4fv(g_lightDiffuseIndex, 1, &g_lightProperties.diffuse[0]);
    glUniform4fv(g_lightSpecularIndex, 1, &g_lightProperties.specular[0]);
    glUniform1fv(g_lightShininessIndex, 1, &g_lightProperties.shininess);
    glUniform3fv(g_lightAttenuationIndex, 1, &g_lightProperties.attenuation[0]);
    glUniform1fv(g_lightCutoffAngleIndex, 1, &g_lightProperties.cutoffAngle);
    glUniform3fv(g_lightDirectionIndex, 1, &g_lightProperties.direction[0]);

    // set uniform shader variables
    glm::mat4 MVP = glm::mat4(1.0f);

...

// Draw Cubes
    // Table top + 4 Table legs
    for (int i = 0; i < (MAX_CUBES - 1); i++)
    {
        MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_cube[i];
        glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
        glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   // display the vertices based on their indices and primitive type
    }

    // Chair (Right)
    for (int i = 0; i < MAX_CUBES; i++)
    {
        MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() 
            * glm::translate(glm::vec3(1.5f, -0.2f, 0.0f)) * glm::scale(glm::vec3(0.7f, 0.7f, 0.7f)) * g_modelMatrix_cube[i];
        glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
        glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   // display the vertices based on their indices and primitive type
    }
    // Chair (Left)
    for (int i = 0; i < MAX_CUBES; i++)
    {
        MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix()
            * glm::rotate(glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f))
            * glm::translate(glm::vec3(1.5f, -0.2f, 0.0f)) * glm::scale(glm::vec3(0.7f, 0.7f, 0.7f)) * g_modelMatrix_cube[i];
        glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
        glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   // display the vertices based on their indices and primitive type
    }

    glBindVertexArray(g_VAO[2]);        // make VAO active

// Draw Meshes
    // Taurus
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_mesh[0];
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
    glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_mesh[0][0][0]);
    glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
    glDrawElements(GL_TRIANGLES, g_numberOfFaces * 3, GL_UNSIGNED_INT, 0);  // display the vertices based on their indices and primitive type

    glBindVertexArray(g_VAO[3]);        // make VAO active

    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_mesh[1];
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
    glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_mesh[1][0][0]);
    glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
    glDrawElements(GL_TRIANGLES, g_numberOfFaces * 3, GL_UNSIGNED_INT, 0);  // display the vertices based on their indices and primitive type

    glFlush();  // flush the pipeline
}

int main(void)
{
    ...

    // create spotlight entries
    TwAddVarRW(TweakBar, "Cutoff", TW_TYPE_FLOAT, &g_lightProperties.cutoffAngle, " group='Spotlight' min=-180.0 max=180.0 step=1.0 ");
    TwAddVarRW(TweakBar, "Direction: x", TW_TYPE_FLOAT, &g_lightProperties.direction[0], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
    TwAddVarRW(TweakBar, "Direction: y", TW_TYPE_FLOAT, &g_lightProperties.direction[1], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
    TwAddVarRW(TweakBar, "Direction: z", TW_TYPE_FLOAT, &g_lightProperties.direction[2], " group='Spotlight' min=-1.0 max=1.0 step=0.1");

    // initialise rendering states
    init(window);

    // the rendering loop
    while (!glfwWindowShouldClose(window))
    {
        g_camera.update(window);    // update camera

        if (g_wireFrame)
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

        render_scene();     // render the scene

        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

        TwDraw();           // draw tweak bar(s)

        glfwSwapBuffers(window);    // swap buffers
        glfwPollEvents();           // poll for events
    }

...

    exit(EXIT_SUCCESS);
}

顶点着色器

#version 330 core

// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aNormal;

// uniform input data
uniform mat4 uModelViewProjectionMatrix;
uniform mat4 uModelMatrix;

// output data (will be interpolated for each fragment)
out vec3 vNormal;
out vec3 vPosition;

void main()
{
    // set vertex position
    gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);

    // world space
    vPosition = (uModelMatrix * vec4(aPosition, 1.0)).xyz;
    vNormal = (uModelMatrix * vec4(aNormal, 0.0)).xyz;
}

片段着色器

#version 330 core

// interpolated values from the vertex shaders
in vec3 vNormal;
in vec3 vPosition;

// uniform input data
struct LightProperties
{
    vec4 position;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
    vec3 attenuation;
    float cutoffAngle;
    vec3 direction;
};

struct MaterialProperties
{
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
};

uniform LightProperties uLightingProperties;
uniform MaterialProperties uMaterialProperties;
uniform vec3 uViewPoint;

// output data
out vec3 fColor;

void main()
{
    // calculate vectors for lighting
    vec3 N = normalize(vNormal);
    vec3 L;
    float attenuation = 1.0f;

    // calculate the attenuation based on distance
    L = (uLightingProperties.position).xyz - vPosition;
    float distance = length(L);
    L = normalize(L);
    attenuation = 1/(uLightingProperties.attenuation.x 
        + uLightingProperties.attenuation.y * distance 
        + uLightingProperties.attenuation.z * distance * distance);

    vec3 V = normalize(uViewPoint - vPosition);
    vec3 R = reflect(-L, N);

    // the direction of the spotlight
    vec3 direction = normalize(uLightingProperties.direction);
    // the angle between the vector from the light to the fragment’s position and the spotlight’s direction
    float angle = degrees(acos(dot(-L, direction)));

    vec3 colour = vec3(0.0f, 0.0f, 0.0f);

    // only compute if angle is less than the cutoff angle
    if(angle <= uLightingProperties.cutoffAngle)
    {
        // calculate Phong lighting
        vec4 ambient  = uLightingProperties.ambient * uMaterialProperties.ambient;
        vec4 diffuse  = uLightingProperties.diffuse * uMaterialProperties.diffuse * max(dot(L, N), 0.0);
        vec4 specular = vec4(0.0f, 0.0f, 0.0f, 1.0f);

        if(dot(L, N) > 0.0f)
        {
            specular = uLightingProperties.specular * uMaterialProperties.specular 
                * pow(max(dot(V, R), 0.0), uLightingProperties.shininess);
        }

        colour = (attenuation * (diffuse + specular)).rgb + ambient.rgb;
        // fade the spotlight's intensity linearly with angle
        colour *= 1.0f - angle/uLightingProperties.cutoffAngle;
    }

    // set output color
    fColor = colour;    
}

2 个答案:

答案 0 :(得分:0)

在函数static void render_scene()中,有两个具有相同索引数的绘制调用,即g_numberOfFaces * 3。猴子和金牛座很可能有不同数量的指数。

这可能不是唯一的错误。我的猜测是,这与索引有某种关系,或者猴子会覆盖以前模型的一些数据。

我建议你制作a minimal example,以便其他人更容易阅读您的代码。此外,您没有显示顶点着色器。

答案 1 :(得分:0)

函数load_mesh从文件中读取数据并分配动态内存并将读取的数据存储在以下全局变量中:

Vertex* g_pMeshVertices = NULL;
GLint   g_numberOfVertices = 0;
GLint*  g_pMeshIndices = NULL;
GLint   g_numberOfFaces = 0;

如果您第二次使用函数load_mesh,则会覆盖第一次使用的数据。除此之外,g_pMeshVerticesg_pMeshIndices的已分配内存未被释放,导致内存泄漏的原因。

在您的代码中,这不会导致任何问题,因为您会立即创建一个数组缓冲区和一个绑定数据的元素数组缓冲区,但绘制网格所需的g_numberOfFaces除外。 对于整个 cow 网格,g_numberOfFaces为低,因为您首先阅读 cow 网格,然后您第二次阅读 monky 网格,并且 monky 网格的索引少于 cow 网格(g_numberOfFaces在读取 monky 网格时过度了。“ / p>

我建议使用方法class为网格数据创建load_mesh

class CMesh
{
public:

    Vertex* m_pMeshVertices = nullptr;
    GLint   m_numberOfVertices = 0;
    GLint*  m_pMeshIndices = nullptr;
    GLint   m_numberOfFaces = 0;

    CMesh(void) {}
    virtual ~CMesh()
    {
      delete m_pMeshVertices;
      delete m_pMeshIndices;
    }

    bool load_mesh( const char* fileName )
};  

这允许您为每个网格实例化一个单独的对象

CMesh monkey;
CMesh cow;

monkey.load_mesh("models/WusonOBJ.obj");
cow.load_mesh("models/suzanne.obj");

除此之外,您应该考虑使用std::vector而不是动态分配的数组:

#include <vector>

std::vector<Vertex> m_pMeshVertices;
std::vector<GLint>  m_pMeshIndices;

扩展答案

当然你可以使用数组:

const int c_noOfMesh = 2;
Vertex* g_pMeshVertices[c_noOfMesh]    = {nullptr}; 
GLint   g_numberOfVertices[c_noOfMesh] = {0};
GLint*  g_pMeshIndices[c_noOfMesh]     = {nullptr};   
GLint   g_numberOfFaces[c_noOfMesh]    = {0};

如果这样做,您应该向函数load_mesh添加一个新的输入参数,该参数指示读取的网格的索引。

bool load_mesh( int iMesh, const char* fileName )
{
    .....
    g_pMeshVertices[iMesh] = .....;
    g_numberOfVertices[iMesh] = .....;
    g_pMeshIndices[iMesh] = .....;
    g_numberOfFaces[iMesh] = .....;
    .....
}

load_mesh( 0, "models/WusonOBJ.obj" );
load_mesh( 1, "models/suzanne.obj" );