How can I get depth from ofFbo.getDepthTexture()?


#1

I would like to get the depth data from ofFbo using the getDepthTexture() function.
But it doesn’t work correctly.
My environment is OF0.10.1 on Windows10 and Visual Studio 2017.
How can I get the depth values correctly from the getDepthTexture() of ofFbo?

The results are as follows,
pixels.png


depth.png

buffer.png

depthBufferDraw.png

The pixels.png as usual rendering result is correct.
The depth.png what saved by fbo.getDepthTexture() is mainly black. There are a few white noises at the top of the image.
The buffer.png seems something depth, but the values are strange and unrecognizable.
The depthBufferDraw is the rendering result of the fbo.getDepthTexture(), it seems correct except for the background.

The test code is as follow,

ofApp.h

#pragma once

#include "ofMain.h"
#include "ofxAssimpModelLoader.h"

class ofApp : public ofBaseApp{

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

		ofxAssimpModelLoader model;
		ofMesh mesh;
		ofFbo fbo;
		ofEasyCam cam;
		ofLight light;

		ofTexture depthBufferTexture;
};

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
	model.loadModel("lofi-bunny.ply", false);
	mesh = model.getMesh(0);

	cam.setDistance(500.f);
	cam.setPosition(0.f, 0.f, 500.f);
	cam.lookAt(mesh.getCentroid(), ofVec3f(0.f, 1.f, 0.f));

	light.setParent(cam);
	light.enable();

	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_COMPONENT32;
	s.textureTarget = GL_TEXTURE_2D;

	fbo.allocate(s);
	fbo.checkStatus();
	fbo.checkGLSupport();
	ofDisableArbTex();
}

//--------------------------------------------------------------
void ofApp::update(){
	ofEnableLighting();
	ofEnableDepthTest();

	fbo.begin();
	cam.begin();
	ofClear(0);
	mesh.draw();
	cam.end();
	fbo.end();

	if (ofGetKeyPressed('r')) {
		ofPixels pixels;
		fbo.readToPixels(pixels);
		ofSaveImage(pixels, "pixels.png");
	}
	if (ofGetKeyPressed('d')) {
		ofTexture texture = fbo.getDepthTexture();
		ofPixels pixels;
		texture.readToPixels(pixels);
		ofSaveImage(pixels, "depth.png");
	}
	if (ofGetKeyPressed('b')) {
		depthBufferTexture = fbo.getDepthTexture();
		ofBufferObject buffer;
		buffer.allocate(ofGetWidth() * ofGetHeight() * 4, GL_STATIC_READ);
		depthBufferTexture.copyTo(buffer);
		unsigned char* f = buffer.map<unsigned char>(GL_READ_ONLY);
		ofPixels pixels;
		pixels.setFromExternalPixels(f, ofGetWidth(), ofGetHeight(), 4);
		ofSaveImage(pixels, "buffer.png");
	}
}

//--------------------------------------------------------------
void ofApp::draw(){
	ofBackground(ofColor::black);

	if (ofGetKeyPressed('b')) {
		depthBufferTexture.draw(0, 0, ofGetWidth(), ofGetHeight());
		ofSaveScreen("depthBufferDraw.png");
	}
	else {
		fbo.draw(0, 0, ofGetWidth(), ofGetHeight());
	}
}

#2

This is on-going status.

  1. I needed to define the NearClip and FarClip expressly.
    ex.
    cam.setNearClip(300);
    cam.setFarClip(1000);

  2. GL_DEPTH_COMPONENT seems to work.

s.depthStencilInternalFormat = GL_DEPTH_COMPONENT; // GL_DEPTH_COMPONENT32;

	if (ofGetKeyPressed('v')) {
		depthBufferTexture = fbo.getDepthTexture();
		ofBufferObject buffer;
		buffer.allocate(ofGetWidth() * ofGetHeight() * 2, GL_STATIC_READ);
		depthBufferTexture.copyTo(buffer);
		unsigned char* f = buffer.map<unsigned char>(GL_READ_ONLY);

		ofPixels pixels;
		pixels.allocate(ofGetWidth(), ofGetHeight(), ofImageType::OF_IMAGE_COLOR_ALPHA);
		for (int i = 0; i < ofGetHeight(); i++) {
			for (int j = 0; j < ofGetWidth(); j++) {
				int idx = (i * ofGetWidth() + j) * 2;
				uint16_t ret;
				ret = f[idx];
				ret |= f[idx + 1] << 8;

				float v = (float)(ret) / 0xffff;
				
				pixels.setColor(j, i, ofFloatColor(v, v, v, 255));
			}
		}
		ofSaveImage(pixels, "bufferFloat.png");
	}

bufferFloat.png