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;