我正在尝试在我的程序中加载2个不同的网格(金牛座和猴子头)。两者都使用相同的load_mesh
函数。
我在load_mesh
函数中使用init
作为金牛座。此网格的顶点数据存储在g_pMeshVertices
中。它看起来像这样。
然后我加载了第二个,它看起来像这样(下图)。第二个网格(猴头)成功出现,但之前网格的一半消失了。
我做的是我再次使用load_mesh
函数,但是init
内的“猴头”。新网格的顶点也存储在g_pMeshVertices
中。但是,我创建了一个新的VBO和VAO来存储g_pMeshVertices
的新顶点,但它似乎正在影响我以前的网格。有人可以告诉我为什么吗?
这是我的代码
#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;
}
答案 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_pMeshVertices
和g_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" );