Thanks!
Me too. I barely understand it, so most of these effects were made by an ancient technique: googleForExamples-copy-paste-itDoesNotWork-changeSomethingAndSeeWhatHappens-fail-tryAgain-loop-mixWithOtherStuff-failAgain-cry-loopAgain-laugh-commentEverything-startOver. But, in case you find it useful, here is the fragment shader (using the default vertex shader):
Code:
#version 120
//\/\/\/\/\/\/\/\/\/\/\/\\/\/\/\/\/\/\//
// Postprocessing effects for Duality //
// 2017 (c) YMR MIT License //
//\/\/\/\/\/\/\/\/\/\/\/\\/\/\/\/\/\/\//
const float pi = 3.14159265;
uniform sampler2D mainTex;
uniform sampler2D heightTex;
// Gaussian Blur
const float numBlurPixelsPerSide = 1.0f;
uniform float sigma; // The sigma value for the gaussian function: higher value means more blur
// A good value for 9x9 is around 3 to 5
// A good value for 7x7 is around 2.5 to 4
// A good value for 5x5 is around 2 to 3.5
// ... play around with this based on what you need :)
uniform float blurSize; // This should usually be equal to
// 1.0f / texture_pixel_width for a horizontal blur, and
// 1.0f / texture_pixel_height for a vertical blur.
// Grayscale
uniform float grayRatio;
// Black and White
uniform float bwRatio;
uniform float bwCut;
// Water distortion
uniform int doWaterEffect; // 0 = false, else = true
uniform float time;
vec4 doBlur(vec4 color, int blurDir)
{
// Adapted from http://callumhay.blogspot.com.es/2010/09/gaussian-blur-shader-glsl.html
vec2 blurMultiplyVec = blurDir == 0 ? vec2(1.0f, 0.0f) : vec2(0.0f, 1.0f);
// Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889)
vec3 incrementalGaussian;
incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * sigma);
incrementalGaussian.y = exp(-0.5f / (sigma * sigma));
incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
vec4 avgValue = vec4(0.0f, 0.0f, 0.0f, 0.0f);
float coefficientSum = 0.0f;
// Take the central sample first...
avgValue += texture2D(mainTex, gl_TexCoord[0].xy) * incrementalGaussian.x;
coefficientSum += incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
// Go through the remaining 8 vertical samples (4 on each side of the center)
for (float i = 1.0f; i <= numBlurPixelsPerSide; i++)
{
avgValue += texture2D(mainTex, gl_TexCoord[0].xy - i * (blurSize / 100) * blurMultiplyVec) * incrementalGaussian.x;
avgValue += texture2D(mainTex, gl_TexCoord[0].xy + i * (blurSize / 100) * blurMultiplyVec) * incrementalGaussian.x;
coefficientSum += 2 * incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
}
return (color + (avgValue / coefficientSum)) / 2;
}
vec4 doGrayscale(vec4 color)
{
vec3 gray = vec3((color.r + color.g + color.b) * .333333);
return vec4((color.rgb * (1. - grayRatio)) + (gray * grayRatio), color.a);
}
vec4 doBlackAndWhite(vec4 color)
{
vec3 bw = vec3(color.r < bwCut ? 0. : 1.);
return vec4((color.rgb * (1. - bwRatio)) + (bw * bwRatio), color.a);
}
vec4 doWater(vec4 color)
{
vec2 v_texCoords = gl_TexCoord[0].xy;
vec2 displacement = texture2D (heightTex, v_texCoords / 6.0).xy * vec2(4.);
float t = v_texCoords.y + displacement.y * 0.1 - 0.15 + (sin (v_texCoords.x * 60.0 + (time * 100)) * 0.025); // Change last value to change speed
vec2 pos = vec2(v_texCoords.x, t * .75);
return texture2D(mainTex, pos);
}
void main()
{
vec4 color = gl_Color * texture2D(mainTex, gl_TexCoord[0].st);
// Water distortion
if (doWaterEffect != 0)
{
color = doWater(color);
}
// Blur
if (blurSize != 0.)
{
color = doBlur(color, 0);
color = doBlur(color, 1);
}
// Grayscale
if (grayRatio != 0.)
{
color = doGrayscale(color);
}
// Black and White
if (bwRatio > 0. && bwCut < 1.)
{
color = doBlackAndWhite(color);
}
gl_FragColor = color;
}
The underwater effect should be used in a different camera pass. This is my current chain:
(Camera => Cam Pass 0 (perspective) => ViewportRenderTarget => ViewportTexture => Cam Pass 1 (orto) => ViewportWaterRenderTarget => ViewportWaterTexture => Cam pass 2 (orto) => Screen) + (Camera => Cam Pass 3 (orto overlay)).