diff --git a/Assets/ssr_material.json b/Assets/ssr_material.json new file mode 100644 index 00000000..ad5eaf9d --- /dev/null +++ b/Assets/ssr_material.json @@ -0,0 +1,16 @@ +{ + "material_resources": [ + { + "contexts": [ + { + "bind_constants": [], + "bind_textures": [ + ], + "id": "ssr_pass" + } + ], + "id": "ssr_material", + "shader": "ssr_pass/ssr_pass" + } + ] +} diff --git a/raw/compile.py b/raw/compile.py index 9df9a0fa..5f9afa11 100644 --- a/raw/compile.py +++ b/raw/compile.py @@ -43,6 +43,10 @@ os.chdir('../dof_pass') make_resources.make('dof_pass.shader.json') make_variants.make('dof_pass.shader.json') +os.chdir('../ssr_pass') +make_resources.make('ssr_pass.shader.json') +make_variants.make('ssr_pass.shader.json') + # os.chdir('../combine_pass') # make_resources.make('combine_pass.shader.json') # make_variants.make('combine_pass.shader.json') diff --git a/raw/ssr_pass/ssr_pass.frag.glsl b/raw/ssr_pass/ssr_pass.frag.glsl new file mode 100644 index 00000000..fe327e05 --- /dev/null +++ b/raw/ssr_pass/ssr_pass.frag.glsl @@ -0,0 +1,244 @@ +#version 450 + +#ifdef GL_ES +precision mediump float; +#endif + +uniform sampler2D tex; +uniform sampler2D gbuffer0; // Normal, depth +uniform sampler2D gbuffer1; // Position, roughness +uniform sampler2D gbuffer2; +uniform mat4 P; +uniform mat4 V; + +// const vec2 gTexSizeInv = vec2(1.0 / 1136.0, 1.0 / 640.0); +const float rayStep = 0.25; +const float minRayStep = 0.1; +const float maxSteps = 20; +const float searchDist = 5; +const float searchDistInv = 0.2; +const int numBinarySearchSteps = 5; +const float maxDDepth = 1.0; +const float maxDDepthInv = 1.0; +const float reflectionSpecularFalloffExponent = 3.0; + +in vec2 texCoord; + +vec3 hitCoord; +float dDepth; + +vec3 BinarySearch(vec3 dir) { + float depth; + vec4 projectedCoord; + + // for (int i = 0; i < numBinarySearchSteps; i++) { + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth > 0.0) { + hitCoord += dir; + } + dir *= 0.5; + hitCoord -= dir; + + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth > 0.0) { + hitCoord += dir; + } + dir *= 0.5; + hitCoord -= dir; + + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth > 0.0) { + hitCoord += dir; + } + dir *= 0.5; + hitCoord -= dir; + + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth > 0.0) { + hitCoord += dir; + } + dir *= 0.5; + hitCoord -= dir; + + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth > 0.0) { + hitCoord += dir; + } + dir *= 0.5; + hitCoord -= dir; + // } + + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + return vec3(projectedCoord.xy, depth); +} + +vec4 RayCast(vec3 dir) { + dir *= rayStep; + float depth; + + // for (int i = 0; i < maxSteps; i++) { + hitCoord += dir; + vec4 projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + + hitCoord += dir; + projectedCoord = P * vec4(hitCoord, 1.0); + projectedCoord.xy /= projectedCoord.w; + projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; + depth = texture(gbuffer0, projectedCoord.xy).a; + dDepth = hitCoord.z - depth; + if (dDepth < 0.0) { + return vec4(BinarySearch(dir), 1.0); + } + // } + + return vec4(0.0, 0.0, 0.0, 0.0); +} + +void main() { + // vec2 gTexCoord = gl_FragCoord.xy * gTexSizeInv; + // Samples + float roughness = texture(gbuffer1, texCoord).a; + float specular = 1.0 - roughness; + if (specular == 0.0) { + gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + + vec4 viewNormal = vec4(texture(gbuffer0, texCoord).rgb, 1.0); + viewNormal = V * viewNormal; + viewNormal /= viewNormal.w; + + vec4 viewPos = vec4(texture(gbuffer1, texCoord).rgb, 1.0); + viewPos = V * viewPos; + viewPos /= viewPos.w; + + // Reflection vector + vec3 reflected = normalize(reflect(normalize(viewPos.xyz), normalize(viewNormal.xyz))); + + // Ray cast + hitCoord = viewPos.xyz; + dDepth = 0.0; + + vec4 coords = RayCast(reflected * max(minRayStep, -viewPos.z)); + vec2 dCoords = abs(vec2(0.5, 0.5) - coords.xy); + + float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0); + + float intensity = pow(specular, reflectionSpecularFalloffExponent) * + screenEdgefactor * clamp(-reflected.z, 0.0, 1.0) * + clamp((searchDist - length(viewPos.xyz - hitCoord)) * searchDistInv, 0.0, 1.0) * coords.w; + + vec4 reflCol = vec4(texture(tex, coords.xy).rgb, 1.0); + + vec4 texColor = texture(tex, texCoord); + gl_FragColor = texColor * (1.0 - intensity) + reflCol * intensity; +} diff --git a/raw/ssr_pass/ssr_pass.shader.json b/raw/ssr_pass/ssr_pass.shader.json new file mode 100755 index 00000000..3897cd70 --- /dev/null +++ b/raw/ssr_pass/ssr_pass.shader.json @@ -0,0 +1,42 @@ +{ + "contexts": [ + { + "id": "ssr_pass", + "params": [ + { + "id": "depth_write", + "value": "true" + }, + { + "id": "compare_mode", + "value": "always" + }, + { + "id": "cull_mode", + "value": "none" + }, + { + "id": "blend_source", + "value": "blend_one" + }, + { + "id": "blend_destination", + "value": "blend_zero" + } + ], + "links": [ + { + "id": "P", + "link": "_projectionMatrix" + }, + { + "id": "V", + "link": "_viewMatrix" + } + ], + "texture_params": [], + "vertex_shader": "ssr_pass.vert.glsl", + "fragment_shader": "ssr_pass.frag.glsl" + } + ] +} diff --git a/raw/ssr_pass/ssr_pass.vert.glsl b/raw/ssr_pass/ssr_pass.vert.glsl new file mode 100644 index 00000000..e1cc9c08 --- /dev/null +++ b/raw/ssr_pass/ssr_pass.vert.glsl @@ -0,0 +1,18 @@ +#version 450 + +#ifdef GL_ES +precision highp float; +#endif + +in vec2 pos; + +out vec2 texCoord; + +const vec2 madd = vec2(0.5, 0.5); + +void main() { + // Scale vertex attribute to [0-1] range + texCoord = pos.xy * madd + madd; + + gl_Position = vec4(pos.xy, 0.0, 1.0); +}