From f9ad6fa902c1167d7622ee7af2617d14b62bee21 Mon Sep 17 00:00:00 2001 From: pryazha Date: Wed, 19 Feb 2025 22:26:48 +0500 Subject: quite a lot of changes that I, of course, are not going to describe;) --- advanced_lighting/1.blinn_phong/blinn_phong.c | 364 ++++------- .../1.blinn_phong/shaders/blinn_phong.frag | 40 ++ .../1.blinn_phong/shaders/blinn_phong.fs | 44 -- .../1.blinn_phong/shaders/blinn_phong.vert | 22 + .../1.blinn_phong/shaders/blinn_phong.vs | 23 - advanced_lighting/1.blinn_phong/shaders/light.frag | 8 + advanced_lighting/1.blinn_phong/shaders/light.fs | 9 - advanced_lighting/1.blinn_phong/shaders/light.vert | 11 + advanced_lighting/1.blinn_phong/shaders/light.vs | 12 - .../2.gamma_correction/gamma_correction.c | 450 +++++--------- .../2.gamma_correction/shaders/blinn_phong.frag | 55 ++ .../2.gamma_correction/shaders/blinn_phong.fs | 58 -- .../2.gamma_correction/shaders/blinn_phong.vert | 22 + .../2.gamma_correction/shaders/blinn_phong.vs | 23 - .../2.gamma_correction/shaders/light.frag | 8 + .../2.gamma_correction/shaders/light.fs | 9 - .../2.gamma_correction/shaders/light.vert | 11 + .../2.gamma_correction/shaders/light.vs | 12 - advanced_lighting/3.1.shadow_mapping/build.sh | 2 +- .../3.1.shadow_mapping/shaders/color.frag | 8 + .../3.1.shadow_mapping/shaders/color.fs | 9 - .../3.1.shadow_mapping/shaders/color.vert | 11 + .../3.1.shadow_mapping/shaders/color.vs | 12 - .../3.1.shadow_mapping/shaders/debug_quad.frag | 25 + .../3.1.shadow_mapping/shaders/debug_quad.fs | 27 - .../3.1.shadow_mapping/shaders/debug_quad.vert | 14 + .../3.1.shadow_mapping/shaders/debug_quad.vs | 14 - .../3.1.shadow_mapping/shaders/shadow.frag | 70 +++ .../3.1.shadow_mapping/shaders/shadow.fs | 72 --- .../3.1.shadow_mapping/shaders/shadow.vert | 25 + .../3.1.shadow_mapping/shaders/shadow.vs | 26 - .../3.1.shadow_mapping/shaders/simple_depth.frag | 5 + .../3.1.shadow_mapping/shaders/simple_depth.fs | 6 - .../3.1.shadow_mapping/shaders/simple_depth.vert | 10 + .../3.1.shadow_mapping/shaders/simple_depth.vs | 11 - .../3.1.shadow_mapping/shadow_mapping.c | 668 ++++++++------------- advanced_lighting/3.2.point_shadows/point_shadows | Bin 1065440 -> 1289368 bytes .../3.2.point_shadows/point_shadows.c | 620 ++++++++----------- .../3.2.point_shadows/shaders/depth.frag | 13 + .../3.2.point_shadows/shaders/depth.fs | 14 - .../3.2.point_shadows/shaders/depth.geom | 20 + .../3.2.point_shadows/shaders/depth.gs | 27 - .../3.2.point_shadows/shaders/depth.vert | 9 + .../3.2.point_shadows/shaders/depth.vs | 10 - .../3.2.point_shadows/shaders/shadow.frag | 103 ++++ .../3.2.point_shadows/shaders/shadow.fs | 105 ---- .../3.2.point_shadows/shaders/shadow.vert | 28 + .../3.2.point_shadows/shaders/shadow.vs | 29 - advanced_lighting/4.normal_mapping/normal_mapping | Bin 1289656 -> 1289432 bytes .../4.normal_mapping/normal_mapping.c | 521 ++++++++-------- .../4.normal_mapping/shaders/color.frag | 8 + .../4.normal_mapping/shaders/color.vert | 11 + .../4.normal_mapping/shaders/depth.fs | 14 - .../4.normal_mapping/shaders/depth.gs | 27 - .../4.normal_mapping/shaders/depth.vs | 10 - .../4.normal_mapping/shaders/normal_map.frag | 51 ++ .../4.normal_mapping/shaders/normal_map.vert | 36 ++ .../4.normal_mapping/shaders/normals_debug.frag | 10 + .../4.normal_mapping/shaders/normals_debug.geom | 44 ++ .../4.normal_mapping/shaders/normals_debug.vert | 22 + .../4.normal_mapping/shaders/shadow.fs | 105 ---- .../4.normal_mapping/shaders/shadow.vs | 29 - 62 files changed, 1737 insertions(+), 2325 deletions(-) create mode 100644 advanced_lighting/1.blinn_phong/shaders/blinn_phong.frag delete mode 100644 advanced_lighting/1.blinn_phong/shaders/blinn_phong.fs create mode 100644 advanced_lighting/1.blinn_phong/shaders/blinn_phong.vert delete mode 100644 advanced_lighting/1.blinn_phong/shaders/blinn_phong.vs create mode 100644 advanced_lighting/1.blinn_phong/shaders/light.frag delete mode 100644 advanced_lighting/1.blinn_phong/shaders/light.fs create mode 100644 advanced_lighting/1.blinn_phong/shaders/light.vert delete mode 100644 advanced_lighting/1.blinn_phong/shaders/light.vs create mode 100644 advanced_lighting/2.gamma_correction/shaders/blinn_phong.frag delete mode 100644 advanced_lighting/2.gamma_correction/shaders/blinn_phong.fs create mode 100644 advanced_lighting/2.gamma_correction/shaders/blinn_phong.vert delete mode 100644 advanced_lighting/2.gamma_correction/shaders/blinn_phong.vs create mode 100644 advanced_lighting/2.gamma_correction/shaders/light.frag delete mode 100644 advanced_lighting/2.gamma_correction/shaders/light.fs create mode 100644 advanced_lighting/2.gamma_correction/shaders/light.vert delete mode 100644 advanced_lighting/2.gamma_correction/shaders/light.vs create mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/color.frag delete mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/color.fs create mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/color.vert delete mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/color.vs create mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.frag delete mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.fs create mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.vert delete mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.vs create mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/shadow.frag delete mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/shadow.fs create mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/shadow.vert delete mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/shadow.vs create mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.frag delete mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.fs create mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.vert delete mode 100644 advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.vs create mode 100644 advanced_lighting/3.2.point_shadows/shaders/depth.frag delete mode 100644 advanced_lighting/3.2.point_shadows/shaders/depth.fs create mode 100644 advanced_lighting/3.2.point_shadows/shaders/depth.geom delete mode 100644 advanced_lighting/3.2.point_shadows/shaders/depth.gs create mode 100644 advanced_lighting/3.2.point_shadows/shaders/depth.vert delete mode 100644 advanced_lighting/3.2.point_shadows/shaders/depth.vs create mode 100644 advanced_lighting/3.2.point_shadows/shaders/shadow.frag delete mode 100644 advanced_lighting/3.2.point_shadows/shaders/shadow.fs create mode 100644 advanced_lighting/3.2.point_shadows/shaders/shadow.vert delete mode 100644 advanced_lighting/3.2.point_shadows/shaders/shadow.vs create mode 100644 advanced_lighting/4.normal_mapping/shaders/color.frag create mode 100644 advanced_lighting/4.normal_mapping/shaders/color.vert delete mode 100644 advanced_lighting/4.normal_mapping/shaders/depth.fs delete mode 100644 advanced_lighting/4.normal_mapping/shaders/depth.gs delete mode 100644 advanced_lighting/4.normal_mapping/shaders/depth.vs create mode 100644 advanced_lighting/4.normal_mapping/shaders/normal_map.frag create mode 100644 advanced_lighting/4.normal_mapping/shaders/normal_map.vert create mode 100644 advanced_lighting/4.normal_mapping/shaders/normals_debug.frag create mode 100644 advanced_lighting/4.normal_mapping/shaders/normals_debug.geom create mode 100644 advanced_lighting/4.normal_mapping/shaders/normals_debug.vert delete mode 100644 advanced_lighting/4.normal_mapping/shaders/shadow.fs delete mode 100644 advanced_lighting/4.normal_mapping/shaders/shadow.vs (limited to 'advanced_lighting') diff --git a/advanced_lighting/1.blinn_phong/blinn_phong.c b/advanced_lighting/1.blinn_phong/blinn_phong.c index 6bbd70a..404df05 100644 --- a/advanced_lighting/1.blinn_phong/blinn_phong.c +++ b/advanced_lighting/1.blinn_phong/blinn_phong.c @@ -1,258 +1,134 @@ -#include "pwyazh.h" - #include "GL/glew.h" #include "GLFW/glfw3.h" +#include "pwyazh.h" #include "pwyazh_GL.h" #include "common.h" -static S32 global_width = 1024, global_height = 768; -static Input global_input; -static V3F camera_dp = (V3F){ 0.0f, 0.0f, 0.0f }; -static V3F light_pos = (V3F){ 0.0f, 0.0f, 0.0f }; -static S32 blinn = 0; - -void -key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +int main(void) { - switch (action) - { - case GLFW_PRESS: { - switch (key) - { - case GLFW_KEY_D: { - global_input.move_right.state = KeyState_PRESS; - } break; - case GLFW_KEY_W: { - global_input.move_forward.state = KeyState_PRESS; - } break; - case GLFW_KEY_A: { - global_input.move_left.state = KeyState_PRESS; - } break; - case GLFW_KEY_S: { - global_input.move_backward.state = KeyState_PRESS; - } break; - case GLFW_KEY_E: { - global_input.move_up.state = KeyState_PRESS; - } break; - case GLFW_KEY_Q: { - global_input.move_down.state = KeyState_PRESS; - } break; - case GLFW_KEY_SPACE: { - global_input.jump.state = KeyState_PRESS; - } break; - case GLFW_KEY_RIGHT: { - global_input.action_right.state = KeyState_PRESS; - } break; - case GLFW_KEY_UP: { - global_input.action_up.state = KeyState_PRESS; - } break; - case GLFW_KEY_LEFT: { - global_input.action_left.state = KeyState_PRESS; - } break; - case GLFW_KEY_ESCAPE: { - global_input.exit.state = KeyState_PRESS; - } break; - } - } break; - - case GLFW_RELEASE: { - switch (key) - { - case GLFW_KEY_D: { - global_input.move_right.state = KeyState_RELEASE; - } break; - case GLFW_KEY_W: { - global_input.move_forward.state = KeyState_RELEASE; - } break; - case GLFW_KEY_A: { - global_input.move_left.state = KeyState_RELEASE; - } break; - case GLFW_KEY_S: { - global_input.move_backward.state = KeyState_RELEASE; - } break; - case GLFW_KEY_E: { - global_input.move_up.state = KeyState_RELEASE; - } break; - case GLFW_KEY_Q: { - global_input.move_down.state = KeyState_RELEASE; - } break; - case GLFW_KEY_SPACE: { - global_input.jump.state = KeyState_RELEASE; - } break; - case GLFW_KEY_RIGHT: { - global_input.action_right.state = KeyState_RELEASE; - } break; - case GLFW_KEY_UP: { - global_input.action_up.state = KeyState_RELEASE; - } break; - case GLFW_KEY_LEFT: { - global_input.action_left.state = KeyState_RELEASE; - } break; - case GLFW_KEY_ESCAPE: { - global_input.exit.state = KeyState_RELEASE; - } break; - } - } break; - } -} + GLFWwindow *window; + State state; + S32 width, height; + Input input; + Arena *arena; + F64 time, last_time; + U32 texture; + S32 blinn = 0; + V3F light_pos = (V3F){ 0.0f, 0.0f, 0.0f }; -void -resize_callback(GLFWwindow* window, int width, int height) -{ - global_width = width; - global_height = height; - glViewport(0, 0, global_width, global_height); -} + glfwSetErrorCallback(error_callback); -void -error_callback(int error, const char *desc) -{ - fprintf(stderr, "[ERROR] GLFW: %s\n", desc); -} + if (glfwInit() == GLFW_FALSE) + return(1); -void -update(State *state) -{ - V3F camera_dv = get_dv_camera_orbital(&global_input, state->camera.pos, - v3f_zero(), state->dt, 2.0f); - if (key_is_pressed(global_input.action_up)) { - camera_dv = v3f_scalef(camera_dv, 3.0f); - } - camera_dp = v3f_add(camera_dp, camera_dv); - camera_dp = v3f_scalef(camera_dp, 0.7f); - state->camera.pos = v3f_add(state->camera.pos, camera_dp); - - if (key_first_press(global_input.jump)) - blinn = blinn ? 0 : 1; - - input_update_last_state(&global_input); -} + width = 1024; + height = 768; -void -render(State *state, U32 *shaders, U32 texture, Mesh **meshes) -{ - MAT4 projection, view, model; - U32 shader; - Mesh *mesh; - - glClearColor(0.15f, 0.15f, 0.15f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - projection = perspective(state->camera.fovx, (F32)global_width/(F32)global_height, - state->camera.near, state->camera.far); - view = look_at(state->camera.pos, v3f_zero(), v3f(0.0f, 1.0f, 0.0f)); - model = mat4_identity(); - - U32 mesh_index = 0; - shader = shaders[mesh_index]; - mesh = meshes[mesh_index]; - glUseProgram(shader); - shader_set_mat4fv(shader, "projection", projection); - shader_set_mat4fv(shader, "view", view); - shader_set_mat4fv(shader, "model", model); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); - shader_set_3fv(shader, "light_pos", light_pos); - shader_set_3fv(shader, "view_pos", state->camera.pos); - shader_set_1i(shader, "blinn", blinn); - mesh_draw(mesh); - mesh_index++; - - shader = shaders[mesh_index]; - mesh = meshes[mesh_index]; - glUseProgram(shader); - shader_set_mat4fv(shader, "projection", projection); - shader_set_mat4fv(shader, "view", view); - model = mat4_make_scale(v3f(0.1f, 0.1f, 0.1f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(mesh); - - glBindTexture(GL_TEXTURE_2D, 0); -} + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_SAMPLES, 4); + window = glfwCreateWindow(width, height, "Blinn-Phong shading", 0, 0); + if (!window) + goto error; -int -main(void) -{ - GLFWwindow *window; - Arena *arena; - State state; - Mesh *meshes[2]; - U32 shaders[2]; - F64 time, last_time; - U32 texture; - - glfwSetErrorCallback(error_callback); - - if (glfwInit() == GLFW_FALSE) - return(1); - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_SAMPLES, 4); - window = glfwCreateWindow(global_width, global_height, "Blinn-Phong shading", 0, 0); - if (!window) - goto error; - - glfwSetKeyCallback(window, key_callback); - glfwSetWindowSizeCallback(window, resize_callback); - - glfwMakeContextCurrent(window); - - if (glewInit() != GLEW_OK) - goto error; - - glEnable(GL_DEPTH_TEST); - glEnable(GL_MULTISAMPLE); - - /* NOTE(pryazha): init */ - arena = arena_alloc(Megabytes(64)); - - state.camera = (Camera){ v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 1000.0f }; - - Vertex vertices[] = { - // positions // normals // texcoords - vertex(v3f( 10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 0.0f)), - vertex(v3f(-10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 0.0f)), - vertex(v3f(-10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 10.0f)), - - vertex(v3f( 10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 0.0f)), - vertex(v3f(-10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 10.0f)), - vertex(v3f( 10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 10.0f)) - }; - U32 indices[] = { 0, 1, 2, 3, 4, 5 }; - meshes[0] = mesh_init(arena, vertices, 6, indices, 6); - meshes[1] = mesh_load_obj(arena, "../../data/models/cube.obj"); - - shaders[0] = create_shader_program("shaders/blinn_phong.vs", "shaders/blinn_phong.fs"); - shaders[1] = create_shader_program("shaders/light.vs", "shaders/light.fs"); - - texture = load_texture("../../data/textures/wood.png"); - - last_time = glfwGetTime(); - - while (!glfwWindowShouldClose(window)) - { - glfwPollEvents(); - if (key_first_press(global_input.exit)) - glfwSetWindowShouldClose(window, GLFW_TRUE); - update(&state); - render(&state, shaders, texture, meshes); - glfwSwapBuffers(window); - - time = glfwGetTime(); - state.dt = time-last_time; - last_time = time; -#if 0 - fprintf(stdout, "[INFO]: dt: %f\n", state.dt); -#endif - } - - glfwTerminate(); - return(0); - - error: - glfwTerminate(); - return(1); + glfwMakeContextCurrent(window); + + if (glewInit() != GLEW_OK) + goto error; + + glEnable(GL_DEPTH_TEST); + glEnable(GL_MULTISAMPLE); + + /* NOTE(pryazha): init */ + arena = arena_alloc(Megabytes(64)); + + state.camera = (Camera){ v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 1000.0f, 0.0f, 0.0f }; + + Vertex vertices[] = { + // positions // normals // texcoords + vertex(v3f( 10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 0.0f)), + vertex(v3f(-10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 0.0f)), + vertex(v3f(-10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 10.0f)), + + vertex(v3f( 10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 0.0f)), + vertex(v3f(-10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 10.0f)), + vertex(v3f( 10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 10.0f)) + }; + U32 indices[] = { 0, 1, 2, 3, 4, 5 }; + Mesh *quad = mesh_init(arena, vertices, 6, indices, 6); + Mesh *cube = mesh_load_obj(arena, "../../data/models/cube.obj"); + + U32 blinn_phong_shader = create_shader_program("shaders/blinn_phong.vert", "shaders/blinn_phong.frag"); + U32 light_shader = create_shader_program("shaders/light.vert", "shaders/light.frag"); + + texture = load_texture("../../data/textures/wood.png"); + + last_time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + /* INFO(pryazha): Update */ + process_glfw_keyboard(window, &input); + glfwGetFramebufferSize(window, &width, &height); + + V3F target = v3f_zero(); + + if (key_first_press(input.exit)) + glfwSetWindowShouldClose(window, GLFW_TRUE); + + if (key_first_press(input.jump)) + blinn = blinn ? 0 : 1; + + V3F dv = get_dv_camera_orbital(&input, state.camera.pos, + target, state.dt, 3.0f); + state.camera.pos = v3f_add(state.camera.pos, dv); + + input_update_last_state(&input); + + /* NOTE(pryazha): Render */ + MAT4 proj, view, model; + + view = look_at(state.camera.pos, target, v3f(0.0f, 1.0f, 0.0f)); + proj = perspective(state.camera.fovx, (F32)width/(F32)height, + state.camera.near, state.camera.far); + model = mat4_identity(); + + glViewport(0, 0, width, height); + glClearColor(0.15f, 0.15f, 0.15f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(blinn_phong_shader); + shader_set_mat4fv(blinn_phong_shader, "proj", proj); + shader_set_mat4fv(blinn_phong_shader, "view", view); + shader_set_mat4fv(blinn_phong_shader, "model", model); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture); + shader_set_3fv(blinn_phong_shader, "light_pos", light_pos); + shader_set_3fv(blinn_phong_shader, "view_pos", state.camera.pos); + shader_set_1i(blinn_phong_shader, "blinn", blinn); + mesh_draw(quad); + + glUseProgram(light_shader); + shader_set_mat4fv(light_shader, "proj", proj); + shader_set_mat4fv(light_shader, "view", view); + model = mat4_make_scale(v3f(0.1f, 0.1f, 0.1f)); + shader_set_mat4fv(light_shader, "model", model); + mesh_draw(cube); + + glfwSwapBuffers(window); + + time = glfwGetTime(); + state.dt = time-last_time; + last_time = time; + } + + glfwTerminate(); + return(0); + +error: + glfwTerminate(); + return(1); } diff --git a/advanced_lighting/1.blinn_phong/shaders/blinn_phong.frag b/advanced_lighting/1.blinn_phong/shaders/blinn_phong.frag new file mode 100644 index 0000000..80f3e47 --- /dev/null +++ b/advanced_lighting/1.blinn_phong/shaders/blinn_phong.frag @@ -0,0 +1,40 @@ +#version 330 core + +in VS_OUT { + vec3 frag_pos; + vec3 normal; + vec2 tex_coords; +} fs_in; + +out vec4 frag_color; + +uniform sampler2D texture0; +uniform vec3 light_pos; +uniform vec3 view_pos; +uniform bool blinn; + +void main(void) +{ + vec3 light_dir = normalize(light_pos-fs_in.frag_pos); + vec3 view_dir = normalize(view_pos-fs_in.frag_pos); + vec3 normal = normalize(fs_in.normal); + + vec3 texture_color = texture(texture0, fs_in.tex_coords).rgb; + + float diff = max(dot(normal, light_dir), 0.0); + + float spec = 0.0; + if (blinn) { + vec3 halfway_dir = normalize(light_dir+view_dir); + spec = pow(max(dot(normal, halfway_dir), 0.0), 16.0); + } else { + vec3 reflect_dir = reflect(-light_dir, normal); + spec = pow(max(dot(view_dir, reflect_dir), 0.0), 8.0); + } + + vec3 ambient = 0.05*texture_color; + vec3 diffuse = diff*texture_color; + vec3 specular = vec3(0.3)*spec; + + frag_color = vec4(ambient+diffuse+specular, 1.0); +} diff --git a/advanced_lighting/1.blinn_phong/shaders/blinn_phong.fs b/advanced_lighting/1.blinn_phong/shaders/blinn_phong.fs deleted file mode 100644 index 5c66b3e..0000000 --- a/advanced_lighting/1.blinn_phong/shaders/blinn_phong.fs +++ /dev/null @@ -1,44 +0,0 @@ -#version 330 core - -in VS_OUT { - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} fs_in; - -out vec4 frag_color; - -uniform sampler2D texture0; -uniform vec3 light_pos; -uniform vec3 view_pos; -uniform bool blinn; - -void -main(void) -{ - vec3 light_dir = normalize(light_pos-fs_in.frag_pos); - vec3 view_dir = normalize(view_pos-fs_in.frag_pos); - vec3 normal = normalize(fs_in.normal); - - vec3 texture_color = texture(texture0, fs_in.tex_coords).rgb; - - float diff = max(dot(normal, light_dir), 0.0); - - float spec = 0.0; - if (blinn) - { - vec3 halfway_dir = normalize(light_dir+view_dir); - spec = pow(max(dot(normal, halfway_dir), 0.0), 16.0); - } - else - { - vec3 reflect_dir = reflect(-light_dir, normal); - spec = pow(max(dot(view_dir, reflect_dir), 0.0), 8.0); - } - - vec3 ambient = 0.05*texture_color; - vec3 diffuse = diff*texture_color; - vec3 specular = vec3(0.3)*spec; - - frag_color = vec4(ambient+diffuse+specular, 1.0); -} diff --git a/advanced_lighting/1.blinn_phong/shaders/blinn_phong.vert b/advanced_lighting/1.blinn_phong/shaders/blinn_phong.vert new file mode 100644 index 0000000..870e7dc --- /dev/null +++ b/advanced_lighting/1.blinn_phong/shaders/blinn_phong.vert @@ -0,0 +1,22 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 2) in vec2 atex_coords; + +out VS_OUT { + vec3 frag_pos; + vec3 normal; + vec2 tex_coords; +} vs_out; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); + vs_out.normal = mat3(transpose(inverse(model)))*anormal; + vs_out.tex_coords = atex_coords; + gl_Position = proj*view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/1.blinn_phong/shaders/blinn_phong.vs b/advanced_lighting/1.blinn_phong/shaders/blinn_phong.vs deleted file mode 100644 index 4d1b792..0000000 --- a/advanced_lighting/1.blinn_phong/shaders/blinn_phong.vs +++ /dev/null @@ -1,23 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; -layout(location = 1) in vec3 anormal; -layout(location = 2) in vec2 atex_coords; - -out VS_OUT { - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} vs_out; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -void -main(void) -{ - vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); - vs_out.normal = mat3(transpose(inverse(model)))*anormal; - vs_out.tex_coords = atex_coords; - gl_Position = projection*view*model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/1.blinn_phong/shaders/light.frag b/advanced_lighting/1.blinn_phong/shaders/light.frag new file mode 100644 index 0000000..c01da99 --- /dev/null +++ b/advanced_lighting/1.blinn_phong/shaders/light.frag @@ -0,0 +1,8 @@ +#version 330 core + +out vec4 frag_color; + +void main(void) +{ + frag_color = vec4(1.0); +} diff --git a/advanced_lighting/1.blinn_phong/shaders/light.fs b/advanced_lighting/1.blinn_phong/shaders/light.fs deleted file mode 100644 index bd00d82..0000000 --- a/advanced_lighting/1.blinn_phong/shaders/light.fs +++ /dev/null @@ -1,9 +0,0 @@ -#version 330 core - -out vec4 frag_color; - -void -main(void) -{ - frag_color = vec4(1.0); -} diff --git a/advanced_lighting/1.blinn_phong/shaders/light.vert b/advanced_lighting/1.blinn_phong/shaders/light.vert new file mode 100644 index 0000000..a8b1247 --- /dev/null +++ b/advanced_lighting/1.blinn_phong/shaders/light.vert @@ -0,0 +1,11 @@ +#version 330 core +layout(location = 0) in vec3 apos; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + gl_Position = proj*view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/1.blinn_phong/shaders/light.vs b/advanced_lighting/1.blinn_phong/shaders/light.vs deleted file mode 100644 index ade669b..0000000 --- a/advanced_lighting/1.blinn_phong/shaders/light.vs +++ /dev/null @@ -1,12 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -void -main(void) -{ - gl_Position = projection*view*model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/2.gamma_correction/gamma_correction.c b/advanced_lighting/2.gamma_correction/gamma_correction.c index 68edae7..a027722 100644 --- a/advanced_lighting/2.gamma_correction/gamma_correction.c +++ b/advanced_lighting/2.gamma_correction/gamma_correction.c @@ -1,297 +1,171 @@ -#include "pwyazh.h" - #include "GL/glew.h" #include "GLFW/glfw3.h" +#include "pwyazh.h" #include "pwyazh_GL.h" #include "common.h" -static S32 global_width = 1024, global_height = 768; -static Input global_input; -static V3F camera_dp = (V3F){ 0.0f, 0.0f, 0.0f }; -static V3F light_pos = (V3F){ 0.0f, 0.0f, 0.0f }; -static U32 gamma_correction = 0; - -static V3F light_positions[] = { - (V3F){-3.0f, 0.0f, 0.0f}, - (V3F){-1.0f, 0.0f, 0.0f}, - (V3F){1.0f, 0.0f, 0.0f}, - (V3F){3.0f, 0.0f, 0.0} -}; -static V3F light_colors[] = { - (V3F){0.25f, 0.25f, 0.25f}, - (V3F){0.50f, 0.50f, 0.50f}, - (V3F){0.75f, 0.75f, 0.75f}, - (V3F){1.0f, 1.0f, 1.0} -}; - -void -key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - switch (action) - { - case GLFW_PRESS: { - switch (key) - { - case GLFW_KEY_D: { - global_input.move_right.state = KeyState_PRESS; - } break; - case GLFW_KEY_W: { - global_input.move_forward.state = KeyState_PRESS; - } break; - case GLFW_KEY_A: { - global_input.move_left.state = KeyState_PRESS; - } break; - case GLFW_KEY_S: { - global_input.move_backward.state = KeyState_PRESS; - } break; - case GLFW_KEY_E: { - global_input.move_up.state = KeyState_PRESS; - } break; - case GLFW_KEY_Q: { - global_input.move_down.state = KeyState_PRESS; - } break; - case GLFW_KEY_SPACE: { - global_input.jump.state = KeyState_PRESS; - } break; - case GLFW_KEY_RIGHT: { - global_input.action_right.state = KeyState_PRESS; - } break; - case GLFW_KEY_UP: { - global_input.action_up.state = KeyState_PRESS; - } break; - case GLFW_KEY_LEFT: { - global_input.action_left.state = KeyState_PRESS; - } break; - case GLFW_KEY_ESCAPE: { - global_input.exit.state = KeyState_PRESS; - } break; - } - } break; - - case GLFW_RELEASE: { - switch (key) - { - case GLFW_KEY_D: { - global_input.move_right.state = KeyState_RELEASE; - } break; - case GLFW_KEY_W: { - global_input.move_forward.state = KeyState_RELEASE; - } break; - case GLFW_KEY_A: { - global_input.move_left.state = KeyState_RELEASE; - } break; - case GLFW_KEY_S: { - global_input.move_backward.state = KeyState_RELEASE; - } break; - case GLFW_KEY_E: { - global_input.move_up.state = KeyState_RELEASE; - } break; - case GLFW_KEY_Q: { - global_input.move_down.state = KeyState_RELEASE; - } break; - case GLFW_KEY_SPACE: { - global_input.jump.state = KeyState_RELEASE; - } break; - case GLFW_KEY_RIGHT: { - global_input.action_right.state = KeyState_RELEASE; - } break; - case GLFW_KEY_UP: { - global_input.action_up.state = KeyState_RELEASE; - } break; - case GLFW_KEY_LEFT: { - global_input.action_left.state = KeyState_RELEASE; - } break; - case GLFW_KEY_ESCAPE: { - global_input.exit.state = KeyState_RELEASE; - } break; - } - } break; - } -} - -void -resize_callback(GLFWwindow* window, int width, int height) -{ - global_width = width; - global_height = height; - glViewport(0, 0, global_width, global_height); -} - -void -error_callback(int error, const char *desc) -{ - fprintf(stderr, "[ERROR] GLFW: %s\n", desc); -} - -void -update(State *state) -{ - V3F camera_dv = get_dv_camera_orbital(&global_input, state->camera.pos, - v3f_zero(), state->dt, 2.0f); - if (key_is_pressed(global_input.action_up)) - camera_dv = v3f_scalef(camera_dv, 3.0f); - camera_dp = v3f_add(camera_dp, camera_dv); - camera_dp = v3f_scalef(camera_dp, 0.7f); - state->camera.pos = v3f_add(state->camera.pos, camera_dp); - - if (key_first_press(global_input.action_right)) - gamma_correction = !gamma_correction; - - F32 time = glfwGetTime(); - for (S32 position_index = 0; - position_index < (S32)ArrayCount(light_positions); - position_index++) - { - F32 radius = position_index*2.0+2.0; - F32 angle = time*position_index*pi_F32/6.0; - F32 x = f32_sin(angle)*radius; - F32 z = f32_cos(angle)*radius; - light_positions[position_index] = v3f(x, light_positions[position_index].y, z); - } - - input_update_last_state(&global_input); -} - -void -render(State *state, U32 *shaders, U32 texture, U32 texture_gamma_corrected, Mesh **meshes) -{ - MAT4 projection, view, model; - U32 shader; - Mesh *mesh; - - glClearColor(0.15f, 0.15f, 0.15f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - projection = perspective(state->camera.fovx, (F32)global_width/(F32)global_height, - state->camera.near, state->camera.far); - view = look_at(state->camera.pos, v3f_zero(), v3f(0.0f, 1.0f, 0.0f)); - model = mat4_identity(); - - U32 mesh_index = 0; - shader = shaders[mesh_index]; - mesh = meshes[mesh_index]; - glUseProgram(shader); - shader_set_mat4fv(shader, "projection", projection); - shader_set_mat4fv(shader, "view", view); - shader_set_mat4fv(shader, "model", model); - if (gamma_correction) - glBindTexture(GL_TEXTURE_2D, texture_gamma_corrected); - else - glBindTexture(GL_TEXTURE_2D, texture); - shader_set_3fv(shader, "light_pos", light_pos); - shader_set_3fv(shader, "view_pos", state->camera.pos); - shader_set_1i(shader, "gamma_correction", gamma_correction); - U32 light_positions_location = glGetUniformLocation(shader, "light_positions"); - glUniform3fv(light_positions_location, 4, (F32 *)&light_positions[0]); - U32 light_colors_location = glGetUniformLocation(shader, "light_colors"); - glUniform3fv(light_colors_location, 4, (F32 *)&light_colors[0]); - mesh_draw(mesh); - mesh_index++; - - shader = shaders[mesh_index]; - mesh = meshes[mesh_index]; - glUseProgram(shader); - shader_set_mat4fv(shader, "projection", projection); - shader_set_mat4fv(shader, "view", view); - for (S32 light_index = 0; - light_index < (S32)ArrayCount(light_positions); - light_index++) - { - model = mat4_make_scale(v3f(0.1f, 0.1f, 0.1f)); - model = mat4_translate(model, light_positions[light_index]); - shader_set_mat4fv(shader, "model", model); - mesh_draw(mesh); - } - glBindTexture(GL_TEXTURE_2D, 0); -} - -int -main(void) +int main(void) { - GLFWwindow *window; - Arena *arena; - State state; - Mesh *meshes[2]; - U32 shaders[2]; - F64 time, last_time; - U32 texture, texture_gamma_corrected; - - glfwSetErrorCallback(error_callback); - - if (glfwInit() == GLFW_FALSE) - return(1); - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_SAMPLES, 4); - window = glfwCreateWindow(global_width, global_height, "Gamma correction", 0, 0); - if (!window) - goto error; - - glfwSetKeyCallback(window, key_callback); - glfwSetWindowSizeCallback(window, resize_callback); - - glfwMakeContextCurrent(window); - - if (glewInit() != GLEW_OK) - goto error; - - glEnable(GL_DEPTH_TEST); - glEnable(GL_MULTISAMPLE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - /* NOTE(pryazha): A less controlled method of applying gamma correction */ - /* glEnable(GL_FRAMEBUFFER_SRGB); */ - - /* NOTE(pryazha): init */ - arena = arena_alloc(Megabytes(64)); - - state.camera = (Camera){ v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 1000.0f }; - - Vertex vertices[] = { - // positions // normals // texcoords - vertex(v3f( 10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 0.0f)), - vertex(v3f(-10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 0.0f)), - vertex(v3f(-10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 10.0f)), - - vertex(v3f( 10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 0.0f)), - vertex(v3f(-10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 10.0f)), - vertex(v3f( 10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 10.0f)) - }; - U32 indices[] = { 0, 1, 2, 3, 4, 5 }; - meshes[0] = mesh_init(arena, vertices, 6, indices, 6); - meshes[1] = mesh_load_obj(arena, "../../data/models/cube.obj"); - - shaders[0] = create_shader_program("shaders/blinn_phong.vs", "shaders/blinn_phong.fs"); - shaders[1] = create_shader_program("shaders/light.vs", "shaders/light.fs"); - - texture = load_texture_gamma("../../data/textures/wood.png", 0); - texture_gamma_corrected = load_texture_gamma("../../data/textures/wood.png", 1); - - last_time = glfwGetTime(); - - while (!glfwWindowShouldClose(window)) - { - glfwPollEvents(); - if (key_first_press(global_input.exit)) - glfwSetWindowShouldClose(window, GLFW_TRUE); - update(&state); - render(&state, shaders, texture, texture_gamma_corrected, meshes); - glfwSwapBuffers(window); - - time = glfwGetTime(); - state.dt = time-last_time; - last_time = time; -#if 0 - fprintf(stdout, "[INFO]: dt: %f\n", state.dt); -#endif - } - - glfwTerminate(); - return(0); - - error: - glfwTerminate(); - return(1); + GLFWwindow *window; + Arena *arena; + State state; + Input input; + F64 time, last_time; + V3F light_pos = (V3F){ 0.0f, 0.0f, 0.0f }; + U32 gamma_correction = 0; + MAT4 proj, view, model; + S32 width, height; + B32 blinn; + + V3F light_positions[] = { + (V3F){-3.0f, 0.0f, 0.0f}, + (V3F){-1.0f, 0.0f, 0.0f}, + (V3F){1.0f, 0.0f, 0.0f}, + (V3F){3.0f, 0.0f, 0.0} + }; + V3F light_colors[] = { + (V3F){0.25f, 0.25f, 0.25f}, + (V3F){0.50f, 0.50f, 0.50f}, + (V3F){0.75f, 0.75f, 0.75f}, + (V3F){1.0f, 1.0f, 1.0} + }; + + glfwSetErrorCallback(error_callback); + + if (glfwInit() == GLFW_FALSE) + return(1); + + width = 1024; + height = 768; + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_SAMPLES, 4); + window = glfwCreateWindow(width, height, "Gamma correction", 0, 0); + if (!window) + goto error; + + glfwMakeContextCurrent(window); + + if (glewInit() != GLEW_OK) + goto error; + + glEnable(GL_DEPTH_TEST); + glEnable(GL_MULTISAMPLE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + /* NOTE(pryazha): A less controlled method of applying gamma correction */ + /* glEnable(GL_FRAMEBUFFER_SRGB); */ + + /* NOTE(pryazha): init */ + arena = arena_alloc(Megabytes(64)); + + state.camera = (Camera){ v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 1000.0f, 0.0f, 0.0f }; + + Vertex vertices[] = { + // positions // normals // texcoords + vertex(v3f( 10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 0.0f)), + vertex(v3f(-10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 0.0f)), + vertex(v3f(-10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 10.0f)), + + vertex(v3f( 10.0f, -0.5f, 10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 0.0f)), + vertex(v3f(-10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 10.0f)), + vertex(v3f( 10.0f, -0.5f, -10.0f), v3f(0.0f, 1.0f, 0.0f), v2f(10.0f, 10.0f)) + }; + U32 indices[] = { 0, 1, 2, 3, 4, 5 }; + Mesh *quad = mesh_init(arena, vertices, 6, indices, 6); + Mesh *cube = mesh_load_obj(arena, "../../data/models/cube.obj"); + + U32 blinn_phong_shader = create_shader_program("shaders/blinn_phong.vert", "shaders/blinn_phong.frag"); + U32 light_shader = create_shader_program("shaders/light.vert", "shaders/light.frag"); + + U32 texture = load_texture_gamma("../../data/textures/wood.png", 0); + U32 texture_gamma_corrected = load_texture_gamma("../../data/textures/wood.png", 1); + + last_time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + /* NOTE(pryazha): Update */ + process_glfw_keyboard(window, &input); + glfwGetFramebufferSize(window, &width, &height); + + V3F target = v3f_zero(); + + if (key_first_press(input.exit)) + glfwSetWindowShouldClose(window, GLFW_TRUE); + + if (key_first_press(input.jump)) + blinn = blinn ? 0 : 1; + + V3F dv = get_dv_camera_orbital(&input, state.camera.pos, + target, state.dt, 3.0f); + state.camera.pos = v3f_add(state.camera.pos, dv); + + if (key_first_press(input.action_right)) + gamma_correction = !gamma_correction; + + for (S32 i = 0; i < (S32)ArrayCount(light_positions); i++) { + F32 radius = i*2.0+2.0; + F32 angle = time*i*pi_F32/6.0; + F32 x = f32_sin(angle)*radius; + F32 z = f32_cos(angle)*radius; + light_positions[i] = v3f(x, light_positions[i].y, z); + } + + input_update_last_state(&input); + + proj = perspective(state.camera.fovx, (F32)width/(F32)height, + state.camera.near, state.camera.far); + view = look_at(state.camera.pos, v3f_zero(), v3f(0.0f, 1.0f, 0.0f)); + model = mat4_identity(); + + /* NOTE(pryazha): Render */ + glViewport(0, 0, width, height); + glClearColor(0.15f, 0.15f, 0.15f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(blinn_phong_shader); + shader_set_mat4fv(blinn_phong_shader, "proj", proj); + shader_set_mat4fv(blinn_phong_shader, "view", view); + shader_set_mat4fv(blinn_phong_shader, "model", model); + if (gamma_correction) + glBindTexture(GL_TEXTURE_2D, texture_gamma_corrected); + else + glBindTexture(GL_TEXTURE_2D, texture); + shader_set_3fv(blinn_phong_shader, "light_pos", light_pos); + shader_set_3fv(blinn_phong_shader, "view_pos", state.camera.pos); + shader_set_1i(blinn_phong_shader, "gamma_correction", gamma_correction); + U32 light_positions_location = glGetUniformLocation(blinn_phong_shader, "light_positions"); + glUniform3fv(light_positions_location, 4, (F32 *)&light_positions[0]); + U32 light_colors_location = glGetUniformLocation(blinn_phong_shader, "light_colors"); + glUniform3fv(light_colors_location, 4, (F32 *)&light_colors[0]); + mesh_draw(quad); + + glUseProgram(light_shader); + shader_set_mat4fv(light_shader, "proj", proj); + shader_set_mat4fv(light_shader, "view", view); + for (S32 i = 0; i < (S32)ArrayCount(light_positions); i++) { + model = mat4_make_scale(v3f(0.1f, 0.1f, 0.1f)); + model = mat4_translate(model, light_positions[i]); + shader_set_mat4fv(light_shader, "model", model); + mesh_draw(cube); + } + glBindTexture(GL_TEXTURE_2D, 0); + + glfwSwapBuffers(window); + + time = glfwGetTime(); + state.dt = time-last_time; + last_time = time; + } + + glfwTerminate(); + return(0); + +error: + glfwTerminate(); + return(1); } diff --git a/advanced_lighting/2.gamma_correction/shaders/blinn_phong.frag b/advanced_lighting/2.gamma_correction/shaders/blinn_phong.frag new file mode 100644 index 0000000..331fc8b --- /dev/null +++ b/advanced_lighting/2.gamma_correction/shaders/blinn_phong.frag @@ -0,0 +1,55 @@ +#version 330 core + +in VS_OUT { + vec3 frag_pos; + vec3 normal; + vec2 tex_coords; +} fs_in; + +out vec4 frag_color; + +uniform sampler2D texture0; +uniform vec3 light_positions[4]; +uniform vec3 light_colors[4]; +uniform vec3 view_pos; +uniform bool gamma_correction; + +vec3 blinn_phong(vec3 light_dir, vec3 view_dir, vec3 normal, + vec3 light_pos, vec3 light_color) +{ + float diff = max(dot(normal, light_dir), 0.0); + vec3 diffuse = diff*light_color; + + vec3 halfway_dir = normalize(light_dir+view_dir); + float spec = pow(max(dot(normal, halfway_dir), 0.0), 16.0); + vec3 specular = spec*light_color; + + float distance = length(light_pos-fs_in.frag_pos); + float attenuation = 1.0/(gamma_correction ? distance*distance : distance); + + return((diffuse+specular)*attenuation); +} + +void main(void) +{ + vec3 view_dir = normalize(view_pos-fs_in.frag_pos); + vec3 normal = normalize(fs_in.normal); + vec3 texture_color = texture(texture0, fs_in.tex_coords).rgb; + + vec3 lighting = vec3(0.0); + for (int i = 0; i < 4; i++) { + vec3 light_pos = light_positions[i]; + vec3 light_color = light_colors[i]; + vec3 light_dir = normalize(light_pos-fs_in.frag_pos); + lighting += blinn_phong(light_dir, view_dir, normal, + light_pos, light_color); + } + + texture_color *= lighting; + + float gamma = 2.2; + if (gamma_correction) + texture_color = pow(texture_color, vec3(1.0/gamma)); + + frag_color = vec4(texture_color, 1.0); +} diff --git a/advanced_lighting/2.gamma_correction/shaders/blinn_phong.fs b/advanced_lighting/2.gamma_correction/shaders/blinn_phong.fs deleted file mode 100644 index 35e701c..0000000 --- a/advanced_lighting/2.gamma_correction/shaders/blinn_phong.fs +++ /dev/null @@ -1,58 +0,0 @@ -#version 330 core - -in VS_OUT { - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} fs_in; - -out vec4 frag_color; - -uniform sampler2D texture0; -uniform vec3 light_positions[4]; -uniform vec3 light_colors[4]; -uniform vec3 view_pos; -uniform bool gamma_correction; - -vec3 -blinn_phong(vec3 light_dir, vec3 view_dir, vec3 normal, - vec3 light_pos, vec3 light_color) -{ - float diff = max(dot(normal, light_dir), 0.0); - vec3 diffuse = diff*light_color; - - vec3 halfway_dir = normalize(light_dir+view_dir); - float spec = pow(max(dot(normal, halfway_dir), 0.0), 16.0); - vec3 specular = spec*light_color; - - float distance = length(light_pos-fs_in.frag_pos); - float attenuation = 1.0/(gamma_correction ? distance*distance : distance); - - return((diffuse+specular)*attenuation); -} - -void -main(void) -{ - vec3 view_dir = normalize(view_pos-fs_in.frag_pos); - vec3 normal = normalize(fs_in.normal); - vec3 texture_color = texture(texture0, fs_in.tex_coords).rgb; - - vec3 lighting = vec3(0.0); - for (int i = 0; i < 4; i++) - { - vec3 light_pos = light_positions[i]; - vec3 light_color = light_colors[i]; - vec3 light_dir = normalize(light_pos-fs_in.frag_pos); - lighting += blinn_phong(light_dir, view_dir, normal, - light_pos, light_color); - } - - texture_color *= lighting; - - float gamma = 2.2; - if (gamma_correction) - texture_color = pow(texture_color, vec3(1.0/gamma)); - - frag_color = vec4(texture_color, 1.0); -} diff --git a/advanced_lighting/2.gamma_correction/shaders/blinn_phong.vert b/advanced_lighting/2.gamma_correction/shaders/blinn_phong.vert new file mode 100644 index 0000000..870e7dc --- /dev/null +++ b/advanced_lighting/2.gamma_correction/shaders/blinn_phong.vert @@ -0,0 +1,22 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 2) in vec2 atex_coords; + +out VS_OUT { + vec3 frag_pos; + vec3 normal; + vec2 tex_coords; +} vs_out; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); + vs_out.normal = mat3(transpose(inverse(model)))*anormal; + vs_out.tex_coords = atex_coords; + gl_Position = proj*view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/2.gamma_correction/shaders/blinn_phong.vs b/advanced_lighting/2.gamma_correction/shaders/blinn_phong.vs deleted file mode 100644 index 4d1b792..0000000 --- a/advanced_lighting/2.gamma_correction/shaders/blinn_phong.vs +++ /dev/null @@ -1,23 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; -layout(location = 1) in vec3 anormal; -layout(location = 2) in vec2 atex_coords; - -out VS_OUT { - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} vs_out; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -void -main(void) -{ - vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); - vs_out.normal = mat3(transpose(inverse(model)))*anormal; - vs_out.tex_coords = atex_coords; - gl_Position = projection*view*model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/2.gamma_correction/shaders/light.frag b/advanced_lighting/2.gamma_correction/shaders/light.frag new file mode 100644 index 0000000..c01da99 --- /dev/null +++ b/advanced_lighting/2.gamma_correction/shaders/light.frag @@ -0,0 +1,8 @@ +#version 330 core + +out vec4 frag_color; + +void main(void) +{ + frag_color = vec4(1.0); +} diff --git a/advanced_lighting/2.gamma_correction/shaders/light.fs b/advanced_lighting/2.gamma_correction/shaders/light.fs deleted file mode 100644 index bd00d82..0000000 --- a/advanced_lighting/2.gamma_correction/shaders/light.fs +++ /dev/null @@ -1,9 +0,0 @@ -#version 330 core - -out vec4 frag_color; - -void -main(void) -{ - frag_color = vec4(1.0); -} diff --git a/advanced_lighting/2.gamma_correction/shaders/light.vert b/advanced_lighting/2.gamma_correction/shaders/light.vert new file mode 100644 index 0000000..a8b1247 --- /dev/null +++ b/advanced_lighting/2.gamma_correction/shaders/light.vert @@ -0,0 +1,11 @@ +#version 330 core +layout(location = 0) in vec3 apos; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + gl_Position = proj*view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/2.gamma_correction/shaders/light.vs b/advanced_lighting/2.gamma_correction/shaders/light.vs deleted file mode 100644 index ade669b..0000000 --- a/advanced_lighting/2.gamma_correction/shaders/light.vs +++ /dev/null @@ -1,12 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -void -main(void) -{ - gl_Position = projection*view*model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/3.1.shadow_mapping/build.sh b/advanced_lighting/3.1.shadow_mapping/build.sh index bba445d..79ca088 100755 --- a/advanced_lighting/3.1.shadow_mapping/build.sh +++ b/advanced_lighting/3.1.shadow_mapping/build.sh @@ -2,4 +2,4 @@ . ../../config TARGET='shadow_mapping' set -x -gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS +gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS && ./$TARGET diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/color.frag b/advanced_lighting/3.1.shadow_mapping/shaders/color.frag new file mode 100644 index 0000000..c01da99 --- /dev/null +++ b/advanced_lighting/3.1.shadow_mapping/shaders/color.frag @@ -0,0 +1,8 @@ +#version 330 core + +out vec4 frag_color; + +void main(void) +{ + frag_color = vec4(1.0); +} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/color.fs b/advanced_lighting/3.1.shadow_mapping/shaders/color.fs deleted file mode 100644 index bd00d82..0000000 --- a/advanced_lighting/3.1.shadow_mapping/shaders/color.fs +++ /dev/null @@ -1,9 +0,0 @@ -#version 330 core - -out vec4 frag_color; - -void -main(void) -{ - frag_color = vec4(1.0); -} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/color.vert b/advanced_lighting/3.1.shadow_mapping/shaders/color.vert new file mode 100644 index 0000000..6aa621e --- /dev/null +++ b/advanced_lighting/3.1.shadow_mapping/shaders/color.vert @@ -0,0 +1,11 @@ +#version 330 core +layout(location = 0) in vec3 apos; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + gl_Position = proj * view * model * vec4(apos, 1.0); +} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/color.vs b/advanced_lighting/3.1.shadow_mapping/shaders/color.vs deleted file mode 100644 index ade669b..0000000 --- a/advanced_lighting/3.1.shadow_mapping/shaders/color.vs +++ /dev/null @@ -1,12 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -void -main(void) -{ - gl_Position = projection*view*model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.frag b/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.frag new file mode 100644 index 0000000..4cb6df1 --- /dev/null +++ b/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.frag @@ -0,0 +1,25 @@ +#version 330 core + +in vec2 tex_coords; + +out vec4 frag_color; + +uniform sampler2D depth_map; +uniform float near; +uniform float far; + +float linearize_depth(float depth) +{ + float z = (depth+1.0)*0.5; + return((2.0*near*far)/(far+near-z*(far-near))); +} + +void main(void) +{ + float depth = texture(depth_map, tex_coords).r; + + /* frag_color = vec4(vec3(depth), 1.0); */ + + /* NOTE(pryazha): For visual debugging of perspective projection light */ + frag_color = vec4(vec3(linearize_depth(depth)/far), 1.0); +} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.fs b/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.fs deleted file mode 100644 index d250894..0000000 --- a/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.fs +++ /dev/null @@ -1,27 +0,0 @@ -#version 330 core - -in vec2 tex_coords; - -out vec4 frag_color; - -uniform sampler2D depth_map; -uniform float near; -uniform float far; - -float -linearize_depth(float depth) -{ - float z = (depth+1.0)*0.5; - return((2.0*near*far)/(far+near-z*(far-near))); -} - -void -main(void) -{ - float depth = texture(depth_map, tex_coords).r; - - /* frag_color = vec4(vec3(depth), 1.0); */ - - /* NOTE(pryazha): For visual debugging of perspective projection light */ - frag_color = vec4(vec3(linearize_depth(depth)/far), 1.0); -} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.vert b/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.vert new file mode 100644 index 0000000..5717608 --- /dev/null +++ b/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.vert @@ -0,0 +1,14 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec2 atex_coords; + +out vec2 tex_coords; + +uniform mat4 model; + +void +main(void) +{ + tex_coords = atex_coords; + gl_Position = model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.vs b/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.vs deleted file mode 100644 index 5717608..0000000 --- a/advanced_lighting/3.1.shadow_mapping/shaders/debug_quad.vs +++ /dev/null @@ -1,14 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; -layout(location = 1) in vec2 atex_coords; - -out vec2 tex_coords; - -uniform mat4 model; - -void -main(void) -{ - tex_coords = atex_coords; - gl_Position = model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/shadow.frag b/advanced_lighting/3.1.shadow_mapping/shaders/shadow.frag new file mode 100644 index 0000000..3403d1d --- /dev/null +++ b/advanced_lighting/3.1.shadow_mapping/shaders/shadow.frag @@ -0,0 +1,70 @@ +#version 330 core + +in VS_OUT { + vec4 frag_pos_light_space; + vec3 frag_pos; + vec3 normal; + vec2 tex_coords; +} fs_in; + +out vec4 frag_color; + +uniform vec3 light_pos; +uniform vec3 view_pos; + +uniform sampler2D diffuse_texture; +uniform sampler2D shadow_map; + +float calculate_shadow() +{ + vec3 proj_coords = fs_in.frag_pos_light_space.xyz/fs_in.frag_pos_light_space.w; + proj_coords = proj_coords*0.5+0.5; + float closest_depth = texture(shadow_map, proj_coords.xy).r; + float current_depth = proj_coords.z; + vec3 normal = normalize(fs_in.normal); + vec3 light_dir = normalize(light_pos-fs_in.frag_pos); + float bias = max(0.04*(1.0-dot(normal, light_dir)), 0.004); + float shadow = 0; + vec2 texel_size = 1.0/textureSize(shadow_map, 0); + for (int x = -1; x <= 1; x++) + { + for (int y = -1; y <= 1; y++) + { + float pcf_depth = texture(shadow_map, proj_coords.xy+vec2(x, y)*texel_size).r; + shadow += (current_depth-bias > pcf_depth) ? 1.0 : 0.0; + } + } + shadow /= 9.0; + + if (proj_coords.z > 1.0) + shadow = 0.0; + + return(shadow); +} + +void main(void) +{ + vec3 color = texture(diffuse_texture, fs_in.tex_coords).rgb; + vec3 normal = normalize(fs_in.normal); + vec3 light_color = vec3(0.3); + + float ambient_strength = 0.01; + vec3 ambient = color*ambient_strength; + + vec3 light_dir = normalize(light_pos-fs_in.frag_pos); + float diff = max(dot(light_dir, normal), 0.0); + vec3 diffuse = diff*color; + + vec3 view_dir = normalize(view_pos-fs_in.frag_pos); + vec3 halfway_dir = normalize(light_dir+view_dir); + float spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0); + vec3 specular = spec*color; + + float shadow = calculate_shadow(); + vec3 lighting = ambient+((diffuse+specular)*(1.0-shadow)*light_color); + + float gamma = 2.2; + lighting = pow(lighting, vec3(1.0/gamma)); + + frag_color = vec4(lighting, 1.0); +} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/shadow.fs b/advanced_lighting/3.1.shadow_mapping/shaders/shadow.fs deleted file mode 100644 index 1c7018a..0000000 --- a/advanced_lighting/3.1.shadow_mapping/shaders/shadow.fs +++ /dev/null @@ -1,72 +0,0 @@ -#version 330 core - -in VS_OUT { - vec4 frag_pos_light_space; - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} fs_in; - -out vec4 frag_color; - -uniform vec3 light_pos; -uniform vec3 view_pos; - -uniform sampler2D diffuse_texture; -uniform sampler2D shadow_map; - -float -calculate_shadow() -{ - vec3 proj_coords = fs_in.frag_pos_light_space.xyz/fs_in.frag_pos_light_space.w; - proj_coords = proj_coords*0.5+0.5; - float closest_depth = texture(shadow_map, proj_coords.xy).r; - float current_depth = proj_coords.z; - vec3 normal = normalize(fs_in.normal); - vec3 light_dir = normalize(light_pos-fs_in.frag_pos); - float bias = max(0.04*(1.0-dot(normal, light_dir)), 0.004); - float shadow = 0; - vec2 texel_size = 1.0/textureSize(shadow_map, 0); - for (int x = -1; x <= 1; x++) - { - for (int y = -1; y <= 1; y++) - { - float pcf_depth = texture(shadow_map, proj_coords.xy+vec2(x, y)*texel_size).r; - shadow += (current_depth-bias > pcf_depth) ? 1.0 : 0.0; - } - } - shadow /= 9.0; - - if (proj_coords.z > 1.0) - shadow = 0.0; - - return(shadow); -} - -void -main(void) -{ - vec3 color = texture(diffuse_texture, fs_in.tex_coords).rgb; - vec3 normal = normalize(fs_in.normal); - vec3 light_color = vec3(0.3); - - float ambient_strength = 0.01; - vec3 ambient = color*ambient_strength; - - vec3 light_dir = normalize(light_pos-fs_in.frag_pos); - float diff = max(dot(light_dir, normal), 0.0); - vec3 diffuse = diff*color; - - vec3 view_dir = normalize(view_pos-fs_in.frag_pos); - vec3 halfway_dir = normalize(light_dir+view_dir); - float spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0); - vec3 specular = spec*color; - - float shadow = calculate_shadow(); - vec3 lighting = ambient+((diffuse+specular)*(1.0-shadow)*light_color); - - float gamma = 2.2; - lighting = pow(lighting, vec3(1.0/gamma)); - - frag_color = vec4(lighting, 1.0); -} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/shadow.vert b/advanced_lighting/3.1.shadow_mapping/shaders/shadow.vert new file mode 100644 index 0000000..3f14663 --- /dev/null +++ b/advanced_lighting/3.1.shadow_mapping/shaders/shadow.vert @@ -0,0 +1,25 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 2) in vec2 atex_coords; + +out VS_OUT { + vec4 frag_pos_light_space; + vec3 frag_pos; + vec3 normal; + vec2 tex_coords; +} vs_out; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; +uniform mat4 light_space_matrix; + +void main(void) +{ + vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); + vs_out.frag_pos_light_space = light_space_matrix*vec4(vs_out.frag_pos, 1.0); + vs_out.normal = mat3(transpose(inverse(model)))*anormal; + vs_out.tex_coords = atex_coords; + gl_Position = proj*view*vec4(vs_out.frag_pos, 1.0); +} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/shadow.vs b/advanced_lighting/3.1.shadow_mapping/shaders/shadow.vs deleted file mode 100644 index 3ecd5b1..0000000 --- a/advanced_lighting/3.1.shadow_mapping/shaders/shadow.vs +++ /dev/null @@ -1,26 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; -layout(location = 1) in vec3 anormal; -layout(location = 2) in vec2 atex_coords; - -out VS_OUT { - vec4 frag_pos_light_space; - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} vs_out; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; -uniform mat4 light_space_matrix; - -void -main(void) -{ - vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); - vs_out.frag_pos_light_space = light_space_matrix*vec4(vs_out.frag_pos, 1.0); - vs_out.normal = mat3(transpose(inverse(model)))*anormal; - vs_out.tex_coords = atex_coords; - gl_Position = projection*view*vec4(vs_out.frag_pos, 1.0); -} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.frag b/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.frag new file mode 100644 index 0000000..d99aab2 --- /dev/null +++ b/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.frag @@ -0,0 +1,5 @@ +#version 330 core + +void main(void) +{ +} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.fs b/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.fs deleted file mode 100644 index 16b9908..0000000 --- a/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.fs +++ /dev/null @@ -1,6 +0,0 @@ -#version 330 core - -void -main(void) -{ -} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.vert b/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.vert new file mode 100644 index 0000000..d3adca9 --- /dev/null +++ b/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.vert @@ -0,0 +1,10 @@ +#version 330 core +layout(location = 0) in vec3 apos; + +uniform mat4 light_space_matrix; +uniform mat4 model; + +void main(void) +{ + gl_Position = light_space_matrix*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.vs b/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.vs deleted file mode 100644 index b9752ed..0000000 --- a/advanced_lighting/3.1.shadow_mapping/shaders/simple_depth.vs +++ /dev/null @@ -1,11 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; - -uniform mat4 light_space_matrix; -uniform mat4 model; - -void -main(void) -{ - gl_Position = light_space_matrix*model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/3.1.shadow_mapping/shadow_mapping.c b/advanced_lighting/3.1.shadow_mapping/shadow_mapping.c index 7f03415..fd03ed9 100644 --- a/advanced_lighting/3.1.shadow_mapping/shadow_mapping.c +++ b/advanced_lighting/3.1.shadow_mapping/shadow_mapping.c @@ -1,417 +1,275 @@ -#include "pwyazh.h" - #include "GL/glew.h" #include "GLFW/glfw3.h" +#include "pwyazh.h" #include "pwyazh_GL.h" #include "common.h" -static S32 global_screen_width = 800, global_screen_height = 600; -static U32 global_shadow_width = 1024, global_shadow_height = 1024; - -static Input global_input; - -static V3F camera_dp = (V3F){ 0.0f, 0.0f, 0.0f }; - -static U32 global_depth_map_fbo, global_depth_map; - -static U32 global_debug_quad_shader, global_simple_depth_shader, - global_shadow_shader, global_color_shader; - -static U32 global_wood_texture; - -static U32 global_quad_vao; - -static U32 shadows_ortho = 1; - -static V3F light_pos; - -void -glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - switch (action) - { - case GLFW_PRESS: { - switch (key) - { - case GLFW_KEY_D: { - global_input.move_right.state = KeyState_PRESS; - } break; - case GLFW_KEY_W: { - global_input.move_forward.state = KeyState_PRESS; - } break; - case GLFW_KEY_A: { - global_input.move_left.state = KeyState_PRESS; - } break; - case GLFW_KEY_S: { - global_input.move_backward.state = KeyState_PRESS; - } break; - case GLFW_KEY_E: { - global_input.move_up.state = KeyState_PRESS; - } break; - case GLFW_KEY_Q: { - global_input.move_down.state = KeyState_PRESS; - } break; - case GLFW_KEY_SPACE: { - global_input.jump.state = KeyState_PRESS; - } break; - case GLFW_KEY_RIGHT: { - global_input.action_right.state = KeyState_PRESS; - } break; - case GLFW_KEY_UP: { - global_input.action_up.state = KeyState_PRESS; - } break; - case GLFW_KEY_LEFT: { - global_input.action_left.state = KeyState_PRESS; - } break; - case GLFW_KEY_DOWN: { - global_input.action_down.state = KeyState_PRESS; - } break; - case GLFW_KEY_ESCAPE: { - global_input.exit.state = KeyState_PRESS; - } break; - } - } break; - - case GLFW_RELEASE: { - switch (key) - { - case GLFW_KEY_D: { - global_input.move_right.state = KeyState_RELEASE; - } break; - case GLFW_KEY_W: { - global_input.move_forward.state = KeyState_RELEASE; - } break; - case GLFW_KEY_A: { - global_input.move_left.state = KeyState_RELEASE; - } break; - case GLFW_KEY_S: { - global_input.move_backward.state = KeyState_RELEASE; - } break; - case GLFW_KEY_E: { - global_input.move_up.state = KeyState_RELEASE; - } break; - case GLFW_KEY_Q: { - global_input.move_down.state = KeyState_RELEASE; - } break; - case GLFW_KEY_SPACE: { - global_input.jump.state = KeyState_RELEASE; - } break; - case GLFW_KEY_RIGHT: { - global_input.action_right.state = KeyState_RELEASE; - } break; - case GLFW_KEY_UP: { - global_input.action_up.state = KeyState_RELEASE; - } break; - case GLFW_KEY_LEFT: { - global_input.action_left.state = KeyState_RELEASE; - } break; - case GLFW_KEY_DOWN: { - global_input.action_down.state = KeyState_RELEASE; - } break; - case GLFW_KEY_ESCAPE: { - global_input.exit.state = KeyState_RELEASE; - } break; - } - } break; - } -} - -void -resize_callback(GLFWwindow* window, int width, int height) -{ - global_screen_width = width; - global_screen_height = height; - glViewport(0, 0, global_screen_width, global_screen_height); -} - -void -error_callback(int error, const char *desc) -{ - fprintf(stderr, "[ERROR] GLFW: %s\n", desc); -} - -void -update(State *state, F32 time) -{ - F32 radius; - - V3F camera_dv = get_dv_camera_orbital(&global_input, state->camera.pos, - v3f_zero(), state->dt, 2.0f); - if (key_is_pressed(global_input.action_up)) - camera_dv = v3f_scalef(camera_dv, 3.0f); - camera_dp = v3f_add(camera_dp, camera_dv); - camera_dp = v3f_scalef(camera_dp, 0.8f); - state->camera.pos = v3f_add(state->camera.pos, camera_dp); - - if (key_first_press(global_input.action_down)) - shadows_ortho = !shadows_ortho; - - input_update_last_state(&global_input); - - F32 x, z, angular_speed; - - angular_speed = 1.0f; - radius = 4.0f; - x = f32_sin(time*angular_speed)*radius; - z = f32_cos(time*angular_speed)*radius; - - light_pos = v3f(x, 4.0f, z); -} - -void -render_scene(U32 shader, Mesh *cube, Mesh *plane) -{ - MAT4 model; - - model = mat4_identity(); - shader_set_mat4fv(shader, "model", model); - mesh_draw(plane); - - /* - model = mat4_identity(); - model = mat4_make_scale(v3f(10.0f, 0.1f, 10.0f)); - model = mat4_translate(model, v3f(0.0f, -0.6f, 0.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); - */ - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); - model = mat4_translate(model, v3f(0.0f, 1.5f, 0.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); - model = mat4_translate(model, v3f(2.0f, 0.0f, 1.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.25f, 0.25f, 0.25f)); - model = mat4_rotate_angles(model, v3f(60.0f, 0.0f, 0.0f)); - model = mat4_translate(model, v3f(-1.0f, 0.0f, 2.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); -} - -void -render(State *state, Mesh *cube, Mesh *plane) +void render_scene(U32 shader, Mesh *cube, Mesh *plane) { - /* MAT4 projection, view, model; */ - MAT4 light_projection, light_view, model; - F32 near, far, fovx; - V3F target, up; - - if (shadows_ortho) - { - near = 1.0f; - far = 10.0f; - F32 half_side = 10.0f; - light_projection = ortho(-half_side, half_side, -half_side, half_side, near, far); - } - else - { - fovx = 90.0f; - near = 1.0f; - far = 50.0f; - light_projection = perspective(fovx, (F32)global_shadow_width/(F32)global_shadow_height, - near, far); - } - - target = v3f_zero(); - up = v3f(0.0f, 1.0f, 0.0f); - light_view = look_at(light_pos, target, up); - MAT4 light_space_matrix = mat4_mul(light_projection, light_view); - - glUseProgram(global_simple_depth_shader); - shader_set_mat4fv(global_simple_depth_shader, "light_space_matrix", light_space_matrix); - glViewport(0, 0, global_shadow_width, global_shadow_height); - glBindFramebuffer(GL_FRAMEBUFFER, global_depth_map_fbo); - glClear(GL_DEPTH_BUFFER_BIT); - // glCullFace(GL_FRONT); - render_scene(global_simple_depth_shader, cube, plane); - // glCullFace(GL_BACK); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glViewport(0, 0, global_screen_width, global_screen_height); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - MAT4 projection = perspective(state->camera.fovx, (F32)global_screen_width/(F32)global_screen_height, - state->camera.near, state->camera.far); - MAT4 view = look_at(state->camera.pos, v3f_zero(), v3f(0.0f, 1.0f, 0.0f)); - glUseProgram(global_shadow_shader); - shader_set_mat4fv(global_shadow_shader, "projection", projection); - shader_set_mat4fv(global_shadow_shader, "view", view); - - shader_set_3fv(global_shadow_shader, "light_pos", light_pos); - shader_set_3fv(global_shadow_shader, "view_pos", state->camera.pos); - shader_set_mat4fv(global_shadow_shader, "light_space_matrix", light_space_matrix); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, global_wood_texture); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, global_depth_map); - render_scene(global_shadow_shader, cube, plane); - - glUseProgram(global_color_shader); - shader_set_mat4fv(global_shadow_shader, "projection", projection); - shader_set_mat4fv(global_shadow_shader, "view", view); - model = mat4_make_scale(v3f(0.1f, 0.1f, 0.1f)); - model = mat4_translate(model, light_pos); - shader_set_mat4fv(global_shadow_shader, "model", model); - mesh_draw(cube); - - glDisable(GL_DEPTH_TEST); - glUseProgram(global_debug_quad_shader); - F32 scale = 0.3f; - Transform transform = transform_make_scale_translate(v3f(scale, scale, scale), - v3f(1.0f-scale, 1.0f-scale, 0.0f)); - model = transform_apply(transform); - shader_set_mat4fv(global_debug_quad_shader, "model", model); - shader_set_1f(global_debug_quad_shader, "near", near); - shader_set_1f(global_debug_quad_shader, "far", far); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, global_depth_map); - glBindVertexArray(global_quad_vao); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - glEnable(GL_DEPTH_TEST); + MAT4 model; + + model = mat4_identity(); + shader_set_mat4fv(shader, "model", model); + mesh_draw(plane); + + /* + model = mat4_identity(); + model = mat4_make_scale(v3f(10.0f, 0.1f, 10.0f)); + model = mat4_translate(model, v3f(0.0f, -0.6f, 0.0f)); + shader_set_mat4fv(shader, "model", model); + mesh_draw(cube); + */ + + model = mat4_identity(); + model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); + model = mat4_translate(model, v3f(0.0f, 1.5f, 0.0f)); + shader_set_mat4fv(shader, "model", model); + mesh_draw(cube); + + model = mat4_identity(); + model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); + model = mat4_translate(model, v3f(2.0f, 0.0f, 1.0f)); + shader_set_mat4fv(shader, "model", model); + mesh_draw(cube); + + model = mat4_identity(); + model = mat4_make_scale(v3f(0.25f, 0.25f, 0.25f)); + model = mat4_rotate_angles(model, v3f(60.0f, 0.0f, 0.0f)); + model = mat4_translate(model, v3f(-1.0f, 0.0f, 2.0f)); + shader_set_mat4fv(shader, "model", model); + mesh_draw(cube); } -int -main(void) +int main(void) { - GLFWwindow *window; - Arena *arena; - State state; - Mesh *cube_mesh, *plane_mesh; - F64 time, last_time; - - glfwSetErrorCallback(error_callback); - - if (glfwInit() == GLFW_FALSE) - return(1); - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_SAMPLES, 4); - window = glfwCreateWindow(global_screen_width, global_screen_height, "Shadow mapping", 0, 0); - if (!window) - goto error; - - glfwSetKeyCallback(window, glfw_key_callback); - glfwSetWindowSizeCallback(window, resize_callback); - - glfwMakeContextCurrent(window); - - if (glewInit() != GLEW_OK) - goto error; - - glEnable(GL_DEPTH_TEST); - // glEnable(GL_CULL_FACE); - - /* NOTE(pryazha): Init */ - arena = arena_alloc(Megabytes(64)); - - state.camera = (Camera){ v3f(0.0f, 1.0f, 3.0f), 90.0f, 0.1f, 100.0f }; - light_pos = v3f(-2.0f, 4.0f, -2.0f); - - /* NOTE(pryazha): Meshes */ - Vertex plane_vertices[] = { - // positions // normals // texcoords - vertex(v3f(-25.0f, -0.5f, 25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(0.0f, 0.0f)), - vertex(v3f(25.0f, -0.5f, 25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(25.0f, 0.0f)), - vertex(v3f(-25.0f, -0.5f, -25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(0.0f, 25.0f)), - - vertex(v3f(25.0f, -0.5f, 25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(25.0f, 0.0f)), - vertex(v3f(25.0f, -0.5f, -25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(25.0f, 25.0f)), - vertex(v3f(-25.0f, -0.5f, -25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(0.0f, 25.0f)), - }; - U32 indices[] = { 0, 1, 2, 3, 4, 5 }; - plane_mesh = mesh_init(arena, plane_vertices, ArrayCount(plane_vertices), indices, ArrayCount(indices)); - cube_mesh = mesh_load_obj(arena, "../../data/models/cube.obj"); - - F32 quad_vertices[] = { - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f - }; - - U32 vbo; - glGenVertexArrays(1, &global_quad_vao); - glBindVertexArray(global_quad_vao); - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32))); - glBindVertexArray(0); - - /* NOTE(pryazha): Shaders */ - global_debug_quad_shader = create_shader_program("shaders/debug_quad.vs", - "shaders/debug_quad.fs"); - global_simple_depth_shader = create_shader_program("shaders/simple_depth.vs", - "shaders/simple_depth.fs"); - global_shadow_shader = create_shader_program("shaders/shadow.vs", "shaders/shadow.fs"); - global_color_shader = create_shader_program("shaders/color.vs", "shaders/color.fs"); - - glUseProgram(global_shadow_shader); - shader_set_1i(global_shadow_shader, "diffuse_texture", 0); - shader_set_1i(global_shadow_shader, "shadow_map", 1); - glUseProgram(0); - - global_wood_texture = load_texture_gamma("../../data/textures/wood.png", 1); - - glGenFramebuffers(1, &global_depth_map_fbo); - glGenTextures(1, &global_depth_map); - glBindTexture(GL_TEXTURE_2D, global_depth_map); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, global_shadow_width, - global_shadow_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glBindFramebuffer(GL_FRAMEBUFFER, global_depth_map_fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, - global_depth_map, 0); - V4F border_color = v4f(1.0f, 1.0f, 1.0f, 1.0f); - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (const F32 *)&border_color); - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - fprintf(stderr, "[ERROR]: Failed to complete depth map framebuffer.\n"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - last_time = glfwGetTime(); - - while (!glfwWindowShouldClose(window)) - { - glfwPollEvents(); - if (key_first_press(global_input.exit)) - glfwSetWindowShouldClose(window, GLFW_TRUE); - update(&state, time); - render(&state, cube_mesh, plane_mesh); - glfwSwapBuffers(window); - - time = glfwGetTime(); - state.dt = time-last_time; - last_time = time; -#if 0 - fprintf(stdout, "[INFO]: dt: %f\n", state.dt); -#endif - } - - glfwTerminate(); - return(0); - - error: - glfwTerminate(); - return(1); + GLFWwindow *window; + Arena *arena; + State state; + F64 time, last_time; + S32 screen_width = 800, screen_height = 600; + U32 shadow_width = 1024, shadow_height = 1024; + Input input; + U32 shadows_ortho = 1; + V3F light_pos = v3f(-2.0f, 4.0f, -2.0f); + + glfwSetErrorCallback(error_callback); + + if (glfwInit() == GLFW_FALSE) + return(1); + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_SAMPLES, 4); + window = glfwCreateWindow(screen_width, screen_height, "Shadow mapping", 0, 0); + if (!window) + goto error; + + glfwMakeContextCurrent(window); + + if (glewInit() != GLEW_OK) + goto error; + + glEnable(GL_DEPTH_TEST); + // glEnable(GL_CULL_FACE); + + /* NOTE(pryazha): Init */ + arena = arena_alloc(Megabytes(64)); + + state.camera = (Camera){ v3f(0.0f, 1.0f, 3.0f), 90.0f, 0.1f, 100.0f, 0.0f, 0.0f }; + + /* NOTE(pryazha): Meshes */ + Vertex plane_vertices[] = { + // positions // normals // texcoords + vertex(v3f(-25.0f, -0.5f, 25.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 0.0f)), + vertex(v3f( 25.0f, -0.5f, 25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(25.0f, 0.0f)), + vertex(v3f(-25.0f, -0.5f, -25.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 25.0f)), + + vertex(v3f( 25.0f, -0.5f, 25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(25.0f, 0.0f)), + vertex(v3f( 25.0f, -0.5f, -25.0f), v3f(0.0f, 1.0f, 0.0f), v2f(25.0f, 25.0f)), + vertex(v3f(-25.0f, -0.5f, -25.0f), v3f(0.0f, 1.0f, 0.0f), v2f( 0.0f, 25.0f)), + }; + U32 indices[] = { 0, 1, 2, 3, 4, 5 }; + Mesh *plane = mesh_init(arena, plane_vertices, ArrayCount(plane_vertices), + indices, ArrayCount(indices)); + Mesh *cube = mesh_load_obj(arena, "../../data/models/cube.obj"); + + F32 quad_vertices[] = { + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f + }; + + U32 quad_vao, vbo; + glGenVertexArrays(1, &quad_vao); + glBindVertexArray(quad_vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32))); + glBindVertexArray(0); + + /* NOTE(pryazha): Shaders */ + U32 debug_quad_shader = create_shader_program("shaders/debug_quad.vert", + "shaders/debug_quad.frag"); + U32 simple_depth_shader = create_shader_program("shaders/simple_depth.vert", + "shaders/simple_depth.frag"); + U32 shadow_shader = create_shader_program("shaders/shadow.vert", + "shaders/shadow.frag"); + U32 color_shader = create_shader_program("shaders/color.vert", + "shaders/color.frag"); + + glUseProgram(shadow_shader); + shader_set_1i(shadow_shader, "diffuse_texture", 0); + shader_set_1i(shadow_shader, "shadow_map", 1); + glUseProgram(0); + + U32 wood_texture = load_texture_gamma("../../data/textures/wood.png", 1); + + U32 depth_map_fbo, depth_map; + glGenFramebuffers(1, &depth_map_fbo); + glGenTextures(1, &depth_map); + glBindTexture(GL_TEXTURE_2D, depth_map); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadow_width, + shadow_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, + depth_map, 0); + V4F border_color = v4f(1.0f, 1.0f, 1.0f, 1.0f); + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (const F32 *)&border_color); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + fprintf(stderr, "[ERROR]: Failed to complete depth map framebuffer.\n"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + last_time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + /* NOTE(pryazha): Update */ + process_glfw_keyboard(window, &input); + glfwGetFramebufferSize(window, &screen_width, &screen_height); + + V3F target = v3f_zero(); + + if (key_first_press(input.exit)) + glfwSetWindowShouldClose(window, GLFW_TRUE); + + V3F dv = get_dv_camera_orbital(&input, state.camera.pos, + target, state.dt, 3.0f); + state.camera.pos = v3f_add(state.camera.pos, dv); + + if (key_first_press(input.action_down)) + shadows_ortho = !shadows_ortho; + + input_update_last_state(&input); + + F32 radius, angular_speed, x, z; + + angular_speed = 1.0f; + radius = 4.0f; + x = f32_sin(time*angular_speed)*radius; + z = f32_cos(time*angular_speed)*radius; + + light_pos = v3f(x, 4.0f, z); + + /* NOTE(pryazha): Render */ + MAT4 proj, view, model, light_proj; + F32 fovx, near, far; + + if (shadows_ortho) { + near = 1.0f; + far = 10.0f; + F32 half_side = 10.0f; + light_proj = ortho(-half_side, half_side, -half_side, half_side, near, far); + } else { + fovx = 90.0f; + near = 1.0f; + far = 50.0f; + light_proj = perspective(fovx, (F32)shadow_width/(F32)shadow_height, + near, far); + } + + V3F up = v3f(0.0f, 1.0f, 0.0f); + MAT4 light_view = look_at(light_pos, target, up); + MAT4 light_space_matrix = mat4_mul(light_proj, light_view); + + glUseProgram(simple_depth_shader); + shader_set_mat4fv(simple_depth_shader, "light_space_matrix", light_space_matrix); + glViewport(0, 0, shadow_width, shadow_height); + glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo); + glClear(GL_DEPTH_BUFFER_BIT); + // glCullFace(GL_FRONT); + render_scene(simple_depth_shader, cube, plane); + // glCullFace(GL_BACK); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glViewport(0, 0, screen_width, screen_height); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + proj = perspective(state.camera.fovx, (F32)screen_width/(F32)screen_height, + state.camera.near, state.camera.far); + view = look_at(state.camera.pos, v3f_zero(), v3f(0.0f, 1.0f, 0.0f)); + + glUseProgram(shadow_shader); + shader_set_mat4fv(shadow_shader, "proj", proj); + shader_set_mat4fv(shadow_shader, "view", view); + shader_set_3fv(shadow_shader, "light_pos", light_pos); + shader_set_3fv(shadow_shader, "view_pos", state.camera.pos); + shader_set_mat4fv(shadow_shader, "light_space_matrix", light_space_matrix); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, wood_texture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, depth_map); + render_scene(shadow_shader, cube, plane); + + glUseProgram(color_shader); + shader_set_mat4fv(shadow_shader, "proj", proj); + shader_set_mat4fv(shadow_shader, "view", view); + model = mat4_make_scale(v3f(0.1f, 0.1f, 0.1f)); + model = mat4_translate(model, light_pos); + shader_set_mat4fv(shadow_shader, "model", model); + mesh_draw(cube); + + glDisable(GL_DEPTH_TEST); + glUseProgram(debug_quad_shader); + F32 scale = 0.3f; + Transform transform = transform_make_scale_translate(v3f(scale, scale, scale), + v3f(1.0f-scale, 1.0f-scale, 0.0f)); + model = transform_apply(transform); + shader_set_mat4fv(debug_quad_shader, "model", model); + shader_set_1f(debug_quad_shader, "near", near); + shader_set_1f(debug_quad_shader, "far", far); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, depth_map); + glBindVertexArray(quad_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + glEnable(GL_DEPTH_TEST); + glfwSwapBuffers(window); + + time = glfwGetTime(); + state.dt = time-last_time; + last_time = time; + } + + glfwTerminate(); + return(0); + +error: + glfwTerminate(); + return(1); } diff --git a/advanced_lighting/3.2.point_shadows/point_shadows b/advanced_lighting/3.2.point_shadows/point_shadows index c4668ab..452a2a2 100755 Binary files a/advanced_lighting/3.2.point_shadows/point_shadows and b/advanced_lighting/3.2.point_shadows/point_shadows differ diff --git a/advanced_lighting/3.2.point_shadows/point_shadows.c b/advanced_lighting/3.2.point_shadows/point_shadows.c index 0f60565..e622f6c 100644 --- a/advanced_lighting/3.2.point_shadows/point_shadows.c +++ b/advanced_lighting/3.2.point_shadows/point_shadows.c @@ -1,383 +1,261 @@ -#include "pwyazh.h" - #include "GL/glew.h" #include "GLFW/glfw3.h" +#include "pwyazh.h" #include "pwyazh_GL.h" #include "common.h" -static S32 global_screen_width = 800, global_screen_height = 600; -static Input global_input; -static B32 first_mouse = 1; - -void -glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - switch (action) - { - case GLFW_PRESS: { - switch (key) - { - case GLFW_KEY_D: { - global_input.move_right.state = KeyState_PRESS; - } break; - case GLFW_KEY_W: { - global_input.move_forward.state = KeyState_PRESS; - } break; - case GLFW_KEY_A: { - global_input.move_left.state = KeyState_PRESS; - } break; - case GLFW_KEY_S: { - global_input.move_backward.state = KeyState_PRESS; - } break; - case GLFW_KEY_E: { - global_input.move_up.state = KeyState_PRESS; - } break; - case GLFW_KEY_Q: { - global_input.move_down.state = KeyState_PRESS; - } break; - case GLFW_KEY_SPACE: { - global_input.jump.state = KeyState_PRESS; - } break; - case GLFW_KEY_RIGHT: { - global_input.action_right.state = KeyState_PRESS; - } break; - case GLFW_KEY_UP: { - global_input.action_up.state = KeyState_PRESS; - } break; - case GLFW_KEY_LEFT: { - global_input.action_left.state = KeyState_PRESS; - } break; - case GLFW_KEY_DOWN: { - global_input.action_down.state = KeyState_PRESS; - } break; - case GLFW_KEY_ESCAPE: { - global_input.exit.state = KeyState_PRESS; - } break; - } - } break; - - case GLFW_RELEASE: { - switch (key) - { - case GLFW_KEY_D: { - global_input.move_right.state = KeyState_RELEASE; - } break; - case GLFW_KEY_W: { - global_input.move_forward.state = KeyState_RELEASE; - } break; - case GLFW_KEY_A: { - global_input.move_left.state = KeyState_RELEASE; - } break; - case GLFW_KEY_S: { - global_input.move_backward.state = KeyState_RELEASE; - } break; - case GLFW_KEY_E: { - global_input.move_up.state = KeyState_RELEASE; - } break; - case GLFW_KEY_Q: { - global_input.move_down.state = KeyState_RELEASE; - } break; - case GLFW_KEY_SPACE: { - global_input.jump.state = KeyState_RELEASE; - } break; - case GLFW_KEY_RIGHT: { - global_input.action_right.state = KeyState_RELEASE; - } break; - case GLFW_KEY_UP: { - global_input.action_up.state = KeyState_RELEASE; - } break; - case GLFW_KEY_LEFT: { - global_input.action_left.state = KeyState_RELEASE; - } break; - case GLFW_KEY_DOWN: { - global_input.action_down.state = KeyState_RELEASE; - } break; - case GLFW_KEY_ESCAPE: { - global_input.exit.state = KeyState_RELEASE; - } break; - } - } break; - } -} - -void -resize_callback(GLFWwindow* window, int width, int height) -{ - global_screen_width = width; - global_screen_height = height; - /* glViewport(0, 0, global_screen_width, global_screen_height); */ -} - -void -error_callback(int error, const char *desc) -{ - fprintf(stderr, "[ERROR] GLFW: %s\n", desc); -} - -void -cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) -{ - if (first_mouse) - { - global_input.last_mouse_pos = v2f(xpos, ypos); - first_mouse = 0; - } - global_input.mouse_offset = v2f(global_input.mouse_offset.x+((F32)xpos-global_input.last_mouse_pos.x), - global_input.mouse_offset.y+((F32)ypos-global_input.last_mouse_pos.y)); - global_input.last_mouse_pos = v2f((F32)xpos, (F32)ypos); -} - - -void -render_scene(U32 shader, Mesh *cube) +void render_scene(U32 shader, Mesh *cube) { - MAT4 model; - - model = mat4_identity(); - model = mat4_make_scale(v3f(5.0f, 5.0f, 5.0f)); - shader_set_mat4fv(shader, "model", model); - glDisable(GL_CULL_FACE); - shader_set_1i(shader, "reverse_normals", 1); - mesh_draw(cube); - shader_set_1i(shader, "reverse_normals", 0); - glEnable(GL_CULL_FACE); - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); - model = mat4_translate(model, v3f(0.0f, 1.5f, 0.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); - model = mat4_translate(model, v3f(2.0f, 0.0f, 1.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.25f, 0.25f, 0.25f)); - model = mat4_rotate_angles(model, v3f(60.0f, 0.0f, 0.0f)); - model = mat4_translate(model, v3f(-1.0f, 0.0f, 2.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); + MAT4 model; + + model = mat4_identity(); + model = mat4_make_scale(v3f(5.0f, 5.0f, 5.0f)); + shader_set_mat4fv(shader, "model", model); + glDisable(GL_CULL_FACE); + shader_set_1i(shader, "reverse_normals", 1); + mesh_draw(cube); + shader_set_1i(shader, "reverse_normals", 0); + glEnable(GL_CULL_FACE); + + model = mat4_identity(); + model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); + model = mat4_translate(model, v3f(0.0f, 1.5f, 0.0f)); + shader_set_mat4fv(shader, "model", model); + mesh_draw(cube); + + model = mat4_identity(); + model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); + model = mat4_translate(model, v3f(2.0f, 0.0f, 1.0f)); + shader_set_mat4fv(shader, "model", model); + mesh_draw(cube); + + model = mat4_identity(); + model = mat4_make_scale(v3f(0.25f, 0.25f, 0.25f)); + model = mat4_rotate_angles(model, v3f(60.0f, 0.0f, 0.0f)); + model = mat4_translate(model, v3f(-1.0f, 0.0f, 2.0f)); + shader_set_mat4fv(shader, "model", model); + mesh_draw(cube); } -int -main(void) +int main(void) { - GLFWwindow *window; - Arena *arena; - State state; - Mesh *cube; - F64 time, last_time; - V3F light_pos; - MAT4 shadow_transforms[6]; - MAT4 proj, view; - - glfwSetErrorCallback(error_callback); - - if (glfwInit() == GLFW_FALSE) - return(1); - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_SAMPLES, 4); - window = glfwCreateWindow(global_screen_width, global_screen_height, "Point shadows", 0, 0); - if (!window) - goto error; - - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - - glfwSetKeyCallback(window, glfw_key_callback); - glfwSetWindowSizeCallback(window, resize_callback); - glfwSetCursorPosCallback(window, cursor_pos_callback); - - glfwMakeContextCurrent(window); - - if (glewInit() != GLEW_OK) - goto error; - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - - /* NOTE(pryazha): Init */ - arena = arena_alloc(Megabytes(64)); - - state.camera = (Camera){ - .pos = v3f(0.0f, 1.0f, 3.0f), - .fovx = 100.0f, - .near = 0.1f, - .far = 100.0f, - .yaw = 0.0f, - .pitch = 0.0f - }; - V3F camera_dp = v3f_zero(); - /* light_pos = v3f(-2.0f, 4.0f, -2.0f); */ - light_pos = v3f_zero(); - - /* NOTE(pryazha): Meshes */ - cube = mesh_load_obj(arena, "../../data/models/cube.obj"); - - F32 quad_vertices[] = { - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f - }; - U32 quad_vao, vbo; - glGenVertexArrays(1, &quad_vao); - glBindVertexArray(quad_vao); - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32))); - glBindVertexArray(0); - - /* NOTE(pryazha): Shaders */ - U32 depth_shader = create_shader_program_geom("shaders/depth.vs", - "shaders/depth.fs", - "shaders/depth.gs"); - U32 shadow_shader = create_shader_program("shaders/shadow.vs", "shaders/shadow.fs"); - - glUseProgram(shadow_shader); - shader_set_1i(shadow_shader, "diffuse_texture", 0); - shader_set_1i(shadow_shader, "depth_cubemap", 1); - glUseProgram(0); - - U32 wood_texture = load_texture_gamma("../../data/textures/wood.png", 0); - - /* NOTE(pryazha): Depth framebuffer init */ - U32 depth_cubemap_fbo, depth_cubemap; - U32 shadow_width = 1024, shadow_height = 1024; - glGenFramebuffers(1, &depth_cubemap_fbo); - glGenTextures(1, &depth_cubemap); - glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap); - for (U32 cubemap_side = 0; cubemap_side < 6; ++cubemap_side) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+cubemap_side, 0, GL_DEPTH_COMPONENT, - shadow_width, shadow_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); - glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo); - glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_cubemap, 0); - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - fprintf(stderr, "[ERROR]: Failed to complete depth map framebuffer.\n"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - last_time = glfwGetTime(); - - while (!glfwWindowShouldClose(window)) - { - glfwPollEvents(); - if (key_first_press(global_input.exit)) - glfwSetWindowShouldClose(window, GLFW_TRUE); - - /* NOTE(pryazha): For now it's easier to write all of the logic in the main loop */ - /* NOTE(pryazha): Update */ - F32 x, y, z, angular_speed, radius; - V3F camera_dv; - - camera_dv = get_dv_camera_first_person(&global_input, &state.camera, - 1.0f, state.dt); - if (key_is_pressed(global_input.action_up)) - camera_dv = v3f_scalef(camera_dv, 3.0f); - camera_dp = v3f_add(camera_dp, camera_dv); - camera_dp = v3f_scalef(camera_dp, 0.8f); - state.camera.pos = v3f_add(state.camera.pos, camera_dp); - - F32 sensitivity = 0.1f; - global_input.mouse_offset = v2f_scalef(global_input.mouse_offset, sensitivity); - state.camera.yaw += global_input.mouse_offset.x; - state.camera.pitch += global_input.mouse_offset.y; - if (state.camera.pitch > 89.0f) - state.camera.pitch = 89.0f; - if (state.camera.pitch < -89.0f) - state.camera.pitch = -89.0f; - - input_update_last_state(&global_input); - - angular_speed = 1.0f; - radius = 4.0f; - x = f32_sin(time*angular_speed)*radius; - y = f32_sin(time*angular_speed)*f32_sin(time*angular_speed)*radius; - z = f32_cos(time*angular_speed)*radius; - - light_pos = v3f(x, y, z); - - /* NOTE(pryazha): Render */ - - /* NOTE(pryazha): Render the depth cubemap */ - F32 fovx, aspect, near, far; - fovx = 90.0f; - aspect = (F32)shadow_width/(F32)shadow_height; - near = 1.0f; - far = 25.0f; - proj = perspective(fovx, aspect, near, far); - shadow_transforms[0] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* right */ - shadow_transforms[1] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f(-1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* left */ - shadow_transforms[2] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 1.0f, 0.0f)), v3f(0.0f, 0.0f, 1.0f))); /* top */ - shadow_transforms[3] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, -1.0f, 0.0f)), v3f(0.0f, 0.0f, -1.0f))); /* bottom */ - shadow_transforms[4] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, 1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* near */ - shadow_transforms[5] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, -1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* far */ - glViewport(0, 0, shadow_width, shadow_height); - glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo); - glClear(GL_DEPTH_BUFFER_BIT); - glUseProgram(depth_shader); - shader_set_1f(depth_shader, "far", far); - shader_set_3fv(depth_shader, "light_pos", light_pos); - for (U32 i = 0; i < 6; ++i) - { - char uniform_name[256]; - snprintf(uniform_name, 256, "shadow_transforms[%d]", i); - shader_set_mat4fv(depth_shader, uniform_name, shadow_transforms[i]); - } - render_scene(depth_shader, cube); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - /* NOTE(pryazha): Render the scene as normal */ - glViewport(0, 0, global_screen_width, global_screen_height); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glUseProgram(shadow_shader); - - aspect = (F32)global_screen_width/(F32)global_screen_height; - proj = perspective(state.camera.fovx, aspect, state.camera.near, state.camera.far); - view = get_view_matrix(&state.camera); - - shader_set_mat4fv(shadow_shader, "projection", proj); - shader_set_mat4fv(shadow_shader, "view", view); - shader_set_3fv(shadow_shader, "light_pos", light_pos); - shader_set_3fv(shadow_shader, "view_pos", state.camera.pos); - shader_set_1f(shadow_shader, "far", far); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, wood_texture); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap); - render_scene(shadow_shader, cube); - - glfwSwapBuffers(window); - - time = glfwGetTime(); - state.dt = time-last_time; - last_time = time; - } - - glfwTerminate(); - return(0); - - error: - glfwTerminate(); - return(1); + GLFWwindow *window; + Arena *arena; + State state; + Input input; + F64 time, last_time; + V3F light_pos; + MAT4 shadow_transforms[6]; + MAT4 proj, view; + S32 screen_width, screen_height; + + glfwSetErrorCallback(error_callback); + + if (glfwInit() == GLFW_FALSE) + return(1); + + screen_width = 800; + screen_height = 600; + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_SAMPLES, 4); + window = glfwCreateWindow(screen_width, screen_height, "Point shadows", 0, 0); + if (!window) + goto error; + + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + glfwMakeContextCurrent(window); + + if (glewInit() != GLEW_OK) + goto error; + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + /* NOTE(pryazha): Init */ + arena = arena_alloc(Megabytes(64)); + + state.camera = (Camera){ + .pos = v3f(0.0f, 1.0f, 3.0f), + .fovx = 100.0f, + .near = 0.1f, + .far = 100.0f, + .yaw = 0.0f, + .pitch = 0.0f + }; + V3F camera_dp = v3f_zero(); + /* light_pos = v3f(-2.0f, 4.0f, -2.0f); */ + light_pos = v3f_zero(); + + /* NOTE(pryazha): Meshes */ + Mesh *cube = mesh_load_obj(arena, "../../data/models/cube.obj"); + + F32 quad_vertices[] = { + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f + }; + U32 quad_vao, vbo; + glGenVertexArrays(1, &quad_vao); + glBindVertexArray(quad_vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32))); + glBindVertexArray(0); + + /* NOTE(pryazha): Shaders */ + U32 depth_shader = create_shader_program_geom("shaders/depth.vert", + "shaders/depth.frag", + "shaders/depth.geom"); + U32 shadow_shader = create_shader_program("shaders/shadow.vert", + "shaders/shadow.frag"); + + glUseProgram(shadow_shader); + shader_set_1i(shadow_shader, "diffuse_texture", 0); + shader_set_1i(shadow_shader, "depth_cubemap", 1); + glUseProgram(0); + + U32 wood_texture = load_texture_gamma("../../data/textures/wood.png", 0); + + /* NOTE(pryazha): Depth framebuffer init */ + U32 depth_cubemap_fbo, depth_cubemap; + U32 shadow_width = 1024, shadow_height = 1024; + glGenFramebuffers(1, &depth_cubemap_fbo); + glGenTextures(1, &depth_cubemap); + glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap); + for (U32 cubemap_side = 0; cubemap_side < 6; ++cubemap_side) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+cubemap_side, 0, GL_DEPTH_COMPONENT, + shadow_width, shadow_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); + glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo); + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_cubemap, 0); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + fprintf(stderr, "[ERROR]: Failed to complete depth map framebuffer.\n"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + last_time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + /* NOTE(pryazha): For now it's easier to write all of the logic in the main loop */ + /* NOTE(pryazha): Update */ + F32 x, y, z, angular_speed, radius; + + glfwGetFramebufferSize(window, &screen_width, &screen_height); + process_glfw_keyboard(window, &input); + process_glfw_mouse_pos(window, &input); + + if (key_first_press(input.exit)) + glfwSetWindowShouldClose(window, GLFW_TRUE); + + F32 speed = 4.0f; + V3F dv = get_dv_camera_first_person(&input, &state.camera, + speed, state.dt); + if (key_is_pressed(input.action_up)) + dv = v3f_scalef(dv, 3.0f); + camera_dp = v3f_add(camera_dp, dv); + camera_dp = v3f_scalef(camera_dp, 0.8f); + state.camera.pos = v3f_add(state.camera.pos, camera_dp); + + F32 sensitivity = 0.1f; + input.mouse_offset = v2f_scalef(input.mouse_offset, sensitivity); + state.camera.yaw += input.mouse_offset.x; + state.camera.pitch += input.mouse_offset.y; + if (state.camera.pitch > 89.0f) + state.camera.pitch = 89.0f; + if (state.camera.pitch < -89.0f) + state.camera.pitch = -89.0f; + + input_update_last_state(&input); + + angular_speed = 1.0f; + radius = 4.0f; + x = f32_sin(time*angular_speed)*radius; + y = f32_sin(time*angular_speed)*f32_sin(time*angular_speed)*radius; + z = f32_cos(time*angular_speed)*radius; + + light_pos = v3f(x, y, z); + + /* NOTE(pryazha): Render */ + + /* NOTE(pryazha): Render the depth cubemap */ + F32 fovx, aspect, near, far; + fovx = 90.0f; + aspect = (F32)shadow_width/(F32)shadow_height; + near = 1.0f; + far = 25.0f; + proj = perspective(fovx, aspect, near, far); + shadow_transforms[0] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* right */ + shadow_transforms[1] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f(-1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* left */ + shadow_transforms[2] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 1.0f, 0.0f)), v3f(0.0f, 0.0f, 1.0f))); /* top */ + shadow_transforms[3] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, -1.0f, 0.0f)), v3f(0.0f, 0.0f, -1.0f))); /* bottom */ + shadow_transforms[4] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, 1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* near */ + shadow_transforms[5] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, -1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* far */ + glViewport(0, 0, shadow_width, shadow_height); + glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo); + glClear(GL_DEPTH_BUFFER_BIT); + glUseProgram(depth_shader); + shader_set_1f(depth_shader, "far", far); + shader_set_3fv(depth_shader, "light_pos", light_pos); + for (U32 i = 0; i < 6; ++i) { + char uniform_name[256]; + snprintf(uniform_name, 256, "shadow_transforms[%d]", i); + shader_set_mat4fv(depth_shader, uniform_name, shadow_transforms[i]); + } + render_scene(depth_shader, cube); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + /* NOTE(pryazha): Render the scene as normal */ + glViewport(0, 0, screen_width, screen_height); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(shadow_shader); + + aspect = (F32)screen_width/(F32)screen_height; + proj = perspective(state.camera.fovx, aspect, state.camera.near, state.camera.far); + view = get_view_matrix(&state.camera); + + shader_set_mat4fv(shadow_shader, "proj", proj); + shader_set_mat4fv(shadow_shader, "view", view); + shader_set_3fv(shadow_shader, "light_pos", light_pos); + shader_set_3fv(shadow_shader, "view_pos", state.camera.pos); + shader_set_1f(shadow_shader, "far", far); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, wood_texture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap); + render_scene(shadow_shader, cube); + + glfwSwapBuffers(window); + + time = glfwGetTime(); + state.dt = time-last_time; + last_time = time; + } + + glfwTerminate(); + return(0); + +error: + glfwTerminate(); + return(1); } diff --git a/advanced_lighting/3.2.point_shadows/shaders/depth.frag b/advanced_lighting/3.2.point_shadows/shaders/depth.frag new file mode 100644 index 0000000..f95c0f8 --- /dev/null +++ b/advanced_lighting/3.2.point_shadows/shaders/depth.frag @@ -0,0 +1,13 @@ +#version 330 core + +in vec4 frag_pos; + +uniform vec3 light_pos; +uniform float far; + +void main(void) +{ + float light_distance = length(frag_pos.xyz-light_pos); + light_distance = light_distance/far; + gl_FragDepth = light_distance; +} diff --git a/advanced_lighting/3.2.point_shadows/shaders/depth.fs b/advanced_lighting/3.2.point_shadows/shaders/depth.fs deleted file mode 100644 index 88fb9e6..0000000 --- a/advanced_lighting/3.2.point_shadows/shaders/depth.fs +++ /dev/null @@ -1,14 +0,0 @@ -#version 330 core - -in vec4 frag_pos; - -uniform vec3 light_pos; -uniform float far; - -void -main(void) -{ - float light_distance = length(frag_pos.xyz-light_pos); - light_distance = light_distance/far; - gl_FragDepth = light_distance; -} diff --git a/advanced_lighting/3.2.point_shadows/shaders/depth.geom b/advanced_lighting/3.2.point_shadows/shaders/depth.geom new file mode 100644 index 0000000..de39788 --- /dev/null +++ b/advanced_lighting/3.2.point_shadows/shaders/depth.geom @@ -0,0 +1,20 @@ +#version 330 core +layout(triangles) in; +layout(triangle_strip, max_vertices=18) out; + +uniform mat4 shadow_transforms[6]; + +out vec4 frag_pos; + +void main(void) +{ + for (int face = 0; face < 6; ++face) { + gl_Layer = face; + for (int vertex = 0; vertex < 3; ++vertex) { + frag_pos = gl_in[vertex].gl_Position; + gl_Position = shadow_transforms[face]*frag_pos; + EmitVertex(); + } + EndPrimitive(); + } +} diff --git a/advanced_lighting/3.2.point_shadows/shaders/depth.gs b/advanced_lighting/3.2.point_shadows/shaders/depth.gs deleted file mode 100644 index 638e2b9..0000000 --- a/advanced_lighting/3.2.point_shadows/shaders/depth.gs +++ /dev/null @@ -1,27 +0,0 @@ -#version 330 core -layout(triangles) in; -layout(triangle_strip, max_vertices=18) out; - -uniform mat4 shadow_transforms[6]; - -out vec4 frag_pos; - -void -main(void) -{ - for (int face = 0; - face < 6; - ++face) - { - gl_Layer = face; - for (int vertex = 0; - vertex < 3; - ++vertex) - { - frag_pos = gl_in[vertex].gl_Position; - gl_Position = shadow_transforms[face]*frag_pos; - EmitVertex(); - } - EndPrimitive(); - } -} diff --git a/advanced_lighting/3.2.point_shadows/shaders/depth.vert b/advanced_lighting/3.2.point_shadows/shaders/depth.vert new file mode 100644 index 0000000..37ffd1b --- /dev/null +++ b/advanced_lighting/3.2.point_shadows/shaders/depth.vert @@ -0,0 +1,9 @@ +#version 330 core +layout(location = 0) in vec3 apos; + +uniform mat4 model; + +void main(void) +{ + gl_Position = model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/3.2.point_shadows/shaders/depth.vs b/advanced_lighting/3.2.point_shadows/shaders/depth.vs deleted file mode 100644 index 37a3484..0000000 --- a/advanced_lighting/3.2.point_shadows/shaders/depth.vs +++ /dev/null @@ -1,10 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; - -uniform mat4 model; - -void -main(void) -{ - gl_Position = model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/3.2.point_shadows/shaders/shadow.frag b/advanced_lighting/3.2.point_shadows/shaders/shadow.frag new file mode 100644 index 0000000..bb006ca --- /dev/null +++ b/advanced_lighting/3.2.point_shadows/shaders/shadow.frag @@ -0,0 +1,103 @@ +#version 330 core + +in VS_OUT { + vec3 frag_pos; + vec3 normal; + vec2 tex_coords; +} fs_in; + +out vec4 frag_color; + +uniform vec3 light_pos; +uniform vec3 view_pos; +uniform float far; + +uniform sampler2D diffuse_texture; +uniform samplerCube depth_cubemap; + +vec3 grid_sampling_disk[20] = vec3[] +( + vec3(1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1), + vec3(1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1), + vec3(1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0), + vec3(1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1), + vec3(0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1) +); + +float calculate_shadow(vec3 frag_pos) +{ + vec3 frag_to_light = frag_pos-light_pos; + /* float closest_depth = texture(depth_cubemap, frag_to_light).r; */ + /* closest_depth *= far; */ + float current_depth = length(frag_to_light); + /* float bias = 0.05; */ + /* float shadow = current_depth-bias > closest_depth ? 1.0 : 0.0; */ + /* NOTE(pryazha): Display depth value for debugging */ + /* frag_color = vec4(vec3(closest_depth/far), 1.0); */ + /* + float shadow = 0.0; + float offset = 0.1; + float samples = 4.0; + for (float x = -offset; + x < offset; + x += offset/(samples*0.5)) + { + for (float y = -offset; + y < offset; + y += offset/(samples*0.5)) + { + for (float z = -offset; + z < offset; + z += offset/(samples*0.5)) + { + float closest_depth = texture(depth_cubemap, frag_to_light+vec3(x, y, z)).r; + closest_depth *= far; + if (current_depth-bias > closest_depth) + shadow += 1.0; + } + } + } + shadow /= (samples*samples*samples); + */ + + float shadow = 0.0; + float bias = 0.15; + int samples = 20; + float view_distance = length(view_pos-frag_pos); + float disk_radius = (1.0+(view_distance/far))/25.0; + for (int sample = 0; + sample < samples; + ++sample) + { + float closest_depth = texture(depth_cubemap, frag_to_light+ + grid_sampling_disk[sample]*disk_radius).r; + closest_depth *= far; + if (current_depth-bias > closest_depth) + shadow += 1.0; + } + shadow /= float(samples); + return(shadow); +} + +void main(void) +{ + vec3 color = texture(diffuse_texture, fs_in.tex_coords).rgb; + vec3 normal = normalize(fs_in.normal); + vec3 light_color = vec3(0.5); + + vec3 ambient = 0.5*light_color; + + vec3 light_dir = normalize(light_pos-fs_in.frag_pos); + float diff = max(dot(light_dir, normal), 0.0); + vec3 diffuse = diff*light_color; + + vec3 view_dir = normalize(view_pos-fs_in.frag_pos); + vec3 halfway_dir = normalize(light_dir+view_dir); + float spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0); + vec3 specular = spec*light_color; + + float shadow = calculate_shadow(fs_in.frag_pos); + vec3 lighting = (ambient+(1.0-shadow)*(diffuse+specular))*color; + + frag_color = vec4(lighting, 1.0); +} diff --git a/advanced_lighting/3.2.point_shadows/shaders/shadow.fs b/advanced_lighting/3.2.point_shadows/shaders/shadow.fs deleted file mode 100644 index 6a3a8b0..0000000 --- a/advanced_lighting/3.2.point_shadows/shaders/shadow.fs +++ /dev/null @@ -1,105 +0,0 @@ -#version 330 core - -in VS_OUT { - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} fs_in; - -out vec4 frag_color; - -uniform vec3 light_pos; -uniform vec3 view_pos; -uniform float far; - -uniform sampler2D diffuse_texture; -uniform samplerCube depth_cubemap; - -vec3 grid_sampling_disk[20] = vec3[] -( - vec3(1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1), - vec3(1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1), - vec3(1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0), - vec3(1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1), - vec3(0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1) -); - -float -calculate_shadow(vec3 frag_pos) -{ - vec3 frag_to_light = frag_pos-light_pos; - /* float closest_depth = texture(depth_cubemap, frag_to_light).r; */ - /* closest_depth *= far; */ - float current_depth = length(frag_to_light); - /* float bias = 0.05; */ - /* float shadow = current_depth-bias > closest_depth ? 1.0 : 0.0; */ - /* NOTE(pryazha): Display depth value for debugging */ - /* frag_color = vec4(vec3(closest_depth/far), 1.0); */ - /* - float shadow = 0.0; - float offset = 0.1; - float samples = 4.0; - for (float x = -offset; - x < offset; - x += offset/(samples*0.5)) - { - for (float y = -offset; - y < offset; - y += offset/(samples*0.5)) - { - for (float z = -offset; - z < offset; - z += offset/(samples*0.5)) - { - float closest_depth = texture(depth_cubemap, frag_to_light+vec3(x, y, z)).r; - closest_depth *= far; - if (current_depth-bias > closest_depth) - shadow += 1.0; - } - } - } - shadow /= (samples*samples*samples); - */ - - float shadow = 0.0; - float bias = 0.15; - int samples = 20; - float view_distance = length(view_pos-frag_pos); - float disk_radius = (1.0+(view_distance/far))/25.0; - for (int sample = 0; - sample < samples; - ++sample) - { - float closest_depth = texture(depth_cubemap, frag_to_light+ - grid_sampling_disk[sample]*disk_radius).r; - closest_depth *= far; - if (current_depth-bias > closest_depth) - shadow += 1.0; - } - shadow /= float(samples); - return(shadow); -} - -void -main(void) -{ - vec3 color = texture(diffuse_texture, fs_in.tex_coords).rgb; - vec3 normal = normalize(fs_in.normal); - vec3 light_color = vec3(0.5); - - vec3 ambient = 0.5*light_color; - - vec3 light_dir = normalize(light_pos-fs_in.frag_pos); - float diff = max(dot(light_dir, normal), 0.0); - vec3 diffuse = diff*light_color; - - vec3 view_dir = normalize(view_pos-fs_in.frag_pos); - vec3 halfway_dir = normalize(light_dir+view_dir); - float spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0); - vec3 specular = spec*light_color; - - float shadow = calculate_shadow(fs_in.frag_pos); - vec3 lighting = (ambient+(1.0-shadow)*(diffuse+specular))*color; - - frag_color = vec4(lighting, 1.0); -} diff --git a/advanced_lighting/3.2.point_shadows/shaders/shadow.vert b/advanced_lighting/3.2.point_shadows/shaders/shadow.vert new file mode 100644 index 0000000..dccaa76 --- /dev/null +++ b/advanced_lighting/3.2.point_shadows/shaders/shadow.vert @@ -0,0 +1,28 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 2) in vec2 atex_coords; + +out VS_OUT { + vec3 frag_pos; + vec3 normal; + vec2 tex_coords; +} vs_out; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +uniform bool reverse_normals; + +void main(void) +{ + vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); + if (reverse_normals) + vs_out.normal = mat3(transpose(inverse(model)))*(-1.0*anormal); + else + vs_out.normal = mat3(transpose(inverse(model)))*anormal; + + vs_out.tex_coords = atex_coords; + gl_Position = proj*view*vec4(vs_out.frag_pos, 1.0); +} diff --git a/advanced_lighting/3.2.point_shadows/shaders/shadow.vs b/advanced_lighting/3.2.point_shadows/shaders/shadow.vs deleted file mode 100644 index ac8ee4f..0000000 --- a/advanced_lighting/3.2.point_shadows/shaders/shadow.vs +++ /dev/null @@ -1,29 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; -layout(location = 1) in vec3 anormal; -layout(location = 2) in vec2 atex_coords; - -out VS_OUT { - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} vs_out; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -uniform bool reverse_normals; - -void -main(void) -{ - vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); - if (reverse_normals) - vs_out.normal = mat3(transpose(inverse(model)))*(-1.0*anormal); - else - vs_out.normal = mat3(transpose(inverse(model)))*anormal; - - vs_out.tex_coords = atex_coords; - gl_Position = projection*view*vec4(vs_out.frag_pos, 1.0); -} diff --git a/advanced_lighting/4.normal_mapping/normal_mapping b/advanced_lighting/4.normal_mapping/normal_mapping index 6d33c26..1fbb26b 100755 Binary files a/advanced_lighting/4.normal_mapping/normal_mapping and b/advanced_lighting/4.normal_mapping/normal_mapping differ diff --git a/advanced_lighting/4.normal_mapping/normal_mapping.c b/advanced_lighting/4.normal_mapping/normal_mapping.c index 1d65b49..980f4a0 100644 --- a/advanced_lighting/4.normal_mapping/normal_mapping.c +++ b/advanced_lighting/4.normal_mapping/normal_mapping.c @@ -1,288 +1,251 @@ -#include "pwyazh.h" - #include "GL/glew.h" #include "GLFW/glfw3.h" +#include "pwyazh.h" #include "pwyazh_GL.h" #include "common.h" -static S32 global_screen_width = 800, global_screen_height = 600; -static Input global_input; -static B32 first_mouse = 1; - -void -resize_callback(GLFWwindow* window, int width, int height) -{ - global_screen_width = width; - global_screen_height = height; - glViewport(0, 0, global_screen_width, global_screen_height); -} - -void -cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) -{ - if (first_mouse) - { - global_input.last_mouse_pos = v2f(xpos, ypos); - first_mouse = 0; - } - global_input.mouse_offset = v2f(global_input.mouse_offset.x+((F32)xpos-global_input.last_mouse_pos.x), - global_input.mouse_offset.y+((F32)ypos-global_input.last_mouse_pos.y)); - global_input.last_mouse_pos = v2f((F32)xpos, (F32)ypos); -} - -void -render_scene(U32 shader, Mesh *cube) -{ - MAT4 model; - - model = mat4_identity(); - model = mat4_make_scale(v3f(5.0f, 5.0f, 5.0f)); - shader_set_mat4fv(shader, "model", model); - glDisable(GL_CULL_FACE); - shader_set_1i(shader, "reverse_normals", 1); - mesh_draw(cube); - shader_set_1i(shader, "reverse_normals", 0); - glEnable(GL_CULL_FACE); - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); - model = mat4_translate(model, v3f(0.0f, 1.5f, 0.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); - model = mat4_translate(model, v3f(2.0f, 0.0f, 1.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); - - model = mat4_identity(); - model = mat4_make_scale(v3f(0.25f, 0.25f, 0.25f)); - model = mat4_rotate_angles(model, v3f(60.0f, 0.0f, 0.0f)); - model = mat4_translate(model, v3f(-1.0f, 0.0f, 2.0f)); - shader_set_mat4fv(shader, "model", model); - mesh_draw(cube); -} - -int -main(void) +int main(void) { - GLFWwindow *window; - Arena *arena; - State state; - Mesh *cube; - F64 time, last_time; - V3F light_pos; - MAT4 shadow_transforms[6]; - MAT4 proj, view; - - glfwSetErrorCallback(error_callback); - - if (glfwInit() == GLFW_FALSE) - return(1); - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_SAMPLES, 4); - window = glfwCreateWindow(global_screen_width, global_screen_height, "Point shadows", 0, 0); - if (!window) - goto error; - - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - - glfwSetWindowSizeCallback(window, resize_callback); - glfwSetCursorPosCallback(window, cursor_pos_callback); - - glfwMakeContextCurrent(window); - - if (glewInit() != GLEW_OK) - goto error; - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - - /* NOTE(pryazha): Init */ - arena = arena_alloc(Megabytes(64)); - - state.camera = (Camera){ - .pos = v3f(0.0f, 1.0f, 3.0f), - .fovx = 100.0f, - .near = 0.1f, - .far = 100.0f, - .yaw = 0.0f, - .pitch = 0.0f - }; - V3F camera_dp = v3f_zero(); - /* light_pos = v3f(-2.0f, 4.0f, -2.0f); */ - light_pos = v3f_zero(); - - /* NOTE(pryazha): Meshes */ - cube = mesh_load_obj(arena, "../../data/models/cube.obj"); - - F32 quad_vertices[] = { - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f - }; - U32 quad_vao, vbo; - glGenVertexArrays(1, &quad_vao); - glBindVertexArray(quad_vao); - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32))); - glBindVertexArray(0); - - /* NOTE(pryazha): Shaders */ - U32 depth_shader = create_shader_program_geom("shaders/depth.vs", - "shaders/depth.fs", - "shaders/depth.gs"); - U32 shadow_shader = create_shader_program("shaders/shadow.vs", "shaders/shadow.fs"); - - glUseProgram(shadow_shader); - shader_set_1i(shadow_shader, "diffuse_texture", 0); - shader_set_1i(shadow_shader, "depth_cubemap", 1); - glUseProgram(0); - - U32 wood_texture = load_texture_gamma("../../data/textures/wood.png", 0); - - /* NOTE(pryazha): Depth framebuffer init */ - U32 depth_cubemap_fbo, depth_cubemap; - U32 shadow_width = 1024, shadow_height = 1024; - glGenFramebuffers(1, &depth_cubemap_fbo); - glGenTextures(1, &depth_cubemap); - glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap); - for (U32 cubemap_side = 0; cubemap_side < 6; ++cubemap_side) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+cubemap_side, 0, GL_DEPTH_COMPONENT, - shadow_width, shadow_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); - glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo); - glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_cubemap, 0); - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - fprintf(stderr, "[ERROR]: Failed to complete depth map framebuffer.\n"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - last_time = glfwGetTime(); - - while (!glfwWindowShouldClose(window)) - { - glfwPollEvents(); - - /* NOTE(pryazha): For now it's easier to write all of the logic in the main loop */ - - /* NOTE(pryazha): Update */ - process_glfw_keyboard(window, &global_input); - - if (key_first_press(global_input.exit)) - glfwSetWindowShouldClose(window, GLFW_TRUE); - - F32 x, y, z, angular_speed, radius; - V3F camera_dv; - - camera_dv = get_dv_camera_first_person(&global_input, &state.camera, - 1.0f, state.dt); - if (key_is_pressed(global_input.action_up)) - camera_dv = v3f_scalef(camera_dv, 3.0f); - camera_dp = v3f_add(camera_dp, camera_dv); - camera_dp = v3f_scalef(camera_dp, 0.8f); - state.camera.pos = v3f_add(state.camera.pos, camera_dp); - - F32 sensitivity = 0.1f; - global_input.mouse_offset = v2f_scalef(global_input.mouse_offset, sensitivity); - state.camera.yaw += global_input.mouse_offset.x; - state.camera.pitch += global_input.mouse_offset.y; - if (state.camera.pitch > 89.0f) - state.camera.pitch = 89.0f; - if (state.camera.pitch < -89.0f) - state.camera.pitch = -89.0f; - - input_update_last_state(&global_input); - - angular_speed = 1.0f; - radius = 4.0f; - x = f32_sin(time*angular_speed)*radius; - y = f32_sin(time*angular_speed)*radius; - z = f32_cos(time*angular_speed)*radius; - - light_pos = v3f(x, y, z); - - /* NOTE(pryazha): Render */ - - /* NOTE(pryazha): Render the depth cubemap */ - F32 fovx, aspect, near, far; - fovx = 90.0f; - aspect = (F32)shadow_width/(F32)shadow_height; - near = 1.0f; - far = 25.0f; - proj = perspective(fovx, aspect, near, far); - shadow_transforms[0] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* right */ - shadow_transforms[1] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f(-1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* left */ - shadow_transforms[2] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 1.0f, 0.0f)), v3f(0.0f, 0.0f, 1.0f))); /* top */ - shadow_transforms[3] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, -1.0f, 0.0f)), v3f(0.0f, 0.0f, -1.0f))); /* bottom */ - shadow_transforms[4] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, 1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* near */ - shadow_transforms[5] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, -1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* far */ - glViewport(0, 0, shadow_width, shadow_height); - glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo); - glClear(GL_DEPTH_BUFFER_BIT); - glUseProgram(depth_shader); - shader_set_1f(depth_shader, "far", far); - shader_set_3fv(depth_shader, "light_pos", light_pos); - for (U32 i = 0; i < 6; ++i) - { - char uniform_name[256]; - snprintf(uniform_name, 256, "shadow_transforms[%d]", i); - shader_set_mat4fv(depth_shader, uniform_name, shadow_transforms[i]); - } - render_scene(depth_shader, cube); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - /* NOTE(pryazha): Render the scene as normal */ - glViewport(0, 0, global_screen_width, global_screen_height); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glUseProgram(shadow_shader); - - aspect = (F32)global_screen_width/(F32)global_screen_height; - proj = perspective(state.camera.fovx, aspect, state.camera.near, state.camera.far); - view = get_view_matrix(&state.camera); - - shader_set_mat4fv(shadow_shader, "projection", proj); - shader_set_mat4fv(shadow_shader, "view", view); - shader_set_3fv(shadow_shader, "light_pos", light_pos); - shader_set_3fv(shadow_shader, "view_pos", state.camera.pos); - shader_set_1f(shadow_shader, "far", far); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, wood_texture); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap); - render_scene(shadow_shader, cube); - - glfwSwapBuffers(window); - - time = glfwGetTime(); - state.dt = time-last_time; - last_time = time; - } - - glfwTerminate(); - return(0); - - error: - glfwTerminate(); - return(1); + GLFWwindow *window; + State state; + Input input; + F64 time, last_time; + V3F light_pos; + MAT4 proj, view, model; + F32 aspect, angle = 0.0f; + Mesh *cube = 0; + Arena *arena = 0; + S32 width, height; + + glfwSetErrorCallback(error_callback); + + if (glfwInit() == GLFW_FALSE) + return(1); + + width = 800; + height = 600; + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_SAMPLES, 4); + window = glfwCreateWindow(width, height, "Point shadows", 0, 0); + if (!window) + goto error; + + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + glfwMakeContextCurrent(window); + + if (glewInit() != GLEW_OK) + goto error; + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + /* NOTE(pryazha): Init */ + arena = arena_alloc(Kilobytes(4)); + + state.camera = (Camera){ v3f(0.0f, 1.0f, 3.0f), 100.0f, 0.1f, 100.0f, 0.0f, 0.0f }; + V3F camera_dp = v3f_zero(); + F32 x, y, z; + + /* NOTE(pryazha): Meshes */ + cube = mesh_load_obj(arena, "../../data/models/cube.obj"); + + /* Positions */ + V3F p1 = v3f(-1.0f, 1.0f, 0.0f); + V3F p2 = v3f(-1.0f, -1.0f, 0.0f); + V3F p3 = v3f(1.0f, -1.0f, 0.0f); + V3F p4 = v3f(1.0f, 1.0f, 0.0f); + /* Texture ccoordinates */ + V2F uv1 = v2f(0.0f, 1.0f); + V2F uv2 = v2f(0.0f, 0.0f); + V2F uv3 = v2f(1.0f, 0.0f); + V2F uv4 = v2f(1.0f, 1.0f); + /* Normal vector */ + V3F nm = v3f(0.0f, 0.0f, 1.0f); + + V3F edge1, edge2; + V2F duv1, duv2; + F32 f; + V3F t1, bit1, t2, bit2; + + edge1 = v3f_sub(p2, p1); + edge2 = v3f_sub(p3, p1); + duv1 = v2f_sub(uv2, uv1); + duv2 = v2f_sub(uv3, uv1); + + f = 1.0f/(duv1.x*duv2.y-duv2.x*duv1.y); + + t1.x = f*(duv2.y*edge1.x-duv1.y*edge2.x); + t1.y = f*(duv2.y*edge1.y-duv1.y*edge2.y); + t1.z = f*(duv2.y*edge1.z-duv1.y*edge2.z); + + bit1.x = f*(-duv2.x*edge1.x+duv1.x*edge2.x); + bit1.y = f*(-duv2.x*edge1.y+duv1.x*edge2.y); + bit1.z = f*(-duv2.x*edge1.z+duv1.x*edge2.z); + + edge1 = v3f_sub(p3, p1); + edge2 = v3f_sub(p4, p1); + duv1 = v2f_sub(uv3, uv1); + duv2 = v2f_sub(uv4, uv1); + + f = 1.0f/(duv1.x*duv2.y-duv2.x*duv1.y); + + t2.x = f*(duv2.y*edge1.x-duv1.y*edge2.x); + t2.y = f*(duv2.y*edge1.y-duv1.y*edge2.y); + t2.z = f*(duv2.y*edge1.z-duv1.y*edge2.z); + + bit2.x = f*(-duv2.x*edge1.x+duv1.x*edge2.x); + bit2.y = f*(-duv2.x*edge1.y+duv1.x*edge2.y); + bit2.z = f*(-duv2.x*edge1.z+duv1.x*edge2.z); + + F32 quad_vertices[] = { + p1.x, p1.y, p1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, t1.x, t1.y, t1.z, bit1.x, bit1.y, bit1.z, + p2.x, p2.y, p2.z, nm.x, nm.y, nm.z, uv2.x, uv2.y, t1.x, t1.y, t1.z, bit1.x, bit1.y, bit1.z, + p3.x, p3.y, p3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, t1.x, t1.y, t1.z, bit1.x, bit1.y, bit1.z, + + p1.x, p1.y, p1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, t2.x, t2.y, t2.z, bit2.x, bit2.y, bit2.z, + p3.x, p3.y, p3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, t2.x, t2.y, t2.z, bit2.x, bit2.y, bit2.z, + p4.x, p4.y, p4.z, nm.x, nm.y, nm.z, uv4.x, uv4.y, t2.x, t2.y, t2.z, bit2.x, bit2.y, bit2.z + }; + U32 quad_vao, vbo; + glGenVertexArrays(1, &quad_vao); + glBindVertexArray(quad_vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)(3*sizeof(F32))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)(6*sizeof(F32))); + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)(8*sizeof(F32))); + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14*sizeof(F32), (void *)(11*sizeof(F32))); + glBindVertexArray(0); + + /* NOTE(pryazha): Shaders */ + U32 normal_map_shader = create_shader_program("shaders/normal_map.vert", + "shaders/normal_map.frag"); + U32 normals_debug_shader = create_shader_program_geom("shaders/normals_debug.vert", + "shaders/normals_debug.frag", + "shaders/normals_debug.geom"); + U32 color_shader = create_shader_program("shaders/color.vert", + "shaders/color.frag"); + + glUseProgram(normal_map_shader); + shader_set_1i(normal_map_shader, "diffuse_texture", 0); + shader_set_1i(normal_map_shader, "normal_map", 1); + glUseProgram(0); + + U32 brickwall_diffuse_texture = load_texture("../../data/textures/brickwall.jpg"); + U32 brickwall_normal_texture = load_texture("../../data/textures/brickwall_normal.jpg"); + + last_time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + /* NOTE(pryazha): For now it's easier to write all of the logic in the main loop */ + + /* NOTE(pryazha): Update */ + glfwGetFramebufferSize(window, &width, &height); + process_glfw_keyboard(window, &input); + process_glfw_mouse_pos(window, &input); + + if (key_first_press(input.exit)) + glfwSetWindowShouldClose(window, GLFW_TRUE); + + F32 speed = 2.0f; + V3F dv = get_dv_camera_first_person(&input, &state.camera, + speed, state.dt); + if (key_is_pressed(input.action_up)) + dv = v3f_scalef(dv, 3.0f); + camera_dp = v3f_add(camera_dp, dv); + camera_dp = v3f_scalef(camera_dp, 0.8f); + state.camera.pos = v3f_add(state.camera.pos, camera_dp); + + F32 sensitivity = 0.1f; + input.mouse_offset = v2f_scalef(input.mouse_offset, sensitivity); + state.camera.yaw += input.mouse_offset.x; + state.camera.pitch += input.mouse_offset.y; + if (state.camera.pitch > 89.0f) + state.camera.pitch = 89.0f; + if (state.camera.pitch < -89.0f) + state.camera.pitch = -89.0f; + + input_update_last_state(&input); + + angle += 40.0f*state.dt; + + x = f32_cos((F32)time); + y = f32_sin((F32)time); + z = 1.0f; + light_pos = v3f(x, y, z); + + /* NOTE(pryazha): Render */ + aspect = (F32)width/(F32)height; + proj = perspective(state.camera.fovx, aspect, + state.camera.near, state.camera.far); + view = get_view_matrix(&state.camera); + + glViewport(0, 0, width, height); + glClearColor(0.15f, 0.15f, 0.15f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(normal_map_shader); + shader_set_mat4fv(normal_map_shader, "proj", proj); + shader_set_mat4fv(normal_map_shader, "view", view); + shader_set_3fv(normal_map_shader, "light_pos", light_pos); + shader_set_3fv(normal_map_shader, "view_pos", state.camera.pos); + model = mat4_rotate_angles(mat4_identity(), v3f(angle, angle, angle)); + shader_set_mat4fv(normal_map_shader, "model", model); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, brickwall_diffuse_texture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, brickwall_normal_texture); + glBindVertexArray(quad_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + glUseProgram(0); + + glUseProgram(color_shader); + shader_set_mat4fv(color_shader, "proj", proj); + shader_set_mat4fv(color_shader, "view", view); + model = mat4_make_scale(v3f(0.05f, 0.05f, 0.05f)); + model = mat4_translate(model, light_pos); + shader_set_mat4fv(color_shader, "model", model); + mesh_draw(cube); + glUseProgram(0); + + glUseProgram(normals_debug_shader); + shader_set_mat4fv(normals_debug_shader, "proj", proj); + shader_set_mat4fv(normals_debug_shader, "view", view); + model = mat4_rotate_angles(mat4_identity(), v3f(angle, angle, angle)); + shader_set_mat4fv(normals_debug_shader, "model", model); + glBindVertexArray(quad_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + glUseProgram(0); + + glfwSwapBuffers(window); + + time = glfwGetTime(); + state.dt = time-last_time; + last_time = time; + } + + arena_release(arena); + glfwTerminate(); + return(0); + +error: + arena_release(arena); + glfwTerminate(); + return(1); } diff --git a/advanced_lighting/4.normal_mapping/shaders/color.frag b/advanced_lighting/4.normal_mapping/shaders/color.frag new file mode 100644 index 0000000..c01da99 --- /dev/null +++ b/advanced_lighting/4.normal_mapping/shaders/color.frag @@ -0,0 +1,8 @@ +#version 330 core + +out vec4 frag_color; + +void main(void) +{ + frag_color = vec4(1.0); +} diff --git a/advanced_lighting/4.normal_mapping/shaders/color.vert b/advanced_lighting/4.normal_mapping/shaders/color.vert new file mode 100644 index 0000000..a8b1247 --- /dev/null +++ b/advanced_lighting/4.normal_mapping/shaders/color.vert @@ -0,0 +1,11 @@ +#version 330 core +layout(location = 0) in vec3 apos; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + gl_Position = proj*view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/4.normal_mapping/shaders/depth.fs b/advanced_lighting/4.normal_mapping/shaders/depth.fs deleted file mode 100644 index 88fb9e6..0000000 --- a/advanced_lighting/4.normal_mapping/shaders/depth.fs +++ /dev/null @@ -1,14 +0,0 @@ -#version 330 core - -in vec4 frag_pos; - -uniform vec3 light_pos; -uniform float far; - -void -main(void) -{ - float light_distance = length(frag_pos.xyz-light_pos); - light_distance = light_distance/far; - gl_FragDepth = light_distance; -} diff --git a/advanced_lighting/4.normal_mapping/shaders/depth.gs b/advanced_lighting/4.normal_mapping/shaders/depth.gs deleted file mode 100644 index 638e2b9..0000000 --- a/advanced_lighting/4.normal_mapping/shaders/depth.gs +++ /dev/null @@ -1,27 +0,0 @@ -#version 330 core -layout(triangles) in; -layout(triangle_strip, max_vertices=18) out; - -uniform mat4 shadow_transforms[6]; - -out vec4 frag_pos; - -void -main(void) -{ - for (int face = 0; - face < 6; - ++face) - { - gl_Layer = face; - for (int vertex = 0; - vertex < 3; - ++vertex) - { - frag_pos = gl_in[vertex].gl_Position; - gl_Position = shadow_transforms[face]*frag_pos; - EmitVertex(); - } - EndPrimitive(); - } -} diff --git a/advanced_lighting/4.normal_mapping/shaders/depth.vs b/advanced_lighting/4.normal_mapping/shaders/depth.vs deleted file mode 100644 index 37a3484..0000000 --- a/advanced_lighting/4.normal_mapping/shaders/depth.vs +++ /dev/null @@ -1,10 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; - -uniform mat4 model; - -void -main(void) -{ - gl_Position = model*vec4(apos, 1.0); -} diff --git a/advanced_lighting/4.normal_mapping/shaders/normal_map.frag b/advanced_lighting/4.normal_mapping/shaders/normal_map.frag new file mode 100644 index 0000000..964d6f8 --- /dev/null +++ b/advanced_lighting/4.normal_mapping/shaders/normal_map.frag @@ -0,0 +1,51 @@ +#version 330 core + +in VS_OUT { + /* mat3 TBN; */ + vec3 frag_pos; + vec3 tangent_light_pos; + vec3 tangent_view_pos; + vec3 tangent_frag_pos; + vec2 tex_coords; +} fs_in; + +out vec4 frag_color; + +/* uniform vec3 light_pos; */ +/* uniform vec3 view_pos; */ + +uniform sampler2D diffuse_texture; +uniform sampler2D normal_map; + +void main(void) +{ + vec3 color = vec3(texture(diffuse_texture, fs_in.tex_coords)); + vec3 normal = vec3(texture(normal_map, fs_in.tex_coords)); + normal = normalize((normal*2.0)-1.0); + /* + normal = normalize(fs_in.TBN*normal); + + vec3 light_dir = fs_in.TBN * normalize(light_pos - fs_in.frag_pos); + vec3 view_dir = fs_in.TBN * normalize(view_pos - fs_in.frag_pos); + */ + + vec3 light_color = vec3(1.0); + + float ambient = 0.01; + + /* vec3 light_dir = normalize(light_pos-fs_in.frag_pos); */ + vec3 light_dir = normalize(fs_in.tangent_light_pos - fs_in.tangent_frag_pos); + float diff = max(dot(light_dir, normal), 0.0); + vec3 diffuse = diff*light_color; + + /* vec3 view_dir = normalize(view_pos-fs_in.frag_pos); */ + vec3 view_dir = normalize(fs_in.tangent_view_pos-fs_in.frag_pos); + vec3 halfway_dir = normalize(light_dir+view_dir); + float spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0); + float spec_strength = 1.0; + vec3 specular = spec_strength*spec*light_color; + + vec3 result = (ambient+diffuse+specular)*color; + + frag_color = vec4(result, 1.0); +} diff --git a/advanced_lighting/4.normal_mapping/shaders/normal_map.vert b/advanced_lighting/4.normal_mapping/shaders/normal_map.vert new file mode 100644 index 0000000..3b089b5 --- /dev/null +++ b/advanced_lighting/4.normal_mapping/shaders/normal_map.vert @@ -0,0 +1,36 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 2) in vec2 atex_coords; +layout(location = 3) in vec3 atangent; +layout(location = 4) in vec3 abitangent; + +out VS_OUT { + /* mat3 TBN; */ + vec3 frag_pos; + vec3 tangent_light_pos; + vec3 tangent_view_pos; + vec3 tangent_frag_pos; + vec2 tex_coords; +} vs_out; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; + +uniform vec3 light_pos; +uniform vec3 view_pos; + +void main(void) +{ + vs_out.frag_pos = vec3(model * vec4(apos, 1.0)); + vs_out.tex_coords = atex_coords; + vec3 T = normalize(vec3(model * vec4(atangent, 0.0))); + vec3 B = normalize(vec3(model * vec4(abitangent, 0.0))); + vec3 N = normalize(vec3(model * vec4(anormal, 0.0))); + mat3 TBN = transpose(mat3(T, B, N)); + vs_out.tangent_light_pos = TBN * light_pos; + vs_out.tangent_view_pos = TBN * view_pos; + vs_out.tangent_frag_pos = TBN * vec3(model * vec4(apos, 0.0)); + gl_Position = proj * view * vec4(vs_out.frag_pos, 1.0); +} diff --git a/advanced_lighting/4.normal_mapping/shaders/normals_debug.frag b/advanced_lighting/4.normal_mapping/shaders/normals_debug.frag new file mode 100644 index 0000000..04dadd4 --- /dev/null +++ b/advanced_lighting/4.normal_mapping/shaders/normals_debug.frag @@ -0,0 +1,10 @@ +#version 330 core + +in vec3 vcolor; + +out vec4 frag_color; + +void main(void) +{ + frag_color = vec4(vcolor, 1.0); +} diff --git a/advanced_lighting/4.normal_mapping/shaders/normals_debug.geom b/advanced_lighting/4.normal_mapping/shaders/normals_debug.geom new file mode 100644 index 0000000..666c08a --- /dev/null +++ b/advanced_lighting/4.normal_mapping/shaders/normals_debug.geom @@ -0,0 +1,44 @@ +#version 330 core +layout(triangles) in; +layout(line_strip, max_vertices=18) out; + +in VS_OUT { + vec4 tangent; + vec4 bitangent; + vec4 normal; +} gs_in[]; + +out vec3 vcolor; + +uniform mat4 proj; + +void gen_normals(int index) +{ + vcolor = vec3(1.0, 0.0, 0.0); + gl_Position = proj*(gl_in[index].gl_Position); + EmitVertex(); + gl_Position = proj*(gl_in[index].gl_Position+0.5*gs_in[index].tangent); + EmitVertex(); + EndPrimitive(); + + vcolor = vec3(0.0, 0.0, 1.0); + gl_Position = proj*(gl_in[index].gl_Position); + EmitVertex(); + gl_Position = proj*(gl_in[index].gl_Position+0.5*gs_in[index].bitangent); + EmitVertex(); + EndPrimitive(); + + vcolor = vec3(0.0, 1.0, 0.0); + gl_Position = proj*(gl_in[index].gl_Position); + EmitVertex(); + gl_Position = proj*(gl_in[index].gl_Position+0.5*gs_in[index].normal); + EmitVertex(); + EndPrimitive(); +} + +void main(void) +{ + gen_normals(0); + gen_normals(1); + gen_normals(2); +} diff --git a/advanced_lighting/4.normal_mapping/shaders/normals_debug.vert b/advanced_lighting/4.normal_mapping/shaders/normals_debug.vert new file mode 100644 index 0000000..d3eed77 --- /dev/null +++ b/advanced_lighting/4.normal_mapping/shaders/normals_debug.vert @@ -0,0 +1,22 @@ +#version 330 core +layout(location = 0) in vec3 apos; +layout(location = 1) in vec3 anormal; +layout(location = 3) in vec3 atangent; +layout(location = 4) in vec3 abitangent; + +out VS_OUT { + vec4 tangent; + vec4 bitangent; + vec4 normal; +} vs_out; + +uniform mat4 view; +uniform mat4 model; + +void main(void) +{ + vs_out.tangent = view*model*vec4(normalize(atangent), 0.0); + vs_out.bitangent = view*model*vec4(normalize(abitangent), 0.0); + vs_out.normal = view*model*vec4(normalize(anormal), 0.0); + gl_Position = view*model*vec4(apos, 1.0); +} diff --git a/advanced_lighting/4.normal_mapping/shaders/shadow.fs b/advanced_lighting/4.normal_mapping/shaders/shadow.fs deleted file mode 100644 index 6a3a8b0..0000000 --- a/advanced_lighting/4.normal_mapping/shaders/shadow.fs +++ /dev/null @@ -1,105 +0,0 @@ -#version 330 core - -in VS_OUT { - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} fs_in; - -out vec4 frag_color; - -uniform vec3 light_pos; -uniform vec3 view_pos; -uniform float far; - -uniform sampler2D diffuse_texture; -uniform samplerCube depth_cubemap; - -vec3 grid_sampling_disk[20] = vec3[] -( - vec3(1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1), - vec3(1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1), - vec3(1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0), - vec3(1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1), - vec3(0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1) -); - -float -calculate_shadow(vec3 frag_pos) -{ - vec3 frag_to_light = frag_pos-light_pos; - /* float closest_depth = texture(depth_cubemap, frag_to_light).r; */ - /* closest_depth *= far; */ - float current_depth = length(frag_to_light); - /* float bias = 0.05; */ - /* float shadow = current_depth-bias > closest_depth ? 1.0 : 0.0; */ - /* NOTE(pryazha): Display depth value for debugging */ - /* frag_color = vec4(vec3(closest_depth/far), 1.0); */ - /* - float shadow = 0.0; - float offset = 0.1; - float samples = 4.0; - for (float x = -offset; - x < offset; - x += offset/(samples*0.5)) - { - for (float y = -offset; - y < offset; - y += offset/(samples*0.5)) - { - for (float z = -offset; - z < offset; - z += offset/(samples*0.5)) - { - float closest_depth = texture(depth_cubemap, frag_to_light+vec3(x, y, z)).r; - closest_depth *= far; - if (current_depth-bias > closest_depth) - shadow += 1.0; - } - } - } - shadow /= (samples*samples*samples); - */ - - float shadow = 0.0; - float bias = 0.15; - int samples = 20; - float view_distance = length(view_pos-frag_pos); - float disk_radius = (1.0+(view_distance/far))/25.0; - for (int sample = 0; - sample < samples; - ++sample) - { - float closest_depth = texture(depth_cubemap, frag_to_light+ - grid_sampling_disk[sample]*disk_radius).r; - closest_depth *= far; - if (current_depth-bias > closest_depth) - shadow += 1.0; - } - shadow /= float(samples); - return(shadow); -} - -void -main(void) -{ - vec3 color = texture(diffuse_texture, fs_in.tex_coords).rgb; - vec3 normal = normalize(fs_in.normal); - vec3 light_color = vec3(0.5); - - vec3 ambient = 0.5*light_color; - - vec3 light_dir = normalize(light_pos-fs_in.frag_pos); - float diff = max(dot(light_dir, normal), 0.0); - vec3 diffuse = diff*light_color; - - vec3 view_dir = normalize(view_pos-fs_in.frag_pos); - vec3 halfway_dir = normalize(light_dir+view_dir); - float spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0); - vec3 specular = spec*light_color; - - float shadow = calculate_shadow(fs_in.frag_pos); - vec3 lighting = (ambient+(1.0-shadow)*(diffuse+specular))*color; - - frag_color = vec4(lighting, 1.0); -} diff --git a/advanced_lighting/4.normal_mapping/shaders/shadow.vs b/advanced_lighting/4.normal_mapping/shaders/shadow.vs deleted file mode 100644 index ac8ee4f..0000000 --- a/advanced_lighting/4.normal_mapping/shaders/shadow.vs +++ /dev/null @@ -1,29 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 apos; -layout(location = 1) in vec3 anormal; -layout(location = 2) in vec2 atex_coords; - -out VS_OUT { - vec3 frag_pos; - vec3 normal; - vec2 tex_coords; -} vs_out; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; - -uniform bool reverse_normals; - -void -main(void) -{ - vs_out.frag_pos = vec3(model*vec4(apos, 1.0)); - if (reverse_normals) - vs_out.normal = mat3(transpose(inverse(model)))*(-1.0*anormal); - else - vs_out.normal = mat3(transpose(inverse(model)))*anormal; - - vs_out.tex_coords = atex_coords; - gl_Position = projection*view*vec4(vs_out.frag_pos, 1.0); -} -- cgit v1.2.3