summaryrefslogtreecommitdiff
path: root/intermediate/mip_spec.glsl
blob: 519fee030d574f5f62e5ffb0fc808893efe9eb9c (plain) (blame)
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
106
107
108
109
110
#ifdef DESC
[program]
type: graphics
vertex: main
fragment: main

[binding]
name: verts
rate: vertex
[attribute]
name: position
type: vec2
[attribute]
name: uv
type: vec2

[interpolator]
name: uv
type: vec2

[struct]
name: Face
[variable]
name: dir
type: vec3
[variable]
name: roughness
type: float
[variable]
name: up
type: vec3

[cbuffer]
name: c_face
type: Face
stage: fragment

[texture]
name: src
stage: fragment
dimension: cube

[target]
name: colour
type: vec4
#endif

#ifdef VERTEX_SHADER
void main() {
	interpolator.uv = uv;
	gl_Position = vec4(position, 1.0, 1.0);
}
#endif

#ifdef FRAGMENT_SHADER
float ri(uint bits)  {
	bits = (bits << 16u) | (bits >> 16u);
	bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xaaaaaaaau) >> 1u);
	bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xccccccccu) >> 2u);
	bits = ((bits & 0x0f0f0f0fu) << 4u) | ((bits & 0xf0f0f0f0u) >> 4u);
	bits = ((bits & 0x00ff00ffu) << 8u) | ((bits & 0xff00ff00u) >> 8u);
	return float(bits) * 2.3283064365386963e-10;
}

vec2 hammersley(uint i, uint n) {
	return vec2(float(i) / float(n), ri(i));
}

#define pi 3.14159265358979323846

vec3 importance_sample_ggx(vec2 xi, float rough, vec3 n) {
	float a = rough * rough;
	float phi = 2 * pi * xi.x;
	float ct = sqrt((1 - xi.y) / (1 + (a * a - 1) * xi.y));
	float st = sqrt(1 - ct * ct);
	vec3 h;
	h.x = st * cos(phi);
	h.y = st * sin(phi);
	h.z = ct;
	vec3 up = abs(n.z) < 0.999 ? vec3(0, 0, 1) : vec3(1, 0, 0);
	vec3 tx = normalize(cross(up, n));
	vec3 ty = cross(n, tx);
	return tx * h.x + ty * h.y + n * h.z;
}

vec3 prefilter_env(float rough, vec3 n) {
	vec3 c = 0.0.xxx;
	int i, samples = 32;
	float w = 1.0 / float(samples);
	for (i = 0; i < samples; i++) {
		vec2 coord = hammersley(i, samples);
		vec3 s = importance_sample_ggx(coord, rough, n);
		vec3 l = 2.0 * dot(n, s) * s - n;
		c += (textureLod(src, l, 0.0).rgb * max(dot(n, l), 0.0)) * w;
	}
	return c;
}

void main() {
	vec2 uv = interpolator.uv * 2.0 - 1.0;
	vec3 n = c_face.dir;
	vec3 u = c_face.up;
	vec3 p1 = normalize(cross(n, u));
	vec3 p2 = normalize(cross(n, p1));
	vec3 uvw = uv.x * p1 + uv.y * p2;
	n = normalize(n + uvw);
	colour = vec4(prefilter_env(c_face.roughness, n), 1.0);
}
#endif