2017-05-23 15:01:56 +02:00
|
|
|
//
|
|
|
|
// Copyright (C) 2012 Jorge Jimenez (jorge@iryoku.com)
|
|
|
|
// Copyright (C) 2012 Diego Gutierrez (diegog@unizar.es)
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are met:
|
|
|
|
//
|
|
|
|
// 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer.
|
|
|
|
//
|
|
|
|
// 2. Redistributions in binary form must reproduce the following disclaimer
|
|
|
|
// in the documentation and/or other materials provided with the
|
|
|
|
// distribution:
|
|
|
|
//
|
|
|
|
// "Uses Separable SSS. Copyright (C) 2012 by Jorge Jimenez and Diego
|
|
|
|
// Gutierrez."
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
|
|
|
|
// IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
|
|
|
|
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
//
|
|
|
|
// The views and conclusions contained in the software and documentation are
|
|
|
|
// those of the authors and should not be interpreted as representing official
|
|
|
|
// policies, either expressed or implied, of the copyright holders.
|
|
|
|
//
|
2016-05-01 00:56:40 +02:00
|
|
|
|
2016-04-30 13:25:26 +02:00
|
|
|
#version 450
|
|
|
|
|
2017-12-13 14:21:42 +01:00
|
|
|
#include "compiled.glsl"
|
2016-07-10 00:51:39 +02:00
|
|
|
|
2016-05-13 00:08:11 +02:00
|
|
|
uniform sampler2D gbufferD;
|
2017-05-23 15:01:56 +02:00
|
|
|
uniform sampler2D gbuffer1;
|
2016-04-30 13:25:26 +02:00
|
|
|
uniform sampler2D tex;
|
|
|
|
|
2016-05-01 00:56:40 +02:00
|
|
|
uniform vec2 dir;
|
2017-11-04 18:35:34 +01:00
|
|
|
uniform vec2 cameraProj;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
2016-04-30 13:25:26 +02:00
|
|
|
in vec2 texCoord;
|
2016-10-12 17:52:27 +02:00
|
|
|
out vec4 fragColor;
|
2016-04-30 13:25:26 +02:00
|
|
|
|
2016-05-01 00:56:40 +02:00
|
|
|
const float SSSS_FOVY = 45.0;
|
|
|
|
|
|
|
|
// Separable SSS Reflectance
|
2017-05-23 15:01:56 +02:00
|
|
|
// const float sssWidth = 0.005;
|
|
|
|
vec4 SSSSBlur() {
|
2016-05-01 00:56:40 +02:00
|
|
|
// Quality = 0
|
|
|
|
const int SSSS_N_SAMPLES = 11;
|
|
|
|
vec4 kernel[SSSS_N_SAMPLES];
|
|
|
|
kernel[0] = vec4(0.560479, 0.669086, 0.784728, 0);
|
|
|
|
kernel[1] = vec4(0.00471691, 0.000184771, 5.07566e-005, -2);
|
|
|
|
kernel[2] = vec4(0.0192831, 0.00282018, 0.00084214, -1.28);
|
|
|
|
kernel[3] = vec4(0.03639, 0.0130999, 0.00643685, -0.72);
|
|
|
|
kernel[4] = vec4(0.0821904, 0.0358608, 0.0209261, -0.32);
|
|
|
|
kernel[5] = vec4(0.0771802, 0.113491, 0.0793803, -0.08);
|
|
|
|
kernel[6] = vec4(0.0771802, 0.113491, 0.0793803, 0.08);
|
|
|
|
kernel[7] = vec4(0.0821904, 0.0358608, 0.0209261, 0.32);
|
|
|
|
kernel[8] = vec4(0.03639, 0.0130999, 0.00643685, 0.72);
|
|
|
|
kernel[9] = vec4(0.0192831, 0.00282018, 0.00084214, 1.28);
|
|
|
|
kernel[10] = vec4(0.00471691, 0.000184771, 5.07565e-005, 2);
|
2016-04-30 13:25:26 +02:00
|
|
|
|
2016-10-17 17:39:40 +02:00
|
|
|
vec4 colorM = texture(tex, texCoord);
|
2016-05-01 00:56:40 +02:00
|
|
|
|
2016-10-17 17:39:40 +02:00
|
|
|
// Initialize the stencil buffer in case it was not already available:
|
|
|
|
// if (initStencil) // (Checked in compile time, it's optimized away)
|
|
|
|
// if (SSSS_STREGTH_SOURCE == 0.0) discard;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
2016-10-17 17:39:40 +02:00
|
|
|
// Fetch linear depth of current pixel
|
2017-05-23 15:01:56 +02:00
|
|
|
float depth = texture(gbufferD, texCoord).r;
|
2017-11-04 18:35:34 +01:00
|
|
|
float depthM = cameraProj.y / (depth - cameraProj.x);
|
2016-05-01 00:56:40 +02:00
|
|
|
|
2016-10-17 17:39:40 +02:00
|
|
|
// Calculate the sssWidth scale (1.0 for a unit plane sitting on the projection window)
|
|
|
|
float distanceToProjectionWindow = 1.0 / tan(0.5 * radians(SSSS_FOVY));
|
|
|
|
float scale = distanceToProjectionWindow / depthM;
|
|
|
|
|
|
|
|
// Calculate the final step to fetch the surrounding pixels
|
|
|
|
vec2 finalStep = sssWidth * scale * dir;
|
2017-05-23 15:01:56 +02:00
|
|
|
// finalStep *= 1.0;//SSSS_STREGTH_SOURCE; // Modulate it using the alpha channel.
|
2016-10-17 17:39:40 +02:00
|
|
|
finalStep *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3.
|
|
|
|
|
|
|
|
// Accumulate the center sample:
|
|
|
|
vec4 colorBlurred = colorM;
|
|
|
|
colorBlurred.rgb *= kernel[0].rgb;
|
|
|
|
|
|
|
|
// Accumulate the other samples
|
|
|
|
// for (int i = 1; i < SSSS_N_SAMPLES; i++) {
|
|
|
|
// Fetch color and depth for current sample
|
|
|
|
vec2 offset = texCoord + kernel[1].a * finalStep;
|
|
|
|
vec4 color = texture(tex, offset);
|
|
|
|
// #if SSSS_FOLLOW_SURFACE == 1
|
|
|
|
// If the difference in depth is huge, we lerp color back to "colorM":
|
|
|
|
// float depth = texture(depthTex, offset).r;
|
|
|
|
// float s = SSSSSaturate(300.0f * distanceToProjectionWindow *
|
|
|
|
// sssWidth * abs(depthM - depth));
|
|
|
|
// color.rgb = SSSSLerp(color.rgb, colorM.rgb, s);
|
|
|
|
// #endif
|
|
|
|
// Accumulate
|
|
|
|
colorBlurred.rgb += kernel[1].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
offset = texCoord + kernel[2].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[2].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
offset = texCoord + kernel[3].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[3].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
offset = texCoord + kernel[4].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[4].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
offset = texCoord + kernel[5].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[5].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
offset = texCoord + kernel[6].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[6].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
offset = texCoord + kernel[7].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[7].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
offset = texCoord + kernel[8].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[8].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
offset = texCoord + kernel[9].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[9].rgb * color.rgb;
|
2016-05-01 00:56:40 +02:00
|
|
|
|
|
|
|
offset = texCoord + kernel[10].a * finalStep;
|
2016-10-17 17:39:40 +02:00
|
|
|
color = texture(tex, offset);
|
|
|
|
colorBlurred.rgb += kernel[10].rgb * color.rgb;
|
|
|
|
// }
|
2016-05-01 00:56:40 +02:00
|
|
|
|
2016-10-17 17:39:40 +02:00
|
|
|
return colorBlurred;
|
2016-05-01 00:56:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
// SSS only masked objects
|
2017-05-23 15:01:56 +02:00
|
|
|
if (floor(texture(gbuffer1, texCoord).a) == 2) {
|
|
|
|
fragColor = clamp(SSSSBlur(), 0.0, 1.0);
|
2016-05-01 00:56:40 +02:00
|
|
|
}
|
|
|
|
else {
|
2016-10-12 17:52:27 +02:00
|
|
|
fragColor = texture(tex, texCoord);
|
2016-05-01 00:56:40 +02:00
|
|
|
}
|
2016-04-30 13:25:26 +02:00
|
|
|
}
|