diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40b1428..078a000 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ add_executable(solver "renderer/buffer.c" "renderer/shader.c" "renderer/camera.c" - "objects/cube.c" "renderer/object.c" "util/dynarray.h" "util/dynarray.c" "scenes/spinning_cubes.h" "scenes/spinning_cubes.c") + "objects/cube.c" "renderer/object.c" "util/dynarray.h" "util/dynarray.c" "scenes/spinning_cubes.h" "scenes/spinning_cubes.c" "renderer/light/point_light.h" "renderer/light/ambient_light.h") target_include_directories(solver PRIVATE ${CMAKE_CURRENT_LIST_DIR} diff --git a/src/objects/cube.c b/src/objects/cube.c index c9fb10e..9ff5983 100644 --- a/src/objects/cube.c +++ b/src/objects/cube.c @@ -17,56 +17,121 @@ static int init_cube_object(void) } create_vao(vao); - float cube_vertices[] = { - -1.0f, -1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, - -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - 1.0f, 1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, + + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, + + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, + + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f }; attach_vertex_buffer(vao, cube_vertices, sizeof(cube_vertices)); unsigned cube_indices[] = { - 0, 1, 2, 2, 1, 3, - 1, 5, 6, 1, 6, 2, - 3, 2, 6, 3, 6, 7, - 4, 5, 1, 4, 1, 0, - 4, 0, 3, 4, 3, 7, - 7, 6, 5, 7, 5, 4 + 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35 }; attach_element_buffer(vao, cube_indices, sizeof(cube_indices)); VertexAttribute attributes[] = { + { GL_FLOAT, 3, sizeof(float) }, { GL_FLOAT, 3, sizeof(float) } }; - set_vertex_layout(vao, attributes, sizeof(attributes) / sizeof(VertexAttribute)); shader = create_shader( "#version 460 core\n" "" "layout (location = 0) in vec3 pos;" + "layout (location = 1) in vec3 normal;" + "" + "out vec3 frag_normal;" + "out vec3 frag_pos;" "" "uniform mat4 model;" "uniform mat4 view;" "uniform mat4 projection;" "" "void main() {" + " frag_normal = mat3(transpose(inverse(model))) * normal;" + " frag_pos = vec3(model * vec4(pos, 1.0));" " gl_Position = projection * view * model * vec4(pos, 1.0);" "}", "#version 460 core\n" "" + "in vec3 frag_pos;" + "in vec3 frag_normal;" + "" + "uniform vec3 ambient_color = vec3(1.0, 1.0, 1.0);" + "uniform float ambient_intens = 1.0f;" + "" + "uniform vec3 point_pos = vec3(0.0, 0.0, 0.0);" + "uniform vec3 point_col = vec3(1.0, 1.0, 1.0);" + "uniform float point_intens = 1.0f;" + "" + "uniform vec3 cam_pos = vec3(0.0, 0.0, 0.0);" + "float specular_strength = 0.5f;" + "" "uniform vec3 cube_color;" + "" "out vec4 FragColor;" "" "void main() {" - " FragColor = vec4(cube_color, 1.0);" + " vec3 ambient = ambient_intens * ambient_color;" + "" + " vec3 norm = normalize(frag_normal);" + " vec3 light_dir = normalize(point_pos - frag_pos);" + " float diff = max(dot(norm, light_dir), 0.0);" + " vec3 diffuse = diff * point_col;" + "" + " vec3 view_dir = normalize(cam_pos - frag_pos);" + " vec3 reflect_dir = reflect(-light_dir, norm);" + "" + " float spec = pow(max(dot(view_dir, reflect_dir), 0.0), 32);" + " vec3 specular = specular_strength * spec * point_col; " + "" + " vec3 result = (ambient + diffuse + specular) * cube_color;" + " FragColor = vec4(result, 1.0);" "}" ); if (shader == 0) @@ -125,7 +190,7 @@ int create_cube(Cube* cube) cube->object.shader = shader; cube->object.child = cube; - cube->object.on_shader_use = on_shader_bind; + cube->object.on_shader_use_obj = on_shader_bind; cube->object.on_update = on_update; cube->object.on_destroy = destroy_cube; diff --git a/src/renderer/light/ambient_light.h b/src/renderer/light/ambient_light.h new file mode 100644 index 0000000..848d1f9 --- /dev/null +++ b/src/renderer/light/ambient_light.h @@ -0,0 +1,12 @@ +#ifndef AMBIENT_LIGHT_H +#define AMBIENT_LIGHT_H + +#include + +typedef struct AmbientLight +{ + vec3 color; + float intensity; +} AmbientLight; + +#endif \ No newline at end of file diff --git a/src/renderer/light/point_light.h b/src/renderer/light/point_light.h new file mode 100644 index 0000000..729da4d --- /dev/null +++ b/src/renderer/light/point_light.h @@ -0,0 +1,13 @@ +#ifndef POINT_LIGHT_H +#define POINT_LIGHT_H + +#include + +typedef struct PointLight +{ + vec3 color; + vec3 position; + float intensity; +} PointLight; + +#endif \ No newline at end of file diff --git a/src/renderer/object.c b/src/renderer/object.c index dbb4bd5..c3f6848 100644 --- a/src/renderer/object.c +++ b/src/renderer/object.c @@ -34,7 +34,8 @@ void render_object(Object* obj, Camera* camera) set_uniform_mat4(obj->shader, "view", get_camera_view(camera)); set_uniform_mat4(obj->shader, "projection", camera->projection); - obj->on_shader_use(obj->child); + obj->on_shader_use_obj(obj->child); + obj->on_shader_use_scene(obj, obj->scene); ctx_draw_elements(obj->vao); } diff --git a/src/renderer/object.h b/src/renderer/object.h index a32063f..100f62f 100644 --- a/src/renderer/object.h +++ b/src/renderer/object.h @@ -19,7 +19,9 @@ typedef struct Object vec3 scale; void* child; - void(*on_shader_use)(void*); + void* scene; + void(*on_shader_use_obj)(void*); + void(*on_shader_use_scene)(void*, void*); void(*on_update)(void*); void(*on_destroy)(void*); } Object; diff --git a/src/renderer/shader.c b/src/renderer/shader.c index bd5c720..9462458 100644 --- a/src/renderer/shader.c +++ b/src/renderer/shader.c @@ -99,6 +99,12 @@ void set_uniform_mat4(Shader shader, const char* name, mat4 mat) glUniformMatrix4fv(location, 1, GL_FALSE, (float*)mat); } +void set_uniform_float(Shader shader, const char* name, float val) +{ + int location = glGetUniformLocation(shader, name); + glUniform1f(location, val); +} + void set_uniform_vec3(Shader shader, const char* name, vec3 vec) { int location = glGetUniformLocation(shader, name); diff --git a/src/renderer/shader.h b/src/renderer/shader.h index 30693cb..7dab914 100644 --- a/src/renderer/shader.h +++ b/src/renderer/shader.h @@ -11,6 +11,7 @@ void destroy_shader(Shader shader); void bind_shader(Shader shader); void set_uniform_mat4(Shader shader, const char* name, mat4 mat); +void set_uniform_float(Shader shader, const char* name, float val); void set_uniform_vec3(Shader shader, const char* name, vec3 vec); #endif // SHADER_H \ No newline at end of file diff --git a/src/renderer/window.c b/src/renderer/window.c index d5f8fbf..e9e65bb 100644 --- a/src/renderer/window.c +++ b/src/renderer/window.c @@ -34,7 +34,7 @@ int create_managed_window(Window* window, const char* title, int width, int heig glfwMakeContextCurrent(window->window); ctx_init(); ctx_enable(GL_DEPTH_TEST); - ctx_front_face(GL_CW); + // ctx_front_face(GL_CW); glfwSetFramebufferSizeCallback(window->window, default_framebuffer_size_callback); diff --git a/src/scene.c b/src/scene.c index 35befbe..5378996 100644 --- a/src/scene.c +++ b/src/scene.c @@ -8,6 +8,20 @@ #include "objects/cube.h" +static void set_lighting_uniforms(Object* obj, Scene* scene) +{ + Shader shader = obj->shader; + + set_uniform_vec3(shader, "ambient_color", scene->ambient_light.color); + set_uniform_float(shader, "ambient_intens", scene->ambient_light.intensity); + + set_uniform_vec3(shader, "point_pos", scene->point_light.position); + set_uniform_vec3(shader, "point_col", scene->point_light.color); + set_uniform_float(shader, "point_intens", scene->point_light.intensity); + + set_uniform_vec3(shader, "cam_pos", scene->camera.object.position); +} + int create_scene(Scene* scene) { assert(scene); @@ -37,6 +51,9 @@ void destroy_scene(Scene scene) void scene_add_object(Scene* scene, Object* object) { assert(scene); + + object->scene = scene; + object->on_shader_use_scene = set_lighting_uniforms; dynamic_array_push(&scene->objects, (void*)&object); } diff --git a/src/scene.h b/src/scene.h index 031b270..8640c9b 100644 --- a/src/scene.h +++ b/src/scene.h @@ -5,11 +5,17 @@ #include "renderer/object.h" #include "util/dynarray.h" +#include "renderer/light/ambient_light.h" +#include "renderer/light/point_light.h" + typedef struct Scene { Camera camera; DynamicArray objects; + AmbientLight ambient_light; + PointLight point_light; + void* child; void(*on_update)(void*, double); double last_frame_start; diff --git a/src/scenes/spinning_cubes.c b/src/scenes/spinning_cubes.c index 6a7eb46..7ca7471 100644 --- a/src/scenes/spinning_cubes.c +++ b/src/scenes/spinning_cubes.c @@ -19,6 +19,8 @@ typedef struct SpinningCubes bool dragging; double drag_speed; double camera_distance; + + double time; } SpinningCubes; static void init_spinning_cubes_data(SpinningCubes* scene) @@ -28,6 +30,7 @@ static void init_spinning_cubes_data(SpinningCubes* scene) scene->camera_distance = 6.5f; scene->dragging = false; scene->drag_speed = 0.01f; + scene->time = 0.0f; } static void get_arcball_vector(vec3 dest, double width, double height, double x, double y) @@ -109,6 +112,13 @@ static void mouse_moved_callback(GLFWwindow* window, double xpos, double ypos) static void on_update(Scene* scene, double frametime) { + SpinningCubes* data = scene->child; + vec3 cam_pos = { 6.0f * sin(2.0f * data->time), 3.5f * cos(data->time), 6.0f * cos(2.0f * data->time)}; + + object_set_position(&scene->camera.object, cam_pos); + data->time += frametime; + + glm_vec3_copy(scene->camera.object.position, scene->point_light.position); } void create_spinning_cubes_scene(Window* window, Scene* scene) @@ -135,10 +145,17 @@ void create_spinning_cubes_scene(Window* window, Scene* scene) scene_add_object(scene, &obj->object); } - vec3 cam_pos = { 0.0f, 4.0f, -3.0 }; + vec3 cam_pos = { 0.0f, 3.5f, 3.0 }; object_set_position(&scene->camera.object, cam_pos); glm_vec3_zero(&scene->camera.look_at); + + glm_vec3_one(scene->ambient_light.color); + scene->ambient_light.intensity = 0.1f; + + glm_vec3_one(scene->point_light.color); + scene->point_light.intensity = 1.0f; + glfwSetMouseButtonCallback(window->window, mouse_button_callback); glfwSetCursorPosCallback(window->window, mouse_moved_callback); }