#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