1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- #[compute]
- #version 450
- #VERSION_DEFINES
- layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
- layout(set = 0, binding = 0) uniform sampler2D source_normal;
- layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_roughness;
- layout(push_constant, std430) uniform Params {
- ivec2 screen_size;
- float curve;
- uint pad;
- }
- params;
- #define HALF_PI 1.5707963267948966
- void main() {
- // Pixel being shaded
- ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing
- return;
- }
- vec3 normal_accum = vec3(0.0);
- float accum = 0.0;
- for (int i = 0; i <= 1; i++) {
- for (int j = 0; j <= 1; j++) {
- normal_accum += normalize(texelFetch(source_normal, pos + ivec2(i, j), 0).xyz * 2.0 - 1.0);
- accum += 1.0;
- }
- }
- normal_accum /= accum;
- float r = length(normal_accum);
- float limit;
- if (r < 1.0) {
- float threshold = 0.4;
- /*
- //Formula from Filament, does not make sense to me.
- float r2 = r * r;
- float kappa = (3.0f * r - r * r2) / (1.0f - r2);
- float variance = 0.25f / kappa;
- limit = sqrt(min(2.0f * variance, threshold * threshold));
- */
- /*
- //Formula based on probability distribution graph
- float width = acos(max(0.0,r)); // convert to angle (width)
- float roughness = pow(width,1.7)*0.854492; //approximate (crappy) formula to convert to roughness
- limit = min(sqrt(roughness), threshold); //convert to perceptual roughness and apply threshold
- */
- limit = min(sqrt(pow(acos(max(0.0, r)) / HALF_PI, params.curve)), threshold); //convert to perceptual roughness and apply threshold
- //limit = 0.5;
- } else {
- limit = 0.0;
- }
- imageStore(dest_roughness, pos, vec4(limit));
- }
|