diff options
author | pryazha <pryadeiniv@mail.ru> | 2025-07-16 19:58:57 +0500 |
---|---|---|
committer | pryazha <pryadeiniv@mail.ru> | 2025-07-16 19:58:57 +0500 |
commit | 76df5cc4186ca3449e9b957e7de753cb6df4047b (patch) | |
tree | 125cb9d9f7261e7bb1f8ce48429ad425d653a042 /pbr/1.1.lighting | |
parent | 6f9ab1f55fd54beab7f0999a69b80ef92fe63722 (diff) |
finished ssao
Diffstat (limited to 'pbr/1.1.lighting')
-rwxr-xr-x | pbr/1.1.lighting/build.sh | 5 | ||||
-rw-r--r-- | pbr/1.1.lighting/default.vert | 2 | ||||
-rw-r--r-- | pbr/1.1.lighting/gbuffer.vert | 9 | ||||
-rw-r--r-- | pbr/1.1.lighting/lighting.c | 128 | ||||
-rw-r--r-- | pbr/1.1.lighting/occlusion.frag | 14 | ||||
-rw-r--r-- | pbr/1.1.lighting/ssao.frag | 45 | ||||
-rw-r--r-- | pbr/1.1.lighting/ssao.vert | 14 |
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); +} |