Add orx-poisson-fill

This commit is contained in:
Edwin Jakobs
2019-11-02 12:47:30 +01:00
parent 3a1f8a2ac7
commit 004eab4fae
16 changed files with 702 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
out vec4 o_output;
void main(){
vec4 c = texture(tex0, v_texCoord0);
o_output.rgb = vec3(step(1.0, c.a));
o_output.a = 1.0;
}

View File

@@ -0,0 +1,37 @@
// adapted from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/fill-boundary.frag
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0; // input image
uniform sampler2D tex1; // mask
out vec4 o_output;
/** Output color only on the edges of the black regions in the input image, along with a 1.0 alpha. */
void main(){
o_output = vec4(0.0);
vec4 fullColor = textureLod(tex0, v_texCoord0, 0.0);
float maskColor = textureLod(tex1, v_texCoord0, 0.0).r;
float isInMask = maskColor == 1.0 ? 1.0 : 0.0;
float maskLaplacian = -4.0 * isInMask;
float mask110 = textureLodOffset(tex1, v_texCoord0, 0.0, ivec2( 1, 0)).r;
float mask101 = textureLodOffset(tex1, v_texCoord0, 0.0, ivec2( 0, 1)).r;
float mask010 = textureLodOffset(tex1, v_texCoord0, 0.0, ivec2(-1, 0)).r;
float mask001 = textureLodOffset(tex1, v_texCoord0, 0.0, ivec2( 0,-1)).r;
maskLaplacian += mask110 == 1.0 ? 1.0 : 0.0;
maskLaplacian += mask101 == 1.0 ? 1.0 : 0.0;
maskLaplacian += mask010 == 1.0 ? 1.0 : 0.0;
maskLaplacian += mask001 == 1.0 ? 1.0 : 0.0;
if(maskLaplacian > 0.0){
o_output.rgb = fullColor.rgb;
o_output.a = 1.0;
}
}

View File

@@ -0,0 +1,45 @@
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0; // membrane
uniform sampler2D tex1; // target image
uniform sampler2D tex2; // source image
uniform sampler2D tex3; // mask
uniform sampler2D tex4; // soft mask
uniform float softMaskGain;
out vec4 o_output;
void main(){
vec4 targetColor = textureLod(tex1, v_texCoord0, 0.0).rgba;
float maskColor = textureLod(tex3, v_texCoord0, 0.0).r;
float mask = maskColor == 1.0 ? 1.0 : 0.0;
float softMask = textureLod(tex4, v_texCoord0, 0.0).r;
float maskLaplacian = -4.0 * mask;
float mask110 = textureLodOffset(tex3, v_texCoord0, 0.0, ivec2( 1, 0)).r;
float mask101 = textureLodOffset(tex3, v_texCoord0, 0.0, ivec2( 0, 1)).r;
float mask010 = textureLodOffset(tex3, v_texCoord0, 0.0, ivec2(-1, 0)).r;
float mask001 = textureLodOffset(tex3, v_texCoord0, 0.0, ivec2( 0,-1)).r;
maskLaplacian += mask110 == 1.0 ? 1.0 : 0.0;
maskLaplacian += mask101 == 1.0 ? 1.0 : 0.0;
maskLaplacian += mask010 == 1.0 ? 1.0 : 0.0;
maskLaplacian += mask001 == 1.0 ? 1.0 : 0.0;
if (maskLaplacian > 0) {
mask = 1;
}
{
vec4 sourceColor = textureLod(tex2, v_texCoord0, 0.0);
vec4 membraneColor = textureLod(tex0, v_texCoord0, 0.0);
membraneColor.rgb /= membraneColor.a;
vec3 blend = membraneColor.rgb + sourceColor.rgb;
o_output.rgb = mix(targetColor.rgb, blend, mask*max(0.0,min(1.0, softMask * softMaskGain)));
o_output.a = 1.0;
}
}

View File

@@ -0,0 +1,25 @@
// from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/fill-boundary.frag
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
uniform int levels;
out vec4 o_output;
uniform float scale;
uniform float phase;
uniform float minValue;
uniform float maxValue;
void main(){
vec4 c = texture(tex0, v_texCoord0);
c.rgb = clamp(c.rgb, vec3(minValue), vec3(maxValue));
o_output = c;
}

View File

@@ -0,0 +1,50 @@
// from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/downscale.frag
#version 330
in vec2 v_texCoord0;
uniform vec2 targetSize;
uniform sampler2D tex0;
out vec4 o_output;
uniform vec2 padding;
uniform float h1[5]; ///< h1 filter parameters.
/** Denotes if a pixel falls outside an image.
\param pos the pixel position
\param size the image size
\return true if the pixel is outside of the image
*/
bool isOutside(ivec2 pos, ivec2 size){
return (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y);
}
/** Apply the h1 filter and downscale the input data by a factor of 2. */
void main(){
vec4 accum = vec4(0.0);
ivec2 size = textureSize(tex0, 0).xy;
ivec2 ts = size;
//ivec2 ts = ivec2(targetSize - 2 * padding);
// Our current size is half this one, so we have to scale by 2.
ivec2 coords = ivec2(floor( targetSize * v_texCoord0)) * 2 - ivec2(10);
for(int dy = -2; dy <=2; dy++){
for(int dx = -2; dx <=2; dx++){
ivec2 newPix = coords+ivec2(dx,dy);
if(isOutside(newPix, size)){
continue;
//accum = vec4(1.0, 0.0, 0.0, 1.0);
}
accum += h1[dx+2] * h1[dy+2] * texelFetch(tex0, newPix,0);
}
}
o_output = accum;
}

View File

@@ -0,0 +1,63 @@
// from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/fill-boundary.frag
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
//layout(binding = 0) uniform sampler2D screenTexture; ///< Image to process.
//layout(location = 0) out vec4 fragColor; ///< Color.
out vec4 o_output;
/** Denotes if a pixel falls outside an image.
\param pos the pixel position
\param size the image size
\return true if the pixel is outside of the image
*/
/** Output color only on the edges of the black regions in the input image, along with a 1.0 alpha. */
void main(){
o_output = vec4(0.0);
vec4 fullColor = textureLod(tex0, v_texCoord0, 0.0);
float isInMask = fullColor.a == 1.0 ? 0.0 : 1.0; //float(all(equal(fullColor.rgb, vec3(0.0))));
float maskLaplacian = -4.0*(1.0-fullColor.a);
// float maskLaplacian = -4.0 * isInMask;
vec4 cola110 = textureLodOffset(tex0, v_texCoord0, 0.0, ivec2( 1, 0));
vec4 cola101 = textureLodOffset(tex0, v_texCoord0, 0.0, ivec2( 0, 1));
vec4 cola010 = textureLodOffset(tex0, v_texCoord0, 0.0, ivec2(-1, 0));
vec4 cola001 = textureLodOffset(tex0, v_texCoord0, 0.0, ivec2( 0,-1));
vec3 col110 = cola110.rgb; // cola110.a;
vec3 col101 = cola101.rgb; // cola101.a;
vec3 col010 = cola010.rgb; // cola010.a;
vec3 col001 = cola001.rgb; // cola001.a;
// maskLaplacian += float(all(equal(col110, vec3(0.0))));
// maskLaplacian += float(all(equal(col101, vec3(0.0))));
// maskLaplacian += float(all(equal(col010, vec3(0.0))));
// maskLaplacian += float(all(equal(col001, vec3(0.0))));
// maskLaplacian += cola110.a == 1.0 ? 0.0 : 1.0;
// maskLaplacian += cola101.a == 1.0 ? 0.0 : 1.0;
// maskLaplacian += cola010.a == 1.0 ? 0.0 : 1.0;
// maskLaplacian += cola001.a == 1.0 ? 0.0 : 1.0;
maskLaplacian += (1.0-cola110.a);
maskLaplacian += (1.0-cola101.a);
maskLaplacian += (1.0-cola010.a);
maskLaplacian += (1.0-cola001.a);
if(maskLaplacian > 0.0){
o_output.rgb = fullColor.rgb;///fullColor.a;;
o_output.a = fullColor.a;
}
}

View File

@@ -0,0 +1,25 @@
// from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/fill-combine.frag
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0; // result of pyramid convolution
uniform sampler2D tex1; // input image
out vec4 o_output;
/** Composite the initial image and the filled image in the regions where the initial image is black. */
void main(){
vec4 inputColor = textureLod(tex1, v_texCoord0, 0.0).rgba;
//float mask = float(all(equal(inputColor, vec3(0.0))));
//float mask = inputColor.a == 1.0? 0.0 : 1.0;
float mask = 1.0 - inputColor.a;
vec4 fillColor = textureLod(tex0, v_texCoord0, 0.0);
fillColor.rgb /= fillColor.a;
o_output.rgb = fillColor.rgb * (mask) + inputColor.rgb; //mix(inputColor.rgb, fillColor.rgb, mask);
o_output.a = 1.0;
}

View File

@@ -0,0 +1,41 @@
// from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/filter.frag
#version 330
//layout(binding = 0) uniform sampler2D screenTexture; ///< Level to filter.
uniform sampler2D tex0;
in vec2 v_texCoord0;
out vec4 o_output;
uniform float g[3]; ///< g filter parameters.
/** Denotes if a pixel falls outside an image.
\param pos the pixel position
\param size the image size
\return true if the pixel is outside of the image
*/
bool isOutside(ivec2 pos, ivec2 size){
return (pos.x < 0 || pos.y < 0 || pos.x >= size.x || pos.y >= size.y);
}
/** Apply the g filter to the input data. */
void main(){
vec4 accum = vec4(0.0);
ivec2 size = textureSize(tex0, 0).xy;
ivec2 coords = ivec2(v_texCoord0 * size);
for(int dy = -1; dy <=1; dy++){
for(int dx = -1; dx <=1; dx++){
ivec2 newPix = coords + ivec2(dx,dy);
if(isOutside(newPix, size)){
continue;
}
accum += g[dx+1] * g[dy+1] * texelFetch(tex0, newPix,0 );
}
}
o_output = accum;
}

View File

@@ -0,0 +1,52 @@
// adapted from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/laplacian.frag
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
out vec4 o_output;
/** Denotes if UV coordinates falls outside an image.
\param pos the UV coordinates
\return true if the UV are outside of the image
*/
bool isOutside(vec2 pos){
return (pos.x < 0.0 || pos.y < 0.0 || pos.x > 1.0 || pos.y > 1.0);
}
/** Compute the Laplacian field of an input RGB image, adding a 1px black border around it before computing the gradients and divergence. */
void main(){
vec3 div = vec3(0.0);
ivec2 size = textureSize(tex0, 0).xy;
vec3 pixelShift = vec3(0.0);
pixelShift.xy = 1.0/vec2(size);
vec2 uvs = v_texCoord0;
if(!isOutside(uvs)){
vec3 col = textureLod(tex0, uvs, 0.0).rgb;
div = 4.0 * col;
}
vec2 uvs110 = uvs + pixelShift.xz;
if(!isOutside(uvs110)){
vec3 col110 = textureLod(tex0, uvs110, 0.0).rgb;
div -= col110;
}
vec2 uvs101 = uvs + pixelShift.zy;
if(!isOutside(uvs101)){
vec3 col101 = textureLod(tex0, uvs101, 0.0).rgb;
div -= col101;
}
vec2 uvs010 = uvs - pixelShift.xz;
if(!isOutside(uvs010)){
vec3 col010 = textureLod(tex0, uvs010, 0.0).rgb;
div -= col010;
}
vec2 uvs001 = uvs - pixelShift.zy;
if(!isOutside(uvs001)){
vec3 col001 = textureLod(tex0, uvs001, 0.0).rgb;
div -= col001;
}
o_output.rgb = div;
o_output.a = 1.0f;
}

View File

@@ -0,0 +1,20 @@
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
out vec4 o_output;
/** Denotes if a pixel falls outside an image.
\param pos the pixel position
\param size the image size
\return true if the pixel is outside of the image
*/
/** Output an image translated by a fixed number of pixels on each axis. useful for padding when rendering in a larger framebuffer. */
void main(){
vec4 c = texture(tex0, v_texCoord0);
o_output.rgb = c.rgb;
o_output.a = 1.0;
}

View File

@@ -0,0 +1,18 @@
// from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/fill-boundary.frag
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
out vec4 o_output;
void main(){
o_output = vec4(0.0);
vec4 fullColor = textureLod(tex0, v_texCoord0, 0.0);
if (fullColor.a == 1.0) {
o_output = fullColor;
}
}

View File

@@ -0,0 +1,60 @@
// from https://github.com/kosua20/Rendu/blob/master/resources/common/shaders/screens/convolution-pyramid/upscale.frag
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0; ///< Current h1 filtered level.
uniform sampler2D tex1; ///< Previous h1+g filtered level.
out vec4 o_output; ///< Color.
uniform float h1[5]; ///< h1 filter parameters.
uniform float h2; ///< h2 scaling parameter.
uniform float g[3]; ///< g filter parameters.
/** Denotes if a pixel falls outside an image.
\param pos the pixel position
\param size the image size
\return true if the pixel is outside of the image
*/
bool isOutside(ivec2 pos, ivec2 size){
return (pos.x < 0 || pos.y < 0 || pos.x >= size.x || pos.y >= size.y);
}
/** Combine previous level filtered with h2 (applying a 0-filled upscaling) and the current level filtered with g.
*/
void main(){
vec4 accum = vec4(0.0);
ivec2 size = textureSize(tex0, 0).xy;
ivec2 coords = ivec2(v_texCoord0 * size);
for(int dy = -1; dy <=1; dy++){
for(int dx = -1; dx <=1; dx++){
ivec2 newPix = coords+ivec2(dx,dy);
if(isOutside(newPix, size)){
continue;
}
accum += g[dx+1] * g[dy+1] * texelFetch(tex0, newPix,0);
}
}
ivec2 sizeSmall = textureSize(tex1, 0).xy;
for(int dy = -2; dy <=2; dy++){
for(int dx = -2; dx <=2; dx++){
ivec2 newPix = coords+ivec2(dx,dy);
// The filter is applied to a texture upscaled by inserting zeros.
if(newPix.x%2 != 0 || newPix.y%2 != 0){
continue;
}
newPix /= 2;
newPix += 5;
if(isOutside(newPix, sizeSmall)){
accum = vec4(0.0, 0.0, 1.0, 1.0);
}
accum += h2 * h1[dx+2] * h1[dy+2] * texelFetch(tex1, newPix, 0);
}
}
o_output = accum;
}