85 lines
No EOL
2.7 KiB
Text
85 lines
No EOL
2.7 KiB
Text
include "pipelines/common.glsl"
|
|
|
|
compute_shader [[
|
|
|
|
layout(std140, binding = 4) uniform Data {
|
|
vec2 u_size;
|
|
float u_max_steps;
|
|
float u_stride;
|
|
};
|
|
|
|
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
|
layout (binding = 0) uniform sampler2D u_depth;
|
|
layout (r8, binding = 1) uniform image2D u_sss_buffer;
|
|
|
|
// based on http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html
|
|
void raycast(vec3 csOrig, vec3 csDir, float stride, float jitter, ivec2 ip0) {
|
|
vec3 csEndPoint = csOrig + abs(csOrig.z * 0.1) * csDir;
|
|
|
|
vec4 H0 = Global.projection * vec4(csOrig, 1);
|
|
vec4 H1 = Global.projection * vec4(csEndPoint, 1);
|
|
|
|
float k0 = 1 / H0.w, k1 = 1 / H1.w;
|
|
|
|
vec2 P0 = toScreenUV(H0.xy * k0 * 0.5 + 0.5) * u_size;
|
|
vec2 P1 = toScreenUV(H1.xy * k1 * 0.5 + 0.5) * u_size;
|
|
|
|
vec2 delta = P1 - P0;
|
|
bool permute = abs(delta.x) < abs(delta.y);
|
|
if (permute) {
|
|
P0 = P0.yx;
|
|
P1 = P1.yx;
|
|
delta = delta.yx;
|
|
}
|
|
|
|
float stepDir = sign(delta.x);
|
|
float invdx = stepDir / delta.x;
|
|
|
|
float dk = ((k1 - k0) * invdx) * stride;
|
|
vec2 dP = (vec2(stepDir, delta.y * invdx)) * stride;
|
|
|
|
vec2 P = P0;
|
|
float k = k0;
|
|
|
|
|
|
uint max_steps = uint(min(abs(P1.x - P0.x), u_max_steps)) >> 2;
|
|
for (uint j = 0; j < 4; ++j) {
|
|
P += dP * jitter;
|
|
k += dk * jitter;
|
|
for (uint i = 0; i < max_steps; ++i) {
|
|
float rayZFar = 1 / k;
|
|
|
|
vec2 p = permute ? P.yx : P;
|
|
if (any(lessThan(p, vec2(0)))) break;
|
|
if (any(greaterThan(p, vec2(u_size)))) break;
|
|
|
|
float depth = texture(u_depth, p / u_size).x;
|
|
depth = toLinearDepth(Global.inv_projection, depth);
|
|
|
|
float dif = rayZFar - depth;
|
|
if (dif < depth * 0.02 && dif > 1e-3) {
|
|
imageStore(u_sss_buffer, ip0, vec4(0));
|
|
return;
|
|
}
|
|
|
|
P += dP;
|
|
k += dk;
|
|
}
|
|
P -= dP;
|
|
k -= dk;
|
|
dP *= 2;
|
|
dk *= 2;
|
|
}
|
|
imageStore(u_sss_buffer, ip0, vec4(1));
|
|
}
|
|
|
|
void main() {
|
|
vec2 inv_size = 1 / u_size;
|
|
vec2 uv = vec2(gl_GlobalInvocationID.xy) * inv_size;
|
|
vec3 p = getViewPosition(u_depth, Global.inv_view_projection, uv);
|
|
vec4 o = Global.view * vec4(p, 1);
|
|
vec3 d = mat3(Global.view) * Global.light_dir.xyz;
|
|
float rr = random(vec2(gl_GlobalInvocationID.xy) + 0.1 * Global.time);
|
|
raycast(o.xyz, d.xyz, u_stride, rr, ivec2(gl_GlobalInvocationID.xy));
|
|
}
|
|
]] |