diff options
author | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-03-14 21:54:55 +1100 |
---|---|---|
committer | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-03-14 21:54:55 +1100 |
commit | 6c581ff56dfcc22c25538e305e58efd967dd640a (patch) | |
tree | add8415857a0a7799d06778f3479601007a20e01 | |
parent | 7b9ef1066e49fe3e0c7791e097b26445f0f35f3d (diff) |
lights, camera, action
-rw-r--r-- | assets/shaders/blinn_phong.frag | 76 | ||||
-rw-r--r-- | examples/obj_loading/ex_obj_loading.c | 39 | ||||
-rw-r--r-- | src/renderer/render.c | 48 | ||||
-rw-r--r-- | src/renderer/render.h | 2 | ||||
-rw-r--r-- | src/renderer/render_types.h | 34 | ||||
-rw-r--r-- | src/resources/obj.c | 23 | ||||
-rw-r--r-- | xmake.lua | 3 |
7 files changed, 205 insertions, 20 deletions
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/ex_obj_loading.c b/examples/obj_loading/ex_obj_loading.c index bdadd7e..02ed606 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(); @@ -22,6 +31,30 @@ int main() { vec3 camera_pos = vec3(3., 4., 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 +63,10 @@ int main() { render_frame_begin(&core->renderer); - // Draw the cube - transform cube_tf = + // Draw the backpack + transform model_tf = transform_create(VEC3_ZERO, quat_ident(), 2.0); // make the backpack a bit bigger - draw_model(&core->renderer, &cam, backpack, cube_tf); + draw_model(&core->renderer, &cam, backpack, model_tf, &our_scene); render_frame_end(&core->renderer); } diff --git a/src/renderer/render.c b/src/renderer/render.c index dc541d2..1c979e5 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 746dfce..483e392 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -78,6 +78,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; @@ -90,8 +111,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 */ @@ -121,6 +140,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..221e3aa 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -35,7 +35,7 @@ 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); @@ -182,7 +182,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 +262,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 +279,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 +337,12 @@ bool load_material_lib(const char *path, material_darray *materials) { // specular exponent sscanf(pch + offset, "%f", ¤t_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 +350,13 @@ bool load_material_lib(const char *path, material_darray *materials) { texture_data_upload(¤t_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; @@ -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") |