summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--assets/models/obj/cube/cube.mtl2
-rw-r--r--assets/shaders/blinn_phong.frag76
-rw-r--r--examples/obj_loading/backpack_screenshot.pngbin0 -> 2404274 bytes
-rw-r--r--examples/obj_loading/ex_obj_loading.c39
-rw-r--r--src/platform/path.c9
-rw-r--r--src/platform/path.h2
-rw-r--r--src/renderer/render.c48
-rw-r--r--src/renderer/render.h2
-rw-r--r--src/renderer/render_types.h34
-rw-r--r--src/resources/obj.c37
-rw-r--r--src/std/mem.c6
-rw-r--r--src/std/mem.h1
-rw-r--r--xmake.lua3
14 files changed, 229 insertions, 32 deletions
diff --git a/README.md b/README.md
index ef09262..db00078 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# celeritas-core
+![Backpack model with lighting](examples/obj_loading/backpack_screenshot.png)
+
Not all files are fleshed out right now.
**Work-in-progress**: porting over code from old repository.
diff --git a/assets/models/obj/cube/cube.mtl b/assets/models/obj/cube/cube.mtl
index 9a17b69..aa04436 100644
--- a/assets/models/obj/cube/cube.mtl
+++ b/assets/models/obj/cube/cube.mtl
@@ -10,4 +10,4 @@ Ke 0.0 0.0 0.0
Ni 1.450000
d 1.000000
illum 2
-map_Kd models/obj/cube/container.jpg
+map_Kd container.jpg
diff --git a/assets/shaders/blinn_phong.frag b/assets/shaders/blinn_phong.frag
index a284948..095b19a 100644
--- a/assets/shaders/blinn_phong.frag
+++ b/assets/shaders/blinn_phong.frag
@@ -9,6 +9,25 @@ struct Material {
float shininess;
};
+struct DirLight {
+ vec3 direction;
+ vec3 ambient;
+ vec3 diffuse;
+ vec3 specular;
+};
+
+struct PointLight {
+ vec3 position;
+ // fall off properties
+ float constant;
+ float linear;
+ float quadratic;
+
+ vec3 ambient;
+ vec3 diffuse;
+ vec3 specular;
+};
+
in VS_OUT {
vec3 FragPos;
vec3 Normal;
@@ -16,6 +35,61 @@ in VS_OUT {
vec4 FragPosLightSpace;
} fs_in;
+// --- Uniforms
+#define NUM_POINT_LIGHTS 4
+uniform vec3 viewPos;
+uniform Material material;
+uniform DirLight dirLight;
+uniform PointLight pointLights[NUM_POINT_LIGHTS];
+
+// --- Function prototypes
+vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
+vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
+
void main() {
- FragColor = vec4(1.0);
+ vec3 norm = normalize(fs_in.Normal);
+ vec3 viewDir = normalize(viewPos - fs_in.FragPos);
+
+ vec3 result = CalcDirLight(dirLight, norm, viewDir);
+ for (int i = 0; i < 4; i++) {
+ result += CalcPointLight(pointLights[i], norm, fs_in.FragPos, viewDir);
+ }
+
+ FragColor = vec4(result, 1.0);
+}
+
+vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
+{
+ vec3 lightDir = normalize(-light.direction);
+ // diffuse shading
+ float diff = max(dot(normal, lightDir), 0.0);
+ // specular shading
+ vec3 reflectDir = reflect(-lightDir, normal);
+ float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
+ // combine result
+ vec3 ambient = light.ambient * vec3(texture(material.diffuse, fs_in.TexCoords));
+ vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, fs_in.TexCoords));
+ vec3 specular = light.specular * spec * vec3(texture(material.specular, fs_in.TexCoords));
+ return (ambient + diffuse + specular);
+}
+
+vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
+{
+ vec3 lightDir = normalize(light.position - fragPos);
+ // diffuse
+ float diff = max(dot(normal, lightDir), 0.0);
+ // specular
+ vec3 reflectDir = reflect(-lightDir, normal);
+ float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
+ // attentuation
+ float distance = length(light.position - fragPos);
+ float attentuation = 1.0 / (light.constant + light.linear * distance * light.quadratic * (distance * distance));
+ // result
+ vec3 ambient = light.ambient * vec3(texture(material.diffuse, fs_in.TexCoords));
+ vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, fs_in.TexCoords));
+ vec3 specular = light.specular * spec * vec3(texture(material.specular, fs_in.TexCoords));
+ ambient *= attentuation;
+ diffuse *= attentuation;
+ specular *= attentuation;
+ return (ambient + diffuse + specular);
} \ No newline at end of file
diff --git a/examples/obj_loading/backpack_screenshot.png b/examples/obj_loading/backpack_screenshot.png
new file mode 100644
index 0000000..a16b1f2
--- /dev/null
+++ b/examples/obj_loading/backpack_screenshot.png
Binary files differ
diff --git a/examples/obj_loading/ex_obj_loading.c b/examples/obj_loading/ex_obj_loading.c
index bdadd7e..6e63938 100644
--- a/examples/obj_loading/ex_obj_loading.c
+++ b/examples/obj_loading/ex_obj_loading.c
@@ -1,4 +1,5 @@
#include <glfw3.h>
+#include <string.h>
#include "camera.h"
#include "core.h"
@@ -7,6 +8,14 @@
#include "render.h"
#include "render_types.h"
+const vec3 pointlight_positions[4] = {
+ { 0.7, 0.2, 2.0 },
+ { 2.3, -3.3, -4.0 },
+ { -4.0, 2.0, -12.0 },
+ { 0.0, 0.0, -3.0 },
+};
+point_light point_lights[4];
+
int main() {
core* core = core_bringup();
@@ -19,9 +28,29 @@ int main() {
// 2. upload vertex data to gpu
model_upload_meshes(&core->renderer, backpack);
// 3. create a camera
- vec3 camera_pos = vec3(3., 4., 10.);
+ vec3 camera_pos = vec3(3., 2., 10.);
vec3 camera_front = vec3_normalise(vec3_negate(camera_pos));
camera cam = camera_create(camera_pos, camera_front, VEC3_Y, deg_to_rad(45.0));
+ // 4. create lights
+
+ // directional (sun) light setup
+ directional_light dir_light = { .direction = (vec3){ -0.2, -1.0, -0.3 },
+ .ambient = (vec3){ 0.2, 0.2, 0.2 },
+ .diffuse = (vec3){ 0.5, 0.5, 0.5 },
+ .specular = (vec3){ 1.0, 1.0, 1.0 } };
+ // point lights setup
+ for (int i = 0; i < 4; i++) {
+ point_lights[i].position = pointlight_positions[i];
+ point_lights[i].ambient = (vec3){ 0.05, 0.05, 0.05 };
+ point_lights[i].diffuse = (vec3){ 0.8, 0.8, 0.8 };
+ point_lights[i].specular = (vec3){ 1.0, 1.0, 1.0 };
+ point_lights[i].constant = 1.0;
+ point_lights[i].linear = 0.09;
+ point_lights[i].quadratic = 0.032;
+ }
+
+ scene our_scene = { .dir_light = dir_light, .n_point_lights = 4 };
+ memcpy(&our_scene.point_lights, &point_lights, sizeof(point_light[4]));
// --- Enter Main loop
while (!glfwWindowShouldClose(core->renderer.window)) {
@@ -30,10 +59,10 @@ int main() {
render_frame_begin(&core->renderer);
- // Draw the cube
- transform cube_tf =
- transform_create(VEC3_ZERO, quat_ident(), 2.0); // make the backpack a bit bigger
- draw_model(&core->renderer, &cam, backpack, cube_tf);
+ // Draw the backpack
+ transform model_tf = transform_create(vec3(0.0, -0.4, 0.0), quat_ident(),
+ 1.8); // make the backpack a bit bigger
+ draw_model(&core->renderer, &cam, backpack, model_tf, &our_scene);
render_frame_end(&core->renderer);
}
diff --git a/src/platform/path.c b/src/platform/path.c
index e67102b..9572941 100644
--- a/src/platform/path.c
+++ b/src/platform/path.c
@@ -1,12 +1,17 @@
#include "path.h"
#include <libgen.h>
+#include <stdlib.h>
#include <string.h>
+#include "mem.h"
#include "str.h"
#if defined(CEL_PLATFORM_LINUX) || defined(CEL_PLATFORM_MAC)
-path_opt path_parent(const char* path) {
- char* path_dirname = dirname(path);
+path_opt path_parent(arena* a, const char* path) {
+ // Duplicate the string because dirname doesnt like const literals
+ char* path_copy = arena_alloc(a, strlen(path) + 1);
+ strcpy(path_copy, path);
+ char* path_dirname = dirname(path_copy);
return (path_opt){ .path = str8_cstr_view(path_dirname), .has_value = true };
}
#endif
diff --git a/src/platform/path.h b/src/platform/path.h
index 0ec6993..73063ea 100644
--- a/src/platform/path.h
+++ b/src/platform/path.h
@@ -13,4 +13,4 @@ typedef struct path_opt {
bool has_value;
} path_opt;
-path_opt path_parent(const char* path); // TODO: convert to using str8 \ No newline at end of file
+path_opt path_parent(arena* a, const char* path); // TODO: convert to using str8 \ No newline at end of file
diff --git a/src/renderer/render.c b/src/renderer/render.c
index dc541d2..7884db6 100644
--- a/src/renderer/render.c
+++ b/src/renderer/render.c
@@ -80,7 +80,7 @@ void default_material_init() {
texture_data_upload(&DEFAULT_MATERIAL.specular_texture);
}
-void draw_model(renderer* ren, camera* camera, model* model, transform tf) {
+void draw_model(renderer* ren, camera* camera, model* model, transform tf, scene* scene) {
// TRACE("Drawing model: %s", model->name);
mat4 view;
mat4 proj;
@@ -88,13 +88,22 @@ void draw_model(renderer* ren, camera* camera, model* model, transform tf) {
set_shader(ren->blinn_phong);
+ // set camera uniform
+ uniform_vec3f(ren->blinn_phong.program_id, "viewPos", &camera->position);
+ // set light uniforms
+ dir_light_upload_uniforms(ren->blinn_phong, &scene->dir_light);
+ for (int i = 0; i < scene->n_point_lights; i++) {
+ point_light_upload_uniforms(ren->blinn_phong, &scene->point_lights[i], '0' + i);
+ }
+
for (size_t i = 0; i < mesh_darray_len(model->meshes); i++) {
mesh* m = &model->meshes->data[i];
if (vertex_darray_len(m->vertices) == 0) {
continue;
}
// TRACE("Drawing mesh %d", i);
- draw_mesh(ren, m, tf, &(DEFAULT_MATERIAL), &view, &proj);
+ material* mat = &model->materials->data[m->material_index];
+ draw_mesh(ren, m, tf, mat, &view, &proj);
}
}
@@ -127,8 +136,6 @@ void draw_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* vie
void model_upload_meshes(renderer* ren, model* model) {
INFO("Upload mesh vertex data to GPU for model %s", model->name);
- // DEBUG("Loading model with handle %d", model_handle.raw);
- // model m = models->data[model_handle.raw];
size_t num_meshes = mesh_darray_len(model->meshes);
u32 VBOs[num_meshes];
@@ -148,7 +155,7 @@ void model_upload_meshes(renderer* ren, model* model) {
glBindBuffer(GL_ARRAY_BUFFER, VBOs[mesh_i]);
size_t num_vertices = vertex_darray_len(model->meshes->data[mesh_i].vertices);
- TRACE("Uploading vertex array data: %d verts", num_vertices);
+ // TRACE("Uploading vertex array data: %d verts", num_vertices);
total_verts += num_vertices;
// TODO: convert this garbage into a function
@@ -256,3 +263,34 @@ void texture_data_upload(texture* tex) {
DEBUG("Freeing texture image data after uploading to GPU");
// stbi_image_free(tex->image_data); // data is on gpu now so we dont need it around
}
+
+void dir_light_upload_uniforms(shader shader, directional_light* light) {
+ uniform_vec3f(shader.program_id, "dirLight.direction", &light->direction);
+ uniform_vec3f(shader.program_id, "dirLight.ambient", &light->ambient);
+ uniform_vec3f(shader.program_id, "dirLight.diffuse", &light->diffuse);
+ uniform_vec3f(shader.program_id, "dirLight.specular", &light->specular);
+}
+
+void point_light_upload_uniforms(shader shader, point_light* light, char index) {
+ char position_str[] = "pointLights[x].position";
+ position_str[12] = (char)index;
+ char ambient_str[] = "pointLights[x].ambient";
+ ambient_str[12] = (char)index;
+ char diffuse_str[] = "pointLights[x].diffuse";
+ diffuse_str[12] = (char)index;
+ char specular_str[] = "pointLights[x].specular";
+ specular_str[12] = (char)index;
+ char constant_str[] = "pointLights[x].constant";
+ constant_str[12] = (char)index;
+ char linear_str[] = "pointLights[x].linear";
+ linear_str[12] = (char)index;
+ char quadratic_str[] = "pointLights[x].quadratic";
+ quadratic_str[12] = (char)index;
+ uniform_vec3f(shader.program_id, position_str, &light->position);
+ uniform_vec3f(shader.program_id, ambient_str, &light->ambient);
+ uniform_vec3f(shader.program_id, diffuse_str, &light->diffuse);
+ uniform_vec3f(shader.program_id, specular_str, &light->specular);
+ uniform_f32(shader.program_id, constant_str, light->constant);
+ uniform_f32(shader.program_id, linear_str, light->linear);
+ uniform_f32(shader.program_id, quadratic_str, light->quadratic);
+} \ No newline at end of file
diff --git a/src/renderer/render.h b/src/renderer/render.h
index 35c2d91..10702e3 100644
--- a/src/renderer/render.h
+++ b/src/renderer/render.h
@@ -17,7 +17,7 @@ void render_frame_end(renderer* ren);
// --- models meshes
void model_upload_meshes(renderer* ren, model* model);
-void draw_model(renderer* ren, camera* camera, model* model, transform tf);
+void draw_model(renderer* ren, camera* camera, model* model, transform tf, scene* scene);
void draw_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* view, mat4* proj);
// ---
diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h
index 3cba2ea..aed18db 100644
--- a/src/renderer/render_types.h
+++ b/src/renderer/render_types.h
@@ -79,6 +79,27 @@ KITC_DECL_TYPED_ARRAY(material) // creates "material_darray"
#define TYPED_MATERIAL_ARRAY
#endif
+// lights
+typedef struct point_light {
+ vec3 position;
+ f32 constant, linear, quadratic;
+ vec3 ambient;
+ vec3 diffuse;
+ vec3 specular;
+} point_light;
+
+typedef struct directional_light {
+ vec3 direction;
+ vec3 ambient;
+ vec3 diffuse;
+ vec3 specular;
+} directional_light;
+
+void point_light_upload_uniforms(shader shader, point_light *light, char index);
+void dir_light_upload_uniforms(shader shader, directional_light *light);
+
+// --- Models & Meshes
+
/** @brief Vertex format for a static mesh */
typedef struct vertex {
vec3 position;
@@ -91,8 +112,6 @@ KITC_DECL_TYPED_ARRAY(vertex) // creates "vertex_darray"
#define TYPED_VERTEX_ARRAY
#endif
-// --- Models & Meshes
-
typedef struct mesh {
vertex_darray *vertices;
u32 vertex_size; /** size in bytes of each vertex including necessary padding */
@@ -122,6 +141,17 @@ KITC_DECL_TYPED_ARRAY(model) // creates "model_darray"
#define TYPED_MODEL_ARRAY
#endif
+// --- Scene
+
+// NOTE: This struct won't stay like this for a long time. It's somewhat temporary
+// in order to get a basic scene working without putting burden on the caller of
+// draw_model()
+typedef struct scene {
+ directional_light dir_light;
+ point_light point_lights[4];
+ size_t n_point_lights;
+} scene;
+
// --- Graphics API related
typedef enum cel_primitive_topology {
diff --git a/src/resources/obj.c b/src/resources/obj.c
index 658967e..c6e9fa6 100644
--- a/src/resources/obj.c
+++ b/src/resources/obj.c
@@ -15,6 +15,7 @@
#include "file.h"
#include "log.h"
#include "maths.h"
+#include "mem.h"
#include "path.h"
#include "render.h"
#include "render_types.h"
@@ -35,21 +36,21 @@ KITC_DECL_TYPED_ARRAY(face)
void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray *tmp_normals,
vec2_darray *tmp_uvs, face_darray *tmp_faces, material_darray *materials,
bool material_loaded, char current_material_name[256]);
-bool load_material_lib(const char *path, material_darray *materials);
+bool load_material_lib(const char *path, str8 relative_path, material_darray *materials);
bool model_load_obj_str(const char *file_string, str8 relative_path, model *out_model,
bool invert_textures_y);
model_handle model_load_obj(core *core, const char *path, bool invert_textures_y) {
+ size_t arena_size = 1024;
+ arena scratch = arena_create(malloc(arena_size), arena_size);
+
TRACE("Loading model at Path %s\n", path);
- path_opt relative_path = path_parent(path);
+ path_opt relative_path = path_parent(&scratch, path);
if (!relative_path.has_value) {
WARN("Couldnt get a relative path for the path to use for loading materials & textures later");
}
- printf("Relative path: %s\n", relative_path.path.buf);
const char *file_string = string_from_file(path);
- // TODO: store the relative path without the name.obj at the end
-
model model = { 0 };
model.name = str8_cstr_view(path);
model.meshes = mesh_darray_new(1);
@@ -64,6 +65,9 @@ model_handle model_load_obj(core *core, const char *path, bool invert_textures_y
u32 index = model_darray_len(core->models);
model_darray_push(core->models, model);
+
+ arena_free_all(&scratch);
+ arena_free_storage(&scratch);
return (model_handle){ .raw = index };
}
@@ -182,7 +186,7 @@ bool model_load_obj_str(const char *file_string, str8 relative_path, model *out_
sscanf(pch + offset, "%s", filename);
char mtllib_path[1024];
snprintf(mtllib_path, sizeof(mtllib_path), "%s/%s", relative_path.buf, filename);
- if (!load_material_lib(mtllib_path, out_model->materials)) {
+ if (!load_material_lib(mtllib_path, relative_path, out_model->materials)) {
ERROR("couldnt load material lib");
return false;
}
@@ -262,7 +266,6 @@ void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray
material_darray_iter mat_iter = material_darray_iter_new(materials);
blinn_phong_material *cur_material;
while ((cur_material = material_darray_iter_next(&mat_iter))) {
- printf("Material name %s vs %s \n", cur_material->name, current_material_name);
if (strcmp(cur_material->name, current_material_name) == 0) {
DEBUG("Found match");
m.material_index = mat_iter.current_idx - 1;
@@ -280,7 +283,7 @@ void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray
mesh_darray_push(meshes, m);
}
-bool load_material_lib(const char *path, material_darray *materials) {
+bool load_material_lib(const char *path, str8 relative_path, material_darray *materials) {
TRACE("BEGIN load material lib at %s", path);
const char *file_string = string_from_file(path);
@@ -338,9 +341,13 @@ bool load_material_lib(const char *path, material_darray *materials) {
// specular exponent
sscanf(pch + offset, "%f", &current_material.spec_exponent);
} else if (strcmp(line_header, "map_Kd") == 0) {
- char diffuse_map_path[1024] = "assets/";
- sscanf(pch + offset, "%s", diffuse_map_path + 7);
+ char diffuse_map_filename[1024];
+ sscanf(pch + offset, "%s", diffuse_map_filename);
+ char diffuse_map_path[1024];
+ snprintf(diffuse_map_path, sizeof(diffuse_map_path), "%s/%s", relative_path.buf,
+ diffuse_map_filename);
printf("load from %s\n", diffuse_map_path);
+
// --------------
texture diffuse_texture = texture_data_load(diffuse_map_path, true);
current_material.diffuse_texture = diffuse_texture;
@@ -348,8 +355,14 @@ bool load_material_lib(const char *path, material_darray *materials) {
texture_data_upload(&current_material.diffuse_texture);
// --------------
} else if (strcmp(line_header, "map_Ks") == 0) {
- char specular_map_path[1024] = "assets/";
- sscanf(pch + offset, "%s", specular_map_path + 7);
+ // char specular_map_path[1024] = "assets/";
+ // sscanf(pch + offset, "%s", specular_map_path + 7);
+ char specular_map_filename[1024];
+ sscanf(pch + offset, "%s", specular_map_filename);
+ char specular_map_path[1024];
+ snprintf(specular_map_path, sizeof(specular_map_path), "%s/%s", relative_path.buf,
+ specular_map_filename);
+ printf("load from %s\n", specular_map_path);
// --------------
texture specular_texture = texture_data_load(specular_map_path, true);
current_material.specular_texture = specular_texture;
diff --git a/src/std/mem.c b/src/std/mem.c
index f5b92d4..d7c0f4c 100644
--- a/src/std/mem.c
+++ b/src/std/mem.c
@@ -16,7 +16,7 @@ void* arena_alloc_align(arena* a, size_t size, size_t align) {
ERROR_EXIT("Arena ran out of memory\n");
}
void* p = a->begin + padding;
- a->begin += padding + size;
+ a->curr += padding + size;
return memset(p, 0, size);
}
void* arena_alloc(arena* a, size_t size) { return arena_alloc_align(a, size, DEFAULT_ALIGNMENT); }
@@ -29,4 +29,6 @@ arena arena_create(void* backing_buffer, size_t capacity) {
void arena_free_all(arena* a) {
a->curr = a->begin; // pop everything at once and reset to the start.
-} \ No newline at end of file
+}
+
+void arena_free_storage(arena* a) { free(a->begin); } \ No newline at end of file
diff --git a/src/std/mem.h b/src/std/mem.h
index c3ec61d..2f92894 100644
--- a/src/std/mem.h
+++ b/src/std/mem.h
@@ -22,4 +22,5 @@ arena arena_create(void* backing_buffer, size_t capacity);
void* arena_alloc(arena* a, size_t size);
void* arena_alloc_align(arena* a, size_t size, size_t align);
void arena_free_all(arena* a);
+void arena_free_storage(arena* a);
// TODO: arena_resize \ No newline at end of file
diff --git a/xmake.lua b/xmake.lua
index 0f039e7..2a899dd 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -14,8 +14,11 @@ add_cflags("-Wall", "-Wextra", "-Wundef", "-Wdouble-promotion")
if is_mode("debug") then
add_cflags("-g") -- Add debug symbols in debug mode
+elseif is_mode("release") then
+ add_defines("CRELEASE")
end
+
-- Platform defines and system packages
if is_plat("linux") then
add_defines("CEL_PLATFORM_LINUX")