#include "GL/glew.h" #include "GLFW/glfw3.h" #include "pwyazh.h" #include "pwyazh_GL.h" #include "common.h" int main(void) { 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); }