diff options
Diffstat (limited to 'advanced_lighting/9.ssao')
-rw-r--r-- | advanced_lighting/9.ssao/blur.frag | 22 | ||||
-rwxr-xr-x | advanced_lighting/9.ssao/build.sh (renamed from advanced_lighting/9.ssao/build) | 0 | ||||
-rw-r--r-- | advanced_lighting/9.ssao/deferred.frag | 4 | ||||
-rw-r--r-- | advanced_lighting/9.ssao/gbuffer.frag | 4 | ||||
-rwxr-xr-x | advanced_lighting/9.ssao/ssao | bin | 1291232 -> 399776 bytes | |||
-rw-r--r-- | advanced_lighting/9.ssao/ssao.c | 649 | ||||
-rw-r--r-- | advanced_lighting/9.ssao/ssao.frag | 6 | ||||
-rw-r--r-- | advanced_lighting/9.ssao/ssao.vert | 4 |
8 files changed, 363 insertions, 326 deletions
diff --git a/advanced_lighting/9.ssao/blur.frag b/advanced_lighting/9.ssao/blur.frag new file mode 100644 index 0000000..dea23e8 --- /dev/null +++ b/advanced_lighting/9.ssao/blur.frag @@ -0,0 +1,22 @@ +#version 330 core + +in vert_t { + vec2 tex_coords; +} vert; + +out float frag_color; + +uniform sampler2D ssao; + +void main() +{ + vec2 texel_size = 1.0 / vec2(textureSize(ssao, 0)); + float result = 0.0; + for (int x = -2; x < 2; x++) { + for (int y = -2; y < 2; y++) { + vec2 offset = vec2(float(x), float(y)) * texel_size; + result += texture(ssao, vert.tex_coords + offset).r; + } + } + frag_color = result / (4.0 * 4.0); +} diff --git a/advanced_lighting/9.ssao/build b/advanced_lighting/9.ssao/build.sh index dc6929a..dc6929a 100755 --- a/advanced_lighting/9.ssao/build +++ b/advanced_lighting/9.ssao/build.sh diff --git a/advanced_lighting/9.ssao/deferred.frag b/advanced_lighting/9.ssao/deferred.frag index 5a3cc33..3e9f740 100644 --- a/advanced_lighting/9.ssao/deferred.frag +++ b/advanced_lighting/9.ssao/deferred.frag @@ -8,7 +8,7 @@ out vec4 frag_color; uniform sampler2D positions; uniform sampler2D normals; -uniform sampler2D albedo; +uniform sampler2D colors; uniform sampler2D ssao; uniform vec3 view_position; @@ -27,7 +27,7 @@ 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; + vec3 color = texture(colors, vert.tex_coords).rgb; float occlusion = texture(ssao, vert.tex_coords).r; vec3 ambient = 0.1 * color * occlusion; diff --git a/advanced_lighting/9.ssao/gbuffer.frag b/advanced_lighting/9.ssao/gbuffer.frag index 7755107..fd90740 100644 --- a/advanced_lighting/9.ssao/gbuffer.frag +++ b/advanced_lighting/9.ssao/gbuffer.frag @@ -7,11 +7,11 @@ in vert_t { layout(location = 0) out vec3 position; layout(location = 1) out vec3 normal; -layout(location = 2) out vec3 albedo; +layout(location = 2) out vec3 color; void main() { position = vert.position; normal = normalize(vert.normal); - albedo.rgb = vec3(0.95); + color.rgb = vec3(0.95); } diff --git a/advanced_lighting/9.ssao/ssao b/advanced_lighting/9.ssao/ssao Binary files differindex 72a9677..2d72697 100755 --- a/advanced_lighting/9.ssao/ssao +++ b/advanced_lighting/9.ssao/ssao diff --git a/advanced_lighting/9.ssao/ssao.c b/advanced_lighting/9.ssao/ssao.c index 3cfca03..5c592f7 100644 --- a/advanced_lighting/9.ssao/ssao.c +++ b/advanced_lighting/9.ssao/ssao.c @@ -12,320 +12,337 @@ 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; + // 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_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + 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 + }; + light_t light = {{2.0f, 2.0f, 2.0f}, {10.0f, 10.0f, 15.0f}}; + + // meshes + Mesh *quad = mesh_gen_quad(arena); + Mesh *cube = mesh_load_obj(arena, "../../data/models/cube.obj"); + + // shaders + U32 shader_gbuffer = load_shader("gbuffer.vert", "gbuffer.frag"); + U32 shader_ssao = load_shader("ssao.vert", "ssao.frag"); + U32 shader_ssao_blur = load_shader("ssao.vert", "blur.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, "colors", 2); + shader_set_1i(shader_deferred, "ssao", 3); + glUseProgram(shader_ssao_blur); + shader_set_1i(shader_ssao_blur, "ssao", 0); + glUseProgram(0); + + // framebuffers + U32 gbuffer; + glGenFramebuffers(1, &gbuffer); + glBindFramebuffer(GL_FRAMEBUFFER, gbuffer); + + U32 gpositions, gnormals, gcolors, rbo; + + 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); + + 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); + + glGenTextures(1, &gcolors); + glBindTexture(GL_TEXTURE_2D, gcolors); + 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, gcolors, 0); + + U32 attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2}; + glDrawBuffers(3, attachments); + + 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"); + + 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; + } + close(file); + 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, + }; + } + + 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); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + U32 ssao_blur_fbo, ssao_blur_colorbuffer; + glGenFramebuffers(1, &ssao_blur_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, ssao_blur_fbo); + glGenTextures(1, &ssao_blur_colorbuffer); + glBindTexture(GL_TEXTURE_2D, ssao_blur_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_blur_colorbuffer, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 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); + V3F 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; + + F32 radius = 3.0f; + light.position = v3f(cos(time) * radius, light.position.y, -sin(time) * radius); + + // 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); + + glBindFramebuffer(GL_FRAMEBUFFER, ssao_blur_fbo); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(shader_ssao_blur); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, ssao_colorbuffer); + 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, gcolors); + mesh_draw(quad); + glUseProgram(0); + + glUseProgram(shader_occlusion); + shader_set_mat4fv(shader_occlusion, "model", rightdown); + glBindTexture(GL_TEXTURE_2D, ssao_blur_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, gcolors); + + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, ssao_blur_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 index e4d04b1..dd03754 100644 --- a/advanced_lighting/9.ssao/ssao.frag +++ b/advanced_lighting/9.ssao/ssao.frag @@ -13,7 +13,7 @@ uniform sampler2D noise; uniform vec3 samples[64]; uniform mat4 projection; -const vec2 noise_scale = vec2(1600.0 / 4.0, 900.0 / 4.0) +const vec2 noise_scale = vec2(1600.0 / 4.0, 900.0 / 4.0); void main() { @@ -37,8 +37,8 @@ void main() 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; + 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 index 3ce6fb2..eed3be3 100644 --- a/advanced_lighting/9.ssao/ssao.vert +++ b/advanced_lighting/9.ssao/ssao.vert @@ -7,10 +7,8 @@ out vert_t { vec2 tex_coords; } vert; -uniform mat4 model; - void main() { vert.tex_coords = tex_coords; - gl_Position = model * vec4(position, 1.0); + gl_Position = vec4(position, 1.0); } |