summaryrefslogtreecommitdiff
path: root/pbr/1.2.textured/pbr.frag
diff options
context:
space:
mode:
Diffstat (limited to 'pbr/1.2.textured/pbr.frag')
-rw-r--r--pbr/1.2.textured/pbr.frag126
1 files changed, 126 insertions, 0 deletions
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);
+}