How to render the Z-buffer to a Texture

Problems building or running the engine, queries about how to use features etc.
marc_christie
Gnoblar
Posts: 2
Joined: Tue Jan 08, 2008 10:23 pm

How to render the Z-buffer to a Texture

Post by marc_christie » Tue Jan 08, 2008 10:35 pm

I need to render a scene from a specific point of view, and have then access to the z-buffer information. I tried to use the RenderTarget, but cannot find how to specify that I need the z information rather than the color information.
I see that I can disable the color rendering (RenderingSystem::_setColourBufferWriteEnabled( false, false, false, false)) but it doesn't seem to do make it.

It is easy in OpenGL by reading the buffer with a GL_DEPTH_COMPONENT.

Thx.
0 x

User avatar
Falagard
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2060
Joined: Thu Feb 26, 2004 12:11 am
Location: Toronto, Canada
Contact:

Post by Falagard » Tue Jan 08, 2008 10:35 pm

Use a floating point render target and render the depth in your pixel shader.

The depth shadow map shaders that come with Ogre show how it's done, and so does the Deferred shading demo.
0 x

marc_christie
Gnoblar
Posts: 2
Joined: Tue Jan 08, 2008 10:23 pm

Post by marc_christie » Wed Jan 09, 2008 9:42 pm

Thx! I've looking at that, but I did't want to go though all the shader stuff,

I was thinking it could be done an other way round. I see there is the PF_DEPTH in OgrePixelFormat. This could be passed to creation of the Texture in the 'createManual()' call, then the HardwarePixelBuffer would point on the depth buffer, and the Blit would give the zbuffer information rather than the color information.

Seems like I'll try the shader stuff :-))

Marc.
0 x

User avatar
cyanbeck
Gnoblar
Posts: 8
Joined: Tue Nov 02, 2004 3:20 pm

Post by cyanbeck » Mon Mar 31, 2008 3:56 am

PF_DEPTH is not implemented due to independent issues.
Falagard proposed the right approach,
but it may not detailed enough for newbies.

So I post some hints here and the code can be found in OGRE SDK media\materials directory.

1. Prepare vertex shader and pixel shader to calculate depth.

Code: Select all

// vertex shader in DepthShadowmap.hlsl
void casterVP(
	float4 position     : POSITION,
	out float4 outPos   : POSITION,
	out float2 outDepth : TEXCOORD0,

	uniform float4x4 worldViewProj,
	uniform float4 texelOffsets,
	uniform float4 depthRange)
{
	outPos = mul(worldViewProj, position);
	outPos.xy += texelOffsets.zw * outPos.w;
	outDepth.x = (outPos.z - depthRange.x) * depthRange.w;
	outDepth.y = outPos.w;
}

// pixel shader in DepthShadowmap.hlsl
void casterFP(
	float2 depth      : TEXCOORD0,
	out float4 result : COLOR)
	
{
	float finalDepth = depth.x;
	result = float4(finalDepth, finalDepth, finalDepth, 1);
}
2. Create the corresponding material scripts for shaders and for objects which you want to apply, i.e the depth of objects you want to calculate.

Code: Select all

// material in DepthShadowmap.material for vertex shader
vertex_program Ogre/DepthShadowmap/CasterVP hlsl
{
    source DepthShadowmap.hlsl
    entry_point casterVP
    target vs_2_0

    default_params
    {
        param_named_auto worldViewProj worldviewproj_matrix
		  param_named_auto texelOffsets texel_offsets
		  param_named_auto depthRange scene_depth_range
    }
}

// material in DepthShadowmap.material for pixel shader
fragment_program Ogre/DepthShadowmap/CasterFP hlsl
{
    source DepthShadowmap.hlsl
    entry_point casterFP
    target ps_2_0

    default_params
    {
    }
}

// material for objects in the scene
material material_name
{
	technique
	{
		pass
		{
			vertex_program_ref Ogre/DepthShadowmap/CasterVP
         {
         }
         fragment_program_ref Ogre/DepthShadowmap/CasterFP
         {
         }
		}
	}
}
3. In your cpp code, for those objects you want to calculate their depth,
call

Code: Select all

object->setMaterial("material_name")
Last edited by cyanbeck on Mon Mar 31, 2008 6:27 am, edited 3 times in total.
0 x

User avatar
cyanbeck
Gnoblar
Posts: 8
Joined: Tue Nov 02, 2004 3:20 pm

Post by cyanbeck » Mon Mar 31, 2008 4:09 am

Now it's time for Render Target Texture (RTT) or just the class name RenderTexture. It means that render the target (scene) to texture. Because the scene is depth map now, all you need to do is render it to the texture. If you don't want the scene be occupied by depth map, you can add RenderTargetListener to perform some processing.

1. Create RTT

Code: Select all

TexturePtr texPtr = TextureManager::getSingleton().createManual("DepthMap", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, 512, 512, 0, PF_R8G8B8, TU_RENDERTARGET);
RenderTexture *depth_map = texPtr->getBuffer()->getRenderTarget();
depth_map->addViewport(camera);
2. Create the corresponding material for RTT

Code: Select all

MaterialPtr matPtr = MaterialManager::getSingleton().create("DepthMapMat", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
matPtr->getTechnique(0)->getPass(0)->createTextureUnitState("DepthMap");
matPtr->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
matPtr->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
matPtr->getTechnique(0)->getPass(0)->setLightingEnabled(false);
3. Refresh the content of RTT every frame if the scene is dynamic.

Code: Select all

TexturePtr texPtr = TextureManager::getSingleton().getByName("DepthMap");
RenderTexture* depth_map = texPtr->getBuffer()->getRenderTarget();
depth_map->update();
OK, it's all done.
I am new to OGRE, too. If there is any error, feel free to correct. 8)
0 x

natepak
Gnoblar
Posts: 20
Joined: Wed Mar 26, 2008 8:26 pm

easier way??

Post by natepak » Tue Apr 01, 2008 5:21 am

Does one really need to set the material of every object in the scene to the DepthMap material in order to render a depth map?

Do the internals of Ogre render shadow maps by switching all objects to use a special DepthMap texture, and then back to their normal textures? Intuitively it seems like there should be an easier method.

I know very little about Ogre, so I just want to make sure that switching the materials back and forth is the best method.
0 x

User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA

Post by nullsquared » Tue Apr 01, 2008 8:47 pm

Code: Select all

// no scene manager render state changes
// (other than object world matrices)
sceneMgr->_suppressRenderStateChanges(true);

// use your depth pass (you could do this manually
// using just the render system, but _setPass()
// is easier if you have a built pass already)
sceneMgr->_setPass(depthMaterial->getBestTechnique()->getPass(0), true, false);

// like said above, _suppressRenderStateChanges(true)
// also suppresses the camera matrices
renderSys->_setViewMatrix(camera->getViewMatrix(true));
renderSys->_setProjectionMatrix(camera->getProjectionMatrixRS());

// you might want to use sceneMgr->_renderScene(...)
// if you need more control
renderTarget->update();

// allow the scene manager to change the render states
sceneMgr->_suppressRenderStateChanges(false);
(Look up the API docs if you want to know what the params do.)
0 x

natepak
Gnoblar
Posts: 20
Joined: Wed Mar 26, 2008 8:26 pm

Post by natepak » Wed Apr 02, 2008 9:53 pm

I'm now able to render the depth map into a normal Ogre window, but not to a render texture. I have created a render texture and material, and attached a listener. The listener's preRenderTargetUpdate function executes the code the nullsquared posted in the previous message.

When I render the scene with the "DepthMap" material applied to each object, then I see the correct results (objects closer to the screen are darker). When I override the pass in the preRendertargetUpdate, the render texture is all black.

The relevant parts of my code are listed below. Can anyone see what I'm doing wrong?

Initialize Ogre:

Code: Select all

void Depth::Init()
{

  this->root = new Ogre::Root();

  this->SetupResources();

  if (this->root->showConfigDialog())
    this->window = this->root->initialise(true);
  else
  {
    printf("Config Error\n");
    return;
  }

  //Choose scene manager
  this->sceneMgr = this->root->createSceneManager(Ogre::ST_GENERIC, "Depths");

  // Get pointer to rendering system
  this->renderSys = this->root->getRenderSystem();

  // Create the camera
  this->camera = this->sceneMgr->createCamera("Camera");
  this->camera->setPosition( Ogre::Vector3(0, 0, 500) );
  this->camera->lookAt( Ogre::Vector3(0, 0, 0) );
  this->camera->setNearClipDistance(1);
  this->camera->setFarClipDistance(1000);

  // Create viewport
  Ogre::Viewport *vp = this->window->addViewport( this->camera );
  vp->setBackgroundColour( Ogre::ColourValue(0,0,0) );
  this->camera->setAspectRatio( Ogre::Real(vp->getActualWidth()) /
                                Ogre::Real(vp->getActualHeight()) );

  // Load resources
  Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

  this->CreateScene();
  
  // Create the Render Texture
  this->renderTexture = Ogre::TextureManager::getSingleton().createManual(
      "DepthMapTexture", 
      Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
      Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET);

  this->renderTarget = this->renderTexture->getBuffer()->getRenderTarget();
  this->renderTarget->addViewport(this->camera);

  // Material for RTT
  Ogre::MaterialPtr matPtr = Ogre::MaterialManager::getSingleton().create("DepthMapMat", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
  matPtr->getTechnique(0)->getPass(0)->createTextureUnitState("DepthMapTexture"); 
  matPtr->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
  matPtr->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
  matPtr->getTechnique(0)->getPass(0)->setLightingEnabled(false);
  

  // Get pointer to the depth map material
  this->depthMaterial = Ogre::MaterialManager::getSingleton().load("Gazebo/DepthMap", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

  // Initialize the listener and attach to the render target
  this->listener.Init(this, this->renderTarget);
  this->renderTarget->addListener( &this->listener );
}
Create the scene (a plane with 2 Ogre heads):

Code: Select all

void Depth::CreateScene()
{
  this->sceneMgr->setAmbientLight(Ogre::ColourValue(1,1,1));

  // Ninja
  Ogre::SceneNode *node = this->sceneMgr->getRootSceneNode()->createChildSceneNode();
  Ogre::Entity *headEntity = this->sceneMgr->createEntity("ninja", "ogrehead.mesh");
  headEntity->setMaterialName("Gazebo/DepthMap");
  node->attachObject( headEntity );
  node->setPosition(0, 0, 0);

  Ogre::SceneNode *node2 = this->sceneMgr->getRootSceneNode()->createChildSceneNode();
  Ogre::Entity *headEntity2 = this->sceneMgr->createEntity("ninja2", "ogrehead.mesh");
  headEntity2->setMaterialName("Gazebo/DepthMap");
  node2->attachObject( headEntity2 );
  node2->setPosition(100, 0, -500);


  // Ground plane
  Ogre::MovablePlane *plane = new Ogre::MovablePlane("mplane");
  plane->normal = Ogre::Vector3::UNIT_Y;
  plane->d = 107;
  Ogre::MeshManager::getSingleton().createPlane("MyPlane",
      Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
      *plane,
      1500, 1500, 50, 50, true, 1, 5, 5, Ogre::Vector3::UNIT_Z);
  Ogre::Entity *planeEntity = this->sceneMgr->createEntity("plane","MyPlane");
  planeEntity->setMaterialName("Gazebo/DepthMap");
  //planeEntity->setMaterialName("Gazebo/GrassFloor");
  planeEntity->setCastShadows(false);
  this->sceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(planeEntity);
Pre & Pose render:

Code: Select all

///////////////////////////////////////////////////////////////////////////////
// Pre
void Depth::MyListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
{
  this->depth->sceneMgr->_suppressRenderStateChanges(true);

  // use your depth pass (you could do this manually 
  // using just the render system, but _setPass()
  // is easier if you have a built pass already)
  this->depth->sceneMgr->_setPass(this->depth->depthMaterial->getBestTechnique()->getPass(0), true, false);

  this->depth->renderSys->_setViewport(this->renderTarget->getViewport(0));

  // like said above, _suppressRenderStateChanges(true)
  // also suppresses the camera matrices
  this->depth->renderSys->_setProjectionMatrix(this->depth->camera->getProjectionMatrixRS());
  this->depth->renderSys->_setViewMatrix(this->depth->camera->getViewMatrix(true));
}

///////////////////////////////////////////////////////////////////////////////
// Post
void Depth::MyListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
{
  this->depth->sceneMgr->_suppressRenderStateChanges(false);
  this->depth->renderTarget->writeContentsToTimestampedFile("target", ".png");
}
Vertext Program:

Code: Select all

uniform mat4 worldViewProj;
uniform vec4 texelOffsets;
  
// X = minDepth
// Y = maxDepth
// Z = depthRange
// W = 1.0 / depthRange                                                         uniform vec4 depthRange;

varying vec2 depth;

void main()
{
  gl_Position = ftransform();                                                   
  // fix pixel / texel alignment
  gl_Position.xy += texelOffsets.zw * gl_Position.w;

  // linear depth storage
  // offset / scale range output
  depth.x = (gl_Position.z - depthRange.x) * depthRange.w;
}
Fragment program:

Code: Select all

varying vec2 depth;

void main()
{
  gl_FragColor = vec4(depth.x, depth.x, depth.x, 1);
}
Material script:

Code: Select all

vertex_program Gazebo/DepthMapVS glsl
{
  source DepthMap.vert

  default_params
  {
    param_named_auto worldViewProj worldviewproj_matrix
    param_named_auto texelOffsets texel_offsets
    param_named_auto depthRange scene_depth_range
  }
}

fragment_program Gazebo/DepthMapFS glsl
{
  source DepthMap.frag
  default_params
  {
  }
}

material Gazebo/DepthMap
{
  technique
  {
    pass
    {
      vertex_program_ref Gazebo/DepthMapVS
      {
      }
      fragment_program_ref Gazebo/DepthMapFS
      {
      }
    }
  }
}
}
0 x

User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA

Post by nullsquared » Wed Apr 02, 2008 10:26 pm

Quickest thing I saw, is that you use RGB8 for the render texture - you need floating point textures (for example, PF_FLOAT16_R) to render depth way you are doing now. Not only that, but you then save it as a PNG - not a great way to visualize floating point depth ;).
0 x

natepak
Gnoblar
Posts: 20
Joined: Wed Mar 26, 2008 8:26 pm

Post by natepak » Wed Apr 02, 2008 11:25 pm

I think the vertex shader normalizes the depth to [0..1], and the fragment shader displays the normalized depth value in the R,G, and B components resulting in a shade of gray (or at least it should).

I may not get the same resolution as PF_FLOAT16, but I can at least visualize it as a png.

If I switch to PF_FLOAT16, how do I go about visualizing the result?

Thanks for your help.
0 x

natepak
Gnoblar
Posts: 20
Joined: Wed Mar 26, 2008 8:26 pm

Post by natepak » Thu Apr 03, 2008 12:27 am

So I think I figured out that the scene_depth_range is not being set properly during the update the of the renderTexture. So this brings up two questions:

1) Should I attach a listener to the renderTexture in order to modify the rendering pass so that a depth image is drawn?

2) How does one force the scene_depth_range to be set properly.


I also found that if I attached the DepthMap material to at least on Object in the scene, then the scene_depth_range is set properly. If I only use the DepthMap material for the renderTexture, then it is not set properly.

Any ideas?
0 x

User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA

Post by nullsquared » Thu Apr 03, 2008 1:53 am

Just render the float16 into an Ogre overlay or Rectangle2D or something.

As for the scene_depth_range - I think you're misusing it. The manual is a bit vague, but from personal testing, the depth range Ogre gives you is view-space vector lengths. However, you're using these values to normalize post-projection Z (which can't be linear, either way).
0 x

natepak
Gnoblar
Posts: 20
Joined: Wed Mar 26, 2008 8:26 pm

Post by natepak » Mon Apr 07, 2008 9:10 pm

So, I can now render to a FLOAT32_R texture. However the values get clamped to [0..1]. Is there a way around this? Specifically I need to read the values of the depth map into an array, and it would be nice to have the full range of floats available.
0 x

milacao
Goblin
Posts: 231
Joined: Thu May 08, 2008 10:39 am
Location: Barcelona, Spain

Post by milacao » Fri Jun 13, 2008 3:04 pm

I also want to do this, but I'm a bit confused about the method.

First of all, I tried the method cyanbeck suggests, by creating a material, the shaders, and applying it to each object, by extending their original materials, adding the depth technique and setting it for a second viewport.
But I don't like this method very much, and I thought there should be a better one. Then I found I could do that by rendering to a texture and applying that texture to an overlay set to fill half the screen.
In the meanwhile, I read something about compositors, and saw the example code.
My question is which is the best way to do an effect like this, or to apply full screen render effects. It seems to me that the best way is the use of compositors, but when I try using one of them to apply the depth calculation shader, all I get is a white rectangle (or the background color).
For creating the compositor I just modified the B&W one in Examples.compositor and replaced the material Ogre/Compositor/BlackAndWhite with DepthMap:

Code: Select all

compositor DepthMap
{
    technique
    {
        // Temporary textures
        texture rt0 target_width target_height PF_A8R8G8B8

        target rt0
        {
            // Render output from previous compositor (or original scene)
            input previous
        }

        target_output
        {
            // Start with clear output
            input none
            // Draw a fullscreen quad with the black and white image
            pass render_quad
            {
                // Renders a fullscreen quad with a material
                material DepthMap
                input 0 rt0
            }
        }
    }
}
My shaders are:

Code: Select all

varying vec4 ecPosition;

void main()
{
    ecPosition = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_Position = ftransform();
}
and:

Code: Select all

uniform float fNearDistance;
uniform float fFarDistance;
uniform float fDepthRange;

varying vec4 ecPosition;

void main()
{
    float fColor = 1.0 - smoothstep(fNearDistance, fFarDistance, ecPosition.z);
    gl_FragColor = vec4(vec3(fColor), 1.0);
}
It seems fColor is always 1.0, so the Z value of ecPosition is always 0.

For sure I am doing something wrong, or I am missing some step, or any other thing, but I cannot find what.
Any ideas?
Thanks!
0 x

milacao
Goblin
Posts: 231
Joined: Thu May 08, 2008 10:39 am
Location: Barcelona, Spain

Post by milacao » Mon Jun 16, 2008 10:30 am

No advances yet...
My scene creation code is (two viewports, splitting the screen horizontally, the compositor and two elements, a plane and a sphere):

Code: Select all

        void createScene(void)
        {
            Viewport *vp = mCamera->getViewport();
            mCamera->getViewport()->setDimensions(0.0, 0.0, 0.5, 1.0);
            vp->setBackgroundColour(ColourValue(1.0, 0.0, 0.0));
            vp = mWindow->addViewport(mCamera, 1, 0.5, 0.0, 0.5, 1.0);
            vp->setBackgroundColour(ColourValue(1.0, 1.0, 0.0));

            createDepthRenderTexture();
            CompositorInstance* pCompositor = CompositorManager::getSingleton().addCompositor(mWindow->getViewport(1), "DepthMap");
            CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(1), "DepthMap", true);
            pCompositor->getTechnique()->getTargetPass(0)->setInputMode(CompositionTargetPass::IM_PREVIOUS);

        // light creation, irrelevant

        // Create the scene node
            SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode1", Vector3(0, 0, 0));
            node->attachObject(mCamera);

            MeshPtr pMesh = MeshManager::getSingleton().createPlane("Plane",
                    ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
                    Plane(Vector3(0.0f, 1.0f, 0.0f), 0.0f),
                          500.0, 500.0, 100, 100, true, 1, 1, 1, Vector3::NEGATIVE_UNIT_Z);
            Entity* pPlaneEntity = mSceneMgr->createEntity("PlaneEntity", "Plane");
            SceneNode* pSceneNodePlane = mSceneMgr->getRootSceneNode()->createChildSceneNode("PlaneNode");
            pSceneNodePlane->attachObject(pPlaneEntity);
            pPlaneEntity->setMaterialName("Document");

            Entity* pSphereEntity = mSceneMgr->createEntity("SphereEntity", SceneManager::PT_SPHERE);
            SceneNode* pSceneNodeSphere = mSceneMgr->getRootSceneNode()->createChildSceneNode("SphereNode");
            pSceneNodeSphere->attachObject(pSphereEntity);
            pSceneNodeSphere->translate(0.0f, 60.0f, 0.0f);
            pSphereEntity->setMaterialName("PlanetMap");
        }
}
The method for creating the RTT is exactly the same as in the DoF demo, just changing the names of the materials.

Any suggestions? Any idea would be usefull :-)
Thanks!
0 x

milacao
Goblin
Posts: 231
Joined: Thu May 08, 2008 10:39 am
Location: Barcelona, Spain

[Solved] How to render the Z-buffer to a Texture

Post by milacao » Thu Jul 03, 2008 2:36 pm

Hi all,
I finally achieved what I wanted time ago, but I forgot to post the solution. I hope this helps anyone in the future.

I have this materials:

Code: Select all

material DepthMap
{
    technique
    {
        pass
        {
            fragment_program_ref FragmentDepthMap
            {
                param_named_auto fNear near_clip_distance
                param_named_auto fFar far_clip_distance
            }
        }
    }
}

material Sampler
{
    technique
    {
        pass
        {
            fragment_program_ref FragmentSampler
            {
            }
            texture_unit
            {
                tex_coord_set 0
                tex_address_mode clamp
                filtering trilinear
            }
        }
    }
}
This fragment shader for the depth map calculation:

Code: Select all

uniform float fNear;
uniform float fFar;

void main()
{
    float fDepth = gl_FragCoord.z / gl_FragCoord.w;
    float fColor = 1.0 - smoothstep(fNear, fFar, fDepth);
    gl_FragColor = vec4(vec3(fColor), 1.0);
}
The shaders's definitions:

Code: Select all

fragment_program FragmentDepthMap glsl
{
	source depthmap.frag
}

fragment_program FragmentSampler glsl
{
    source sampler.frag
    default_params
    {
        param_named Depth int 0
    }
}
The second shader for using the RTT:

Code: Select all

uniform sampler2D Depth;

void main()
{
    gl_FragColor = texture2D(Depth, gl_TexCoord[0].xy);
}
And the compositor:

Code: Select all

compositor DepthMap
{
    technique
    {
        // Temporary textures
        texture rt0 target_width target_height PF_A8R8G8B8

        target rt0
        {
            // Render output from previous compositor (or original scene)
            input previous
        }

        target_output
        {
            // Start with clear output
            input none

            // Draw a fullscreen quad with the black and white image
            pass render_quad
            {
                // Renders a fullscreen quad with a material
                material Sampler
                input 0 rt0
            }
        }
    }
}
The code for the creation of the RTT applying the shader to the whole scene:

Code: Select all

        void createDepthRenderTexture()
        {
    // Create the depth render texture
            TexturePtr depthTexture = TextureManager::getSingleton().createManual(
                    "NinjaDepthMap", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
                    TEX_TYPE_2D, mCamera->getViewport()->getActualWidth(), mCamera->getViewport()->getActualHeight(),
                            0, PF_FLOAT16_R, TU_RENDERTARGET);

    // Get its render target and add a viewport to it
            depthTarget = depthTexture->getBuffer()->getRenderTarget();
            Viewport* depthViewport = depthTarget->addViewport(pCamera, 40);
            depthViewport->setBackgroundColour(ColourValue::Black);

    // Register 'this' as a render target listener
            depthTarget->addListener(this);

    // Get the technique to use when rendering the depth render texture
            MaterialPtr mDepthMaterial = MaterialManager::getSingleton().getByName("DepthMap");
            mDepthMaterial->load(); // needs to be loaded manually
            mDepthTechnique = mDepthMaterial->getBestTechnique();

    // Create a custom render queue invocation sequence for the depth render texture
            RenderQueueInvocationSequence* invocationSequence =
                    Root::getSingleton().createRenderQueueInvocationSequence("DepthMap");

    // Add a render queue invocation to the sequence, and disable shadows for it
            RenderQueueInvocation* invocation = invocationSequence->add(RENDER_QUEUE_MAIN, "main");
            invocation->setSuppressShadows(true);

    // Set the render queue invocation sequence for the depth render texture viewport
            depthViewport->setRenderQueueInvocationSequenceName("DepthMap");
            depthViewport2->setRenderQueueInvocationSequenceName("DepthMap");
        }
As the last step, add the code to add and enable the compositor and that's all :-)
Cheers!
0 x

plies
Kobold
Posts: 31
Joined: Tue Jul 01, 2008 3:17 pm

Post by plies » Fri Jul 11, 2008 4:01 pm

Is this the only way to obtain a depth map? Because when I use your approach my application crashes without error message as does the Deferred demo. So I would guess my system does not support the shading stuff.

Isn't it possible to bypass ogre and access directly the opengl GL_DEPTH_COMPONENT for a given viewport?

Alternatively I would code a ray tracer which creates a depth map, or can someone imagine why demo and code crash w/o message? All other demos work perfectly.
0 x

milacao
Goblin
Posts: 231
Joined: Thu May 08, 2008 10:39 am
Location: Barcelona, Spain

Post by milacao » Fri Jul 11, 2008 6:24 pm

It is said in a previous message it's not possible to access that freely the GL_DEPTH_COMPONENT, and I haven't found any way. So it seems the proper way is through shaders.
But this is what I've done with Eihort. Shoggoth provides a mechanism to use a material to render all objects in the scene, so I'll try it when I install 1.6 :-)
0 x

plies
Kobold
Posts: 31
Joined: Tue Jul 01, 2008 3:17 pm

Post by plies » Fri Jul 11, 2008 7:38 pm

ok, since I need the depth map system by next weeks friday, I'll code the ray tracer. I'll post the code as soon as the system works 8)
0 x

milacao
Goblin
Posts: 231
Joined: Thu May 08, 2008 10:39 am
Location: Barcelona, Spain

Post by milacao » Mon Jul 14, 2008 7:30 am

In my opinion that will be far more complicated, but let us know :-) Will you cast rays for each vertex? how will you deal with inter-vertex regions?
Good luck!
0 x

plies
Kobold
Posts: 31
Joined: Tue Jul 01, 2008 3:17 pm

Post by plies » Wed Jul 16, 2008 1:44 pm

Hi,

ray tracer works perfectly, the results are precisely what I needed.
Image
Performance is crap, ~5sec per frame on my machine (some Mac thing running Linux), but since I don't need the depth map for every frame but only at specific positions it's fine for me.

The approach is quite simple. I send a ray through every pixel of the viewport and collect all bounding boxes the ray hits (as DefaultRaySceneQuery does). Then I iterate through the BB list (ordered in ascending distance), grep the mesh of the object and compute the intersection of ray with every triangle. The shortest distance is taken as depth value, or the far clipping distance if no triangle was hit.

I need to optimize and clean the code a bit, then I'll share it.

edit: I think I won't be able to provide a commonly usable version but if someone needs my code just send me a pn.
Last edited by plies on Tue Sep 16, 2008 6:10 pm, edited 1 time in total.
0 x

milacao
Goblin
Posts: 231
Joined: Thu May 08, 2008 10:39 am
Location: Barcelona, Spain

Post by milacao » Wed Jul 16, 2008 2:01 pm

:shock: Well, the algorithm seems to be very very heavy in terms of processing power (although conceptually is very simple). In this case you don't need the map every frame, but I think you should consider changing to shaders, where you will have a much simpler and faster algorithm. As an example, in my machine (P4@2.8GHz, NVidia 7600 GT), your scene would run at more or less 180 FPS :)
0 x

plies
Kobold
Posts: 31
Joined: Tue Jul 01, 2008 3:17 pm

Post by plies » Wed Jul 16, 2008 4:58 pm

There are 3 problems:
1. Changing the material for each object as proposed before is a pain in the a...
2. The shader demo and my app with your shader code crashes w/o error message and sometimes kills the complete xserver so there must be a hw/driver issue.
3. When I did 3D programming there were no shaders (OpenGL 1.2 or 1.3 was state-of-the-art :D) and I don't want to read into shader programming since I won't need it anymore

Maybe I give the shaders a shot once problem 1 is solved by Shoggoth and hopefully problem 2 will then be solved too.
0 x

User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA

Post by nullsquared » Wed Jul 16, 2008 5:12 pm

When worst comes to worst, why not just use a material scheme?
0 x

milacao
Goblin
Posts: 231
Joined: Thu May 08, 2008 10:39 am
Location: Barcelona, Spain

Post by milacao » Wed Jul 16, 2008 8:23 pm

I don't want to read into shader programming since I won't need it anymore
You should never say something like "I won't ever drink this water" (a typical Spanish say, perhaps not a proper translation :) ) What I mean is that, with the modern advances in GPUs, saying NO cathegorically to GPU programming, IMHO is an error, since it is more and more used, and for instance, as far as I know, Microsoft is planning to remove some parts of the fixed pipeline.

Edit: Sorry, I think I'm going a bit off-topic :) Forget this message...
0 x

Post Reply