FBO - get real Depth Values

Hey Guys,
I want to get the depth Information about different vertices in a 3d-scene. My idea is to filter out just the rendered Verticies by comparing the distance of one vertex with its screenposition-depthValue of the rendered scene. Therefor I write the scene in an fbo and take the vertex´ depth-information as a Value. But: the depthTexture just gives a pixel-Image with color informations which is not very concrete. Is there a way to get the real depth(distance to camera).
My first guess was the screenToWorld function. But this just gives me coordinates of the Screen-Plane.
I hope you understand the problem. Otherwise I can post some code.
The problem was discussed earlier here:
https://forum.openframeworks.cc/t/vertex-rendering-information/15253/3

But I don’t want to use Shaders. I need the infos in the cpu and performance is not the problem because I don’t need this function every draw.

the information you get is in normalized device coordinates you need to turn it into world coordinates. To do that, first you need to turn the depth you get from 0…1 to -1…1 since that’s what open gl uses by default. then turn that into z in the real world. the easiest although not the fastest way to do it is to multiply a point with that depth by the inverse of the viewProjection matrix:

depth = depth * 2. - 1.;
glm::vec4 p = glm::inverse(viewProjection) * glm::vec4(0., 0., depth, 1.);
float z = (glm::vec3(p) / p.w).z;
1 Like

Thanks arturo,

unfortunately I am still struggling. Here Is a sample code of one method with the screenToWorld-Function and one with the color of the depthTexture:

.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

    ofVboMesh vboMesh;
    
    ofEasyCam cam;
    
    ofFbo screenFbo;
    ofTexture screenDepth;
		
};

.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofBoxPrimitive box;
    box.set( 100 );
    
    vboMesh = box.getMesh();
    vboMesh.setMode(OF_PRIMITIVE_TRIANGLES);
    
    cam.setNearClip(10);
    cam.setFarClip(1000);
    
    
    
    ofEnableArbTex();
    ofFboSettings s;
    s.width = ofGetWidth();
    s.height = ofGetHeight();
    s.internalformat = GL_RGBA;
    s.useDepth = true;
    s.useStencil = false;
    s.depthStencilAsTexture = true;
    s.numSamples = 0;
    s.depthStencilInternalFormat = GL_DEPTH_COMPONENT;
    s.textureTarget = GL_TEXTURE_2D;
    
    
    screenFbo.allocate(s);
    screenFbo.checkStatus();
    screenFbo.checkGLSupport();
    ofDisableArbTex();
    
    screenDepth.allocate(ofGetWidth(),ofGetHeight(),GL_RGBA);
    
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
    
    //screenToWorldMethod/////////////////////
    ofEnableDepthTest();
    cam.begin();
    vboMesh.draw();
    cam.end();
    ofDisableDepthTest();
    
    glm::mat4 viewProjection= cam.getProjectionMatrix();
    
    ofVec3f mousePos = ofVec3f(ofGetMouseX(),ofGetMouseY(),0.);
    
    float depth = cam.screenToWorld(mousePos).z;
    cout <<"depth: "<< depth <<endl;
    depth = depth * 2. - 1.;
    glm::vec4 p = glm::inverse(viewProjection) * glm::vec4(0., 0., depth, 1.);
    float z = (glm::vec3(p) / p.w).z;
    
    cout <<"depthProjcted: "<< z <<endl;
    
    
    //depthTextureMethod/////////////////////
    
    screenFbo.begin();
    ofClear(0.,0.,0.,0.);
    ofEnableDepthTest();
    cam.begin();
    vboMesh.draw();
    cam.end();
    ofDisableDepthTest();
    screenFbo.end();
    
    screenDepth = screenFbo.getDepthTexture();
    
    screenDepth.draw(0,0);
    
    ofPixels pix;
    pix.allocate(ofGetWidth(),ofGetHeight(), GL_RGBA);
    screenDepth.readToPixels(pix);
    
    
    ofColor col = pix.getColor(mousePos.x, mousePos.y);
    
    float depth2 = col.getBrightness();
    cout <<"col: "<< col <<endl;
    cout <<"brightness: "<< depth2 <<endl;
    
}

I tried your projection calculation on the mousePosition, but it gives me everywhere the same value and when I rotate the cam out of default it seems like it gives me the z=0 plane coordinates of world-projection without regarding the object.

In the other method I find it really strange that it just give me white everywhere, although I clearly can see the shape when I draw the texture:

any idea?

Haven’t tested so there might be some wrong step but i think the following should give you world coordinates z. Be aware that readPixels is slow and using it to get the depth might make an application too slow to be usable

    ofPixels pix;
    pix.allocate(ofGetWidth(),ofGetHeight(), GL_RGBA);
    screenDepth.readToPixels(pix);    
    ofVec3f mousePos = ofVec3f(ofGetMouseX(),ofGetMouseY(),0.);
    float depth = pix.getColor(mousePos.x, mousePos.y).r;
    glm::mat4 viewProjection= cam.getProjectionMatrix();
    depth = depth * 2. - 1.;
    glm::vec4 p = glm::inverse(viewProjection) * glm::vec4(0., 0., depth, 1.);
    float z = (glm::vec3(p) / p.w).z;