#include "GL/glew.h" #include "GLFW/glfw3.h" #include "common.h" int main(void) { state_t state = init_state(1600, 800); init_glfw(&state); init_gl(); glDepthFunc(GL_LEQUAL); /* meshes */ Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj"); Mesh *sphere = mesh_load_obj(state.arena, "../../data/models/sphere.obj"); Mesh *quad = mesh_gen_quad(state.arena); /* shaders */ add_shader("pbr.vert", "pbr.frag", 0); add_shader("hdr.vert", "hdr.frag", 0); add_shader("cubemap.vert", "cubemap.frag", 0); add_shader("background.vert", "background.frag", 0); add_shader("convolution.vert", "convolution.frag", 0); light_t lights[4] = { {{-10.0f, 0.0f, 20.0f}, {300.0f, 300.0f, 300.0f}}, {{-5.0f, 0.0f, 20.0f}, {300.0f, 300.0f, 300.0f}}, {{ 5.0f, 0.0f, 20.0f}, {300.0f, 300.0f, 300.0f}}, {{ 10.0f, 0.0f, 20.0f}, {300.0f, 300.0f, 300.0f}}, }; /* textures */ U32 hdr_texture = load_hdr_texture("../../data/textures/loigerwiesen.hdr");; /* framebuffers */ U32 hdr_fbo, hdr_colorbuffer, hdr_rbo; glGenFramebuffers(1, &hdr_fbo); glGenTextures(1, &hdr_colorbuffer); glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, state.width, state.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, &hdr_rbo); glBindRenderbuffer(GL_RENDERBUFFER, hdr_rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, state.width, state.height); glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hdr_colorbuffer, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, hdr_rbo); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) die("failed to create framebuffer"); glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); U32 capture_fbo, capture_rbo; glGenFramebuffers(1, &capture_fbo); glGenRenderbuffers(1, &capture_rbo); glBindFramebuffer(GL_FRAMEBUFFER, capture_fbo); glBindRenderbuffer(GL_RENDERBUFFER, capture_rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 512, 512); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, capture_rbo); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) die("failed to create framebuffer"); glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); U32 cubemap; glGenTextures(1, &cubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); for (U32 i = 0; i < 6; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 512, 512, 0, GL_RGB, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); MAT4 capture_projection = perspective(90.0f, 1.0f, 0.1f, 10.0f); V3F capture_origin = {0}; MAT4 capture_views[6] = { look_at(capture_origin, v3f( 1.0f, 0.0f, 0.0f), v3f(0.0f, -1.0f, 0.0f)), look_at(capture_origin, v3f(-1.0f, 0.0f, 0.0f), v3f(0.0f, -1.0f, 0.0f)), look_at(capture_origin, v3f( 0.0f, 1.0f, 0.0f), v3f(0.0f, 0.0f, 1.0f)), look_at(capture_origin, v3f( 0.0f, -1.0f, 0.0f), v3f(0.0f, 0.0f, -1.0f)), look_at(capture_origin, v3f( 0.0f, 0.0f, 1.0f), v3f(0.0f, -1.0f, 0.0f)), look_at(capture_origin, v3f( 0.0f, 0.0f, -1.0f), v3f(0.0f, -1.0f, 0.0f)), }; glBindFramebuffer(GL_FRAMEBUFFER, capture_fbo); U32 shader = find_shader("cubemap"); if (!shader) die("waht"); glUseProgram(shader); shader_set_mat4fv(shader, "projection", capture_projection); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, hdr_texture); glViewport(0, 0, 512, 512); for (U32 i = 0; i < 6; i++) { shader_set_mat4fv(shader, "view", capture_views[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); mesh_draw(cube); } glUseProgram(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); U32 irradiance_map; glGenTextures(1, &irradiance_map); glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance_map); for (U32 i = 0; i < 6; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 32, 32, 0, GL_RGB, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glBindFramebuffer(GL_FRAMEBUFFER, capture_fbo); glBindRenderbuffer(GL_RENDERBUFFER, capture_rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 32, 32); glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, capture_fbo); shader = find_shader("convolution"); glUseProgram(shader); shader_set_mat4fv(shader, "projection", capture_projection); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); glViewport(0, 0, 32, 32); for (U32 i = 0; i < 6; i++) { shader_set_mat4fv(shader, "view", capture_views[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance_map, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); mesh_draw(cube); } glUseProgram(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, state.width, state.height); F32 time = 0; while (!glfwWindowShouldClose(state.window)) { handle_glfw_events(state.window, &state.input); F32 dt = lock_framerate(60); fps_info(dt, 10); /* update */ update_camera_first_person(&state.camera, &state.input, dt, 2.0f); F32 limit = 4.0f; for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++) lights[i].position.y = sinf(time + i) * limit; time += dt; /* render */ F32 ar = (F32)state.width / (F32)state.height; MAT4 projection = camera_persp(state.camera, ar); MAT4 view = get_view_matrix(&state.camera); glClearColor(0.16f, 0.16f, 0.16f, 1.0f); glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader = find_shader("pbr"); glUseProgram(shader); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance_map); shader_set_mat4fv(shader, "projection", projection); shader_set_mat4fv(shader, "view", view); shader_set_3fv(shader, "camera", state.camera.pos); shader_set_3fv(shader, "color", v3f(0.04, 0.04, 0.04)); shader_set_1f(shader, "ao", 1.0f); for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++) { char str[512]; snprintf(str, 512, "lights[%d].position", i); shader_set_3fv(shader, str, lights[i].position); snprintf(str, 512, "lights[%d].color", i); shader_set_3fv(shader, str, lights[i].color); } S32 rows = 7; S32 cols = 7; F32 offset = 3.0f; for (S32 row = 0; row < rows; row++) { shader_set_1f(shader, "metallic", (F32)row / (F32)rows); for (S32 col = 0; col < cols; col++) { shader_set_1f(shader, "roughness", clamp(0.05f, (F32)col / (F32)cols, 1.0f)); V3F pos = {(col - cols / 2.0f) * offset, (row - rows / 2.0f) * offset, 0.0f}; MAT4 model = mat4_make_translate(pos); shader_set_mat4fv(shader, "model", model); mesh_draw(sphere); } } for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++) { MAT4 model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f)); model = mat4_translate(model, lights[i].position); shader_set_mat4fv(shader, "model", model); mesh_draw(sphere); } glUseProgram(0); shader = find_shader("background"); glUseProgram(shader); shader_set_mat4fv(shader, "projection", projection); shader_set_mat4fv(shader, "view", view); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance_map); mesh_draw(cube); glUseProgram(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader = find_shader("hdr"); if (!shader) die("failed to find hdr shader!"); glUseProgram(shader); glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer); shader_set_mat4fv(shader, "model", mat4_identity()); mesh_draw(quad); glUseProgram(0); glfwSwapBuffers(state.window); } return 0; }