diff --git a/Makefile b/Makefile index 1b47404..eef3363 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CXX = g++ -CXXFLAGS = -std=c++11 -g -ggdb -Wall -I/usr/include/SDL2 -Iext/aixlog/include -Iext/stb_libs +CXXFLAGS = -std=c++11 -g -ggdb3 -Wall -I/usr/include/SDL2 -Iext/aixlog/include -Iext/stb_libs SRC_DIR = src OBJ_DIR = build diff --git a/data/default.fs b/data/default.fs index ef1d157..7c9e6ff 100644 --- a/data/default.fs +++ b/data/default.fs @@ -1,8 +1,11 @@ #version 330 core -in vec3 fragmentColor; +in vec3 fragColor; in vec3 fragNormal; in vec3 fragVertex; +in vec2 fragUV; + +out vec4 color; uniform mat4 model; uniform mat3 normal_matrix; @@ -17,7 +20,8 @@ struct point_light { uniform point_light lights[MAX_LIGHTS]; uniform uint num_lights = 0u; -out vec3 color; +uniform sampler2D sampler; + void main() { @@ -32,6 +36,8 @@ void main() totalBrightness += brightness; } - color = clamp(totalBrightness, 0, 1) * fragmentColor; + vec4 sampled_color = texture(sampler, fragUV.st); + color = clamp(totalBrightness, 0, 1) * sampled_color; + //color = clamp(totalBrightness, 0, 1) * fragColor; } diff --git a/data/default.vs b/data/default.vs index 0bbe9a8..b8911dd 100644 --- a/data/default.vs +++ b/data/default.vs @@ -3,10 +3,12 @@ layout (location = 0) in vec3 vertexPosition_modelspace; layout (location = 1) in vec3 vertexColor; layout (location = 2) in vec3 normal; +layout (location = 3) in vec3 texCoord; -out vec3 fragmentColor; +out vec3 fragColor; out vec3 fragNormal; out vec3 fragVertex; +out vec2 fragUV; uniform mat4 model; uniform mat4 view; @@ -14,9 +16,10 @@ uniform mat4 projection; void main() { - fragmentColor = vertexColor; + fragColor = vertexColor; fragNormal = normal; fragVertex = vertexPosition_modelspace; + fragUV = texCoord.st; gl_Position = projection * view * model * vec4(vertexPosition_modelspace, 1); } diff --git a/data/test.level.dae b/data/test.level.dae index 52bdf1b..f51d83a 100644 --- a/data/test.level.dae +++ b/data/test.level.dae @@ -5,8 +5,8 @@ Blender User Blender 2.79.0 commit date:2018-05-26, commit time:21:51, hash:32432d91bbe - 2018-12-24T11:48:15 - 2018-12-24T11:48:15 + 2018-12-24T10:36:57 + 2018-12-24T10:36:57 Z_UP @@ -16,7 +16,7 @@ - + @@ -29,21 +29,27 @@ - + + + 0 0 0 1 + + + 0 0 0 1 + - + - - 0 0 0 1 - - + + 1 + + - - + + @@ -81,7 +87,7 @@ - + @@ -98,9 +104,7 @@ - - - + diff --git a/src/mesh.cpp b/src/mesh.cpp index ed22eb4..adfa171 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -14,9 +14,14 @@ #include "mesh.h" +// forward declarations +meMeshInfo* allocateMeshInfo(uint num_vertices, uint num_indices, bool has_normals, bool has_texture); +void freeMesh(meMeshInfo* mesh); inline glm::vec3 copyVector(aiVector3D v_in, glm::vec3& v_out); meMeshInfo* copyMeshInfo(const char* data_dir, const aiScene* scene, aiMesh* mesh); -void freeMesh(meMeshInfo* mesh); + + +// interface bool meInitAssimp() @@ -75,6 +80,37 @@ meShutdownAssimp() aiDetachAllLogStreams(); } + +// internal + +meMeshInfo* +allocateMeshInfo(uint num_vertices, uint num_indices, bool has_normals, bool has_texture) +{ + meMeshInfo* mi = UTIL_ALLOC(1, meMeshInfo); + mi->model_transform = glm::mat4(1); + + // allocate buffers for vertex and index data from mesh + mi->num_vertices = num_vertices; + mi->vertices = UTIL_ALLOC(mi->num_vertices, glm::vec3); + mi->num_indices = num_indices; + mi->indices = UTIL_ALLOC(num_indices, uint); + if (has_normals) mi->normals = UTIL_ALLOC(mi->num_vertices, glm::vec3); + if (has_texture) mi->texture_coords = UTIL_ALLOC(mi->num_vertices, glm::vec3); + + return mi; +} + +void +freeMesh(meMeshInfo* mesh) +{ + utilFreeImage(mesh->diffuse_texture); + utilSafeFree(mesh->vertices); + utilSafeFree(mesh->normals); + utilSafeFree(mesh->texture_coords); + utilSafeFree(mesh->indices); + utilSafeFree(mesh); +} + inline glm::vec3 copyVector(aiVector3D v_in, glm::vec3& v_out) { @@ -87,22 +123,21 @@ copyVector(aiVector3D v_in, glm::vec3& v_out) meMeshInfo* copyMeshInfo(const char* data_dir, const aiScene* scene, aiMesh* mesh) { - meMeshInfo* mi = UTIL_ALLOC(1, meMeshInfo); - mi->model_transform = glm::mat4(1); + bool has_tex = mesh->HasTextureCoords(0); + bool has_normals = mesh->HasNormals(); + meMeshInfo* mi = allocateMeshInfo(mesh->mNumVertices, mesh->mNumFaces * 3, has_normals, has_tex); - // allocate buffers for vertex and index data from mesh - mi->num_vertices = mesh->mNumVertices; - mi->vertices = UTIL_ALLOC(mi->num_vertices, glm::vec3); - mi->normals = UTIL_ALLOC(mi->num_vertices, glm::vec3); - mi->num_indices = mesh->mNumFaces * 3; // NOTE: assume 3 vertices per face - mi->indices = UTIL_ALLOC(mi->num_indices, uint); - - // copy vertices and normals + // copy vertices, normals, and texture coords for (uint i = 0; i < mi->num_vertices; i++) { copyVector(mesh->mVertices[i], mi->vertices[i]); - if (mesh->HasNormals()) + if (has_normals) copyVector(mesh->mNormals[i], mi->normals[i]); + + if (has_tex) { + mi->texture_coords[i].x = mesh->mTextureCoords[0][i].x; + mi->texture_coords[i].y = mesh->mTextureCoords[0][i].y; + } } // copy indices @@ -113,9 +148,8 @@ copyMeshInfo(const char* data_dir, const aiScene* scene, aiMesh* mesh) // material aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; aiColor3D color(0.f, 0.f, 0.f); - if (AI_SUCCESS != mat->Get(AI_MATKEY_COLOR_DIFFUSE, color)) { - LOG(ERROR) << "Some Assimp-type-error\n"; - } else { + + if (AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE, color)) { mi->diffuse_color.r = color.r; mi->diffuse_color.g = color.g; mi->diffuse_color.b = color.b; @@ -130,21 +164,9 @@ copyMeshInfo(const char* data_dir, const aiScene* scene, aiMesh* mesh) file_path.append(data_dir).append("/").append(file_name.C_Str()); LOG(INFO) << "Loading texture file: " << file_name.C_Str() << "\n"; mi->diffuse_texture = utilLoadImage(file_path.c_str()); + mi->use_texture = true; } } return mi; } - -void -freeMesh(meMeshInfo* mesh) -{ - if (mesh->diffuse_texture.pixels != 0) - utilFreeImage(mesh->diffuse_texture); - - utilSafeFree(mesh->vertices); - utilSafeFree(mesh->normals); - utilSafeFree(mesh->indices); - utilSafeFree(mesh); -} - diff --git a/src/mesh.h b/src/mesh.h index fca6e14..a07d04f 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -15,10 +15,12 @@ struct meMeshInfo uint num_vertices = 0; glm::vec3* vertices = nullptr; glm::vec3* normals = nullptr; + glm::vec3* texture_coords = nullptr; // NOTE: using vec3 to stay aligned with other props uint num_indices = 0; uint* indices = nullptr; glm::vec3 diffuse_color; + bool use_texture = false; util_image diffuse_texture; }; diff --git a/src/render_group.cpp b/src/render_group.cpp index b7e48cd..1406e12 100644 --- a/src/render_group.cpp +++ b/src/render_group.cpp @@ -20,7 +20,8 @@ render_object * allocateRenderObject(uint buffer_len, uint index_len = 0); void freeRenderObject(render_object* ro); -bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals); +bool initGLTexture(render_object* ro, util_image image); +bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture); void sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target); @@ -72,6 +73,7 @@ rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char sp.projection_matrix_id = glGetUniformLocation(sp.program_id, "projection"); sp.normal_matrix_id = glGetUniformLocation(sp.program_id, "normal_matrix"); sp.num_lights_id = glGetUniformLocation(sp.program_id, "num_lights"); + sp.sampler_id = glGetUniformLocation(sp.program_id, "sampler"); glDetachShader(sp.program_id, vertex_shader_id); glDetachShader(sp.program_id, fragment_shader_id); @@ -121,17 +123,27 @@ rgInitEntity(Entity* e) for (uint i = 0; i < num_meshes; i++) { - uint buffer_len = e->mesh_group.meshes[i]->num_vertices * 3; - uint index_len = e->mesh_group.meshes[i]->num_indices; + meMeshInfo* mesh = e->mesh_group.meshes[i]; + uint buffer_len = mesh->num_vertices * 3; + uint index_len = mesh->num_indices; rg->render_objects[i] = allocateRenderObject(buffer_len, index_len); + render_object* ro = rg->render_objects[i]; - if (rg->render_objects[i] == nullptr) + if (ro == nullptr) return false; - if (!convertMeshInfo(e->mesh_group.meshes[i], rg->render_objects[i], rg->use_normals)) { + if (!convertMeshInfo(mesh, ro, rg->use_normals, mesh->use_texture)) { rgFree(rg); return false; } + + if (mesh->use_texture) { + ro->use_texture = true; + if (!initGLTexture(ro, mesh->diffuse_texture)) { + LOG(ERROR) << "Error initializing GL texture\n"; + return false; + } + } } return true; @@ -210,6 +222,14 @@ rgDraw(render_group* rg, glm::mat4 model_matrix, } } + if (ro->use_texture) { + glEnableVertexAttribArray(3); + glBindBuffer(GL_ARRAY_BUFFER, ro->uv_buffer.buffer_id); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + glBindTexture(GL_TEXTURE_2D, ro->tex_id); + glUniform1i(rg->shader.sampler_id, 0); + } + // draw if (rg->draw_indexed) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ro->index_buffer.buffer_id); @@ -224,6 +244,8 @@ rgDraw(render_group* rg, glm::mat4 model_matrix, glDisableVertexAttribArray(1); if (rg->use_normals) glDisableVertexAttribArray(2); + if (ro->use_texture) + glDisableVertexAttribArray(3); glUseProgram(0); } @@ -261,6 +283,8 @@ allocateRenderObject(uint buffer_len, uint index_len) ro->normal_buffer.buffer_len = buffer_len; ro->color_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat); ro->color_buffer.buffer_len = buffer_len; + ro->uv_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat); + ro->uv_buffer.buffer_len = buffer_len; if (index_len > 0) { ro->index_buffer.buffer = UTIL_ALLOC(index_len, uint); @@ -282,40 +306,38 @@ allocateRenderObject(uint buffer_len, uint index_len) void freeRenderObject(render_object* ro) { + if (ro == nullptr) { + LOG(ERROR) << "Tried to free nullptr\n"; + return; + } + utilSafeFree(ro->vertex_buffer.buffer); utilSafeFree(ro->normal_buffer.buffer); utilSafeFree(ro->color_buffer.buffer); + utilSafeFree(ro->uv_buffer.buffer); utilSafeFree(ro->index_buffer.buffer); utilSafeFree(ro); } -void -sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target) -{ - glGenBuffers(1, &index_buffer->buffer_id); - glBindBuffer(target, index_buffer->buffer_id); - glBufferData(target, index_buffer->buffer_len * sizeof(uint), index_buffer->buffer, usage); -} - bool -convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals) +convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture) { uint vertex_buf_len = mesh->num_vertices * 3; GLfloat* vertex_buf = ro->vertex_buffer.buffer; GLfloat* color_buf = ro->color_buffer.buffer; GLfloat* normal_buf = ro->normal_buffer.buffer; + GLfloat* uv_buf = ro->uv_buffer.buffer; uint* index_buf = ro->index_buffer.buffer; if (!vertex_buf || !color_buf || !normal_buf || !index_buf) return false; - // dump vertices, colors, and normals into render_group buffers + // dump vertices, colors, normals, and texture coords into render_group buffers uint vertex_index = 0; uint vertex_prop_index = 0; for (uint i = 0; i < vertex_buf_len; i++) { const glm::vec3& vertex = mesh->vertices[vertex_index]; - const glm::vec3& normal = mesh->normals[vertex_index]; switch (vertex_prop_index) { case 0: vertex_buf[i] = vertex.x; break; @@ -324,6 +346,7 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals) } if (use_normals) { + const glm::vec3& normal = mesh->normals[vertex_index]; switch (vertex_prop_index) { case 0: normal_buf[i] = normal.x; break; case 1: normal_buf[i] = normal.y; break; @@ -331,6 +354,15 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals) } } + if (use_texture) { + const glm::vec3& uv = mesh->texture_coords[vertex_index]; + switch (vertex_prop_index) { + case 0: uv_buf[i] = uv.x; break; + case 1: uv_buf[i] = uv.y; break; + case 2: uv_buf[i] = uv.z; break; + } + } + color_buf[i] = mesh->diffuse_color[vertex_prop_index]; vertex_prop_index++; @@ -348,8 +380,34 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals) rgBufferData(&ro->color_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); if (use_normals) rgBufferData(&ro->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); + if (use_texture) + rgBufferData(&ro->uv_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); sendIndexBufferToGL(&ro->index_buffer, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); return true; } +bool +initGLTexture(render_object* ro, util_image image) +{ + glGenTextures(1, &ro->tex_id); + glBindTexture(GL_TEXTURE_2D, ro->tex_id); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + GLenum pixel_format = (image.num_channels == 3) ? GL_RGB : GL_RGBA; + glTexImage2D(GL_TEXTURE_2D, 0, pixel_format, image.w, image.h, 0, + pixel_format, GL_UNSIGNED_BYTE, image.pixels); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + return (glGetError() == GL_NO_ERROR); +} + +void +sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target) +{ + glGenBuffers(1, &index_buffer->buffer_id); + glBindBuffer(target, index_buffer->buffer_id); + glBufferData(target, index_buffer->buffer_len * sizeof(uint), index_buffer->buffer, usage); +} + + diff --git a/src/render_group.h b/src/render_group.h index e59a0b5..3f68af5 100644 --- a/src/render_group.h +++ b/src/render_group.h @@ -24,25 +24,32 @@ struct gl_index_buffer uint* buffer = nullptr; }; -struct render_object -{ - gl_buffer vertex_buffer; - gl_buffer normal_buffer; - gl_buffer color_buffer; - gl_index_buffer index_buffer; -}; - struct rg_shader_program { GLuint program_id = 0; + GLuint model_matrix_id = 0; GLuint view_matrix_id = 0; GLuint projection_matrix_id = 0; GLuint normal_matrix_id = 0; + GLuint vertex_array_id = 0; + GLuint sampler_id = 0; GLuint num_lights_id = 0; }; +struct render_object +{ + bool use_texture = false; + GLuint tex_id = 0; + + gl_buffer vertex_buffer; + gl_buffer normal_buffer; + gl_buffer color_buffer; + gl_buffer uv_buffer; + gl_index_buffer index_buffer; +}; + struct render_group { uint num_objects = 0;