From d65ddd07a43d5ffdcf2ddf90d6f86626cf9b92d8 Mon Sep 17 00:00:00 2001 From: pryazha Date: Tue, 18 Mar 2025 11:31:31 +0500 Subject: hdr --- advanced_lighting/6.hdr/hdr.c | 254 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 advanced_lighting/6.hdr/hdr.c (limited to 'advanced_lighting/6.hdr/hdr.c') diff --git a/advanced_lighting/6.hdr/hdr.c b/advanced_lighting/6.hdr/hdr.c new file mode 100644 index 0000000..911f9da --- /dev/null +++ b/advanced_lighting/6.hdr/hdr.c @@ -0,0 +1,254 @@ +#include "GL/glew.h" +#include "GLFW/glfw3.h" + +#include "pwyazh.h" +#include "pwyazh_GL.h" + +#include "common.h" + +#define LCOUNT 8 + +int main(void) +{ + S32 width, height; + + GLFWwindow *window; + F64 time, last_time; + + State state = {0}; + + U32 wooodtex; + + Mesh *quad, + *cube, + *tubecube; + + U32 blinn_shader, + hdr_shader, + light_shader, + normals_debug_shader; + + U32 hdrfbo, + hdrcolorbuf, + hdrrbo; + + S32 i; + + F32 a, da, r; + V3F lpos[LCOUNT]; + + F32 exposure; + + S32 show_normals, show_lights; + + width = 800; + height = 600; + + /* NOTE(pryazha): GLFW init */ + glfwSetErrorCallback(error_callback); + + if (glfwInit() == GLFW_FALSE) + return 1; + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + window = glfwCreateWindow(width, height, "HDR", 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); + + /* NOTE(pryazha): Program init */ + state.arena = arena_alloc(Kilobytes(256)); + + state.input.first_mouse = 1; + + state.camera = (Camera){ v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 100.0f, 0.0f, 0.0f }; + state.camera_dp = v3f_zero(); + + da = 2.0f*pi_F32/LCOUNT; + for (i = 0, a = 0.0f, r = 2.0f; i < LCOUNT; i++, a += da) + lpos[i] = v3f(f32_sin(a)*r, 0.0f, f32_cos(a)*r); + + exposure = 1.0f; + + show_normals = 0; + show_lights = 1; + + /* NOTE(pryazha): Textures */ + wooodtex = load_texture_gamma("../../data/textures/wood.png", 1); + + /* NOTE(pryazha): Meshes */ + quad = mesh_gen_quad(state.arena); + cube = mesh_load_obj(state.arena, "../../data/models/cube.obj"); + tubecube = mesh_load_obj(state.arena, "../../data/models/tube_with_cube.obj"); + + /* NOTE(pryazha): Shaders */ + blinn_shader = create_shader_program("shaders/blinn.vert", "shaders/blinn.frag"); + hdr_shader = create_shader_program("shaders/hdr.vert", "shaders/hdr.frag"); + light_shader = create_shader_program("shaders/light.vert", "shaders/light.frag"); + normals_debug_shader = create_shader_program_geom("shaders/normals_debug.vert", + "shaders/normals_debug.frag", + "shaders/normals_debug.geom"); + + /* NOTE(pryazha): Create HDR framebuffer, color buffer texture and + * renderbuffer */ + glGenFramebuffers(1, &hdrfbo); + glGenTextures(1, &hdrcolorbuf); + glBindTexture(GL_TEXTURE_2D, hdrcolorbuf); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glGenRenderbuffers(1, &hdrrbo); + glBindRenderbuffer(GL_RENDERBUFFER, hdrrbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); + + glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hdrcolorbuf, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, hdrrbo); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + fprintf(stderr, "[ERROR] : GL : Failed to complete framebuffer\n"); + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + last_time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + glfwGetFramebufferSize(window, &width, &height); + process_glfw_keyboard(window, &state.input); + process_glfw_mouse_pos(window, &state.input); + + if (key_first_press(state.input.exit)) + glfwSetWindowShouldClose(window, GLFW_TRUE); + + /* NOTE(pryazha): Update */ + F32 speed, sensitivity; + V3F dv; + + speed = 2.0f; + dv = get_dv_camera_first_person(&state.input, &state.camera, speed, state.dt); + state.camera_dp = v3f_add(state.camera_dp, dv); + state.camera_dp = v3f_scalef(state.camera_dp, 0.8f); + state.camera.pos = v3f_add(state.camera.pos, state.camera_dp); + + sensitivity = 0.1f; + state.input.mouse_offset = v2f_scalef(state.input.mouse_offset, sensitivity); + state.camera.yaw += state.input.mouse_offset.x; + state.camera.pitch += state.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; + + if (key_first_press(state.input.jump)) { + show_normals = !show_normals; + show_lights = !show_lights; + } + + if (key_is_pressed(state.input.action_down)) + exposure -= 0.01f; + if (key_is_pressed(state.input.action_up)) + exposure += 0.01f; + + for (i = 0; i < LCOUNT; i++) + lpos[i].y = f32_sin(glfwGetTime()+i); + + /* NOTE(pryazha): Render */ + F32 ar; + MAT4 proj, view, model; + char lstr[1024]; + + ar = (F32)width/(F32)height; + proj = camera_persp(state.camera, ar); + view = get_view_matrix(&state.camera); + + glClearColor(0.15f, 0.15f, 0.15f, 1.0f); + + glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo); + + glViewport(0, 0, width, height); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + model = mat4_identity(); + + glUseProgram(blinn_shader); + shader_set_mat4fv(blinn_shader, "proj", proj); + shader_set_mat4fv(blinn_shader, "view", view); + shader_set_mat4fv(blinn_shader, "model", model); + shader_set_1i(blinn_shader, "lcount", LCOUNT); + for (i = 0; i < LCOUNT; i++) { + snprintf(lstr, 1024, "lpos[%d]", i); + shader_set_3fv(blinn_shader, lstr, lpos[i]); + } + glBindTexture(GL_TEXTURE_2D, wooodtex); + shader_set_1i(blinn_shader, "invert_normals", 0); + mesh_draw(cube); + shader_set_1i(blinn_shader, "invert_normals", 1); + mesh_draw(tubecube); + glBindTexture(GL_TEXTURE_2D, 0); + glUseProgram(0); + + if (show_lights) { + glUseProgram(light_shader); + shader_set_mat4fv(light_shader, "proj", proj); + shader_set_mat4fv(light_shader, "view", view); + for (i = 0; i < LCOUNT; i++) { + model = mat4_make_scale(v3f(0.2f, 0.2f, 0.2f)); + model = mat4_translate(model, lpos[i]); + shader_set_mat4fv(light_shader, "model", model); + mesh_draw(cube); + } + glUseProgram(0); + } + + if (show_normals) { + model = mat4_identity(); + + glUseProgram(normals_debug_shader); + shader_set_mat4fv(normals_debug_shader, "proj", proj); + shader_set_mat4fv(normals_debug_shader, "view", view); + shader_set_mat4fv(normals_debug_shader, "model", model); + mesh_draw(cube); + glUseProgram(0); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(hdr_shader); + shader_set_1f(hdr_shader, "exposure", exposure); + glBindTexture(GL_TEXTURE_2D, hdrcolorbuf); + mesh_draw(quad); + glUseProgram(0); + + glfwSwapBuffers(window); + + time = glfwGetTime(); + state.dt = time-last_time; + last_time = time; + + input_update_last_state(&state.input); + } + + arena_release(state.arena); + glfwTerminate(); + return 0; + +error: + arena_release(state.arena); + glfwTerminate(); + return 1; +} -- cgit v1.2.3