summaryrefslogtreecommitdiff
path: root/pbr/1.2.textured
diff options
context:
space:
mode:
authorpryazha <pryadeiniv@mail.ru>2025-07-23 20:55:29 +0500
committerpryazha <pryadeiniv@mail.ru>2025-07-23 20:55:29 +0500
commit33d5f67044d104d69cb2d11e78e6a79bc20d4c4e (patch)
tree61a61becc4a2ccf2638403ecd85518d26bbf1a23 /pbr/1.2.textured
parent76df5cc4186ca3449e9b957e7de753cb6df4047b (diff)
some prb examples
Diffstat (limited to 'pbr/1.2.textured')
-rwxr-xr-xpbr/1.2.textured/build.sh5
-rw-r--r--pbr/1.2.textured/hdr.frag18
-rw-r--r--pbr/1.2.textured/hdr.vert17
-rw-r--r--pbr/1.2.textured/pbr.frag126
-rw-r--r--pbr/1.2.textured/pbr.vert24
-rwxr-xr-xpbr/1.2.textured/texturedbin0 -> 397880 bytes
-rw-r--r--pbr/1.2.textured/textured.c151
7 files changed, 341 insertions, 0 deletions
diff --git a/pbr/1.2.textured/build.sh b/pbr/1.2.textured/build.sh
new file mode 100755
index 0000000..5c5427f
--- /dev/null
+++ b/pbr/1.2.textured/build.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+. ../../config
+TARGET='textured'
+set -x
+gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS $TARGET.c $LIBS
diff --git a/pbr/1.2.textured/hdr.frag b/pbr/1.2.textured/hdr.frag
new file mode 100644
index 0000000..01650ae
--- /dev/null
+++ b/pbr/1.2.textured/hdr.frag
@@ -0,0 +1,18 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D colorbuffer;
+
+void main(void)
+{
+ const float gamma = 2.2;
+ vec3 color = vec3(texture(colorbuffer, vert.tex_coords));
+ color /= color + vec3(1.0);
+ color = pow(color, vec3(1.0 / gamma));
+ frag_color = vec4(color, 1.0);
+}
diff --git a/pbr/1.2.textured/hdr.vert b/pbr/1.2.textured/hdr.vert
new file mode 100644
index 0000000..1b953d7
--- /dev/null
+++ b/pbr/1.2.textured/hdr.vert
@@ -0,0 +1,17 @@
+#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(void)
+{
+ gl_Position = model * vec4(position, 1.0);
+
+ vert.tex_coords = tex_coords;
+}
diff --git a/pbr/1.2.textured/pbr.frag b/pbr/1.2.textured/pbr.frag
new file mode 100644
index 0000000..f0aaeca
--- /dev/null
+++ b/pbr/1.2.textured/pbr.frag
@@ -0,0 +1,126 @@
+#version 330 core
+
+in vert_t {
+ vec3 position;
+ vec3 normal;
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform vec3 camera;
+
+uniform sampler2D color_map;
+uniform sampler2D normal_map;
+uniform sampler2D metallic_map;
+uniform sampler2D roughness_map;
+uniform sampler2D ao_map;
+
+struct light_t {
+ vec3 position;
+ vec3 color;
+};
+
+const int light_count = 4;
+uniform light_t lights[light_count];
+
+const float PI = 3.14159265358;
+
+vec3 get_normal_from_map()
+{
+ vec3 tangent = texture(normal_map, vert.tex_coords).xyz * 2.0 - 1.0;
+ vec3 q1 = dFdx(vert.position);
+ vec3 q2 = dFdy(vert.position);
+ vec2 st1 = dFdx(vert.tex_coords);
+ vec2 st2 = dFdy(vert.tex_coords);
+ vec3 n = normalize(vert.normal);
+ vec3 t = normalize(q1*st2.t - q2*st1.t);
+ vec3 b = -normalize(cross(n, t));
+ mat3 tbn = mat3(t, b, n);
+ return normalize(tbn * tangent);
+}
+
+vec3 fresnel_shlick(float costheta, vec3 f0)
+{
+ return f0 + (1.0 - f0) * pow(1.0 - costheta, 5.0);
+}
+
+float distribution_ggx(vec3 n, vec3 h, float roughness)
+{
+ float a = roughness * roughness;
+ float a2 = a * a;
+ float ndoth = max(dot(n, h), 0.0);
+ float ndoth2 = ndoth * ndoth;
+
+ float num = a2;
+ float denom = (ndoth2 * (a2 - 1.0) + 1.0);
+ denom = PI * denom * denom;
+
+ return num / denom;
+}
+
+float geometry_shlick_ggx(float ndotv, float roughness)
+{
+ float r = roughness + 1.0;
+ float k = r * r / 8.0;
+
+ float num = ndotv;
+ float denom = ndotv * (1.0 - k) + k;
+
+ return num / denom;
+}
+
+float geometry_smith(vec3 n, vec3 v, vec3 l, float roughness)
+{
+ float ndotv = max(dot(n, v), 0.0);
+ float ndotl = max(dot(n, l), 0.0);
+ float ggx2 = geometry_shlick_ggx(ndotv, roughness);
+ float ggx1 = geometry_shlick_ggx(ndotl, roughness);
+
+ return ggx1 * ggx2;
+}
+
+void main(void)
+{
+ vec3 color = pow(texture(color_map, vert.tex_coords).rgb, vec3(2.2));
+ float metallic = texture(metallic_map, vert.tex_coords).r;
+ float roughness = texture(roughness_map, vert.tex_coords).r;
+ float ao = texture(ao_map, vert.tex_coords).r;
+
+ vec3 n = get_normal_from_map();
+ vec3 v = normalize(camera - vert.position);
+
+ vec3 lo = vec3(0.0);
+ for (int i = 0; i < light_count; i++) {
+ vec3 l = normalize(lights[i].position - vert.position);
+ vec3 h = normalize(v + l);
+ float ndotv = max(dot(n, v), 0.0);
+ float ndotl = max(dot(n, l), 0.0);
+
+ float distance = length(lights[i].position - vert.position);
+ float attenuation = 1.0 / (distance * distance);
+
+ vec3 radiance = lights[i].color * attenuation;
+
+ vec3 f0 = vec3(0.04);
+ f0 = mix(f0, color, metallic);
+ vec3 f = fresnel_shlick(max(dot(h, v), 0.0), f0);
+
+ float ndf = distribution_ggx(n, h, roughness);
+ float g = geometry_smith(n, v, l, roughness);
+
+ vec3 numerator = ndf * g * f;
+ float denominator = 4.0 * ndotv * ndotl;
+ vec3 specular = numerator / max(denominator, 0.001);
+
+ vec3 ks = f;
+ vec3 kd = vec3(1.0) - ks;
+
+ kd *= 1.0 - metallic;
+
+ lo += (kd * color / PI + specular) * radiance * ndotl;
+ }
+
+ vec3 ambient = vec3(0.03) * color * ao;
+ frag_color = vec4(ambient + lo, 1.0);
+}
diff --git a/pbr/1.2.textured/pbr.vert b/pbr/1.2.textured/pbr.vert
new file mode 100644
index 0000000..0ff1bdb
--- /dev/null
+++ b/pbr/1.2.textured/pbr.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(void)
+{
+ gl_Position = projection * view * model * vec4(position, 1.0);
+
+ vert.position = vec3(model * vec4(position, 1.0));
+ vert.normal = normalize(mat3(transpose(inverse(model))) * normal);
+ vert.tex_coords = tex_coords;
+}
diff --git a/pbr/1.2.textured/textured b/pbr/1.2.textured/textured
new file mode 100755
index 0000000..e339406
--- /dev/null
+++ b/pbr/1.2.textured/textured
Binary files differ
diff --git a/pbr/1.2.textured/textured.c b/pbr/1.2.textured/textured.c
new file mode 100644
index 0000000..e8ed096
--- /dev/null
+++ b/pbr/1.2.textured/textured.c
@@ -0,0 +1,151 @@
+#include "GL/glew.h"
+#include "GLFW/glfw3.h"
+#include "common.h"
+
+int main(void)
+{
+ state_t state = init_state(1600, 800);
+
+ init_glfw(&state);
+ init_gl();
+
+ /* meshes */
+ Mesh *sphere = mesh_load_obj(state.arena, "../../data/models/sphere.obj");
+ Mesh *cube = mesh_load_obj(state.arena, "../../data/models/cube.obj");
+ Mesh *quad = mesh_gen_quad(state.arena);
+
+ /* shaders */
+ add_shader("pbr.vert", "pbr.frag", 0);
+ add_shader("hdr.vert", "hdr.frag", 0);
+
+ U32 shader = find_shader("pbr");
+ if (!shader)
+ die("not again");
+ glUseProgram(shader);
+ shader_set_1i(shader, "color_map", 0);
+ shader_set_1i(shader, "normal_map", 1);
+ shader_set_1i(shader, "metallic_map", 2);
+ shader_set_1i(shader, "roughness_map", 3);
+ shader_set_1i(shader, "ao_map", 4);
+ glUseProgram(0);
+
+ light_t lights[4] = {
+ {{-6.0f, 0.0f, 7.0f}, {300.0f, 300.0f, 300.0f}},
+ {{-4.0f, 0.0f, 6.0f}, {300.0f, 300.0f, 300.0f}},
+ {{ 1.0f, 0.0f, 5.0f}, {300.0f, 300.0f, 300.0f}},
+ {{ 3.0f, 0.0f, 8.0f}, {300.0f, 300.0f, 300.0f}},
+ };
+
+ /* textures */
+ U32 color_map = load_texture("../../data/textures/pbr/albedo.png");
+ U32 normal_map = load_texture("../../data/textures/pbr/normal.png");
+ U32 metallic_map = load_texture("../../data/textures/pbr/metallic.png");
+ U32 roughness_map = load_texture("../../data/textures/pbr/roughness.png");
+ U32 ao_map = load_texture("../../data/textures/pbr/ao.png");
+
+ /* framebuffers */
+ U32 hdr_fbo, hdr_colorbuffer, hdr_rbo;
+ glGenFramebuffers(1, &hdr_fbo);
+ glGenTextures(1, &hdr_colorbuffer);
+ glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, state.width, state.height, 0, GL_RGBA, GL_FLOAT, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glGenRenderbuffers(1, &hdr_rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, hdr_rbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, state.width, state.height);
+ glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hdr_colorbuffer, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, hdr_rbo);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ die("failed to create framebuffer");
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ F32 time = 0;
+
+ while (!glfwWindowShouldClose(state.window)) {
+ handle_glfw_events(state.window, &state.input);
+ F32 dt = lock_framerate(60);
+ fps_info(dt, 10);
+
+ /* update */
+ update_camera_first_person(&state.camera, &state.input, dt, 2.0f);
+ F32 limit = 4.0f;
+ for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++)
+ lights[i].position.y = sinf(2.0f * time + i) * limit;
+ time += dt;
+
+ /* render */
+ F32 ar = (F32)state.width / (F32)state.height;
+ MAT4 projection = camera_persp(state.camera, ar);
+ MAT4 view = get_view_matrix(&state.camera);
+
+ glClearColor(0.16f, 0.16f, 0.16f, 1.0f);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ shader = find_shader("pbr");
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, color_map);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, normal_map);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, metallic_map);
+ glActiveTexture(GL_TEXTURE3);
+ glBindTexture(GL_TEXTURE_2D, roughness_map);
+ glActiveTexture(GL_TEXTURE4);
+ glBindTexture(GL_TEXTURE_2D, ao_map);
+
+ if (!shader) die("wha");
+ glUseProgram(shader);
+ shader_set_mat4fv(shader, "projection", projection);
+ shader_set_mat4fv(shader, "view", view);
+ shader_set_3fv(shader, "camera", state.camera.pos);
+ for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++) {
+ char str[512];
+ snprintf(str, 512, "lights[%d].position", i);
+ shader_set_3fv(shader, str, lights[i].position);
+ snprintf(str, 512, "lights[%d].color", i);
+ shader_set_3fv(shader, str, lights[i].color);
+ }
+ S32 rows = 7;
+ S32 cols = 7;
+ F32 offset = 3.0f;
+ for (S32 row = 0; row < rows; row++) {
+ for (S32 col = 0; col < cols; col++) {
+ V3F pos = {(col - cols / 2.0f) * offset, (row - rows / 2.0f) * offset, 0.0f};
+ MAT4 model = mat4_make_translate(pos);
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(cube);
+ }
+ }
+
+ for (U32 i = 0; i < (sizeof(lights) / sizeof(lights[0])); i++) {
+ MAT4 model = mat4_make_scale(v3f(0.5f, 0.5f, 0.5f));
+ model = mat4_translate(model, lights[i].position);
+ shader_set_mat4fv(shader, "model", model);
+ mesh_draw(sphere);
+ }
+
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ shader = find_shader("hdr");
+ if (!shader) die("!");
+ glUseProgram(shader);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, hdr_colorbuffer);
+ shader_set_mat4fv(shader, "model", mat4_identity());
+ mesh_draw(quad);
+ glUseProgram(0);
+
+ glfwSwapBuffers(state.window);
+ }
+
+ return 0;
+}