commit 2383374a49b5d0ddd8f9cd4431960274905627c0
parent 9f66964e39c327a807f748b41dc36dedb465b1fa
Author: William Casarin <jb55@jb55.com>
Date: Mon, 12 Nov 2018 13:33:57 -0800
initial pbr
Diffstat:
3 files changed, 63 insertions(+), 27 deletions(-)
diff --git a/etc/shaders/lighting.glsl b/etc/shaders/lighting.glsl
@@ -14,7 +14,7 @@
// return clouds;
// }
-const float pi = 3.14159265;
+const float PI = 3.14159265;
vec3 gamma_correct(vec3 color) {
return pow(color, vec3(1.0/2.2));
@@ -62,13 +62,13 @@ vec3 standard_light(vec3 color, vec4 position, vec4 normal) {
float spec;
bool blinn = true;
if (blinn) {
- const float energy_conservation = ( 8.0 + shiny ) / ( 8.0 * pi );
+ const float energy_conservation = ( 8.0 + shiny ) / ( 8.0 * PI );
vec3 halfway_dir = normalize(light_dir + view_dir); // blinn-phong
spec = energy_conservation * pow(max(dot(normal.xyz, halfway_dir), 0.0), shiny);
}
else {
- const float energy_conservation = ( 2.0 + shiny ) / ( 2.0 * pi );
+ const float energy_conservation = ( 2.0 + shiny ) / ( 2.0 * PI );
vec3 reflect_dir = reflect(-light_dir, normal.xyz); // phong
spec = energy_conservation * pow(max(dot(view_dir, reflect_dir), 0.0), shiny);
}
@@ -85,34 +85,37 @@ vec3 standard_light(vec3 color, vec4 position, vec4 normal) {
return final;
}
-float dist_ggx(vec3 N, vec3 H, float a)
+float dist_ggx(vec3 N, vec3 H, float roughness)
{
- float a2 = a*a;
+ float a = roughness * roughness;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH*NdotH;
- float nom = a2;
- float denom = (NdotH2 * (a2 - 1.0) + 1.0);
- denom = pi * denom * denom;
+ float num = a;
+ float denom = (NdotH2 * (a - 1.0) + 1.0);
+ denom = PI * denom * denom;
- return nom / denom;
+ return num / denom;
}
-float geom_schlick_ggx(float NdotV, float k)
+float geom_schlick_ggx(float NdotV, float roughness)
{
- float nom = NdotV;
+ float r = (roughness + 1.0);
+ float k = (r*r) / 8.0;
+
+ float num = NdotV;
float denom = NdotV * (1.0 - k) + k;
- return nom / denom;
+ return num / denom;
}
-float geom_smith(vec3 N, vec3 V, vec3 L, float k)
+float geom_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 ggx1 = geom_schlick_ggx(NdotV, k);
- float ggx2 = geom_schlick_ggx(NdotL, k);
+ float ggx1 = geom_schlick_ggx(NdotV, roughness);
+ float ggx2 = geom_schlick_ggx(NdotL, roughness);
return ggx1 * ggx2;
}
@@ -122,15 +125,48 @@ vec3 fresnel_schlick(float cos_theta, vec3 F0)
return F0 + (1.0 - F0) * pow(1.0 - cos_theta, 5.0);
}
-vec3 pbr(vec3 V, vec3 normal) {
- const float albedo = 0.2;
+vec3 pbr(vec3 albedo, vec3 V, vec3 normal) {
+ const float ao = 2.0;
const float metallic = 0.8;
+ const float roughness = 0.2;
+ vec3 radiance = sun_color * light_intensity;
vec3 N = normalize(normal);
vec3 L = normalize(light_dir);
vec3 H = normalize(V + L);
+ // non-metallic is always 0.04
vec3 F0 = vec3(0.04);
+ // while we do vary F0 based on the metalness of a surface by linearly
+ // interpolating between the original F0 and the albedo value given the
+ // metallic property
F0 = mix(F0, albedo, metallic);
- float cos_theta = max(dot(H, V))
- vec3 F = fresnel_schlick(cos_theta, )
+ float HdotV = max(0.0, dot(H, V));
+ vec3 F = fresnel_schlick(HdotV, F0);
+ float NDF = dist_ggx(N, H, roughness);
+ float G = geom_smith(N, V, L, roughness);
+
+ float NdotL = max(0.0, dot(N, L));
+
+ // Cook-Torrance BRDF
+ vec3 numerator = NDF * G * F;
+ float denominator = 4.0 * max(0.0, dot(N, V)) * NdotL;
+ vec3 specular = numerator / max(denominator, 0.001);
+
+ // kS = energy of light that gets reflected
+ // kD = remaining energy that gets refracted
+ vec3 kS = F;
+ vec3 kD = vec3(1.0) - kS;
+ kD *= 1.0 - metallic;
+
+ // because metallic surfaces don't refract light and thus have no diffuse
+ // reflections we enforce this property by nullifying kD if the surface is
+ // metallic
+
+ // Lo = outgoing radiance
+ // the result of the reflectance equation's integral ∫ over Ω
+ vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL;
+
+ vec3 ambient = vec3(0.03) * albedo * ao;
+ vec3 color = ambient + Lo;
+ return color;
}
diff --git a/etc/shaders/test.f.glsl b/etc/shaders/test.f.glsl
@@ -37,14 +37,14 @@ void main() {
vec4 v4_normal = vec4(vertex.normal, 1.0);
// vec3 color = standard_light(vertex.color, v4_pos, v4_normal);
- vec3 color = pbr(normalize(V));
+ vec3 color = pbr(vertex.color, normalize(V), vertex.normal);
- // if (fog_on) {
- // vec3 fog = apply_fog(color, length(v_ray), camera_position, v_ray);
- // color = fog;
- // }
+ if (fog_on) {
+ vec3 fog = apply_fog(color, length(V), camera_position, V);
+ color = fog;
+ }
- // color *= shadow_strength(v4_pos, v4_normal, vertex.shadow_coord);
+ color *= shadow_strength(v4_pos, v4_normal, vertex.shadow_coord);
// vec3 color = reflect_env(vertex.position);
frag_color = vec4(gamma_correct(color), 1.0);
diff --git a/src/game.c b/src/game.c
@@ -75,7 +75,7 @@ void game_init(struct game *game, int width, int height) {
check_gl();
init_terrain(terrain, size);
- get_entity(&terrain->entity_id)->flags |= ENT_INVISIBLE;
+ /* get_entity(&terrain->entity_id)->flags |= ENT_INVISIBLE; */
create_skybox(&res->skybox, &res->programs[SKYBOX_PROGRAM]);
/* node_translate(&res->skybox.node, V3(-100.0, -100.0, 0.0)); */
@@ -119,7 +119,7 @@ void game_init(struct game *game, int width, int height) {
res->camera.coords.azimuth = -quat_yaw(player->node.orientation) - RAD(90.0);
res->camera.coords.inclination = RAD(60);
- res->camera.coords.radius = 5.0;
+ res->camera.coords.radius = 100.0;
struct entity *tower = new_entity(NULL);
ok = load_model(&tower->model, "tower");