How to render z-buffer (Depth pass) image of a 3D scene?

edited December 2013 in How To...

image alt text

How to render z-buffer (Depth pass) image of a 3D scene? like in the image.

Tagged:

Answers

  • edited December 2013

    To the best of my knowledge there is not a shortcut for doing that. You would have to set up a "virtual camera" which really just a 3D point in space. Between the virtual camera and the 3D objects you have a "virtual grid" which represents the pixels from the virtual camera's point of view. Then you would shoot a ray from the virtual camera through each hole in the grid, determine which 3D object the ray intersected, and get the length of the ray. Then you would map the lengths of the rays to black and white pixels.

    Here is an image that hopefully helps the explanation. Ignore the light source and shadow in the diagram, you don't need a light source for what you want:

    Ray Tracing Diagram

  • edited March 2014 Answer ✓

    Using a simple vertex and a slightly more complex fragment shader.

    Processing code:

    PShader depthShader;
    float angle = 0.0;
    
    
    void setup(){
        
        // Set screen size and renderer
        size(600, 480, P3D);
        noStroke();
        
        // Load shader
        depthShader = loadShader("frag.glsl", "vert.glsl");
        //depthShader.set("near", 40.0); // Standard: 0.0
        //depthShader.set("far", 60.0); // Standard: 100.0
        //depthShader.set("nearColor", 1.0, 0.0, 0.0, 1.0); // Standard: white
        //depthShader.set("farColor", 0.0, 0.0, 1.0, 1.0); // Standard: black
        
    }
    
     
    void draw(){
        
        // Fill background and set camera
        background(#000000);
        camera(0.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
        
        // Bind shader
        shader(depthShader);
        
        // Calculate angle
        angle += 0.01;
        
        // Render "sky"-cube
        pushMatrix();
        rotate(angle, 0.0, 1.0, 0.0);
        box(100.0);
        popMatrix();
        
        // Render cubes
        pushMatrix();
        translate(-30.0, 20.0, -50.0);
        rotate(angle, 1.0, 1.0, 1.0);
        box(25.0);
        popMatrix();
        pushMatrix();
        translate(30.0, -20.0, -50.0);
        rotate(angle, 1.0, 1.0, 1.0);
        box(25.0);
        popMatrix();
        
        // Render spheres
        pushMatrix();
        translate(-30.0, -20.0, -50.0);
        rotate(angle, 1.0, 1.0, 1.0);
        sphere(20.0);
        popMatrix();
        pushMatrix();
        translate(30.0, 20.0, -50.0);
        rotate(angle, 1.0, 1.0, 1.0);
        sphere(20.0);
        popMatrix();
        
    }
    

    Vertex shader code:

    uniform mat4 transform;
    
    attribute vec4 vertex;
    attribute vec4 color;
    
    varying vec4 vertColor;
    
    void main() {
        gl_Position = transform * vertex;
        vertColor = color;
    }
    

    Fragment shader code:

    #ifdef GL_ES
    precision mediump float;
    precision mediump int;
    #endif
    
    uniform vec4 nearColor = vec4(1.0, 1.0, 1.0, 1.0);
    uniform vec4 farColor = vec4(0.0, 0.0, 0.0, 1.0);
    uniform float near = 0.0;
    uniform float far = 100.0;
    
    varying vec4 vertColor;
    
    void main() {
        gl_FragColor = mix(nearColor, farColor, smoothstep(near, far, gl_FragCoord.z / gl_FragCoord.w));
    }
    

    In case you don't know how to use these code-snippets:

    • Create a new processing project named DepthTest.
    • Name the vertex shader file vert.glsl and put it in DepthTest -> data.
    • Name the fragment shader file frag.glsl and put it in DepthTest -> data.
  • edited March 2014

    Hello, Unfortunately, that's exactly what I'm trying to do and the above code won't work and give the following error :

    ================================================== java.lang.runtimeException : Cannot compile vertex shader;0(18) warning C7583: Initialization of uniform variables require #120 or later0(19)

    "java.lang.NullPointerException at processing.mode.java.runner.Runner.findException(Runner.java:926) at processing.mode.java.runner.Runner.reportException(Runner.java:871) at processing.mode.java.runner.Runner.exceptionEvent(Runner.java:797) at processing.mode.java.runner.Runner$2.run(Runner.java:686) "

    ==================================================

    I'm using processing 2.1.1.. Any clue please ?

  • edited March 2014

    @capturevision: That means, that your GLSL version doesn't allow you to initialize uniform variables directly. Just initialize them via Processing's set() function instead.

    In the fragment shader code, replace lines 6 till 9 with:

    uniform vec4 nearColor;
    uniform vec4 farColor;
    uniform float near;
    uniform float far;
    

    And in the Processing code, replace lines 13 till 16 with:

    depthShader.set("near", 0.0);
    depthShader.set("far", 100.0);
    depthShader.set("nearColor", 1.0, 1.0, 1.0, 1.0);
    depthShader.set("farColor", 0.0, 0.0, 0.0, 1.0);
    
  • edited March 2014

    Hey ;) !

    @Poersch : Thanks a lot.. works like a charm !

    But, does that mean that I have to update my GLSL version ? I don't know how to do that, and my GPU drivers are up to date..

Sign In or Register to comment.