Skip to content

Instantly share code, notes, and snippets.

@texone
Forked from LingDong-/PoissonFill.java
Created January 2, 2023 18:33
Show Gist options
  • Save texone/ce9e2c570b8f8c620b63e3f512b4b3d3 to your computer and use it in GitHub Desktop.
Save texone/ce9e2c570b8f8c620b63e3f512b4b3d3 to your computer and use it in GitHub Desktop.
Poisson Filling Shader for Processing(Java)
// Poisson Filling for Processing
// Made possible with support from The Frank-Ratchye STUDIO For Creative Inquiry
// At Carnegie Mellon University. http://studioforcreativeinquiry.org/
// #define PROCESSING_COLOR_SHADER
uniform sampler2D unf;
uniform sampler2D fil;
uniform int w;
uniform int h;
uniform bool isup;
float h1(int i){
if (i == 0 || i == 4){
return 0.1507;
}
if (i == 1 || i == 3){
return 0.6836;
}
return 1.0334;
}
float G(int i){
if (i == 0 || i == 2){
return 0.0312;
}
return 0.7753;
}
void main() {
float ab = 0.0;
vec2 step = 1.0 / vec2(float(w),float(h));
int i = int(gl_FragCoord.y+0.5);
int j = int(gl_FragCoord.x+0.5);
if (!isup){
int x = (j);
int y = (i);
vec4 acc = vec4(0.0,0.0,0.0,0.0);
for (int dy = -2; dy <= 2; dy++) {
for (int dx = -2; dx <= 2; dx++) {
int nx = x + dx;
int ny = y + dy;
vec4 col = texture2D(unf, vec2((float(nx)) * step.x, (float(ny)) * step.y));
acc.r += h1(dx+2) * h1(dy+2) * (col.r*floor(col.a+ab));
acc.g += h1(dx+2) * h1(dy+2) * (col.g*floor(col.a+ab));
acc.b += h1(dx+2) * h1(dy+2) * (col.b*floor(col.a+ab));
acc.a += h1(dx+2) * h1(dy+2) * floor(col.a+ab);
}
}
if (acc.a == 0.0){
gl_FragColor = acc;
}else{
gl_FragColor = vec4(acc.r/acc.a,acc.g/acc.a,acc.b/acc.a,1.0);
}
}else{
float h2 = 0.0270;
vec4 acc = vec4(0.0,0.0,0.0,0.0);
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
int nx = j + dx;
int ny = i + dy;
vec4 col = texture2D(unf, 1.0*vec2((float(nx)-0.75) * step.x, (float(ny)-0.75) * step.y));
acc.r += G(dx+1) * G(dy+1) * (col.r*floor(col.a+ab));
acc.g += G(dx+1) * G(dy+1) * (col.g*floor(col.a+ab));
acc.b += G(dx+1) * G(dy+1) * (col.b*floor(col.a+ab));
acc.a += G(dx+1) * G(dy+1) * floor(col.a+ab);
}
}
for (int dy = -2; dy <= 2; dy++) {
for (int dx = -2; dx <= 2; dx++) {
float nx = float(j) + float(dx)*1.0;
float ny = float(i) + float(dy)*1.0;
vec4 col = texture2D(fil, 1.0*vec2((float(nx)-0.75) * step.x, (float(ny)-0.75) * step.y));
acc.r += h2 * h1(dx+2) * h1(dy+2) * (col.r*floor(col.a+ab));
acc.g += h2 * h1(dx+2) * h1(dy+2) * (col.g*floor(col.a+ab));
acc.b += h2 * h1(dx+2) * h1(dy+2) * (col.b*floor(col.a+ab));
acc.a += h2 * h1(dx+2) * h1(dy+2) * floor(col.a+ab);
}
}
if (acc.a == 0.0){
gl_FragColor = acc;
}else{
gl_FragColor = vec4(acc.r/acc.a,acc.g/acc.a,acc.b/acc.a,1.0);
}
}
}
/* Poisson Filling for Processing
* Made possible with support from The Frank-Ratchye STUDIO For Creative Inquiry
* At Carnegie Mellon University. http://studioforcreativeinquiry.org/
*/
package poissonfill;
import processing.core.*;
import processing.opengl.*;
import java.util.*;
public class PoissonFill{
PShader shader1;
PShader shader2;
PApplet app;
public ArrayList<PGraphics> downs;
public ArrayList<PGraphics> ups;
int w;
int h;
public int depth;
public PoissonFill(PApplet _app, int _w, int _h, int _depth){
app = _app;
w = _w;
h = _h;
depth = _depth;
app.noStroke();
app.hint(PApplet.DISABLE_TEXTURE_MIPMAPS);
app.pixelDensity(1);
shader1 = shader2way();
shader2 = shader2way();
downs = new ArrayList<PGraphics>();
ups = new ArrayList<PGraphics>();
for (int i = 0; i < depth; i++){
_w/=2;
_h/=2;
downs.add(app.createGraphics(_w,_h,PApplet.P2D));
downs.get(i).noSmooth();
}
for (int i = 0; i < depth; i++){
_w*=2;
_h*=2;
ups.add(app.createGraphics(_w,_h,PApplet.P2D));
ups.get(i).noSmooth();
}
}
public PoissonFill(PApplet _app, int _w, int _h){
this(_app,_w,_h,_app.floor(_app.log(_app.min(_w,_h))/_app.log(2))-1);
}
public void process(PImage tex){
int i;
pass(shader1,downs.get(0),tex,null);
for (i = 1; i < depth; i++){
pass(shader1,downs.get(i),downs.get(i-1),null);
}
pass(shader2,ups.get(0),downs.get(depth-2),downs.get(depth-1));
for (i = 1; i < depth-1; i++){
pass(shader2,ups.get(i),downs.get(depth-i-2),ups.get(i-1));
}
pass(shader2,ups.get(depth-1),tex,ups.get(depth-2));
}
public PImage getTexture(){
return ups.get(depth-1);
}
void pass(PShader shader,PGraphics p,PImage tex1,PImage tex2){
p.beginDraw();
shader.set("unf", tex1);
if (tex2 != null){
shader.set("fil", tex2);
}
shader.set("isup", tex2 != null);
shader.set("w",p.width);
shader.set("h",p.height);
p.clear();
p.noStroke();
p.fill(255);
p.shader(shader);
p.rect(0, 0, p.width, p.height);
p.endDraw();
}
PShader shader2way(){
return app.loadShader("poissonfill.frag");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment