#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; }