summaryrefslogtreecommitdiff
path: root/pbr/1.1.lighting/lighting.c
diff options
context:
space:
mode:
Diffstat (limited to 'pbr/1.1.lighting/lighting.c')
-rw-r--r--pbr/1.1.lighting/lighting.c233
1 files changed, 131 insertions, 102 deletions
diff --git a/pbr/1.1.lighting/lighting.c b/pbr/1.1.lighting/lighting.c
index 87621ba..d2a941d 100644
--- a/pbr/1.1.lighting/lighting.c
+++ b/pbr/1.1.lighting/lighting.c
@@ -1,126 +1,155 @@
#include "GL/glew.h"
#include "GLFW/glfw3.h"
-#include "pwyazh.h"
#include "common.h"
-typedef struct {
- Arena *arena;
- Input input;
- Camera camera;
- Mesh *cube;
- GLFWwindow *window;
-} state_t;
-
-static S32 width = 1600;
-static S32 height = 800;
-
-void die(const char *fmt, ...)
-{
- fprintf(stderr, "error: ");
- va_list args;
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-void init_glfw(state_t *state) {
- glfwSetErrorCallback(error_callback);
- if (glfwInit() == GLFW_FALSE)
- die("failed to initialize glfw");
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
- state->window = glfwCreateWindow(width, height, "prb lighting", 0, 0);
- if (!state->window)
- die("failed to create window");
- glfwSetInputMode(state->window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
- glfwMakeContextCurrent(state->window);
-}
-
-void init_gl(void)
-{
- if (glewInit() != GLEW_OK)
- die("failed to initialize glew");
- glEnable(GL_DEPTH_TEST);
-}
-
-state_t init_state(void)
-{
- state_t state = {
- .arena = arena_alloc(Kilobytes(256)),
- .input = input_init(),
- .camera = {
- .pos = v3f(0.0f, 2.0f, 5.0f),
- .fovx = 90.0f,
- .near = 0.1f,
- .far = 100.0f,
- .yaw = 0.0f,
- .pitch = 0.0f
- },
- };
- return state;
-}
-
int main(void)
{
- state_t state = init_state();
+ state_t state = init_state(1600, 800);
init_glfw(&state);
init_gl();
- // meshes
- Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj");
+ /* meshes */
+ Mesh *sphere = mesh_load_obj(state.arena, "../../data/models/sphere.obj");
+ Mesh *quad = mesh_gen_quad(state.arena);
+
+ /* shaders */
+ add_shader("default.vert", "default.frag", 0);
+ add_shader("pbr.vert", "pbr.frag", 0);
+ add_shader("hdr.vert", "hdr.frag", 0);
+
+ light_t lights[4] = {
+ {{-6.0f, 0.0f, 7.0f}, {300.0f, 300.0f, 300.0f}},
+ {{-4.0f, 0.0f, 6.0f}, {300.0f, 300.0f, 300.0f}},
+ {{ 1.0f, 0.0f, 5.0f}, {300.0f, 300.0f, 300.0f}},
+ {{ 3.0f, 0.0f, 8.0f}, {300.0f, 300.0f, 300.0f}},
+ };
- // shaders
- U32 shader = load_shader("default.vert", "default.frag");
+ /* 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);
+
+ F32 time = 0;
+
+ S32 show_gamma = 0;
- F64 last_time = glfwGetTime();
while (!glfwWindowShouldClose(state.window)) {
- F64 time = glfwGetTime();
- F32 dt = time - last_time;
- last_time = time;
-
- input_update_last_state(&state.input);
-
- glfwPollEvents();
- process_glfw_keyboard(state.window, &state.input);
- process_glfw_mouse_pos(state.window, &state.input);
-
- if (key_first_press(state.input.exit))
- glfwSetWindowShouldClose(state.window, GLFW_TRUE);
-
- F32 speed = 2.0f;
- V3F dv = get_dv_camera_first_person(&state.input, &state.camera, speed, dt);
- V3F 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;
- 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;
-
- // update
-
- // render
- F32 ar = (F32)width / (F32)height;
+ 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;
+
+ if (key_first_press(state.input.jump))
+ show_gamma = 1 - show_gamma;
+
+ /* render */
+ F32 ar = 0;
+ if (show_gamma) {
+ ar = (F32)state.width / 2.0f / (F32)state.height;
+ } else {
+ ar = (F32)state.width / (F32)state.height;
+ }
MAT4 projection = camera_persp(state.camera, ar);
MAT4 view = get_view_matrix(&state.camera);
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClearColor(0.16f, 0.16f, 0.16f, 1.0f);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ U32 shader = find_shader("pbr");
+ if (!shader) die("wha");
glUseProgram(shader);
- mesh_draw(cube);
+ 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);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (show_gamma) {
+ shader = find_shader("default");
+ if (!shader) die("!");
+ glUseProgram(shader);
+ glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer);
+ MAT4 model = mat4_make_scale(v3f(0.5f, 1.0f, 1.0f));
+ model = mat4_translate(model, v3f(-0.5f, 0.0f, 0.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(quad);
+ glUseProgram(0);
+
+ shader = find_shader("hdr");
+ if (!shader) die("!");
+ glUseProgram(shader);
+ glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer);
+ model = mat4_make_scale(v3f(0.5f, 1.0f, 1.0f));
+ model = mat4_translate(model, v3f(0.5f, 0.0f, 0.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(quad);
+ glUseProgram(0);
+ } else {
+ shader = find_shader("hdr");
+ if (!shader) die("!");
+ glUseProgram(shader);
+ glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer);
+ shader_set_mat4fv(shader, "model", mat4_identity());
+ mesh_draw(quad);
+ glUseProgram(0);
+ }
+
glfwSwapBuffers(state.window);
}