summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpryazha <pryadeiniv@mail.ru>2025-06-15 16:11:31 +0500
committerpryazha <pryadeiniv@mail.ru>2025-06-15 16:11:31 +0500
commit9d944f26d359e4bc1ffd8e44350b0df9f0935b18 (patch)
tree9759a83a76ab741a587b99f00c2463eafd05d813
parentd65ddd07a43d5ffdcf2ddf90d6f86626cf9b92d8 (diff)
something
-rw-r--r--advanced_lighting/1.blinn_phong/blinn_phong.c5
-rwxr-xr-xadvanced_lighting/1.blinn_phong/build (renamed from advanced_lighting/1.blinn_phong/build.sh)0
-rwxr-xr-xadvanced_lighting/2.gamma_correction/build (renamed from advanced_lighting/2.gamma_correction/build.sh)0
-rw-r--r--advanced_lighting/2.gamma_correction/gamma_correction.c4
-rwxr-xr-xadvanced_lighting/3.1.shadow_mapping/build (renamed from advanced_lighting/3.1.shadow_mapping/build.sh)0
-rw-r--r--advanced_lighting/3.1.shadow_mapping/shadow_mapping.c12
-rwxr-xr-xadvanced_lighting/3.2.point_shadows/build (renamed from advanced_lighting/3.2.point_shadows/build.sh)0
-rw-r--r--advanced_lighting/3.2.point_shadows/point_shadows.c481
-rwxr-xr-xadvanced_lighting/4.normal_mapping/build (renamed from advanced_lighting/4.normal_mapping/build.sh)0
-rw-r--r--advanced_lighting/4.normal_mapping/normal_mapping.c10
-rwxr-xr-xadvanced_lighting/5.parallax_mapping/build (renamed from advanced_lighting/5.parallax_mapping/build.sh)0
-rw-r--r--advanced_lighting/5.parallax_mapping/parallax_mapping.c6
-rwxr-xr-xadvanced_lighting/6.hdr/build (renamed from advanced_lighting/6.hdr/build.sh)0
-rw-r--r--advanced_lighting/6.hdr/hdr.c86
-rw-r--r--advanced_lighting/7.bloom/bloom.c287
-rwxr-xr-xadvanced_lighting/7.bloom/build5
-rw-r--r--advanced_lighting/7.bloom/shaders/bloom.frag45
-rw-r--r--advanced_lighting/7.bloom/shaders/bloom.vert24
-rw-r--r--advanced_lighting/7.bloom/shaders/blur.frag29
-rw-r--r--advanced_lighting/7.bloom/shaders/blur.vert14
-rw-r--r--advanced_lighting/7.bloom/shaders/final.frag25
-rw-r--r--advanced_lighting/7.bloom/shaders/final.vert14
-rw-r--r--advanced_lighting/7.bloom/shaders/light.frag22
-rw-r--r--advanced_lighting/7.bloom/shaders/test_blur.frag28
-rw-r--r--advanced_lighting/7.bloom/shaders/test_blur.vert14
-rwxr-xr-xadvanced_lighting/8.deferred_shading/build5
-rw-r--r--advanced_lighting/8.deferred_shading/deferred.c274
-rw-r--r--advanced_lighting/8.deferred_shading/shaders/deferred.frag46
-rw-r--r--advanced_lighting/8.deferred_shading/shaders/gbuffer.frag23
-rw-r--r--advanced_lighting/8.deferred_shading/shaders/gbuffer.vert24
-rw-r--r--advanced_lighting/8.deferred_shading/shaders/light.frag11
-rw-r--r--advanced_lighting/8.deferred_shading/shaders/light.vert12
-rw-r--r--advanced_lighting/8.deferred_shading/shaders/screen.frag14
-rw-r--r--advanced_lighting/8.deferred_shading/shaders/screen.vert16
-rw-r--r--advanced_lighting/8.deferred_shading/shaders/specular.frag14
-rwxr-xr-xadvanced_lighting/9.ssao/build5
-rw-r--r--advanced_lighting/9.ssao/deferred.frag44
-rw-r--r--advanced_lighting/9.ssao/deferred.vert16
-rw-r--r--advanced_lighting/9.ssao/gbuffer.frag17
-rw-r--r--advanced_lighting/9.ssao/gbuffer.vert21
-rw-r--r--advanced_lighting/9.ssao/occlusion.frag14
-rw-r--r--advanced_lighting/9.ssao/screen.frag14
-rw-r--r--advanced_lighting/9.ssao/screen.vert16
-rwxr-xr-xadvanced_lighting/9.ssao/ssaobin0 -> 1291232 bytes
-rw-r--r--advanced_lighting/9.ssao/ssao.c331
-rw-r--r--advanced_lighting/9.ssao/ssao.frag45
-rw-r--r--advanced_lighting/9.ssao/ssao.vert16
-rw-r--r--advanced_lighting/9.ssao/xoshiro128plus.c28
-rwxr-xr-xadvanced_lighting/build (renamed from advanced_opengl/build.sh)4
-rwxr-xr-xadvanced_opengl/1.depth/build (renamed from advanced_opengl/1.depth/build.sh)0
-rw-r--r--advanced_opengl/1.depth/depth.c340
-rw-r--r--advanced_opengl/10.antialiasing/anti_aliasing_msaa.c9
-rw-r--r--advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c7
-rwxr-xr-xadvanced_opengl/10.antialiasing/build (renamed from advanced_opengl/10.antialiasing/build.sh)0
-rwxr-xr-xadvanced_opengl/2.stencil/build (renamed from advanced_opengl/2.stencil/build.sh)0
-rw-r--r--advanced_opengl/2.stencil/stencil.c4
-rw-r--r--advanced_opengl/3.blending/blending.c4
-rwxr-xr-xadvanced_opengl/3.blending/build (renamed from advanced_opengl/3.blending/build.sh)0
-rwxr-xr-xadvanced_opengl/4.face_culling/build (renamed from advanced_opengl/4.face_culling/build.sh)0
-rw-r--r--advanced_opengl/4.face_culling/face_culling.c3
-rwxr-xr-xadvanced_opengl/5.framebuffers/build (renamed from advanced_opengl/5.framebuffers/build.sh)0
-rw-r--r--advanced_opengl/5.framebuffers/framebuffers.c16
-rwxr-xr-xadvanced_opengl/6.cubemaps/build (renamed from advanced_opengl/6.cubemaps/build.sh)0
-rw-r--r--advanced_opengl/6.cubemaps/cubemaps.c9
-rwxr-xr-xadvanced_opengl/7.uniform_buffer/build (renamed from advanced_opengl/7.uniform_buffer/build.sh)0
-rw-r--r--advanced_opengl/7.uniform_buffer/uniform_buffer.c13
-rwxr-xr-xadvanced_opengl/8.geometry_shader/build (renamed from advanced_opengl/8.geometry_shader/build.sh)0
-rw-r--r--advanced_opengl/8.geometry_shader/geometry_shader.c16
-rwxr-xr-xadvanced_opengl/9.instancing/build (renamed from advanced_opengl/9.instancing/build.sh)0
-rw-r--r--advanced_opengl/9.instancing/instancing.c9
-rwxr-xr-xadvanced_opengl/build (renamed from advanced_lighting/build.sh)0
-rw-r--r--libs/common.h187
-rw-r--r--libs/pwyazh/v3f.h7
73 files changed, 2094 insertions, 651 deletions
diff --git a/advanced_lighting/1.blinn_phong/blinn_phong.c b/advanced_lighting/1.blinn_phong/blinn_phong.c
index 404df05..3974243 100644
--- a/advanced_lighting/1.blinn_phong/blinn_phong.c
+++ b/advanced_lighting/1.blinn_phong/blinn_phong.c
@@ -28,6 +28,7 @@ int main(void)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+ glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
glfwWindowHint(GLFW_SAMPLES, 4);
window = glfwCreateWindow(width, height, "Blinn-Phong shading", 0, 0);
if (!window)
@@ -60,8 +61,8 @@ int main(void)
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 blinn_phong_shader = load_shader("shaders/blinn_phong.vert", "shaders/blinn_phong.frag");
+ U32 light_shader = load_shader("shaders/light.vert", "shaders/light.frag");
texture = load_texture("../../data/textures/wood.png");
diff --git a/advanced_lighting/1.blinn_phong/build.sh b/advanced_lighting/1.blinn_phong/build
index 41fb831..41fb831 100755
--- a/advanced_lighting/1.blinn_phong/build.sh
+++ b/advanced_lighting/1.blinn_phong/build
diff --git a/advanced_lighting/2.gamma_correction/build.sh b/advanced_lighting/2.gamma_correction/build
index 2b65776..2b65776 100755
--- a/advanced_lighting/2.gamma_correction/build.sh
+++ b/advanced_lighting/2.gamma_correction/build
diff --git a/advanced_lighting/2.gamma_correction/gamma_correction.c b/advanced_lighting/2.gamma_correction/gamma_correction.c
index a027722..65d1d58 100644
--- a/advanced_lighting/2.gamma_correction/gamma_correction.c
+++ b/advanced_lighting/2.gamma_correction/gamma_correction.c
@@ -77,8 +77,8 @@ int main(void)
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 blinn_phong_shader = load_shader("shaders/blinn_phong.vert", "shaders/blinn_phong.frag");
+ U32 light_shader = load_shader("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);
diff --git a/advanced_lighting/3.1.shadow_mapping/build.sh b/advanced_lighting/3.1.shadow_mapping/build
index bba445d..bba445d 100755
--- a/advanced_lighting/3.1.shadow_mapping/build.sh
+++ b/advanced_lighting/3.1.shadow_mapping/build
diff --git a/advanced_lighting/3.1.shadow_mapping/shadow_mapping.c b/advanced_lighting/3.1.shadow_mapping/shadow_mapping.c
index fd03ed9..f691035 100644
--- a/advanced_lighting/3.1.shadow_mapping/shadow_mapping.c
+++ b/advanced_lighting/3.1.shadow_mapping/shadow_mapping.c
@@ -117,14 +117,10 @@ int main(void)
glBindVertexArray(0);
/* NOTE(pryazha): Shaders */
- U32 debug_quad_shader = create_shader_program("shaders/debug_quad.vert",
- "shaders/debug_quad.frag");
- U32 simple_depth_shader = create_shader_program("shaders/simple_depth.vert",
- "shaders/simple_depth.frag");
- U32 shadow_shader = create_shader_program("shaders/shadow.vert",
- "shaders/shadow.frag");
- U32 color_shader = create_shader_program("shaders/color.vert",
- "shaders/color.frag");
+ U32 debug_quad_shader = load_shader("shaders/debug_quad.vert", "shaders/debug_quad.frag");
+ U32 simple_depth_shader = load_shader("shaders/simple_depth.vert", "shaders/simple_depth.frag");
+ U32 shadow_shader = load_shader("shaders/shadow.vert", "shaders/shadow.frag");
+ U32 color_shader = load_shader("shaders/color.vert", "shaders/color.frag");
glUseProgram(shadow_shader);
shader_set_1i(shadow_shader, "diffuse_texture", 0);
diff --git a/advanced_lighting/3.2.point_shadows/build.sh b/advanced_lighting/3.2.point_shadows/build
index bf934b6..bf934b6 100755
--- a/advanced_lighting/3.2.point_shadows/build.sh
+++ b/advanced_lighting/3.2.point_shadows/build
diff --git a/advanced_lighting/3.2.point_shadows/point_shadows.c b/advanced_lighting/3.2.point_shadows/point_shadows.c
index e622f6c..8989bff 100644
--- a/advanced_lighting/3.2.point_shadows/point_shadows.c
+++ b/advanced_lighting/3.2.point_shadows/point_shadows.c
@@ -8,254 +8,247 @@
void render_scene(U32 shader, Mesh *cube)
{
- MAT4 model;
-
- model = mat4_identity();
- model = mat4_make_scale(v3f(5.0f, 5.0f, 5.0f));
- shader_set_mat4fv(shader, "model", model);
- glDisable(GL_CULL_FACE);
- shader_set_1i(shader, "reverse_normals", 1);
- mesh_draw(cube);
- shader_set_1i(shader, "reverse_normals", 0);
- glEnable(GL_CULL_FACE);
-
- model = mat4_identity();
- model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
- model = mat4_translate(model, v3f(0.0f, 1.5f, 0.0f));
- shader_set_mat4fv(shader, "model", model);
- mesh_draw(cube);
-
- model = mat4_identity();
- model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
- model = mat4_translate(model, v3f(2.0f, 0.0f, 1.0f));
- shader_set_mat4fv(shader, "model", model);
- mesh_draw(cube);
-
- model = mat4_identity();
- model = mat4_make_scale(v3f(0.25f, 0.25f, 0.25f));
- model = mat4_rotate_angles(model, v3f(60.0f, 0.0f, 0.0f));
- model = mat4_translate(model, v3f(-1.0f, 0.0f, 2.0f));
- shader_set_mat4fv(shader, "model", model);
- mesh_draw(cube);
+ MAT4 model;
+
+ model = mat4_identity();
+ model = mat4_make_scale(v3f(5.0f, 5.0f, 5.0f));
+ shader_set_mat4fv(shader, "model", model);
+ glDisable(GL_CULL_FACE);
+ shader_set_1i(shader, "reverse_normals", 1);
+ mesh_draw(cube);
+ shader_set_1i(shader, "reverse_normals", 0);
+ glEnable(GL_CULL_FACE);
+
+ model = mat4_identity();
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_translate(model, v3f(0.0f, 1.5f, 0.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+
+ model = mat4_identity();
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_translate(model, v3f(2.0f, 0.0f, 1.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+
+ model = mat4_identity();
+ model = mat4_make_scale(v3f(0.25f, 0.25f, 0.25f));
+ model = mat4_rotate_angles(model, v3f(60.0f, 0.0f, 0.0f));
+ model = mat4_translate(model, v3f(-1.0f, 0.0f, 2.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
}
int main(void)
{
- GLFWwindow *window;
- Arena *arena;
- State state;
- Input input;
- F64 time, last_time;
- V3F light_pos;
- MAT4 shadow_transforms[6];
- MAT4 proj, view;
- S32 screen_width, screen_height;
-
- glfwSetErrorCallback(error_callback);
-
- if (glfwInit() == GLFW_FALSE)
- return(1);
-
- screen_width = 800;
- screen_height = 600;
-
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- glfwWindowHint(GLFW_SAMPLES, 4);
- window = glfwCreateWindow(screen_width, screen_height, "Point shadows", 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);
- glEnable(GL_CULL_FACE);
-
- /* NOTE(pryazha): Init */
- arena = arena_alloc(Megabytes(64));
-
- state.camera = (Camera){
- .pos = v3f(0.0f, 1.0f, 3.0f),
- .fovx = 100.0f,
- .near = 0.1f,
- .far = 100.0f,
- .yaw = 0.0f,
- .pitch = 0.0f
- };
- V3F camera_dp = v3f_zero();
- /* light_pos = v3f(-2.0f, 4.0f, -2.0f); */
- light_pos = v3f_zero();
-
- /* NOTE(pryazha): Meshes */
- Mesh *cube = mesh_load_obj(arena, "../../data/models/cube.obj");
-
- F32 quad_vertices[] = {
- -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
- 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
- 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
- -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
- 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
- -1.0f, 1.0f, 0.0f, 0.0f, 1.0f
- };
- U32 quad_vao, vbo;
- glGenVertexArrays(1, &quad_vao);
- glBindVertexArray(quad_vao);
- glGenBuffers(1, &vbo);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32)));
- glBindVertexArray(0);
-
- /* NOTE(pryazha): Shaders */
- U32 depth_shader = create_shader_program_geom("shaders/depth.vert",
- "shaders/depth.frag",
- "shaders/depth.geom");
- U32 shadow_shader = create_shader_program("shaders/shadow.vert",
- "shaders/shadow.frag");
-
- glUseProgram(shadow_shader);
- shader_set_1i(shadow_shader, "diffuse_texture", 0);
- shader_set_1i(shadow_shader, "depth_cubemap", 1);
- glUseProgram(0);
-
- U32 wood_texture = load_texture_gamma("../../data/textures/wood.png", 0);
-
- /* NOTE(pryazha): Depth framebuffer init */
- U32 depth_cubemap_fbo, depth_cubemap;
- U32 shadow_width = 1024, shadow_height = 1024;
- glGenFramebuffers(1, &depth_cubemap_fbo);
- glGenTextures(1, &depth_cubemap);
- glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap);
- for (U32 cubemap_side = 0; cubemap_side < 6; ++cubemap_side)
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+cubemap_side, 0, GL_DEPTH_COMPONENT,
- shadow_width, shadow_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
- glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo);
- glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_cubemap, 0);
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- fprintf(stderr, "[ERROR]: Failed to complete depth map framebuffer.\n");
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- last_time = glfwGetTime();
-
- while (!glfwWindowShouldClose(window)) {
- glfwPollEvents();
-
- /* NOTE(pryazha): For now it's easier to write all of the logic in the main loop */
- /* NOTE(pryazha): Update */
- F32 x, y, z, angular_speed, radius;
-
- glfwGetFramebufferSize(window, &screen_width, &screen_height);
- process_glfw_keyboard(window, &input);
- process_glfw_mouse_pos(window, &input);
-
- if (key_first_press(input.exit))
- glfwSetWindowShouldClose(window, GLFW_TRUE);
-
- F32 speed = 4.0f;
- V3F dv = get_dv_camera_first_person(&input, &state.camera,
- speed, state.dt);
- if (key_is_pressed(input.action_up))
- dv = v3f_scalef(dv, 3.0f);
- 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;
- input.mouse_offset = v2f_scalef(input.mouse_offset, sensitivity);
- state.camera.yaw += input.mouse_offset.x;
- state.camera.pitch += 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;
-
- input_update_last_state(&input);
-
- angular_speed = 1.0f;
- radius = 4.0f;
- x = f32_sin(time*angular_speed)*radius;
- y = f32_sin(time*angular_speed)*f32_sin(time*angular_speed)*radius;
- z = f32_cos(time*angular_speed)*radius;
-
- light_pos = v3f(x, y, z);
-
- /* NOTE(pryazha): Render */
-
- /* NOTE(pryazha): Render the depth cubemap */
- F32 fovx, aspect, near, far;
- fovx = 90.0f;
- aspect = (F32)shadow_width/(F32)shadow_height;
- near = 1.0f;
- far = 25.0f;
- proj = perspective(fovx, aspect, near, far);
- shadow_transforms[0] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* right */
- shadow_transforms[1] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f(-1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* left */
- shadow_transforms[2] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 1.0f, 0.0f)), v3f(0.0f, 0.0f, 1.0f))); /* top */
- shadow_transforms[3] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, -1.0f, 0.0f)), v3f(0.0f, 0.0f, -1.0f))); /* bottom */
- shadow_transforms[4] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, 1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* near */
- shadow_transforms[5] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, -1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* far */
- glViewport(0, 0, shadow_width, shadow_height);
- glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo);
- glClear(GL_DEPTH_BUFFER_BIT);
- glUseProgram(depth_shader);
- shader_set_1f(depth_shader, "far", far);
- shader_set_3fv(depth_shader, "light_pos", light_pos);
- for (U32 i = 0; i < 6; ++i) {
- char uniform_name[256];
- snprintf(uniform_name, 256, "shadow_transforms[%d]", i);
- shader_set_mat4fv(depth_shader, uniform_name, shadow_transforms[i]);
- }
- render_scene(depth_shader, cube);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- /* NOTE(pryazha): Render the scene as normal */
- glViewport(0, 0, screen_width, screen_height);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glUseProgram(shadow_shader);
-
- aspect = (F32)screen_width/(F32)screen_height;
- proj = perspective(state.camera.fovx, aspect, state.camera.near, state.camera.far);
- view = get_view_matrix(&state.camera);
-
- shader_set_mat4fv(shadow_shader, "proj", proj);
- shader_set_mat4fv(shadow_shader, "view", view);
- shader_set_3fv(shadow_shader, "light_pos", light_pos);
- shader_set_3fv(shadow_shader, "view_pos", state.camera.pos);
- shader_set_1f(shadow_shader, "far", far);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, wood_texture);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap);
- render_scene(shadow_shader, cube);
-
- glfwSwapBuffers(window);
-
- time = glfwGetTime();
- state.dt = time-last_time;
- last_time = time;
- }
-
- glfwTerminate();
- return(0);
+ Input input;
+ F64 time, last_time;
+ V3F light_pos;
+ MAT4 shadow_transforms[6];
+ MAT4 proj, view;
+
+ glfwSetErrorCallback(error_callback);
+
+ if (glfwInit() == GLFW_FALSE)
+ return(1);
+
+ S32 screen_width = 800;
+ S32 screen_height = 600;
+
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+ glfwWindowHint(GLFW_SAMPLES, 4);
+ GLFWwindow *window = glfwCreateWindow(screen_width, screen_height, "Point shadows", 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);
+ glEnable(GL_CULL_FACE);
+
+ /* NOTE(pryazha): Init */
+ Arena *arena = arena_alloc(Megabytes(64));
+
+ State state = {0};
+ state.camera = (Camera){
+ .pos = v3f(0.0f, 1.0f, 3.0f),
+ .fovx = 100.0f,
+ .near = 0.1f,
+ .far = 100.0f,
+ .yaw = 0.0f,
+ .pitch = 0.0f
+ };
+ V3F camera_dp = v3f_zero();
+ light_pos = v3f_zero();
+
+ /* NOTE(pryazha): Meshes */
+ Mesh *cube = mesh_load_obj(arena, "../../data/models/cube.obj");
+
+ F32 quad_vertices[] = {
+ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
+ 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
+ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
+ -1.0f, 1.0f, 0.0f, 0.0f, 1.0f
+ };
+ U32 quad_vao, vbo;
+ glGenVertexArrays(1, &quad_vao);
+ glBindVertexArray(quad_vao);
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32)));
+ glBindVertexArray(0);
+
+ /* NOTE(pryazha): Shaders */
+ U32 depth_shader = load_shader_geom("shaders/depth.vert", "shaders/depth.frag", "shaders/depth.geom");
+ U32 shadow_shader = load_shader("shaders/shadow.vert", "shaders/shadow.frag");
+
+ glUseProgram(shadow_shader);
+ shader_set_1i(shadow_shader, "diffuse_texture", 0);
+ shader_set_1i(shadow_shader, "depth_cubemap", 1);
+ glUseProgram(0);
+
+ U32 wood_texture = load_texture_gamma("../../data/textures/wood.png", 0);
+
+ /* NOTE(pryazha): Depth framebuffer init */
+ U32 depth_cubemap_fbo, depth_cubemap;
+ U32 shadow_width = 1024, shadow_height = 1024;
+ glGenFramebuffers(1, &depth_cubemap_fbo);
+ glGenTextures(1, &depth_cubemap);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap);
+ for (U32 cubemap_side = 0; cubemap_side < 6; ++cubemap_side)
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+cubemap_side, 0, GL_DEPTH_COMPONENT,
+ shadow_width, shadow_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
+ glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo);
+ glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_cubemap, 0);
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "[ERROR]: Failed to complete depth map framebuffer.\n");
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ last_time = glfwGetTime();
+
+ while (!glfwWindowShouldClose(window)) {
+ glfwPollEvents();
+
+ /* NOTE(pryazha): For now it's easier to write all of the logic in the main loop */
+ /* NOTE(pryazha): Update */
+ F32 x, y, z, angular_speed, radius;
+
+ glfwGetFramebufferSize(window, &screen_width, &screen_height);
+ process_glfw_keyboard(window, &input);
+ process_glfw_mouse_pos(window, &input);
+
+ if (key_first_press(input.exit))
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+
+ F32 speed = 4.0f;
+ V3F dv = get_dv_camera_first_person(&input, &state.camera,
+ speed, state.dt);
+ if (key_is_pressed(input.action_up))
+ dv = v3f_scalef(dv, 3.0f);
+ 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;
+ input.mouse_offset = v2f_scalef(input.mouse_offset, sensitivity);
+ state.camera.yaw += input.mouse_offset.x;
+ state.camera.pitch += 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;
+
+ input_update_last_state(&input);
+
+ angular_speed = 1.0f;
+ radius = 4.0f;
+ x = f32_sin(time*angular_speed)*radius;
+ y = f32_sin(time*angular_speed)*f32_sin(time*angular_speed)*radius;
+ z = f32_cos(time*angular_speed)*radius;
+
+ light_pos = v3f(x, y, z);
+
+ /* NOTE(pryazha): Render */
+
+ /* NOTE(pryazha): Render the depth cubemap */
+ F32 fovx, aspect, near, far;
+ fovx = 90.0f;
+ aspect = (F32)shadow_width/(F32)shadow_height;
+ near = 1.0f;
+ far = 25.0f;
+ proj = perspective(fovx, aspect, near, far);
+ shadow_transforms[0] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* right */
+ shadow_transforms[1] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f(-1.0f, 0.0f, 0.0f)), v3f(0.0f, -1.0f, 0.0f))); /* left */
+ shadow_transforms[2] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 1.0f, 0.0f)), v3f(0.0f, 0.0f, 1.0f))); /* top */
+ shadow_transforms[3] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, -1.0f, 0.0f)), v3f(0.0f, 0.0f, -1.0f))); /* bottom */
+ shadow_transforms[4] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, 1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* near */
+ shadow_transforms[5] = mat4_mul(proj, look_at(light_pos, v3f_add(light_pos, v3f( 0.0f, 0.0f, -1.0f)), v3f(0.0f, -1.0f, 0.0f))); /* far */
+ glViewport(0, 0, shadow_width, shadow_height);
+ glBindFramebuffer(GL_FRAMEBUFFER, depth_cubemap_fbo);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glUseProgram(depth_shader);
+ shader_set_1f(depth_shader, "far", far);
+ shader_set_3fv(depth_shader, "light_pos", light_pos);
+ for (U32 i = 0; i < 6; ++i) {
+ char uniform_name[256];
+ snprintf(uniform_name, 256, "shadow_transforms[%d]", i);
+ shader_set_mat4fv(depth_shader, uniform_name, shadow_transforms[i]);
+ }
+ render_scene(depth_shader, cube);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ /* NOTE(pryazha): Render the scene as normal */
+ glViewport(0, 0, screen_width, screen_height);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram(shadow_shader);
+
+ aspect = (F32)screen_width/(F32)screen_height;
+ proj = perspective(state.camera.fovx, aspect, state.camera.near, state.camera.far);
+ view = get_view_matrix(&state.camera);
+
+ shader_set_mat4fv(shadow_shader, "proj", proj);
+ shader_set_mat4fv(shadow_shader, "view", view);
+ shader_set_3fv(shadow_shader, "light_pos", light_pos);
+ shader_set_3fv(shadow_shader, "view_pos", state.camera.pos);
+ shader_set_1f(shadow_shader, "far", far);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, wood_texture);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cubemap);
+ render_scene(shadow_shader, cube);
+
+ glfwSwapBuffers(window);
+
+ time = glfwGetTime();
+ state.dt = time-last_time;
+ last_time = time;
+ }
+
+ glfwTerminate();
+ return(0);
error:
- glfwTerminate();
- return(1);
+ glfwTerminate();
+ return(1);
}
diff --git a/advanced_lighting/4.normal_mapping/build.sh b/advanced_lighting/4.normal_mapping/build
index 4209fd0..4209fd0 100755
--- a/advanced_lighting/4.normal_mapping/build.sh
+++ b/advanced_lighting/4.normal_mapping/build
diff --git a/advanced_lighting/4.normal_mapping/normal_mapping.c b/advanced_lighting/4.normal_mapping/normal_mapping.c
index 980f4a0..5051cb7 100644
--- a/advanced_lighting/4.normal_mapping/normal_mapping.c
+++ b/advanced_lighting/4.normal_mapping/normal_mapping.c
@@ -130,13 +130,9 @@ int main(void)
glBindVertexArray(0);
/* NOTE(pryazha): Shaders */
- U32 normal_map_shader = create_shader_program("shaders/normal_map.vert",
- "shaders/normal_map.frag");
- U32 normals_debug_shader = create_shader_program_geom("shaders/normals_debug.vert",
- "shaders/normals_debug.frag",
- "shaders/normals_debug.geom");
- U32 color_shader = create_shader_program("shaders/color.vert",
- "shaders/color.frag");
+ U32 normal_map_shader = load_shader("shaders/normal_map.vert", "shaders/normal_map.frag");
+ U32 normals_debug_shader = load_shader_geom("shaders/normals_debug.vert", "shaders/normals_debug.frag", "shaders/normals_debug.geom");
+ U32 color_shader = load_shader("shaders/color.vert", "shaders/color.frag");
glUseProgram(normal_map_shader);
shader_set_1i(normal_map_shader, "diffuse_texture", 0);
diff --git a/advanced_lighting/5.parallax_mapping/build.sh b/advanced_lighting/5.parallax_mapping/build
index e36f110..e36f110 100755
--- a/advanced_lighting/5.parallax_mapping/build.sh
+++ b/advanced_lighting/5.parallax_mapping/build
diff --git a/advanced_lighting/5.parallax_mapping/parallax_mapping.c b/advanced_lighting/5.parallax_mapping/parallax_mapping.c
index 35859d2..e877926 100644
--- a/advanced_lighting/5.parallax_mapping/parallax_mapping.c
+++ b/advanced_lighting/5.parallax_mapping/parallax_mapping.c
@@ -142,10 +142,8 @@ int main(void)
depth_texture = load_texture("../../data/textures/bricks2_disp.jpg");
/* NOTE(pryazha): Shaders */
- parallax_shader = create_shader_program("shaders/parallax.vert", "shaders/parallax.frag");
- normals_debug_shader = create_shader_program_geom("shaders/normals_debug.vert",
- "shaders/normals_debug.frag",
- "shaders/normals_debug.geom");
+ parallax_shader = load_shader("shaders/parallax.vert", "shaders/parallax.frag");
+ normals_debug_shader = load_shader_geom("shaders/normals_debug.vert", "shaders/normals_debug.frag", "shaders/normals_debug.geom");
glUseProgram(parallax_shader);
shader_set_1i(parallax_shader, "diffuse_texture", 0);
diff --git a/advanced_lighting/6.hdr/build.sh b/advanced_lighting/6.hdr/build
index 3957e1d..3957e1d 100755
--- a/advanced_lighting/6.hdr/build.sh
+++ b/advanced_lighting/6.hdr/build
diff --git a/advanced_lighting/6.hdr/hdr.c b/advanced_lighting/6.hdr/hdr.c
index 911f9da..655ab06 100644
--- a/advanced_lighting/6.hdr/hdr.c
+++ b/advanced_lighting/6.hdr/hdr.c
@@ -10,39 +10,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;
+ S32 width = 800;
+ S32 height = 600;
/* NOTE(pryazha): GLFW init */
glfwSetErrorCallback(error_callback);
@@ -53,7 +22,7 @@ int main(void)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
- window = glfwCreateWindow(width, height, "HDR", 0, 0);
+ GLFWwindow *window = glfwCreateWindow(width, height, "HDR", 0, 0);
if (!window)
goto error;
@@ -67,46 +36,49 @@ int main(void)
glEnable(GL_DEPTH_TEST);
/* NOTE(pryazha): Program init */
+ State state = {0};
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)
+ F32 da = 2.0f*pi_F32/LCOUNT;
+ F32 a = 0.0f;
+ F32 r = 2.0f;
+ V3F lpos[LCOUNT];
+ for (S32 i = 0; i < LCOUNT; i++, a += da)
lpos[i] = v3f(f32_sin(a)*r, 0.0f, f32_cos(a)*r);
- exposure = 1.0f;
+ F32 exposure = 1.0f;
- show_normals = 0;
- show_lights = 1;
+ S32 show_normals = 0;
+ S32 show_lights = 1;
/* NOTE(pryazha): Textures */
- wooodtex = load_texture_gamma("../../data/textures/wood.png", 1);
+ U32 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");
+ Mesh *quad = mesh_gen_quad(state.arena);
+ Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj");
+ Mesh *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");
+ U32 blinn_shader = load_shader("shaders/blinn.vert", "shaders/blinn.frag");
+ U32 hdr_shader = load_shader("shaders/hdr.vert", "shaders/hdr.frag");
+ U32 light_shader = load_shader("shaders/light.vert", "shaders/light.frag");
+ U32 normals_debug_shader = load_shader_geom("shaders/normals_debug.vert", "shaders/normals_debug.frag", "shaders/normals_debug.geom");
/* NOTE(pryazha): Create HDR framebuffer, color buffer texture and
* renderbuffer */
+ U32 hdrfbo, hdrcolorbuf;
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);
+
+ U32 hdrrbo;
glGenRenderbuffers(1, &hdrrbo);
glBindRenderbuffer(GL_RENDERBUFFER, hdrrbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
@@ -121,7 +93,7 @@ int main(void)
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- last_time = glfwGetTime();
+ F64 last_time = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
@@ -161,7 +133,9 @@ int main(void)
if (key_is_pressed(state.input.action_up))
exposure += 0.01f;
- for (i = 0; i < LCOUNT; i++)
+ printf("exposure = %f\n", exposure);
+
+ for (S32 i = 0; i < LCOUNT; i++)
lpos[i].y = f32_sin(glfwGetTime()+i);
/* NOTE(pryazha): Render */
@@ -188,7 +162,7 @@ int main(void)
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++) {
+ for (S32 i = 0; i < LCOUNT; i++) {
snprintf(lstr, 1024, "lpos[%d]", i);
shader_set_3fv(blinn_shader, lstr, lpos[i]);
}
@@ -204,7 +178,7 @@ int main(void)
glUseProgram(light_shader);
shader_set_mat4fv(light_shader, "proj", proj);
shader_set_mat4fv(light_shader, "view", view);
- for (i = 0; i < LCOUNT; i++) {
+ for (S32 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);
@@ -236,7 +210,7 @@ int main(void)
glfwSwapBuffers(window);
- time = glfwGetTime();
+ F64 time = glfwGetTime();
state.dt = time-last_time;
last_time = time;
diff --git a/advanced_lighting/7.bloom/bloom.c b/advanced_lighting/7.bloom/bloom.c
new file mode 100644
index 0000000..70adcfe
--- /dev/null
+++ b/advanced_lighting/7.bloom/bloom.c
@@ -0,0 +1,287 @@
+#include "GL/glew.h"
+#include "GLFW/glfw3.h"
+
+#include "pwyazh.h"
+#include "pwyazh_GL.h"
+
+#include "common.h"
+
+#define LIGHT_COUNT 3
+
+int main(void)
+{
+ S32 width = 1600;
+ S32 height = 900;
+
+ /* 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);
+ GLFWwindow *window = glfwCreateWindow(width, height, "Bloom", 0, 0);
+ if (!window)
+ return 1;
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ glfwMakeContextCurrent(window);
+ if (glewInit() != GLEW_OK)
+ return 1;
+
+ glEnable(GL_DEPTH_TEST);
+
+ /* NOTE(pryazha): Program init */
+ State state = {0};
+ 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 };
+
+ V3F light_positions[LIGHT_COUNT];
+ F32 da = 2.0f*pi_F32/LIGHT_COUNT;
+ F32 a = 0.0f;
+ F32 r = 2.0f;
+ for (S32 i = 0; i < LIGHT_COUNT; i++, a += da)
+ light_positions[i] = v3f(f32_sin(a)*r, 0.0f, f32_cos(a)*r);
+
+ V3F light_colors[LIGHT_COUNT] = {
+ {5.0f, 5.0f, 5.0f},
+ {10.0f, 0.0f, 0.0f},
+ {0.0f, 5.0f, 0.0f},
+ };
+
+ S32 bloom = 0;
+ F32 exposure = 1.0f;
+
+ /* NOTE(pryazha): Textures */
+ U32 woood_texture = load_texture_gamma("../../data/textures/wood.png", 1);
+
+ /* NOTE(pryazha): Meshes */
+ Mesh *quad = mesh_gen_quad(state.arena);
+ Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj");
+
+ /* NOTE(pryazha): Shaders */
+ U32 shader = load_shader("shaders/bloom.vert", "shaders/bloom.frag");
+ U32 shader_light = load_shader("shaders/bloom.vert", "shaders/light.frag");
+ U32 shader_blur = load_shader("shaders/blur.vert", "shaders/blur.frag");
+ U32 shader_test_blur = load_shader("shaders/test_blur.vert", "shaders/test_blur.frag");
+ U32 shader_final = load_shader("shaders/final.vert", "shaders/final.frag");
+
+ glUseProgram(shader_final);
+ shader_set_1i(shader_final, "scene", 0);
+ shader_set_1i(shader_final, "blur", 1);
+
+ /* NOTE(pryazha): Framebuffers */
+ U32 hdrfbo;
+ glGenFramebuffers(1, &hdrfbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo);
+
+ U32 colorbuffers[2];
+ glGenTextures(2, colorbuffers);
+ for (S32 i = 0; i < 2; ++i) {
+ glBindTexture(GL_TEXTURE_2D, colorbuffers[i]);
+ 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);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, colorbuffers[i], 0);
+ }
+
+ U32 hdrrbo;
+ glGenRenderbuffers(1, &hdrrbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, hdrrbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, hdrrbo);
+
+ U32 attachments[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
+ glDrawBuffers(2, attachments);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "error: framebuffer not complete\n");
+
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ U32 pingpong_fbo[2];
+ U32 pingpong_colorbuffers[2];
+ glGenFramebuffers(2, pingpong_fbo);
+ glGenTextures(2, pingpong_colorbuffers);
+ for (S32 i = 0; i < 2; i++) {
+ glBindFramebuffer(GL_FRAMEBUFFER, pingpong_fbo[i]);
+ glBindTexture(GL_TEXTURE_2D, pingpong_colorbuffers[i]);
+ 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);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpong_colorbuffers[i], 0);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "error: framebuffer not complete\n");
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ U32 blur_fbo;
+ glGenFramebuffers(1, &blur_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, blur_fbo);
+ U32 blur_colorbuffer;
+ glGenTextures(1, &blur_colorbuffer);
+ glBindTexture(GL_TEXTURE_2D, blur_colorbuffer);
+ 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);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blur_colorbuffer, 0);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "error: blur framebuffer not complete\n");
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ S32 myblur = 0;
+
+ F64 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);
+
+ F32 speed = 2.0f;
+ V3F 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);
+
+ 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;
+
+ /* NOTE(pryazha): Update */
+ if (key_is_pressed(state.input.action_down))
+ exposure -= 0.01f;
+ if (key_is_pressed(state.input.action_up))
+ exposure += 0.01f;
+
+ if (key_first_press(state.input.jump))
+ bloom = !bloom;
+
+ if (key_first_press(state.input.action_left))
+ myblur = !myblur;
+
+ for (S32 i = 0; i < LIGHT_COUNT; i++)
+ light_positions[i].y = f32_sin(glfwGetTime()+i);
+
+ /* NOTE(pryazha): Render */
+ glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* Render to HDR framebuffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ F32 ar = (F32)width/(F32)height;
+ MAT4 projection = camera_persp(state.camera, ar);
+ MAT4 view = get_view_matrix(&state.camera);
+
+ glUseProgram(shader);
+ shader_set_mat4fv(shader, "projection", projection);
+ shader_set_mat4fv(shader, "view", view);
+ for (S32 i = 0; i < LIGHT_COUNT; i++) {
+ char light_string[1024];
+ snprintf(light_string, 1024, "lights[%d].position", i);
+ shader_set_3fv(shader, light_string, light_positions[i]);
+ snprintf(light_string, 1024, "lights[%d].color", i);
+ shader_set_3fv(shader, light_string, light_colors[i]);
+ }
+ shader_set_3fv(shader, "view_pos", state.camera.pos);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, woood_texture);
+
+ MAT4 model = mat4_make_scale(v3f(10.0f, 0.25f, 10.0f));
+ model = mat4_translate(model, v3f(0.0f, -2.0f, 0.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_rotate_angles(model, v3f(30.0f, 45.0f, 0.0f));
+ model = mat4_translate(model, v3f(-0.5f, -1.0f, -2.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_rotate_angles(model, v3f(-30.0f, 45.0f, 90.0f));
+ model = mat4_translate(model, v3f(0.75f, -1.5f, 1.0f));
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glUseProgram(0);
+
+ glUseProgram(shader_light);
+ shader_set_mat4fv(shader_light, "projection", projection);
+ shader_set_mat4fv(shader_light, "view", view);
+ for (S32 i = 0; i < LIGHT_COUNT; i++) {
+ model = mat4_make_scale(v3f(0.2f, 0.2f, 0.2f));
+ model = mat4_translate(model, light_positions[i]);
+ shader_set_mat4fv(shader_light, "model", model);
+ shader_set_3fv(shader_light, "light_color", light_colors[i]);
+ mesh_draw(cube);
+ }
+ glUseProgram(0);
+
+ S32 horizontal = 1, first = 1, amount = 10;
+ glUseProgram(shader_blur);
+ for (S32 i = 0; i < amount; i++) {
+ glBindFramebuffer(GL_FRAMEBUFFER, pingpong_fbo[horizontal]);
+ shader_set_1i(shader_blur, "horizontal", horizontal);
+ glBindTexture(GL_TEXTURE_2D, first ? colorbuffers[1] : pingpong_colorbuffers[!horizontal]);
+ mesh_draw(quad);
+ horizontal = !horizontal;
+ if (first)
+ first = 0;
+ }
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, blur_fbo);
+ glUseProgram(shader_test_blur);
+ glActiveTexture(0);
+ glBindTexture(GL_TEXTURE_2D, colorbuffers[1]);
+ mesh_draw(quad);
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram(shader_final);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, colorbuffers[0]);
+ glActiveTexture(GL_TEXTURE1);
+ if (myblur) {
+ glBindTexture(GL_TEXTURE_2D, blur_colorbuffer);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, pingpong_colorbuffers[!horizontal]);
+ }
+ shader_set_1i(shader_final, "bloom", bloom);
+ shader_set_1f(shader_final, "exposure", exposure);
+ mesh_draw(quad);
+
+ glfwSwapBuffers(window);
+
+ F64 time = glfwGetTime();
+ state.dt = time - last_time;
+ last_time = time;
+
+ input_update_last_state(&state.input);
+ }
+
+ return 0;
+}
diff --git a/advanced_lighting/7.bloom/build b/advanced_lighting/7.bloom/build
new file mode 100755
index 0000000..99df29a
--- /dev/null
+++ b/advanced_lighting/7.bloom/build
@@ -0,0 +1,5 @@
+#!/bin/sh
+. ../../config
+TARGET='bloom'
+set -x
+gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS
diff --git a/advanced_lighting/7.bloom/shaders/bloom.frag b/advanced_lighting/7.bloom/shaders/bloom.frag
new file mode 100644
index 0000000..88decf8
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/bloom.frag
@@ -0,0 +1,45 @@
+#version 330 core
+
+in VS_OUT {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vs_out;
+
+layout(location = 0) out vec4 frag_color;
+layout(location = 1) out vec4 bright_color;
+
+struct light_t {
+ vec3 position;
+ vec3 color;
+};
+
+uniform light_t lights[3];
+uniform sampler2D diffuse_texture;
+uniform vec3 view_pos;
+
+const int light_count = 3;
+
+void main(void)
+{
+ vec3 color = texture(diffuse_texture, vs_out.tex_coords).rgb;
+ vec3 ambient = 0.01 * color;
+ vec3 lighting = vec3(0.0);
+ vec3 view_dir = normalize(view_pos - vs_out.position);
+ for (int i = 0; i < light_count; i++) {
+ vec3 light_dir = normalize(lights[i].position - vs_out.position);
+ float diff = max(dot(light_dir, vs_out.normal), 0.0);
+ vec3 result = lights[i].color * diff * color;
+ float distance = length(vs_out.position - lights[i].position);
+ result *= 1.0 / (distance * distance);
+ lighting += result;
+ }
+ vec3 result = ambient + lighting;
+ float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722));
+ if (brightness > 1.0) {
+ bright_color = vec4(result, 1.0);
+ } else {
+ bright_color = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/bloom.vert b/advanced_lighting/7.bloom/shaders/bloom.vert
new file mode 100644
index 0000000..0c9dc02
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/bloom.vert
@@ -0,0 +1,24 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec3 normal;
+layout (location = 2) in vec2 tex_coords;
+
+out VS_OUT {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vs_out;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 model;
+
+void main()
+{
+ vs_out.position = vec3(model * vec4(position, 1.0));
+ mat3 normal_matrix = transpose(inverse(mat3(model)));
+ vs_out.normal = normalize(normal_matrix * normal);
+ vs_out.tex_coords = tex_coords;
+ gl_Position = projection * view * model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/blur.frag b/advanced_lighting/7.bloom/shaders/blur.frag
new file mode 100644
index 0000000..67b7e43
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/blur.frag
@@ -0,0 +1,29 @@
+#version 330 core
+
+in VS_OUT {
+ vec2 tex_coords;
+} vs_out;
+
+out vec4 frag_color;
+
+uniform sampler2D image;
+uniform bool horizontal;
+uniform float weights[5] = float[](0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162);
+
+void main(void)
+{
+ vec2 tex_offset = 1.0 / textureSize(image, 0);
+ vec3 result = texture(image, vs_out.tex_coords).rgb * weights[0];
+ if (horizontal) {
+ for (int i = 1; i < 5; i++) {
+ result += texture(image, vs_out.tex_coords + vec2(tex_offset.x * i, 0.0)).rgb * weights[i];
+ result += texture(image, vs_out.tex_coords - vec2(tex_offset.x * i, 0.0)).rgb * weights[i];
+ }
+ } else {
+ for (int i = 1; i < 5; i++) {
+ result += texture(image, vs_out.tex_coords + vec2(0.0, tex_offset.y * i)).rgb * weights[i];
+ result += texture(image, vs_out.tex_coords - vec2(0.0, tex_offset.y * i)).rgb * weights[i];
+ }
+ }
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/blur.vert b/advanced_lighting/7.bloom/shaders/blur.vert
new file mode 100644
index 0000000..e4ced24
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/blur.vert
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 2) in vec2 tex_coords;
+
+out VS_OUT {
+ vec2 tex_coords;
+} vs_out;
+
+void main(void)
+{
+ vs_out.tex_coords = tex_coords;
+ gl_Position = vec4(position, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/final.frag b/advanced_lighting/7.bloom/shaders/final.frag
new file mode 100644
index 0000000..fe9f5d7
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/final.frag
@@ -0,0 +1,25 @@
+#version 330 core
+
+in VS_OUT {
+ vec2 tex_coords;
+} vs_out;
+
+out vec4 frag_color;
+
+uniform sampler2D scene;
+uniform sampler2D blur;
+uniform bool bloom;
+uniform float exposure;
+
+void main()
+{
+ const float gamma = 2.2;
+ vec3 scene_color = texture(scene, vs_out.tex_coords).rgb;
+ vec3 blur_color = texture(blur, vs_out.tex_coords).rgb;
+ if (bloom) {
+ scene_color += blur_color;
+ }
+ vec3 result = vec3(1.0) - exp(-scene_color * exposure);
+ result = pow(result, vec3(1.0 / gamma));
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/final.vert b/advanced_lighting/7.bloom/shaders/final.vert
new file mode 100644
index 0000000..f6a4e38
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/final.vert
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 2) in vec2 tex_coords;
+
+out VS_OUT {
+ vec2 tex_coords;
+} vs_out;
+
+void main()
+{
+ vs_out.tex_coords = tex_coords;
+ gl_Position = vec4(position, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/light.frag b/advanced_lighting/7.bloom/shaders/light.frag
new file mode 100644
index 0000000..72a2874
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/light.frag
@@ -0,0 +1,22 @@
+#version 330 core
+
+in VS_OUT {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vs_out;
+
+layout(location = 0) out vec4 frag_color;
+layout(location = 1) out vec4 bright_color;
+
+uniform vec3 light_color;
+
+void main()
+{
+ frag_color = vec4(light_color, 1.0);
+ float brightness = dot(vec3(frag_color), vec3(0.2126, 0.7152, 0.0722));
+ if (brightness > 1.0)
+ bright_color = vec4(vec3(frag_color), 1.0);
+ else
+ bright_color = vec4(0.0, 0.0, 0.0, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/test_blur.frag b/advanced_lighting/7.bloom/shaders/test_blur.frag
new file mode 100644
index 0000000..8d7ee9a
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/test_blur.frag
@@ -0,0 +1,28 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D colorbuffer;
+
+uniform float weights[5] = float[](0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162);
+
+void main()
+{
+ vec2 texture_offset = 1.0 / textureSize(colorbuffer, 0);
+ vec3 result = texture(colorbuffer, vert.tex_coords).rgb * weights[0];
+ for (int x = 1; x < weights.length(); x++) {
+ vec2 offset = vec2(texture_offset.x * x, 0.0f);
+ result += texture(colorbuffer, vert.tex_coords + offset).rgb * weights[x];
+ result += texture(colorbuffer, vert.tex_coords - offset).rgb * weights[x];
+ }
+ for (int y = 1; y < weights.length(); y++) {
+ vec2 offset = vec2(0.0f, texture_offset.y * y);
+ result += texture(colorbuffer, vert.tex_coords + offset).rgb * weights[y];
+ result += texture(colorbuffer, vert.tex_coords - offset).rgb * weights[y];
+ }
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/7.bloom/shaders/test_blur.vert b/advanced_lighting/7.bloom/shaders/test_blur.vert
new file mode 100644
index 0000000..eed3be3
--- /dev/null
+++ b/advanced_lighting/7.bloom/shaders/test_blur.vert
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout(location = 0) in vec3 position;
+layout(location = 2) in vec2 tex_coords;
+
+out vert_t {
+ vec2 tex_coords;
+} vert;
+
+void main()
+{
+ vert.tex_coords = tex_coords;
+ gl_Position = vec4(position, 1.0);
+}
diff --git a/advanced_lighting/8.deferred_shading/build b/advanced_lighting/8.deferred_shading/build
new file mode 100755
index 0000000..fc81382
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/build
@@ -0,0 +1,5 @@
+#!/bin/sh
+. ../../config
+TARGET='deferred'
+set -x
+gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS
diff --git a/advanced_lighting/8.deferred_shading/deferred.c b/advanced_lighting/8.deferred_shading/deferred.c
new file mode 100644
index 0000000..d411b41
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/deferred.c
@@ -0,0 +1,274 @@
+#include "GL/glew.h"
+#include "GLFW/glfw3.h"
+
+#include "pwyazh.h"
+#include "pwyazh_GL.h"
+
+#include "common.h"
+
+#define LIGHT_COUNT 200
+#define CUBE_COUNT 1000
+
+int main(void)
+{
+ /* 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);
+ S32 width = 1600;
+ S32 height = 900;
+ GLFWwindow *window = glfwCreateWindow(width, height, "deferred", 0, 0);
+ if (!window)
+ return 1;
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ glfwMakeContextCurrent(window);
+ if (glewInit() != GLEW_OK)
+ return 1;
+ glEnable(GL_DEPTH_TEST);
+
+ /* NOTE(pryazha): Program init */
+ State state = {0};
+ state.arena = arena_alloc(Kilobytes(256));
+ state.input.first_mouse = 1;
+ state.camera = (Camera){ v3f(0.0f, 2.0f, 5.0f), 90.0f, 0.1f, 100.0f, 0.0f, 0.0f };
+
+ /* NOTE(pryazha): Textures */
+ U32 woood_texture = load_texture("../../data/textures/wood.png");
+
+ /* NOTE(pryazha): Meshes */
+ Mesh *quad = mesh_gen_quad(state.arena);
+ Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj");
+
+ /* NOTE(pryazha): Framebuffers */
+ U32 gbuffer;
+ glGenFramebuffers(1, &gbuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, gbuffer);
+
+ // position color buffer
+ U32 gpositions;
+ glGenTextures(1, &gpositions);
+ glBindTexture(GL_TEXTURE_2D, gpositions);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gpositions, 0);
+ // normal
+ U32 gnormals;
+ glGenTextures(1, &gnormals);
+ glBindTexture(GL_TEXTURE_2D, gnormals);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gnormals, 0);
+ // color + specular
+ U32 gcolor_specular;
+ glGenTextures(1, &gcolor_specular);
+ glBindTexture(GL_TEXTURE_2D, gcolor_specular);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gcolor_specular, 0);
+ U32 attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
+ glDrawBuffers(3, attachments);
+ U32 rbo;
+ glGenRenderbuffers(1, &rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "error: gbuffer not complete\n");
+ fprintf(stdout, "info: gbuffer complete\n");
+
+ /* NOTE(pryazha): Shaders */
+ U32 shader_gbuffer = load_shader("shaders/gbuffer.vert", "shaders/gbuffer.frag");
+ U32 shader_screen = load_shader("shaders/screen.vert", "shaders/screen.frag");
+ U32 shader_specular = load_shader("shaders/screen.vert", "shaders/specular.frag");
+ U32 shader_deferred = load_shader("shaders/screen.vert", "shaders/deferred.frag");
+ U32 shader_light = load_shader("shaders/light.vert", "shaders/light.frag");
+
+ glUseProgram(shader_deferred);
+ shader_set_1i(shader_deferred, "positions", 0);
+ shader_set_1i(shader_deferred, "normals", 1);
+ shader_set_1i(shader_deferred, "color_specular", 2);
+ glUseProgram(0);
+
+ V3F cube_positions[CUBE_COUNT];
+ S32 cols = 30;
+ F32 spacing = 3.0f;
+ for (S32 i = 0; i < CUBE_COUNT; i++) {
+ S32 col = i % cols;
+ S32 row = i / cols;
+ cube_positions[i] = v3f(col * spacing, 0.0f, row * spacing);
+ }
+
+ light_t lights[LIGHT_COUNT];
+#if 0
+ V3F origin = {50.0f, 3.0f, 50.0f};
+ F32 da = 2.0f*pi_F32/LIGHT_COUNT;
+ F32 a = 0.0f;
+ F32 radius = 20.0f;
+ for (S32 i = 0; i < LIGHT_COUNT; i++, a += da) {
+ lights[i].position = v3f_add(v3f(f32_sin(a) * radius, 0.0f, f32_cos(a) * radius), origin);
+ F32 r = (F32)(rand() % 100) / 100.0f;
+ F32 g = (F32)(rand() % 100) / 100.0f;
+ F32 b = (F32)(rand() % 100) / 100.0f;
+ lights[i].color = v3f(r, g, b);
+ }
+#else
+ V3F origin = {0.0f, 3.0f, 0.0f};
+ cols = 30;
+ spacing = 3.0f;
+ for (S32 i = 0; i < LIGHT_COUNT; i++) {
+ S32 col = i % cols;
+ S32 row = i / cols;
+ lights[i].position = v3f_add(v3f(col * spacing, 0.0f, row * spacing), origin);
+ F32 r = (F32)(rand() % 100) / 100.0f;
+ F32 g = (F32)(rand() % 100) / 100.0f;
+ F32 b = (F32)(rand() % 100) / 100.0f;
+ lights[i].color = v3f(r, g, b);
+ }
+#endif
+
+ S32 show_gbuffer = 0;
+
+ F64 last_time = glfwGetTime();
+ while (!glfwWindowShouldClose(window)) {
+ F64 time = glfwGetTime();
+ state.dt = time - last_time;
+ last_time = time;
+
+ input_update_last_state(&state.input);
+
+ 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);
+
+ F32 speed = 2.0f;
+ V3F 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);
+
+ 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;
+
+ /* NOTE(pryazha): Update */
+ for (S32 i = 0; i < LIGHT_COUNT; i++)
+ lights[i].position.y = origin.y + f32_sin(glfwGetTime() + i);
+
+ if (key_first_press(state.input.jump)) {
+ show_gbuffer = !show_gbuffer;
+ }
+
+ /* NOTE(pryazha): Render */
+ F32 ar = (F32)width/(F32)height;
+ MAT4 projection = camera_persp(state.camera, ar);
+ MAT4 view = get_view_matrix(&state.camera);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, gbuffer);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glUseProgram(shader_gbuffer);
+ shader_set_mat4fv(shader_gbuffer, "projection", projection);
+ shader_set_mat4fv(shader_gbuffer, "view", view);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, woood_texture);
+
+ for (S32 i = 0; i < CUBE_COUNT; i++) {
+ MAT4 model = mat4_make_translate(cube_positions[i]);
+ shader_set_mat4fv(shader_gbuffer, "model", model);
+ mesh_draw(cube);
+ }
+
+ glUseProgram(0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (show_gbuffer) {
+ glDisable(GL_DEPTH_TEST);
+ glUseProgram(shader_screen);
+ MAT4 model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_translate(model, v3f(-0.5f, 0.5f, 0.0f));
+ shader_set_mat4fv(shader_screen, "model", model);
+ glBindTexture(GL_TEXTURE_2D, gpositions);
+ mesh_draw(quad);
+
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_translate(model, v3f(0.5f, 0.5f, 0.0f));
+ shader_set_mat4fv(shader_screen, "model", model);
+ glBindTexture(GL_TEXTURE_2D, gnormals);
+ mesh_draw(quad);
+
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_translate(model, v3f(-0.5f, -0.5f, 0.0f));
+ shader_set_mat4fv(shader_screen, "model", model);
+ glBindTexture(GL_TEXTURE_2D, gcolor_specular);
+ mesh_draw(quad);
+ glUseProgram(0);
+
+ glUseProgram(shader_specular);
+ model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_translate(model, v3f(0.5f, -0.5f, 0.0f));
+ shader_set_mat4fv(shader_specular, "model", model);
+ glBindTexture(GL_TEXTURE_2D, gcolor_specular);
+ mesh_draw(quad);
+ glUseProgram(0);
+ glEnable(GL_DEPTH_TEST);
+ } else {
+ glUseProgram(shader_deferred);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, gpositions);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, gnormals);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, gcolor_specular);
+ shader_set_3fv(shader_deferred, "view_position", state.camera.pos);
+ for (S32 i = 0; i < LIGHT_COUNT; i++) {
+ char light_string[512];
+ snprintf(light_string, 512, "lights[%d].position", i);
+ shader_set_3fv(shader_deferred, light_string, lights[i].position);
+ snprintf(light_string, 512, "lights[%d].color", i);
+ shader_set_3fv(shader_deferred, light_string, lights[i].color);
+ }
+ MAT4 model = mat4_identity();
+ shader_set_mat4fv(shader_deferred, "model", model);
+ mesh_draw(quad);
+ glUseProgram(0);
+ glEnable(GL_DEPTH_TEST);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, gbuffer);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
+ GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ glUseProgram(shader_light);
+ shader_set_mat4fv(shader_light, "projection", projection);
+ shader_set_mat4fv(shader_light, "view", view);
+ for (S32 i = 0; i < LIGHT_COUNT; i++) {
+ shader_set_3fv(shader_light, "light_color", lights[i].color);
+ model = mat4_make_scale(v3f(0.2f, 0.2f, 0.2f));
+ model = mat4_translate(model, lights[i].position);
+ shader_set_mat4fv(shader_light, "model", model);
+ mesh_draw(cube);
+ }
+ glUseProgram(0);
+ }
+
+ glfwSwapBuffers(window);
+ }
+
+ return 0;
+}
diff --git a/advanced_lighting/8.deferred_shading/shaders/deferred.frag b/advanced_lighting/8.deferred_shading/shaders/deferred.frag
new file mode 100644
index 0000000..56e5f58
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/shaders/deferred.frag
@@ -0,0 +1,46 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D positions;
+uniform sampler2D normals;
+uniform sampler2D color_specular;
+
+uniform vec3 view_position;
+
+struct light_t {
+ vec3 position;
+ vec3 color;
+};
+
+const int light_count = 200;
+uniform light_t lights[light_count];
+
+const float linear = 0.7f;
+const float quadratic = 1.8f;
+
+void main()
+{
+ vec3 position = texture(positions, vert.tex_coords).rgb;
+ vec3 normal = texture(normals, vert.tex_coords).rgb;
+ vec3 color = texture(color_specular, vert.tex_coords).rgb;
+ float specular = texture(color_specular, vert.tex_coords).a;
+
+ vec3 ambient = 0.1 * color;
+ vec3 view_dir = normalize(view_position - position);
+ vec3 result = ambient;
+ for (int i = 0; i < light_count; i++) {
+ vec3 light_dir = normalize(lights[i].position - position);
+ vec3 diffuse = max(dot(normal, light_dir), 0.0) * color * lights[i].color;
+ float distance = length(lights[i].position - position);
+ float attenuation = 1.0 / (1.0 + linear * distance + quadratic * distance * distance);
+ vec3 halfway_dir = normalize(view_dir + light_dir);
+ vec3 specular = pow(max(dot(halfway_dir, normal), 0.0), 32.0) * vec3(0.5);
+ result += (diffuse + specular) * attenuation;
+ }
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/8.deferred_shading/shaders/gbuffer.frag b/advanced_lighting/8.deferred_shading/shaders/gbuffer.frag
new file mode 100644
index 0000000..5f82c0b
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/shaders/gbuffer.frag
@@ -0,0 +1,23 @@
+#version 330 core
+
+in vert_t {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vert;
+
+layout (location = 0) out vec3 position;
+layout (location = 1) out vec3 normal;
+layout (location = 2) out vec4 color_specular;
+
+uniform sampler2D texture_diffuse;
+
+void main()
+{
+ position = vert.position;
+ normal = vert.normal;
+ color_specular.rgb = texture(texture_diffuse, vert.tex_coords).rgb;
+ // TODO(pryazha): add specular texture
+ // color_specular.a = texture(texture_specular, vert.tex_coords).r;
+ color_specular.a = 1;
+}
diff --git a/advanced_lighting/8.deferred_shading/shaders/gbuffer.vert b/advanced_lighting/8.deferred_shading/shaders/gbuffer.vert
new file mode 100644
index 0000000..1e825c8
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/shaders/gbuffer.vert
@@ -0,0 +1,24 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec3 normal;
+layout (location = 2) in vec2 tex_coords;
+
+out vert_t {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vert;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 model;
+
+void main()
+{
+ vert.position = vec3(model * vec4(position, 1.0));
+ mat3 matrix_normal = transpose(inverse(mat3(model)));
+ vert.normal = matrix_normal * normal;
+ vert.tex_coords = tex_coords;
+ gl_Position = projection * view * model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/8.deferred_shading/shaders/light.frag b/advanced_lighting/8.deferred_shading/shaders/light.frag
new file mode 100644
index 0000000..e654b0e
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/shaders/light.frag
@@ -0,0 +1,11 @@
+#version 330 core
+
+out vec4 frag_color;
+
+uniform vec3 light_color;
+
+void main()
+{
+ frag_color = vec4(light_color, 1.0);
+}
+
diff --git a/advanced_lighting/8.deferred_shading/shaders/light.vert b/advanced_lighting/8.deferred_shading/shaders/light.vert
new file mode 100644
index 0000000..03ac7e2
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/shaders/light.vert
@@ -0,0 +1,12 @@
+#version 330 core
+
+layout(location = 0) in vec3 position;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 model;
+
+void main()
+{
+ gl_Position = projection * view * model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/8.deferred_shading/shaders/screen.frag b/advanced_lighting/8.deferred_shading/shaders/screen.frag
new file mode 100644
index 0000000..3ae592d
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/shaders/screen.frag
@@ -0,0 +1,14 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D colorbuffer;
+
+void main()
+{
+ frag_color = vec4(texture(colorbuffer, vert.tex_coords).rgb, 1.0);
+}
diff --git a/advanced_lighting/8.deferred_shading/shaders/screen.vert b/advanced_lighting/8.deferred_shading/shaders/screen.vert
new file mode 100644
index 0000000..335635b
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/shaders/screen.vert
@@ -0,0 +1,16 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 2) in vec2 tex_coords;
+
+out vert_t {
+ vec2 tex_coords;
+} vert;
+
+uniform mat4 model;
+
+void main()
+{
+ vert.tex_coords = tex_coords;
+ gl_Position = model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/8.deferred_shading/shaders/specular.frag b/advanced_lighting/8.deferred_shading/shaders/specular.frag
new file mode 100644
index 0000000..e6ea10e
--- /dev/null
+++ b/advanced_lighting/8.deferred_shading/shaders/specular.frag
@@ -0,0 +1,14 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D colorbuffer;
+
+void main()
+{
+ frag_color = vec4(vec3(texture(colorbuffer, vert.tex_coords).a), 1.0);
+}
diff --git a/advanced_lighting/9.ssao/build b/advanced_lighting/9.ssao/build
new file mode 100755
index 0000000..dc6929a
--- /dev/null
+++ b/advanced_lighting/9.ssao/build
@@ -0,0 +1,5 @@
+#!/bin/sh
+. ../../config
+TARGET='ssao'
+set -x
+gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS
diff --git a/advanced_lighting/9.ssao/deferred.frag b/advanced_lighting/9.ssao/deferred.frag
new file mode 100644
index 0000000..5a3cc33
--- /dev/null
+++ b/advanced_lighting/9.ssao/deferred.frag
@@ -0,0 +1,44 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D positions;
+uniform sampler2D normals;
+uniform sampler2D albedo;
+uniform sampler2D ssao;
+
+uniform vec3 view_position;
+
+struct light_t {
+ vec3 position;
+ vec3 color;
+};
+
+uniform light_t light;
+
+const float linear = 0.7f;
+const float quadratic = 1.8f;
+
+void main()
+{
+ vec3 position = texture(positions, vert.tex_coords).xyz;
+ vec3 normal = texture(normals, vert.tex_coords).xyz;
+ vec3 color = texture(albedo, vert.tex_coords).rgb;
+ float occlusion = texture(ssao, vert.tex_coords).r;
+
+ vec3 ambient = 0.1 * color * occlusion;
+ vec3 result = ambient;
+ vec3 view_dir = normalize(-position);
+ vec3 light_dir = normalize(light.position - position);
+ vec3 diffuse = max(dot(normal, light_dir), 0.0) * color * light.color;
+ vec3 halfway_dir = normalize(view_dir + light_dir);
+ vec3 specular = pow(max(dot(halfway_dir, normal), 0.0), 16.0) * vec3(0.5);
+ float distance = length(light.position - position);
+ float attenuation = 1.0 / (1.0 + linear * distance + quadratic * distance * distance);
+ result += (diffuse + specular) * attenuation;
+ frag_color = vec4(result, 1.0);
+}
diff --git a/advanced_lighting/9.ssao/deferred.vert b/advanced_lighting/9.ssao/deferred.vert
new file mode 100644
index 0000000..335635b
--- /dev/null
+++ b/advanced_lighting/9.ssao/deferred.vert
@@ -0,0 +1,16 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 2) in vec2 tex_coords;
+
+out vert_t {
+ vec2 tex_coords;
+} vert;
+
+uniform mat4 model;
+
+void main()
+{
+ vert.tex_coords = tex_coords;
+ gl_Position = model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/9.ssao/gbuffer.frag b/advanced_lighting/9.ssao/gbuffer.frag
new file mode 100644
index 0000000..7755107
--- /dev/null
+++ b/advanced_lighting/9.ssao/gbuffer.frag
@@ -0,0 +1,17 @@
+#version 330 core
+
+in vert_t {
+ vec3 position;
+ vec3 normal;
+} vert;
+
+layout(location = 0) out vec3 position;
+layout(location = 1) out vec3 normal;
+layout(location = 2) out vec3 albedo;
+
+void main()
+{
+ position = vert.position;
+ normal = normalize(vert.normal);
+ albedo.rgb = vec3(0.95);
+}
diff --git a/advanced_lighting/9.ssao/gbuffer.vert b/advanced_lighting/9.ssao/gbuffer.vert
new file mode 100644
index 0000000..81ab951
--- /dev/null
+++ b/advanced_lighting/9.ssao/gbuffer.vert
@@ -0,0 +1,21 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec3 normal;
+
+out vert_t {
+ vec3 position;
+ vec3 normal;
+} vert;
+
+uniform mat4 projection;
+uniform mat4 view;
+uniform mat4 model;
+
+void main()
+{
+ vert.position = vec3(view * model * vec4(position, 1.0));
+ mat3 matrix_normal = transpose(inverse(mat3(view * model)));
+ vert.normal = matrix_normal * normal;
+ gl_Position = projection * view * model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/9.ssao/occlusion.frag b/advanced_lighting/9.ssao/occlusion.frag
new file mode 100644
index 0000000..41a436b
--- /dev/null
+++ b/advanced_lighting/9.ssao/occlusion.frag
@@ -0,0 +1,14 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D colorbuffer;
+
+void main()
+{
+ frag_color = vec4(vec3(texture(colorbuffer, vert.tex_coords).r), 1.0);
+}
diff --git a/advanced_lighting/9.ssao/screen.frag b/advanced_lighting/9.ssao/screen.frag
new file mode 100644
index 0000000..3ae592d
--- /dev/null
+++ b/advanced_lighting/9.ssao/screen.frag
@@ -0,0 +1,14 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D colorbuffer;
+
+void main()
+{
+ frag_color = vec4(texture(colorbuffer, vert.tex_coords).rgb, 1.0);
+}
diff --git a/advanced_lighting/9.ssao/screen.vert b/advanced_lighting/9.ssao/screen.vert
new file mode 100644
index 0000000..335635b
--- /dev/null
+++ b/advanced_lighting/9.ssao/screen.vert
@@ -0,0 +1,16 @@
+#version 330 core
+
+layout (location = 0) in vec3 position;
+layout (location = 2) in vec2 tex_coords;
+
+out vert_t {
+ vec2 tex_coords;
+} vert;
+
+uniform mat4 model;
+
+void main()
+{
+ vert.tex_coords = tex_coords;
+ gl_Position = model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/9.ssao/ssao b/advanced_lighting/9.ssao/ssao
new file mode 100755
index 0000000..72a9677
--- /dev/null
+++ b/advanced_lighting/9.ssao/ssao
Binary files differ
diff --git a/advanced_lighting/9.ssao/ssao.c b/advanced_lighting/9.ssao/ssao.c
new file mode 100644
index 0000000..3cfca03
--- /dev/null
+++ b/advanced_lighting/9.ssao/ssao.c
@@ -0,0 +1,331 @@
+#include "GL/glew.h"
+#include "GLFW/glfw3.h"
+
+#include "pwyazh.h"
+#include "pwyazh_GL.h"
+
+#include "xoshiro128plus.c"
+
+#include "common.h"
+
+#include "assert.h"
+
+int main(void)
+{
+ // 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);
+ S32 width = 1600;
+ S32 height = 900;
+ GLFWwindow *window = glfwCreateWindow(width, height, "ssao", 0, 0);
+ if (!window)
+ return 1;
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ glfwMakeContextCurrent(window);
+ if (glewInit() != GLEW_OK)
+ return 1;
+ glEnable(GL_DEPTH_TEST);
+
+ // program init
+ Arena *arena = arena_alloc(Kilobytes(256));
+ Input input = input_init();
+ Camera camera = {
+ .pos = v3f(0.0f, 2.0f, 5.0f),
+ .fovx = 90.0f,
+ .near = 0.1f,
+ .far = 100.0f,
+ .yaw = 0.0f,
+ .pitch = 0.0f
+ };
+ V3F camera_dp = {0};
+ light_t light = {{2.0f, 2.0f, 2.0f}, {5.0f, 5.0f, 10.0f}};
+
+ // meshes
+ Mesh *quad = mesh_gen_quad(arena);
+ Mesh *cube = mesh_load_obj(arena, "../../data/models/cube.obj");
+
+ // framebuffers
+ U32 gbuffer;
+ glGenFramebuffers(1, &gbuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, gbuffer);
+
+ U32 gpositions;
+ glGenTextures(1, &gpositions);
+ glBindTexture(GL_TEXTURE_2D, gpositions);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gpositions, 0);
+
+ U32 gnormals;
+ glGenTextures(1, &gnormals);
+ glBindTexture(GL_TEXTURE_2D, gnormals);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gnormals, 0);
+
+ U32 galbedo;
+ glGenTextures(1, &galbedo);
+ glBindTexture(GL_TEXTURE_2D, galbedo);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, galbedo, 0);
+ U32 attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
+ glDrawBuffers(3, attachments);
+
+ U32 rbo;
+ glGenRenderbuffers(1, &rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ fprintf(stderr, "error: gbuffer not complete\n");
+ fprintf(stdout, "info: gbuffer complete\n");
+
+ // shaders
+ U32 shader_gbuffer = load_shader("gbuffer.vert", "gbuffer.frag");
+ U32 shader_ssao = load_shader("ssao.vert", "ssao.frag");
+ U32 shader_deferred = load_shader("deferred.vert", "deferred.frag");
+ U32 shader_screen = load_shader("screen.vert", "screen.frag");
+ U32 shader_occlusion = load_shader("screen.vert", "occlusion.frag");
+
+ glUseProgram(shader_ssao);
+ shader_set_1i(shader_ssao, "positions", 0);
+ shader_set_1i(shader_ssao, "normals", 1);
+ shader_set_1i(shader_ssao, "noise", 2);
+ glUseProgram(shader_deferred);
+ shader_set_1i(shader_deferred, "positions", 0);
+ shader_set_1i(shader_deferred, "normals", 1);
+ shader_set_1i(shader_deferred, "albedo", 2);
+ shader_set_1i(shader_deferred, "ssao", 3);
+ glUseProgram(0);
+
+ S32 show_gbuffer = 0;
+
+ S32 nsamples = 64;
+ V3F *samples = malloc(nsamples * sizeof(V3F));
+ S32 file = open("/dev/urandom", O_RDONLY);
+ if (file < 0) {
+ perror("error:");
+ return 1;
+ }
+ U32 seed[4];
+ if (read(file, seed, sizeof(seed)) < 0) {
+ perror("error");
+ return 1;
+ }
+ for (S32 i = 0; i < nsamples; i++) {
+ V3F sample = {
+ nextf(seed) * 2.0f - 1.0f,
+ nextf(seed) * 2.0f - 1.0f,
+ nextf(seed)
+ };
+ sample = v3f_norm(sample);
+ float scale = (F32)i / 64.0f;
+ scale = lerp(0.1f, 1.0f, scale * scale);
+ sample = v3f_scalef(sample, scale);
+ samples[i] = sample;
+ assert(-1.0f < sample.x && sample.x < 1.0f);
+ assert(-1.0f < sample.y && sample.y < 1.0f);
+ assert(0.0f < sample.z && sample.z < 1.0f);
+ // printf("color:\t%f\t%f\t%f\n", sample.x, sample.y, sample.z);
+ }
+ V3F noise[16];
+ for (S32 i = 0; i < 16; i++) {
+ noise[i] = (V3F){
+ nextf(seed) * 2.0f - 1.0f,
+ nextf(seed) * 2.0f - 1.0f,
+ 0.0f,
+ };
+ }
+ close(file);
+
+ U32 noise_texture;
+ glGenTextures(1, &noise_texture);
+ glBindTexture(GL_TEXTURE_2D, noise_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 4, 4, 0, GL_RGB, GL_FLOAT, noise);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ U32 ssao_fbo;
+ glGenFramebuffers(1, &ssao_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, ssao_fbo);
+ U32 ssao_colorbuffer;
+ glGenTextures(1, &ssao_colorbuffer);
+ glBindTexture(GL_TEXTURE_2D, ssao_colorbuffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssao_colorbuffer, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ F64 last_time = glfwGetTime();
+ while (!glfwWindowShouldClose(window)) {
+ F64 time = glfwGetTime();
+ F32 dt = time - last_time;
+ last_time = time;
+
+ input_update_last_state(&input);
+
+ glfwPollEvents();
+ glfwGetFramebufferSize(window, &width, &height);
+ process_glfw_keyboard(window, &input);
+ process_glfw_mouse_pos(window, &input);
+
+ if (key_first_press(input.exit))
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+
+ F32 speed = 2.0f;
+ V3F dv = get_dv_camera_first_person(&input, &camera, speed, dt);
+ camera_dp = v3f_add(camera_dp, dv);
+ camera_dp = v3f_scalef(camera_dp, 0.8f);
+ camera.pos = v3f_add(camera.pos, camera_dp);
+
+ F32 sensitivity = 0.1f;
+ input.mouse_offset = v2f_scalef(input.mouse_offset, sensitivity);
+ camera.yaw += input.mouse_offset.x;
+ camera.pitch += input.mouse_offset.y;
+ if (camera.pitch > 89.0f)
+ camera.pitch = 89.0f;
+ if (camera.pitch < -89.0f)
+ camera.pitch = -89.0f;
+
+ // update
+ if (key_first_press(input.jump))
+ show_gbuffer = !show_gbuffer;
+
+ // render
+ F32 ar = (F32)width / (F32)height;
+ MAT4 projection = camera_persp(camera, ar);
+ MAT4 view = get_view_matrix(&camera);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // render stuff into gbuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, gbuffer);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram(shader_gbuffer);
+
+ shader_set_mat4fv(shader_gbuffer, "projection", projection);
+ shader_set_mat4fv(shader_gbuffer, "view", view);
+
+ shader_set_mat4fv(shader_gbuffer, "model", mat4_identity());
+ mesh_draw(cube);
+
+ MAT4 model = mat4_make_scale(v3f(10.0f, 0.2f, 10.0f));
+ model = mat4_translate(model, v3f(0.0f, -1.25f, 0.0f));
+ shader_set_mat4fv(shader_gbuffer, "model", model);
+ mesh_draw(cube);
+
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ // render ssao texture
+ glBindFramebuffer(GL_FRAMEBUFFER, ssao_fbo);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glUseProgram(shader_ssao);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, gpositions);
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, gnormals);
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, noise_texture);
+
+ for (S32 i = 0; i < nsamples; i++) {
+
+ char str[512] = {0};
+ snprintf(str, 512, "samples[%d]", i);
+ shader_set_3fv(shader_ssao, str, samples[i]);
+ }
+ shader_set_mat4fv(shader_ssao, "projection", projection);
+
+ mesh_draw(quad);
+
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ if (show_gbuffer) {
+ MAT4 scale = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ MAT4 leftup = mat4_translate(scale, v3f(-0.5f, 0.5f, 0.0f));
+ MAT4 rightup = mat4_translate(scale, v3f(0.5f, 0.5f, 0.0f));
+ MAT4 leftdown = mat4_translate(scale, v3f(-0.5f, -0.5f, 0.0f));
+ MAT4 rightdown = mat4_translate(scale, v3f(0.5f, -0.5f, 0.0f));
+
+ glDisable(GL_DEPTH_TEST);
+
+ glUseProgram(shader_screen);
+ shader_set_mat4fv(shader_screen, "model", leftup);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, gpositions);
+ mesh_draw(quad);
+
+ shader_set_mat4fv(shader_screen, "model", rightup);
+ glBindTexture(GL_TEXTURE_2D, gnormals);
+ mesh_draw(quad);
+
+ shader_set_mat4fv(shader_screen, "model", leftdown);
+ glBindTexture(GL_TEXTURE_2D, galbedo);
+ mesh_draw(quad);
+ glUseProgram(0);
+
+ glUseProgram(shader_occlusion);
+ shader_set_mat4fv(shader_occlusion, "model", rightdown);
+ glBindTexture(GL_TEXTURE_2D, ssao_colorbuffer);
+ mesh_draw(quad);
+ glUseProgram(0);
+
+ glEnable(GL_DEPTH_TEST);
+ } else {
+ // render scene lighting
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram(shader_deferred);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, gpositions);
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, gnormals);
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, galbedo);
+
+ glActiveTexture(GL_TEXTURE3);
+ glBindTexture(GL_TEXTURE_2D, ssao_colorbuffer);
+
+ V4F light_pos_v4 = v4f(light.position.x, light.position.y, light.position.z, 1.0f);
+ V4F light_view_pos = mat4_v4f_mul(view, light_pos_v4);
+ shader_set_3fv(shader_deferred, "light.position", v3f_from_v4f(light_view_pos));
+ shader_set_3fv(shader_deferred, "light.color", light.color);
+ shader_set_mat4fv(shader_deferred, "model", mat4_identity());
+
+ mesh_draw(quad);
+
+ glUseProgram(0);
+ }
+
+ glfwSwapBuffers(window);
+ }
+
+ return 0;
+}
diff --git a/advanced_lighting/9.ssao/ssao.frag b/advanced_lighting/9.ssao/ssao.frag
new file mode 100644
index 0000000..e4d04b1
--- /dev/null
+++ b/advanced_lighting/9.ssao/ssao.frag
@@ -0,0 +1,45 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out float frag_color;
+
+uniform sampler2D positions;
+uniform sampler2D normals;
+uniform sampler2D noise;
+
+uniform vec3 samples[64];
+uniform mat4 projection;
+
+const vec2 noise_scale = vec2(1600.0 / 4.0, 900.0 / 4.0)
+
+void main()
+{
+ vec3 position = texture(positions, vert.tex_coords).rgb;
+ vec3 normal = texture(normals, vert.tex_coords).rgb;
+ vec3 random = texture(noise, vert.tex_coords * noise_scale).rgb;
+
+ vec3 tangent = normalize(random - normal * dot(random, normal));
+ vec3 bitangent = cross(normal, tangent);
+ mat3 TBN = mat3(tangent, bitangent, normal);
+
+ int nsamples = 64;
+ float radius = 0.5;
+ float bias = 0.025;
+ float occlusion = 0.0;
+ for (int i = 0; i < nsamples; i++) {
+ vec3 sample = TBN * samples[i];
+ sample = position + sample * radius;
+ vec4 offset = vec4(sample, 1.0);
+ offset = projection * offset;
+ offset.xyz /= offset.w;
+ offset.xyz = offset.xyz * 0.5 + 0.5;
+ float depth = texture(positions, offset.xy).z;
+ // float range_check = smoothstep(0.0, 1.0, radius / abs(position.z - depth));
+ occlusion += (depth >= sample.z + bias ? 1.0 : 0.0); // * range_check;
+ }
+ occlusion = 1.0 - (occlusion / nsamples);
+ frag_color = occlusion;
+}
diff --git a/advanced_lighting/9.ssao/ssao.vert b/advanced_lighting/9.ssao/ssao.vert
new file mode 100644
index 0000000..3ce6fb2
--- /dev/null
+++ b/advanced_lighting/9.ssao/ssao.vert
@@ -0,0 +1,16 @@
+#version 330 core
+
+layout(location = 0) in vec3 position;
+layout(location = 2) in vec2 tex_coords;
+
+out vert_t {
+ vec2 tex_coords;
+} vert;
+
+uniform mat4 model;
+
+void main()
+{
+ vert.tex_coords = tex_coords;
+ gl_Position = model * vec4(position, 1.0);
+}
diff --git a/advanced_lighting/9.ssao/xoshiro128plus.c b/advanced_lighting/9.ssao/xoshiro128plus.c
new file mode 100644
index 0000000..b55c63b
--- /dev/null
+++ b/advanced_lighting/9.ssao/xoshiro128plus.c
@@ -0,0 +1,28 @@
+#include <stdint.h>
+
+/* --- xoshiro128+ --- */
+static inline uint32_t rotl(const uint32_t x, int k) {
+ return (x << k) | (x >> (32 - k));
+}
+
+uint32_t next(uint32_t *s) {
+ const uint32_t result = s[0] + s[3];
+ const uint32_t t = s[1] << 9;
+ s[2] ^= s[0];
+ s[3] ^= s[1];
+ s[1] ^= s[2];
+ s[0] ^= s[3];
+ s[2] ^= t;
+ s[3] = rotl(s[3], 11);
+ return result;
+}
+/* --- /xoshiro128+ --- */
+
+float int_to_float(uint32_t random) {
+ union { uint32_t u32; float f; } u = { .u32 = random >> 9 | 0x3f800000 };
+ return u.f - 1.0;
+}
+
+float nextf(uint32_t* s) {
+ return int_to_float(next(s));
+}
diff --git a/advanced_opengl/build.sh b/advanced_lighting/build
index 4829c7d..1168d91 100755
--- a/advanced_opengl/build.sh
+++ b/advanced_lighting/build
@@ -1,9 +1,9 @@
#!/bin/sh
targets=$(ls)
for target in $targets ; do
- if [ $target != 'build.sh' ] ; then
+ if [ $target != 'build' ] ; then
cd $target
- ./build.sh
+ ./build
cd ..
fi
done
diff --git a/advanced_opengl/1.depth/build.sh b/advanced_opengl/1.depth/build
index 04fe803..04fe803 100755
--- a/advanced_opengl/1.depth/build.sh
+++ b/advanced_opengl/1.depth/build
diff --git a/advanced_opengl/1.depth/depth.c b/advanced_opengl/1.depth/depth.c
index 03092df..71a7ffc 100644
--- a/advanced_opengl/1.depth/depth.c
+++ b/advanced_opengl/1.depth/depth.c
@@ -8,178 +8,170 @@
int main(void)
{
- GLFWwindow *window;
- State state;
- S32 width, height;
- Input input;
-
- if (glfwInit() == GLFW_FALSE) {
- fprintf(stderr, "[ERROR] Failed to initialize glfw.\n");
- return(1);
- }
-
- width = 1024;
- height = 768;
-
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- window = glfwCreateWindow(width, height, "Depth testing.", 0, 0);
- if (!window) {
- fprintf(stderr, "[ERROR] Failed to create window.\n");
- glfwTerminate();
- return(1);
- }
-
- glfwMakeContextCurrent(window);
-
- if (glewInit() != GLEW_OK) {
- fprintf(stderr, "[ERROR] Failed to initialize glew.\n");
- glfwTerminate();
- return(1);
- }
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
-
- U32 shader = create_shader_program("shaders/depth.vert", "shaders/depth.frag");
- U32 marble_texture = load_texture("../../data/textures/marble.jpg");
- U32 metal_texture = load_texture("../../data/textures/metal.png");
-
- F32 a = 0.5f;
- F32 vertices[] = {
- -a, -a, -a, 0.0f, 0.0f,
- a, -a, -a, 1.0f, 0.0f,
- a, a, -a, 1.0f, 1.0f,
- a, a, -a, 1.0f, 1.0f,
- -a, a, -a, 0.0f, 1.0f,
- -a, -a, -a, 0.0f, 0.0f,
-
- -a, -a, a, 0.0f, 0.0f,
- a, -a, a, 1.0f, 0.0f,
- a, a, a, 1.0f, 1.0f,
- a, a, a, 1.0f, 1.0f,
- -a, a, a, 0.0f, 1.0f,
- -a, -a, a, 0.0f, 0.0f,
-
- -a, a, a, 1.0f, 0.0f,
- -a, a, -a, 1.0f, 1.0f,
- -a, -a, -a, 0.0f, 1.0f,
- -a, -a, -a, 0.0f, 1.0f,
- -a, -a, a, 0.0f, 0.0f,
- -a, a, a, 1.0f, 0.0f,
-
- a, a, a, 1.0f, 0.0f,
- a, a, -a, 1.0f, 1.0f,
- a, -a, -a, 0.0f, 1.0f,
- a, -a, -a, 0.0f, 1.0f,
- a, -a, a, 0.0f, 0.0f,
- a, a, a, 1.0f, 0.0f,
-
- -a, -a, -a, 0.0f, 1.0f,
- a, -a, -a, 1.0f, 1.0f,
- a, -a, a, 1.0f, 0.0f,
- a, -a, a, 1.0f, 0.0f,
- -a, -a, a, 0.0f, 0.0f,
- -a, -a, -a, 0.0f, 1.0f,
-
- -a, a, -a, 0.0f, 1.0f,
- a, a, -a, 1.0f, 1.0f,
- a, a, a, 1.0f, 0.0f,
- a, a, a, 1.0f, 0.0f,
- -a, a, a, 0.0f, 0.0f,
- -a, a, -a, 0.0f, 1.0f
- };
-
- Transform cube_positions[] = {
- transform_default(),
- transform_make_translate(v3f(a, 0.0f, -4*a))
- };
-
- V3F platform_pos = v3f(10.0f, 0.2f, 10.0f);
- V3F platform_scale = v3f(0.0f, -(a+(a*0.2f)+0.01f), 0.0f);
- Transform platform_transform = transform_make_scale_translate(platform_pos, platform_scale);
-
- U32 VAO, VBO;
- glGenVertexArrays(1, &VAO);
- glBindVertexArray(VAO);
- glGenBuffers(1, &VBO);
- glBindBuffer(GL_ARRAY_BUFFER, VBO);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32)));
- glBindVertexArray(0);
-
- state.camera = (Camera) {
- v3f(0.0f, 0.0f, 3.0f),
- 90.0f, 0.1f, 100.0f,
- 0.0f, 0.0f
- };
-
- F32 target_fps = 60.0f;
- F32 target_spf = 1.0f/target_fps;
- F32 last_time = glfwGetTime();
-
- while (!glfwWindowShouldClose(window)) {
- glfwPollEvents();
-
- process_glfw_keyboard(window, &input);
- glfwGetFramebufferSize(window, &width, &height);
-
- /* INFO(pryazha): Update */
- V3F target = v3f_zero();
-
- if (key_first_press(input.exit))
- glfwSetWindowShouldClose(window, GLFW_TRUE);
-
- V3F dv = get_dv_camera_orbital(&input, state.camera.pos,
- target, state.dt, 3.0f);
- state.camera.pos = v3f_add(state.camera.pos, dv);
-
- input_update_last_state(&input);
-
- /* INFO(pryazha): Render */
- MAT4 model, view, proj;
- view = look_at(state.camera.pos, target, v3f(0.0f, 1.0f, 0.0f));
- /* proj = ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f); */
- proj = perspective(state.camera.fovx, (F32)width/(F32)height,
- state.camera.near, state.camera.far);
-
- glViewport(0, 0, width, height);
- glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glUseProgram(shader);
- shader_set_mat4fv(shader, "view", view);
- shader_set_mat4fv(shader, "proj", proj);
- glBindTexture(GL_TEXTURE_2D, marble_texture);
- glBindVertexArray(VAO);
- for (S32 i = 0; i < (S32)ArrayCount(cube_positions); ++i) {
- model = transform_apply(cube_positions[i]);
- shader_set_mat4fv(shader, "model", model);
- glDrawArrays(GL_TRIANGLES, 0, 36);
- }
- glBindTexture(GL_TEXTURE_2D, metal_texture);
- model = transform_apply(platform_transform);
- shader_set_mat4fv(shader, "model", model);
- glDrawArrays(GL_TRIANGLES, 0, 36);
- glBindVertexArray(0);
-
- glfwSwapBuffers(window);
-
- F32 elapsed = glfwGetTime()-last_time;
- if (elapsed < target_spf) {
- U32 sleep_time = (U32)(target_spf-elapsed);
- if (sleep_time > 0)
- sleep(sleep_time);
- }
- F32 current_time = glfwGetTime();
- state.dt = current_time-last_time;
- last_time = current_time;
- }
-
- glfwTerminate();
- return(0);
+ if (glfwInit() == GLFW_FALSE) {
+ fprintf(stderr, "[ERROR] Failed to initialize glfw.\n");
+ return(1);
+ }
+
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ S32 width = 1024;
+ S32 height = 768;
+ GLFWwindow *window = glfwCreateWindow(width, height, "Depth testing.", 0, 0);
+ if (!window) {
+ fprintf(stderr, "[ERROR] Failed to create window.\n");
+ glfwTerminate();
+ return(1);
+ }
+
+ glfwMakeContextCurrent(window);
+
+ if (glewInit() != GLEW_OK) {
+ fprintf(stderr, "[ERROR] Failed to initialize glew.\n");
+ glfwTerminate();
+ return(1);
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ U32 shader = load_shader("shaders/depth.vert", "shaders/depth.frag");
+ U32 marble_texture = load_texture("../../data/textures/marble.jpg");
+ U32 metal_texture = load_texture("../../data/textures/metal.png");
+
+ F32 a = 0.5f;
+ F32 vertices[] = {
+ -a, -a, -a, 0.0f, 0.0f,
+ a, -a, -a, 1.0f, 0.0f,
+ a, a, -a, 1.0f, 1.0f,
+ a, a, -a, 1.0f, 1.0f,
+ -a, a, -a, 0.0f, 1.0f,
+ -a, -a, -a, 0.0f, 0.0f,
+
+ -a, -a, a, 0.0f, 0.0f,
+ a, -a, a, 1.0f, 0.0f,
+ a, a, a, 1.0f, 1.0f,
+ a, a, a, 1.0f, 1.0f,
+ -a, a, a, 0.0f, 1.0f,
+ -a, -a, a, 0.0f, 0.0f,
+
+ -a, a, a, 1.0f, 0.0f,
+ -a, a, -a, 1.0f, 1.0f,
+ -a, -a, -a, 0.0f, 1.0f,
+ -a, -a, -a, 0.0f, 1.0f,
+ -a, -a, a, 0.0f, 0.0f,
+ -a, a, a, 1.0f, 0.0f,
+
+ a, a, a, 1.0f, 0.0f,
+ a, a, -a, 1.0f, 1.0f,
+ a, -a, -a, 0.0f, 1.0f,
+ a, -a, -a, 0.0f, 1.0f,
+ a, -a, a, 0.0f, 0.0f,
+ a, a, a, 1.0f, 0.0f,
+
+ -a, -a, -a, 0.0f, 1.0f,
+ a, -a, -a, 1.0f, 1.0f,
+ a, -a, a, 1.0f, 0.0f,
+ a, -a, a, 1.0f, 0.0f,
+ -a, -a, a, 0.0f, 0.0f,
+ -a, -a, -a, 0.0f, 1.0f,
+
+ -a, a, -a, 0.0f, 1.0f,
+ a, a, -a, 1.0f, 1.0f,
+ a, a, a, 1.0f, 0.0f,
+ a, a, a, 1.0f, 0.0f,
+ -a, a, a, 0.0f, 0.0f,
+ -a, a, -a, 0.0f, 1.0f
+ };
+
+ Transform cube_positions[] = {
+ transform_default(),
+ transform_make_translate(v3f(a, 0.0f, -4*a))
+ };
+
+ V3F platform_pos = v3f(10.0f, 0.2f, 10.0f);
+ V3F platform_scale = v3f(0.0f, -(a+(a*0.2f)+0.01f), 0.0f);
+ Transform platform_transform = transform_make_scale_translate(platform_pos, platform_scale);
+
+ U32 VAO, VBO;
+ glGenVertexArrays(1, &VAO);
+ glBindVertexArray(VAO);
+ glGenBuffers(1, &VBO);
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)0);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(F32), (void *)(3*sizeof(F32)));
+ glBindVertexArray(0);
+
+ State state = {0};
+ Input input = {0};
+ state.camera = (Camera){v3f(0.0f, 0.0f, 3.0f), 90.0f, 0.1f, 100.0f, 0.0f, 0.0f};
+
+ F32 target_fps = 60.0f;
+ F32 target_spf = 1.0f/target_fps;
+ F32 last_time = glfwGetTime();
+
+ while (!glfwWindowShouldClose(window)) {
+ glfwPollEvents();
+
+ process_glfw_keyboard(window, &input);
+ glfwGetFramebufferSize(window, &width, &height);
+
+ /* INFO(pryazha): Update */
+ V3F target = v3f_zero();
+
+ if (key_first_press(input.exit))
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+
+ V3F dv = get_dv_camera_orbital(&input, state.camera.pos,
+ target, state.dt, 3.0f);
+ state.camera.pos = v3f_add(state.camera.pos, dv);
+
+ input_update_last_state(&input);
+
+ /* INFO(pryazha): Render */
+ MAT4 model, view, proj;
+ view = look_at(state.camera.pos, target, v3f(0.0f, 1.0f, 0.0f));
+ /* proj = ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f); */
+ proj = perspective(state.camera.fovx, (F32)width/(F32)height,
+ state.camera.near, state.camera.far);
+
+ glViewport(0, 0, width, height);
+ glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram(shader);
+ shader_set_mat4fv(shader, "view", view);
+ shader_set_mat4fv(shader, "proj", proj);
+ glBindTexture(GL_TEXTURE_2D, marble_texture);
+ glBindVertexArray(VAO);
+ for (S32 i = 0; i < (S32)ArrayCount(cube_positions); ++i) {
+ model = transform_apply(cube_positions[i]);
+ shader_set_mat4fv(shader, "model", model);
+ glDrawArrays(GL_TRIANGLES, 0, 36);
+ }
+ glBindTexture(GL_TEXTURE_2D, metal_texture);
+ model = transform_apply(platform_transform);
+ shader_set_mat4fv(shader, "model", model);
+ glDrawArrays(GL_TRIANGLES, 0, 36);
+ glBindVertexArray(0);
+
+ glfwSwapBuffers(window);
+
+ F32 elapsed = glfwGetTime()-last_time;
+ if (elapsed < target_spf) {
+ U32 sleep_time = (U32)(target_spf-elapsed);
+ if (sleep_time > 0)
+ sleep(sleep_time);
+ }
+ F32 current_time = glfwGetTime();
+ state.dt = current_time-last_time;
+ last_time = current_time;
+ }
+
+ glfwTerminate();
+ return(0);
}
diff --git a/advanced_opengl/10.antialiasing/anti_aliasing_msaa.c b/advanced_opengl/10.antialiasing/anti_aliasing_msaa.c
index 250ab97..07c82c7 100644
--- a/advanced_opengl/10.antialiasing/anti_aliasing_msaa.c
+++ b/advanced_opengl/10.antialiasing/anti_aliasing_msaa.c
@@ -15,7 +15,6 @@ int main(void)
F32 target_fps, target_spf, last_time;
MAT4 proj, view, model;
State state;
- S32 width, height;
U32 color_shader;
if (glfwInit() == GLFW_FALSE) {
@@ -23,12 +22,13 @@ int main(void)
return(1);
}
- width = 1024;
- height = 768;
+ S32 width = 1024;
+ S32 height = 768;
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);
glfwWindowHint(GLFW_SAMPLES, 4);
window = glfwCreateWindow(width, height, "Anti Aliasing (MSAA)", 0, 0);
if (!window) {
@@ -53,8 +53,7 @@ int main(void)
arena = arena_alloc(Kilobytes(4));
cube = mesh_load_obj(arena, "../../data/models/cube.obj");
- color_shader = create_shader_program("shaders/color.vert",
- "shaders/color.frag");
+ color_shader = load_shader("shaders/color.vert", "shaders/color.frag");
state.camera = (Camera) {
v3f(0.0f, 0.0f, 3.0f),
diff --git a/advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c b/advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c
index 31f3cae..beb0d12 100644
--- a/advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c
+++ b/advanced_opengl/10.antialiasing/anti_aliasing_offscreen.c
@@ -32,6 +32,7 @@ int main(void)
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);
window = glfwCreateWindow(width, height, "Anti Aliasing (Off-screen)", 0, 0);
if (!window) {
fprintf(stderr, "[ERROR] Failed to create window.\n");
@@ -52,10 +53,8 @@ int main(void)
arena = arena_alloc(Kilobytes(4));
cube = mesh_load_obj(arena, "../../data/models/cube.obj");
- color_shader = create_shader_program("shaders/color.vert",
- "shaders/color.frag");
- screen_shader = create_shader_program("shaders/screen.vert",
- "shaders/screen.frag");
+ color_shader = load_shader("shaders/color.vert", "shaders/color.frag");
+ screen_shader = load_shader("shaders/screen.vert", "shaders/screen.frag");
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &color_tex);
diff --git a/advanced_opengl/10.antialiasing/build.sh b/advanced_opengl/10.antialiasing/build
index 9d1011a..9d1011a 100755
--- a/advanced_opengl/10.antialiasing/build.sh
+++ b/advanced_opengl/10.antialiasing/build
diff --git a/advanced_opengl/2.stencil/build.sh b/advanced_opengl/2.stencil/build
index c4aa562..c4aa562 100755
--- a/advanced_opengl/2.stencil/build.sh
+++ b/advanced_opengl/2.stencil/build
diff --git a/advanced_opengl/2.stencil/stencil.c b/advanced_opengl/2.stencil/stencil.c
index 3b01f5b..924d8f6 100644
--- a/advanced_opengl/2.stencil/stencil.c
+++ b/advanced_opengl/2.stencil/stencil.c
@@ -43,8 +43,8 @@ int main(void)
glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- U32 shader = create_shader_program("shaders/stencil.vert", "shaders/stencil.frag");
- U32 outline_shader = create_shader_program("shaders/stencil.vert", "shaders/outline.frag");
+ U32 shader = load_shader("shaders/stencil.vert", "shaders/stencil.frag");
+ U32 outline_shader = load_shader("shaders/stencil.vert", "shaders/outline.frag");
U32 marble_texture = load_texture("../../data/textures/marble.jpg");
U32 metal_texture = load_texture("../../data/textures/metal.png");
diff --git a/advanced_opengl/3.blending/blending.c b/advanced_opengl/3.blending/blending.c
index 8142ab3..dcc189f 100644
--- a/advanced_opengl/3.blending/blending.c
+++ b/advanced_opengl/3.blending/blending.c
@@ -43,8 +43,8 @@ int main(void)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- U32 shader = create_shader_program("shaders/blending.vert", "shaders/blending.frag");
- U32 grass_shader = create_shader_program("shaders/blending.vert", "shaders/grass.frag");
+ U32 shader = load_shader("shaders/blending.vert", "shaders/blending.frag");
+ U32 grass_shader = load_shader("shaders/blending.vert", "shaders/grass.frag");
U32 marble_texture = load_texture("../../data/textures/marble.jpg");
U32 metal_texture = load_texture("../../data/textures/metal.png");
U32 grass_texture = load_texture("../../data/textures/grass.png");
diff --git a/advanced_opengl/3.blending/build.sh b/advanced_opengl/3.blending/build
index 51f3629..51f3629 100755
--- a/advanced_opengl/3.blending/build.sh
+++ b/advanced_opengl/3.blending/build
diff --git a/advanced_opengl/4.face_culling/build.sh b/advanced_opengl/4.face_culling/build
index d67eefa..d67eefa 100755
--- a/advanced_opengl/4.face_culling/build.sh
+++ b/advanced_opengl/4.face_culling/build
diff --git a/advanced_opengl/4.face_culling/face_culling.c b/advanced_opengl/4.face_culling/face_culling.c
index c3a31c0..0e65e08 100644
--- a/advanced_opengl/4.face_culling/face_culling.c
+++ b/advanced_opengl/4.face_culling/face_culling.c
@@ -44,8 +44,7 @@ int main(void)
glFrontFace(GL_CW);
glCullFace(GL_BACK);
- U32 shader = create_shader_program("shaders/face_culling.vert",
- "shaders/face_culling.frag");
+ U32 shader = load_shader("shaders/face_culling.vert", "shaders/face_culling.frag");
U32 grid_texture = load_texture("../../data/textures/grid.png");
diff --git a/advanced_opengl/5.framebuffers/build.sh b/advanced_opengl/5.framebuffers/build
index cb55ebf..cb55ebf 100755
--- a/advanced_opengl/5.framebuffers/build.sh
+++ b/advanced_opengl/5.framebuffers/build
diff --git a/advanced_opengl/5.framebuffers/framebuffers.c b/advanced_opengl/5.framebuffers/framebuffers.c
index 7948a61..67745ef 100644
--- a/advanced_opengl/5.framebuffers/framebuffers.c
+++ b/advanced_opengl/5.framebuffers/framebuffers.c
@@ -24,6 +24,7 @@ int main(void)
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);
window = glfwCreateWindow(width, height, "Framebuffers", 0, 0);
if (!window) {
fprintf(stderr, "[ERROR] Failed to create window.\n");
@@ -39,10 +40,8 @@ int main(void)
return(1);
}
- U32 screen_shader = create_shader_program("shaders/screen.vert",
- "shaders/screen.frag");
- U32 cube_shader = create_shader_program("shaders/cube.vert",
- "shaders/cube.frag");
+ U32 screen_shader = load_shader("shaders/screen.vert", "shaders/screen.frag");
+ U32 cube_shader = load_shader("shaders/cube.vert", "shaders/cube.frag");
U32 marble_texture = load_texture("../../data/textures/marble.jpg");
U32 metal_texture = load_texture("../../data/textures/metal.png");
U32 window_texture = load_texture("../../data/textures/window.png");
@@ -56,14 +55,12 @@ int main(void)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, texture_colorbuffer, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_colorbuffer, 0);
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, rbo);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
fprintf(stderr, "[ERROR]: Framebuffer is not complete.\n");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -120,8 +117,7 @@ int main(void)
V3F platform_pos = v3f(10.0f, 0.2f, 10.0f);
V3F platform_scale = v3f(0.0f, -(a+(a*0.2f)+0.01f), 0.0f);
- Transform platform_transform = transform_make_scale_translate(platform_pos,
- platform_scale);
+ Transform platform_transform = transform_make_scale_translate(platform_pos, platform_scale);
U32 cube_vao, quad_vao, vbo;
glGenVertexArrays(1, &cube_vao);
glBindVertexArray(cube_vao);
diff --git a/advanced_opengl/6.cubemaps/build.sh b/advanced_opengl/6.cubemaps/build
index 9bda0bc..9bda0bc 100755
--- a/advanced_opengl/6.cubemaps/build.sh
+++ b/advanced_opengl/6.cubemaps/build
diff --git a/advanced_opengl/6.cubemaps/cubemaps.c b/advanced_opengl/6.cubemaps/cubemaps.c
index 32a53d1..d1088a4 100644
--- a/advanced_opengl/6.cubemaps/cubemaps.c
+++ b/advanced_opengl/6.cubemaps/cubemaps.c
@@ -24,6 +24,7 @@ int main(void)
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);
window = glfwCreateWindow(width, height, "Cubemaps", 0, 0);
if (!window) {
fprintf(stderr, "[ERROR] Failed to create window.\n");
@@ -44,10 +45,10 @@ int main(void)
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
- U32 skybox_shader = create_shader_program("shaders/skybox.vert", "shaders/skybox.frag");
- U32 reflection_shader = create_shader_program("shaders/reflection.vert", "shaders/reflection.frag");
- U32 refraction_shader = create_shader_program("shaders/refraction.vert", "shaders/refraction.frag");
- U32 cube_shader = create_shader_program("shaders/cube.vert", "shaders/cube.frag");
+ U32 skybox_shader = load_shader("shaders/skybox.vert", "shaders/skybox.frag");
+ U32 reflection_shader = load_shader("shaders/reflection.vert", "shaders/reflection.frag");
+ U32 refraction_shader = load_shader("shaders/refraction.vert", "shaders/refraction.frag");
+ U32 cube_shader = load_shader("shaders/cube.vert", "shaders/cube.frag");
U32 grid_texture = load_texture("../../data/textures/grid.png");
const char *cube_texture_filenames[6] = {
diff --git a/advanced_opengl/7.uniform_buffer/build.sh b/advanced_opengl/7.uniform_buffer/build
index 54642df..54642df 100755
--- a/advanced_opengl/7.uniform_buffer/build.sh
+++ b/advanced_opengl/7.uniform_buffer/build
diff --git a/advanced_opengl/7.uniform_buffer/uniform_buffer.c b/advanced_opengl/7.uniform_buffer/uniform_buffer.c
index a27c115..752b171 100644
--- a/advanced_opengl/7.uniform_buffer/uniform_buffer.c
+++ b/advanced_opengl/7.uniform_buffer/uniform_buffer.c
@@ -24,6 +24,7 @@ int main(void)
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);
window = glfwCreateWindow(width, height, "Advanced data (uniform buffer)", 0, 0);
if (!window) {
fprintf(stderr, "[ERROR] Failed to create window.\n");
@@ -44,9 +45,9 @@ int main(void)
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
- U32 skybox_shader = create_shader_program("shaders/skybox.vert", "shaders/skybox.frag");
- U32 cube_shader = create_shader_program("shaders/cube.vert", "shaders/cube.frag");
- U32 color_cube_shader = create_shader_program("shaders/color_cube.vert", "shaders/color_cube.frag");
+ U32 skybox_shader = load_shader("shaders/skybox.vert", "shaders/skybox.frag");
+ U32 cube_shader = load_shader("shaders/cube.vert", "shaders/cube.frag");
+ U32 color_cube_shader = load_shader("shaders/color_cube.vert", "shaders/color_cube.frag");
U32 skybox_matrices = glGetUniformBlockIndex(skybox_shader, "Matrices");
U32 cube_matrices = glGetUniformBlockIndex(cube_shader, "Matrices");
@@ -235,12 +236,10 @@ int main(void)
state.camera.near, state.camera.far);
glBindBuffer(GL_UNIFORM_BUFFER, matrices_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(MAT4),
- (const void *)&proj);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(MAT4), (const void *)&proj);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBuffer(GL_UNIFORM_BUFFER, matrices_ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, sizeof(MAT4),
- sizeof(MAT4), (const void *)&view);
+ glBufferSubData(GL_UNIFORM_BUFFER, sizeof(MAT4), sizeof(MAT4), (const void *)&view);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
diff --git a/advanced_opengl/8.geometry_shader/build.sh b/advanced_opengl/8.geometry_shader/build
index f3339cb..f3339cb 100755
--- a/advanced_opengl/8.geometry_shader/build.sh
+++ b/advanced_opengl/8.geometry_shader/build
diff --git a/advanced_opengl/8.geometry_shader/geometry_shader.c b/advanced_opengl/8.geometry_shader/geometry_shader.c
index f242709..03bb7b9 100644
--- a/advanced_opengl/8.geometry_shader/geometry_shader.c
+++ b/advanced_opengl/8.geometry_shader/geometry_shader.c
@@ -33,6 +33,7 @@ int main(void)
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);
window = glfwCreateWindow(width, height, "depth testing", 0, 0);
if (!window) {
fprintf(stderr, "[ERROR] Failed to create window.\n");
@@ -50,17 +51,10 @@ int main(void)
glEnable(GL_DEPTH_TEST);
- U32 shader = create_shader_program_geom("shaders/base.vert",
- "shaders/base.frag",
- "shaders/base.geom");
- U32 explosion_shader = create_shader_program_geom("shaders/explosion.vert",
- "shaders/explosion.frag",
- "shaders/explosion.geom");
- U32 normals_shader = create_shader_program_geom("shaders/normals.vert",
- "shaders/normals.frag",
- "shaders/normals.geom");
- U32 basic_shader = create_shader_program("shaders/basic.vert",
- "shaders/basic.frag");
+ U32 shader = load_shader_geom("shaders/base.vert", "shaders/base.frag", "shaders/base.geom");
+ U32 explosion_shader = load_shader_geom("shaders/explosion.vert", "shaders/explosion.frag", "shaders/explosion.geom");
+ U32 normals_shader = load_shader_geom("shaders/normals.vert", "shaders/normals.frag", "shaders/normals.geom");
+ U32 basic_shader = load_shader("shaders/basic.vert", "shaders/basic.frag");
U32 grid_texture = load_texture("../../data/textures/grid.png");
diff --git a/advanced_opengl/9.instancing/build.sh b/advanced_opengl/9.instancing/build
index ebb6a01..ebb6a01 100755
--- a/advanced_opengl/9.instancing/build.sh
+++ b/advanced_opengl/9.instancing/build
diff --git a/advanced_opengl/9.instancing/instancing.c b/advanced_opengl/9.instancing/instancing.c
index e77c693..16fd373 100644
--- a/advanced_opengl/9.instancing/instancing.c
+++ b/advanced_opengl/9.instancing/instancing.c
@@ -26,6 +26,7 @@ int main(void)
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);
window = glfwCreateWindow(width, height, "Instancing", 0, 0);
if (!window) {
fprintf(stderr, "[ERROR] Failed to create window.\n");
@@ -44,13 +45,13 @@ int main(void)
glEnable(GL_DEPTH_TEST);
- U32 instancing_uniform_array_shader = create_shader_program("shaders/instancing_uniform_array.vert",
+ U32 instancing_uniform_array_shader = load_shader("shaders/instancing_uniform_array.vert",
"shaders/instancing_uniform_array.frag");
- U32 instanced_arrays_shader = create_shader_program("shaders/instanced_arrays.vert",
+ U32 instanced_arrays_shader = load_shader("shaders/instanced_arrays.vert",
"shaders/instanced_arrays.frag");
- U32 default_shader = create_shader_program("shaders/default.vert",
+ U32 default_shader = load_shader("shaders/default.vert",
"shaders/default.frag");
- U32 instanced_shader = create_shader_program("shaders/instanced_mat4.vert",
+ U32 instanced_shader = load_shader("shaders/instanced_mat4.vert",
"shaders/instanced_mat4.frag");
F32 quad_vertices[] = {
diff --git a/advanced_lighting/build.sh b/advanced_opengl/build
index 4829c7d..4829c7d 100755
--- a/advanced_lighting/build.sh
+++ b/advanced_opengl/build
diff --git a/libs/common.h b/libs/common.h
index b535c72..c373e9a 100644
--- a/libs/common.h
+++ b/libs/common.h
@@ -12,28 +12,24 @@
#include <sys/stat.h>
#include <fcntl.h>
-U8 *read_entire_file(const char *filename)
+char *read_entire_file(const char *filename)
{
- U8 *result;
- FILE *f;
- long file_size;
-
- result = 0;
+ char *result = 0;
if (!filename)
return(result);
- f = fopen(filename, "rb");
- if (!f)
+ FILE *file = fopen(filename, "rb");
+ if (!file)
return(result);
- fseek(f, 0, SEEK_END);
- file_size = ftell(f);
- fseek(f, 0, SEEK_SET);
+ fseek(file, 0, SEEK_END);
+ long file_size = ftell(file);
+ fseek(file, 0, SEEK_SET);
- result = malloc(file_size + 1);
- fread(result, file_size, 1, f);
- fclose(f);
+ result = malloc(file_size+1);
+ fread(result, file_size, 1, file);
+ fclose(file);
result[file_size] = 0;
@@ -42,16 +38,13 @@ U8 *read_entire_file(const char *filename)
void *mmap_file(size_t *len, const char *filename)
{
- struct stat sb;
- char* p;
- int fd;
-
- fd = open(filename, O_RDONLY);
+ int fd = open(filename, O_RDONLY);
if (fd == -1) {
perror("open");
return NULL;
}
+ struct stat sb;
if (fstat(fd, &sb) == -1) {
perror("fstat");
return NULL;
@@ -62,7 +55,7 @@ void *mmap_file(size_t *len, const char *filename)
return NULL;
}
- p = (char*)mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ char *p = (char*)mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (p == MAP_FAILED) {
perror("mmap");
@@ -97,28 +90,21 @@ void read_entire_file_mmap(void* ctx, const char* filename, const int is_mtl,
Mesh *mesh_gen_quad(Arena *arena)
{
- Mesh *m;
- Vertex verts[4];
- U32 ids[6];
-
- m = 0;
-
- verts[0] = vertex(v3f( 1.0f, 1.0f, 0.0f), v3f_zero(), v2f(1.0f, 1.0f));
- verts[1] = vertex(v3f(-1.0f, 1.0f, 0.0f), v3f_zero(), v2f(0.0f, 1.0f));
- verts[2] = vertex(v3f(-1.0f, -1.0f, 0.0f), v3f_zero(), v2f(0.0f, 0.0f));
- verts[3] = vertex(v3f( 1.0f, -1.0f, 0.0f), v3f_zero(), v2f(1.0f, 0.0f));
+ Vertex verts[4] = {
+ vertex(v3f( 1.0f, 1.0f, 0.0f), v3f_zero(), v2f(1.0f, 1.0f)),
+ vertex(v3f(-1.0f, 1.0f, 0.0f), v3f_zero(), v2f(0.0f, 1.0f)),
+ vertex(v3f(-1.0f, -1.0f, 0.0f), v3f_zero(), v2f(0.0f, 0.0f)),
+ vertex(v3f( 1.0f, -1.0f, 0.0f), v3f_zero(), v2f(1.0f, 0.0f)),
+ };
- ids[0] = 0;
- ids[1] = 1;
- ids[2] = 2;
+ U32 ids[6] = {
+ 0, 1, 2,
+ 0, 2, 3
+ };
- ids[3] = 0;
- ids[4] = 2;
- ids[5] = 3;
+ Mesh *mesh = mesh_init(arena, verts, 4, ids, 6);
- m = mesh_init(arena, verts, 4, ids, 6);
-
- return m;
+ return mesh;
}
Mesh *mesh_load_obj(Arena *arena, const char *filename)
@@ -158,7 +144,7 @@ Mesh *mesh_load_obj(Arena *arena, const char *filename)
Assert(attrib.face_num_verts[i]%3 == 0);
- Assert(attrib.face_num_verts[i]/3 > 3);
+ Assert(attrib.face_num_verts[i]/3 > 0);
Assert(attrib.num_texcoords);
@@ -198,87 +184,80 @@ Mesh *mesh_load_obj(Arena *arena, const char *filename)
U32 compile_shader(GLenum type, const char *filename)
{
- U32 shader;
- S32 status;
- char logs[512];
-
const char *source = (const char *)read_entire_file(filename);
if (!source) {
fprintf(stderr, "[ERROR]: Failed to read the file \"%s\"\n", filename);
return(0);
}
- shader = glCreateShader(type);
+ U32 shader = glCreateShader(type);
glShaderSource(shader, 1, &source, 0);
free((void *)source);
glCompileShader(shader);
+
+ S32 status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
- glGetShaderInfoLog(shader, 512, 0, logs);
- fprintf(stderr, "[ERROR]: Failed to compile: \"%s\"\n%s", filename, logs);
+ char log[512];
+ glGetShaderInfoLog(shader, 512, 0, log);
+ fprintf(stderr, "error: failed to compile: \"%s\"\n%s", filename, log);
} else {
- fprintf(stdout, "[INFO]: \"%s\" compiled successfuly.\n", filename);
+ fprintf(stdout, "info: \"%s\" compiled successfuly.\n", filename);
}
return(shader);
}
-U32 create_shader_program(char *vertex_shader_filename,
- char *fragment_shader_filename)
+U32 load_shader(const char *vert_filename, const char *frag_filename)
{
- S32 success;
- char logs[512];
+ U32 vert = compile_shader(GL_VERTEX_SHADER, vert_filename);
+ U32 frag = compile_shader(GL_FRAGMENT_SHADER, frag_filename);
- U32 vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_filename);
- U32 fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_filename);
+ U32 program = glCreateProgram();
+ glAttachShader(program, vert);
+ glAttachShader(program, frag);
+ glLinkProgram(program);
- U32 shader_program;
- shader_program = glCreateProgram();
- glAttachShader(shader_program, vertex_shader);
- glAttachShader(shader_program, fragment_shader);
- glLinkProgram(shader_program);
- glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
+ S32 success;
+ glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success == GL_FALSE) {
- glGetProgramInfoLog(shader_program, 512, 0, logs);
- fprintf(stderr, "[ERROR]: Failed to link shader program:\n%s", logs);
+ char log[512];
+ glGetProgramInfoLog(program, 512, 0, log);
+ fprintf(stderr, "error: failed to link program:\n%s\n", log);
} else {
- fprintf(stdout, "[INFO]: Shader program linked successfuly.\n\n");
+ fprintf(stdout, "info: compiled successully\n\n");
}
- glDeleteShader(vertex_shader);
- glDeleteShader(fragment_shader);
+ glDeleteShader(vert);
+ glDeleteShader(frag);
- return(shader_program);
+ return(program);
}
-U32 create_shader_program_geom(char *vertex_shader_filename,
- char *fragment_shader_filename,
- char *geometry_shader_filename)
+U32 load_shader_geom(const char *vert_filename, const char *frag_filename, const char *geom_filename)
{
+ U32 vert = compile_shader(GL_VERTEX_SHADER, vert_filename);
+ U32 frag = compile_shader(GL_FRAGMENT_SHADER, frag_filename);
+ U32 geom = compile_shader(GL_GEOMETRY_SHADER, geom_filename);
+
+ U32 program = glCreateProgram();
+ glAttachShader(program, vert);
+ glAttachShader(program, frag);
+ glAttachShader(program, geom);
+ glLinkProgram(program);
+
S32 success;
- char logs[512];
-
- U32 vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_filename);
- U32 fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_filename);
- U32 geometry_shader = compile_shader(GL_GEOMETRY_SHADER, geometry_shader_filename);
-
- U32 shader_program;
- shader_program = glCreateProgram();
- glAttachShader(shader_program, vertex_shader);
- glAttachShader(shader_program, fragment_shader);
- glAttachShader(shader_program, geometry_shader);
- glLinkProgram(shader_program);
- glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
+ glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success == GL_FALSE) {
- glGetProgramInfoLog(shader_program, 512, 0, logs);
- fprintf(stderr, "[ERROR]: Failed to link shader program:\n%s",
- logs);
+ char log[512];
+ glGetProgramInfoLog(program, 512, 0, log);
+ fprintf(stderr, "error: failed to link shader program:\n%s\n", log);
} else {
- fprintf(stdout, "[INFO]: Shader program linked successfuly.\n\n");
+ fprintf(stdout, "info: shader program linked successfuly.\n\n");
}
- glDeleteShader(vertex_shader);
- glDeleteShader(fragment_shader);
- glDeleteShader(geometry_shader);
+ glDeleteShader(vert);
+ glDeleteShader(frag);
+ glDeleteShader(geom);
- return(shader_program);
+ return(program);
}
void shader_set_3f(U32 shader_program, char *uniform_name, F32 x, F32 y, F32 z)
@@ -319,12 +298,11 @@ void shader_set_1i(U32 shader_program, char *uniform_name, S32 value)
U32 load_texture(char *texture_filename)
{
- S32 width, height, number_channels;
U32 texture_id;
-
glGenTextures(1, &texture_id);
stbi_set_flip_vertically_on_load(1);
+ S32 width, height, number_channels;
U8 *data = stbi_load(texture_filename, &width, &height, &number_channels, 0);
if (data) {
GLenum format = 0;
@@ -344,11 +322,9 @@ U32 load_texture(char *texture_filename)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
- fprintf(stdout, "[INFO]: Texture (\"%s\") is loaded successfully\n",
- texture_filename);
+ fprintf(stdout, "info: texture (\"%s\") is loaded successfully\n", texture_filename);
} else {
- fprintf(stderr, "[ERROR]: Failed to load texture: \"%s\"\n",
- texture_filename);
+ fprintf(stderr, "error: failed to load texture: \"%s\"\n", texture_filename);
}
stbi_image_free(data);
@@ -461,9 +437,9 @@ typedef struct {
Input input_init()
{
- Input r = {0};
- r.first_mouse = 1;
- return(r);
+ Input input = {0};
+ input.first_mouse = 1;
+ return(input);
}
void input_update_last_state(Input *input)
@@ -765,8 +741,7 @@ void get_camera_vectors(Camera *camera, V3F *l, V3F *u, V3F *f)
*f = v3f(-view.m0.z, -view.m1.z, -view.m2.z);
}
-V3F get_dv_camera_first_person(Input *input, Camera *camera,
- F32 acceleration, F32 dt)
+V3F get_dv_camera_first_person(Input *input, Camera *camera, F32 acceleration, F32 dt)
{
V3F f, l, u, dv;
get_camera_vectors(camera, &l, &u, &f);
@@ -801,6 +776,11 @@ MAT4 camera_persp(Camera camera, F32 ar)
}
typedef struct {
+ V3F position;
+ V3F color;
+} light_t;
+
+typedef struct {
Arena *arena;
Input input;
@@ -811,4 +791,9 @@ typedef struct {
F32 dt;
} State;
+F32 lerp(F32 a, F32 b, F32 f)
+{
+ return a + f * (b - a);
+}
+
#endif /* COMMON_H */
diff --git a/libs/pwyazh/v3f.h b/libs/pwyazh/v3f.h
index ba2e140..f1b4ff7 100644
--- a/libs/pwyazh/v3f.h
+++ b/libs/pwyazh/v3f.h
@@ -9,6 +9,13 @@ v3f(F32 x, F32 y, F32 z)
}
V3F
+v3f_from_v4f(V4F a)
+{
+ V3F result = { a.x, a.y, a.z };
+ return(result);
+}
+
+V3F
v3f_zero()
{
V3F result = { 0.0f, 0.0f, 0.0f };