summaryrefslogtreecommitdiff
path: root/pbr/2.1.1.ibl_irradiance_conversion/pbr.frag
blob: db9edea519f83234519be740f063db6ecce78e08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#version 330 core

in vert_t {
	vec3 position;
	vec3 normal;
} vert;

out vec4 frag_color;

uniform vec3 camera;

uniform vec3 color;
uniform float metallic;
uniform float roughness;
uniform float ao;

struct light_t {
	vec3 position;
	vec3 color;
};

const int light_count = 4;
uniform light_t lights[light_count];

const float PI = 3.14159265358; 

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 n = vert.normal;
	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);
}