summaryrefslogtreecommitdiff
path: root/pbr
diff options
context:
space:
mode:
Diffstat (limited to 'pbr')
-rwxr-xr-xpbr/1.1.lighting/build.sh5
-rw-r--r--pbr/1.1.lighting/default.vert2
-rw-r--r--pbr/1.1.lighting/gbuffer.vert9
-rw-r--r--pbr/1.1.lighting/lighting.c128
-rw-r--r--pbr/1.1.lighting/occlusion.frag14
-rw-r--r--pbr/1.1.lighting/ssao.frag45
-rw-r--r--pbr/1.1.lighting/ssao.vert14
7 files changed, 217 insertions, 0 deletions
diff --git a/pbr/1.1.lighting/build.sh b/pbr/1.1.lighting/build.sh
new file mode 100755
index 0000000..2cd71b7
--- /dev/null
+++ b/pbr/1.1.lighting/build.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+. ../../config
+TARGET='lighting'
+set -x
+gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS
diff --git a/pbr/1.1.lighting/default.vert b/pbr/1.1.lighting/default.vert
new file mode 100644
index 0000000..d83afbf
--- /dev/null
+++ b/pbr/1.1.lighting/default.vert
@@ -0,0 +1,2 @@
+#version 330 core
+layout(location = 0)
diff --git a/pbr/1.1.lighting/gbuffer.vert b/pbr/1.1.lighting/gbuffer.vert
new file mode 100644
index 0000000..c53439c
--- /dev/null
+++ b/pbr/1.1.lighting/gbuffer.vert
@@ -0,0 +1,9 @@
+#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 {
+ vec2 tex_coords;
+} vert;
diff --git a/pbr/1.1.lighting/lighting.c b/pbr/1.1.lighting/lighting.c
new file mode 100644
index 0000000..87621ba
--- /dev/null
+++ b/pbr/1.1.lighting/lighting.c
@@ -0,0 +1,128 @@
+#include "GL/glew.h"
+#include "GLFW/glfw3.h"
+#include "pwyazh.h"
+#include "common.h"
+
+typedef struct {
+ Arena *arena;
+ Input input;
+ Camera camera;
+ Mesh *cube;
+ GLFWwindow *window;
+} state_t;
+
+static S32 width = 1600;
+static S32 height = 800;
+
+void die(const char *fmt, ...)
+{
+ fprintf(stderr, "error: ");
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+void init_glfw(state_t *state) {
+ glfwSetErrorCallback(error_callback);
+ if (glfwInit() == GLFW_FALSE)
+ die("failed to initialize glfw");
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
+ state->window = glfwCreateWindow(width, height, "prb lighting", 0, 0);
+ if (!state->window)
+ die("failed to create window");
+ glfwSetInputMode(state->window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ glfwMakeContextCurrent(state->window);
+}
+
+void init_gl(void)
+{
+ if (glewInit() != GLEW_OK)
+ die("failed to initialize glew");
+ glEnable(GL_DEPTH_TEST);
+}
+
+state_t init_state(void)
+{
+ state_t state = {
+ .arena = arena_alloc(Kilobytes(256)),
+ .input = input_init(),
+ .camera = {
+ .pos = v3f(0.0f, 2.0f, 5.0f),
+ .fovx = 90.0f,
+ .near = 0.1f,
+ .far = 100.0f,
+ .yaw = 0.0f,
+ .pitch = 0.0f
+ },
+ };
+ return state;
+}
+
+int main(void)
+{
+ state_t state = init_state();
+
+ init_glfw(&state);
+ init_gl();
+
+ // meshes
+ Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj");
+
+ // shaders
+ U32 shader = load_shader("default.vert", "default.frag");
+
+ F64 last_time = glfwGetTime();
+ while (!glfwWindowShouldClose(state.window)) {
+ F64 time = glfwGetTime();
+ F32 dt = time - last_time;
+ last_time = time;
+
+ input_update_last_state(&state.input);
+
+ glfwPollEvents();
+ process_glfw_keyboard(state.window, &state.input);
+ process_glfw_mouse_pos(state.window, &state.input);
+
+ if (key_first_press(state.input.exit))
+ glfwSetWindowShouldClose(state.window, GLFW_TRUE);
+
+ F32 speed = 2.0f;
+ V3F dv = get_dv_camera_first_person(&state.input, &state.camera, speed, dt);
+ V3F camera_dp = v3f_add(camera_dp, dv);
+ camera_dp = v3f_scalef(camera_dp, 0.8f);
+ state.camera.pos = v3f_add(state.camera.pos, camera_dp);
+
+ F32 sensitivity = 0.1f;
+ state.input.mouse_offset = v2f_scalef(state.input.mouse_offset, sensitivity);
+ state.camera.yaw += state.input.mouse_offset.x;
+ state.camera.pitch += state.input.mouse_offset.y;
+ if (state.camera.pitch > 89.0f)
+ state.camera.pitch = 89.0f;
+ if (state.camera.pitch < -89.0f)
+ state.camera.pitch = -89.0f;
+
+ // update
+
+ // render
+ F32 ar = (F32)width / (F32)height;
+ MAT4 projection = camera_persp(state.camera, ar);
+ MAT4 view = get_view_matrix(&state.camera);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram(shader);
+ mesh_draw(cube);
+ glUseProgram(0);
+
+ glfwSwapBuffers(state.window);
+ }
+
+ return 0;
+}
diff --git a/pbr/1.1.lighting/occlusion.frag b/pbr/1.1.lighting/occlusion.frag
new file mode 100644
index 0000000..41a436b
--- /dev/null
+++ b/pbr/1.1.lighting/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/pbr/1.1.lighting/ssao.frag b/pbr/1.1.lighting/ssao.frag
new file mode 100644
index 0000000..dd03754
--- /dev/null
+++ b/pbr/1.1.lighting/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/pbr/1.1.lighting/ssao.vert b/pbr/1.1.lighting/ssao.vert
new file mode 100644
index 0000000..eed3be3
--- /dev/null
+++ b/pbr/1.1.lighting/ssao.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);
+}