Depth of Field effect with a shader

Hi all,

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 but can’t seem to make the DoF effect work.
I’m pretty sure I have to draw the points into an off-screen graphics buffer but can’t figure out which one and why. I got lost in the process…

Would appreciate your help.

PS: this new forum looks good !

add_library('peasycam')
liste = []

def setup():
    global depthShader, depthPGraphics, dofPGraphics, dofShader, cam, buf
    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.016)
    dofShader.set("aperture", 0.02)
    
    dofPGraphics = createGraphics(width, height, P3D)
    depthPGraphics = createGraphics(width, height, P3D)
    dofPGraphics.shader(dofShader)
    depthPGraphics.shader(depthShader)
    
    frameRate(1000)
    
def draw():
    background(255)
    shader(depthShader)

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

    dofShader.set("focus", map(mouseX, 0, width, -0.5, 1.5))
    dofShader.set("tDepth", depthPGraphics)    
    filter(dofShader)
1 Like

Your old forum topic-related post: :wink:

I think I’m getting closer…
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)

I’ve been trying to implement the example sketch provided by @hamoid where the Proscene dependency is no longer needed but I still can’t figure out why the amount of blur stays the same for each and every object drawn in the scene, no matter how far they are from the camera (PeasyCam).

I suspect the depthShader not to be correcly working on the canvas PGraphics buffer but can’t say for sure.

Basically, what I’m doing here:

  • I’m drawing cubes on the scene PGraphics buffer.
  • Then I draw the same thing on the canvas PGraphics buffer where the depthShader shader is applied.
  • Finally I display the first scene through a third graphic buffer named buf where the dofShader is applied. (the tDepth setting of this shader is based on the second canvas)

Once again I would really appreciate any help.

Thank you

add_library('peasycam')
liste = []

def setup():
    global depthShader, dofShader, cam, canvas, buf, scene, shp
    size(900, 900, P3D)
    
    cam = PeasyCam(this, 900)
    cam.setMaximumDistance(width)
        
    depthShader, dofShader = loadShader("depth.glsl"), loadShader("dof.glsl")
    dofShader.set("aspect", width / float(height))

    
    canvas, buf, scene = createGraphics(width, height, P3D), createGraphics(width, height, P3D), createGraphics(width, height, P3D)
    canvas.smooth(8)
    canvas.shader(depthShader)
    
    for e in range(100): liste.append(PVector(random(width), random(height), random(width))) 
    
    frameRate(1000)
    
    shp = createShape(BOX, 60)
    shp.setStroke(color(120))
        

def draw():
        
    scene.beginDraw()
    scene.background(255)
    for i in range(10):
        scene.pushMatrix()
        scene.translate((i*7763)%width, (i*777)%height, 30*i*sin(i)-500)
        scene.shape(shp)
        scene.popMatrix()
    scene.endDraw()

    canvas.beginDraw()
    canvas.background(255)
    for i in range(10):
        canvas.pushMatrix()
        canvas.translate((i*7763)%width, (i*777)%height, 30*i*sin(i)-500)
        canvas.shape(shp)
        canvas.popMatrix()
    canvas.endDraw()

    depthShader.set("maxDepth", cam.getDistance())

    buf.beginDraw()
    dofShader.set("tDepth", canvas)
    dofShader.set("maxBlur", 0.015)
    dofShader.set("focus", map(mouseX, 0, width, float(-0.5), float(1.5)))
    dofShader.set("aperture", float(0.02))
    buf.shader(dofShader)
    
    buf.image(scene, 0, 0)
    buf.endDraw()

    cam.beginHUD()
    image(buf, 0, 0)
    cam.endHUD()
    #cam.getState().apply(scene)

Depth of Field effect with PeasyCam, working :smiley: :sob: example sketch:

add_library('peasycam')
liste = []
colors = [[0,189,202], [251,183,0], [255,17,79], [252,128,35], [0,108,254]]

def setup():
    global depthShader, dofShader, cam, canvas, buf, scene, pnt
    size(900, 900, P3D)
    
    cam = PeasyCam(this, 900)
    cam.setMaximumDistance(width)
        
    depthShader, dofShader = loadShader("depth.glsl"), loadShader("dof.glsl")
    depthShader.set("maxDepth", cam.getDistance()*2)
    dofShader.set("aspect", width / float(height))
    dofShader.set("maxBlur", 0.025)
    dofShader.set("aperture", 0.05)
    
    canvas, buf, scene = createGraphics(width, height, P3D), createGraphics(width, height, P3D), createGraphics(width, height, P3D)
    canvas.shader(depthShader) 
    buf.shader(dofShader)
    buf.smooth(8)
    scene.smooth(8)

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

    pnt = createShape(SPHERE, 12)
    pnt.setStroke(False)
    
    frameRate(1000)

def draw():
    scene.beginDraw()
    scene.background(0)
    for i in range(len(liste)):
        scene.pushMatrix()
        scene.translate(liste[i].x-width/2, liste[i].y-width/2, liste[i].z-width/2)
        scene.shape(pnt)
        pnt.setFill(color(colors[i%4][0], colors[i%4][1], colors[i%4][2]))
        scene.popMatrix()
    scene.endDraw()

    canvas.beginDraw()
    canvas.background(0)
    for i in range(len(liste)):
        canvas.pushMatrix()
        canvas.translate(liste[i].x-width/2, liste[i].y-width/2, liste[i].z-width/2)
        canvas.shape(pnt)
        canvas.popMatrix()
    canvas.endDraw()

    buf.beginDraw()
    dofShader.set("tDepth", canvas)
    dofShader.set("focus", map(mouseX, 0, width, .3, 1))
    buf.image(scene, 0, 0)
    buf.endDraw()

    cam.beginHUD()
    image(buf, 0, 0)
    cam.getState().apply(canvas)
    cam.getState().apply(scene)
    cam.endHUD()
    
    cam.rotateY(.002)

If someone knows how get a DoF effect with points instead of sphere shapes, please let me know.

Congratulations! Is that still using the same depth.glsl and dof.glsl that you posted above, or have they changed?

1 Like

@jeremydouglass Thank you. Yes, the sketch is using the shaders posted above.

For clarity let me re-post the whole thing with an updated script.

sketch.pyde

add_library('peasycam')
colors, liste = [[0,189,202], [251,183,0], [255,17,79], [252,128,35], [0,108,254]], []

def setup():
    global depthShader, dofShader, cam, buf1, buf2, buf3, pnt
    size(900, 900, P3D)
    frameRate(1000)

    cam = PeasyCam(this, 900)
    cam.setMaximumDistance(width)
    pnt = createShape(BOX, 30)
    pnt.setStroke(False)
        
    depthShader, dofShader = loadShader("depth.glsl"), loadShader("dof.glsl")
    depthShader.set("maxDepth", cam.getDistance()*2)
    dofShader.set("aspect", width / float(height)), dofShader.set("maxBlur", 0.02), dofShader.set("aperture", 0.06)
    
    buf1, buf2, buf3 = [createGraphics(width, height, P3D) for e in range(3)]
    buf1.smooth(8), buf2.shader(depthShader), buf3.shader(dofShader)

    for e in range(300): liste.append(PVector(random(width), random(height), random(width))) 
    
def drawScene(pg):
    pg.beginDraw()
    pg.background(0)
    for i in range(len(liste)):
        pg.pushMatrix()
        pg.translate(liste[i].x-width/2, liste[i].y-width/2, liste[i].z-width/2)
        pg.shape(pnt)
        pnt.setFill(color(colors[i%5][0], colors[i%5][1], colors[i%5][2]))
        pg.popMatrix()
    pg.endDraw()
    cam.getState().apply(pg)

def draw():
    drawScene(buf1), drawScene(buf2)

    buf3.beginDraw()
    dofShader.set("tDepth", buf2)
    dofShader.set("focus", map(mouseX, 0, width, .3, 1))
    buf3.image(buf1, 0, 0)
    buf3.endDraw()
    
    cam.beginHUD()
    image(buf3, 0, 0)
    cam.endHUD()

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;
}

I still have one problem though: I’d like to draw points instead of spheres but when I do so (createShape(POINT, x, y, z) the DoF doesn’t work anymore. Why is that ?

1 Like

Sorry to be persistent but I really would like to solve the one remaining issue I mentionned in my previous comments.

Goal: I would like to display thousands of points on a 3D canvas where the Depth of Field effect above is applied.

Problem: For some reason the sketch I posted works with every primitives except POINT and LINE. I could certainly replace points by spheres, but as I just mentionned I’m trying to display thousands of points and drawing spheres instead would be too computer-intensive.

More specifically: when drawing points (pnt = createShape(POINT, 0, 0, 0) instead of pnt = createShape(SPHERE, 4)) on line 11:

  • The depth of field doesn’t work anymore (distance from camera not taken into account ?)
  • Only pink, yellow and orange points seem to be reacting to the change of focus (when moving the mouse). Dark blue and light blue points stay blurry


For comparison, the same sketch displaying spheres:

2 Likes

POINT and LINE shaders behave differently than COLOR shaders. Check out the Processing Shaders tutorial on how to do the math for the projection of POINTS

10. Point and line shaders

The point and line shaders are only used by the P3D renderer in order to draw stroke geometry. The reason is that the stroke geometry is always screen-facing in 3D, so it needs a different projection calculation in the vertex stage. In P2D, all the geometry is contained in the same plane, so there is no need of special handling for stroke lines and points (everything is just rendered as triangles with an orthographic projection).

2 Likes

Thanks @WakeMeAtThree, just figured this out yesterday. I’ll try to find some time later next week to make that shader work. Maybe I’ll make some changes in the blur computation as well (I find the Gaussian blur softer to the eye).

Btw I like your work on morphing, very cool stuff.

1 Like

I have tweaked the point shader from the shaders tutorial to take the depth information into acount and implemented it in the script I posted previsoulsy.

At first glance, the sketch seems to work:

But I’m still having a problem with colors.
The Depth of Field works with white / reddish / yellowish colors but not with bluish / greenish colors:

Do you know what could be missing in the following point shaders ?

pointfrag.glsl

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

varying vec4 vertColor;
uniform float maxDepth;
 
void main() {

  float depth = gl_FragCoord.z / gl_FragCoord.w;
  gl_FragColor = vec4(vec3(vertColor - depth/maxDepth), 1) ;

}

pointvert.glsl

uniform mat4 projection;
uniform mat4 modelview;

attribute vec4 position;
attribute vec4 color;
attribute vec2 offset;


varying vec4 vertColor;
varying vec4 vertTexCoord;

void main() {
  vec4 pos = modelview * position;
  vec4 clip = projection * pos;

  gl_Position = clip + projection * vec4(offset, 0, 0);

  vertColor = color;
}

Overall I’m not really satisfied with that DOF shader: I don’t like the halo seen around the primitives and the points tend to pixelate:

Example sketch (Python mode + PeasyCam library needed)

add_library('peasycam')

def setup():
    global pointShader, cam, pg, depthShader, dofShader, buf1, buf2, buf3
    size(900, 900, P3D)
    frameRate(1000)
    smooth(8)
    
    cam = PeasyCam(this, 500)
    cam.setMaximumDistance(width)
    perspective(60 * DEG_TO_RAD, width/float(height), 2, 6000)
    
    pointShader = loadShader("pointfrag.glsl", "pointvert.glsl")
    pointShader.set("maxDepth", cam.getDistance()*3)
    
    depthShader, dofShader = loadShader("depth.glsl"), loadShader("dof.glsl")
    dofShader.set("aspect", width / float(height)), dofShader.set("maxBlur", 0.015), dofShader.set("aperture", 0.06)
    
    buf1, buf2, buf3 = [createGraphics(width, height, P3D) for e in range(3)]
    buf2.shader(depthShader), buf3.shader(dofShader)

    pg = createShape()
    pg.beginShape(POINTS)
    pg.strokeWeight(5)
    pg.stroke(255)
    pg.translate(-width/2, -width/2, -width/2)    
    for e in range(5000):
        pg.vertex(random(width), random(width), random(width))
    pg.endShape()
    
def drawScene(buf):
    buf.beginDraw()
    buf.shader(pointShader, POINTS)
    buf.background(0)
    buf.shape(pg,0,0)
    buf.endDraw()
    cam.getState().apply(buf)
    
def draw():
    drawScene(buf1)
    drawScene(buf2)
            
    buf3.beginDraw()
    dofShader.set("tDepth", buf2)
    dofShader.set("focus", map(mouseX, 0, width, .3, 1))
    buf3.image(buf1, 0, 0)
    buf3.endDraw()
    
    cam.beginHUD()
    image(buf3, 0, 0)
    cam.endHUD()
    cam.rotateY(.0002)
    cam.rotateX(.0001)

I found that adding minDepth can make better effect. This case you should keep focus parameter to 0.5 and move minDepth and maxDepth instead.

varying vec4 vertColor;
uniform float minDepth;
uniform float maxDepth;

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