Depth of Field effect with a shader

edited May 2018 in Python Mode

Posting the question back here since it seems I won't get any help on the new forum (?).

As some of you may already know I'm trying to make a Depth of Field effect in Python mode. I've recently stumbled onto this thread where I could get hold of a Proscene DOF demo sketch based on the following shaders:

depth.glsl

uniform float maxDepth;

void main() {
  float depth = gl_FragCoord.z / gl_FragCoord.w;
  gl_FragColor = vec4(vec3(1.0 - depth/maxDepth), 1.0);
}

dof.glsl

uniform sampler2D texture;

varying vec4 vertexture;
varying vec4 vertTexCoord;

uniform sampler2D tDepth;

uniform float maxBlur; // max blur amount
uniform float aperture; // aperture - bigger values for shallower depth of field

uniform float focus;
uniform float aspect;

void main() {
    vec2 vUv = vertTexCoord.st;

    vec2 aspectcorrect = vec2( 1.0, aspect );

    vec4 depth1 = texture2D( tDepth, vUv );

    float factor = depth1.x - focus;

    vec2 dofblur = vec2 ( clamp( factor * aperture, -maxBlur, maxBlur ) );

    vec2 dofblur9 = dofblur * 0.9;
    vec2 dofblur7 = dofblur * 0.7;
    vec2 dofblur4 = dofblur * 0.4;

    vec4 col = vec4( 0.0 );

    col += texture2D( texture, vUv.xy );
    col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );
    col += texture2D( texture, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );

    col += texture2D( texture, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );

    col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );

    col += texture2D( texture, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );
    col += texture2D( texture, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );
    col += texture2D( texture, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );

    gl_FragColor = col / 41.0;
    gl_FragColor.a = 1.0;
}

What I'd like is to be able to use those shaders using the PeasyCam library instead of the Proscene dependency.

In the sketch below I'm testing the shaders on a point cloud. I’m drawing the points on the scene PGraphics and then passing it through 2 other PGraphics (canvas and buf). In theory it should work but I’m still stuck with the PeasyCam part at the very end of the script.

If I write:

  • cam.getState().apply(canvas): I get a DoF effect BUT on a 2D canvas
  • cam.getState().apply(scene) : I get a 3D canvas BUT without a DoF effect

Any help would be really appreciated.

add_library('peasycam')
liste = []

def setup():
    global depthShader, dofShader, cam, canvas, buf, scene
    size(900, 900, P3D)

    cam = PeasyCam(this, 900)
    cam.setMaximumDistance(width)

    for e in range(100):
        liste.append(PVector(random(width), random(height), random(width)))

    depthShader = loadShader("depth.glsl")
    dofShader = loadShader("dof.glsl")

    depthShader.set("maxDepth", cam.getDistance())
    dofShader.set("aspect", width / float(height))
    dofShader.set("maxBlur", 0.015)
    dofShader.set("aperture", 0.02)

    canvas = createGraphics(width, height, P3D)
    canvas.shader(depthShader)
    buf = createGraphics(width, height, P3D)
    buf.shader(dofShader)

    scene = createGraphics(width, height, P3D)

    frameRate(1000)

def draw():

    scene.beginDraw()
    scene.background(255)
    scene.stroke(0)
    scene.strokeWeight(10)
    for e in liste:
        scene.point(e.x-width/2, e.y-height/2, e.z-height/2)
    scene.endDraw()

    canvas.beginDraw()
    canvas.image(scene, 0, 0)
    canvas.endDraw()

    buf.beginDraw()
    dofShader.set("focus", map(mouseX, 0, width, -0.5, 1.5))
    dofShader.set("tDepth", canvas)
    buf.image(scene, 0, 0)
    buf.endDraw()

    cam.beginHUD()
    image(buf, 0, 0)
    cam.endHUD()

    cam.getState().apply(scene)

Answers

  • edited May 2018

    Hi @solub -- I'm happy to answer on the new forum, but your updates on that thread haven't given me a concrete question. You've said things like "I think I’m getting closer…" and "I’m still stuck with the PeasyCam part" but I didn't know how to answer that. I know that your overall goal is "I want this code to work," but something more concrete would be helpful. I am familiar with PeasyCam.

    That said, I'm also not experienced with GLSL Shaders. You are at the intersection of two minority communities in Processing -- few people know Python mode, fewer people know PShader, and fewest know both. This may be why you aren't getting a lot of uptake. If you break parts of it into narrower problems more people might have the experience to address it.

Sign In or Register to comment.