How to render the Z-buffer to a Texture
-
- Gnoblar
- Posts: 2
- Joined: Tue Jan 08, 2008 10:23 pm
How to render the Z-buffer to a Texture
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.
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.
- Falagard
- OGRE Retired Moderator
- Posts: 2060
- Joined: Thu Feb 26, 2004 12:11 am
- Location: Toronto, Canada
- x 3
- Contact:
-
- Gnoblar
- Posts: 2
- Joined: Tue Jan 08, 2008 10:23 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.
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.
- cyanbeck
- Gnoblar
- Posts: 8
- Joined: Tue Nov 02, 2004 3:20 pm
- x 1
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.
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.
3. In your cpp code, for those objects you want to calculate their depth,
call
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);
}
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
{
}
}
}
}
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.
- cyanbeck
- Gnoblar
- Posts: 8
- Joined: Tue Nov 02, 2004 3:20 pm
- x 1
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
2. Create the corresponding material for RTT
3. Refresh the content of RTT every frame if the scene is dynamic.
OK, it's all done.
I am new to OGRE, too. If there is any error, feel free to correct.
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);
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);
Code: Select all
TexturePtr texPtr = TextureManager::getSingleton().getByName("DepthMap");
RenderTexture* depth_map = texPtr->getBuffer()->getRenderTarget();
depth_map->update();
I am new to OGRE, too. If there is any error, feel free to correct.
-
- Gnoblar
- Posts: 20
- Joined: Wed Mar 26, 2008 8:26 pm
- x 1
easier way??
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.
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.
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
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);
-
- Gnoblar
- Posts: 20
- Joined: Wed Mar 26, 2008 8:26 pm
- x 1
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:
Create the scene (a plane with 2 Ogre heads):
Pre & Pose render:
Vertext Program:
Fragment program:
Material script:
}
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 );
}
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);
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");
}
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;
}
Code: Select all
varying vec2 depth;
void main()
{
gl_FragColor = vec4(depth.x, depth.x, depth.x, 1);
}
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
{
}
}
}
}
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
-
- Gnoblar
- Posts: 20
- Joined: Wed Mar 26, 2008 8:26 pm
- x 1
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.
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.
-
- Gnoblar
- Posts: 20
- Joined: Wed Mar 26, 2008 8:26 pm
- x 1
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?
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?
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
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).
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).
-
- Gnoblar
- Posts: 20
- Joined: Wed Mar 26, 2008 8:26 pm
- x 1
-
- Goblin
- Posts: 231
- Joined: Thu May 08, 2008 10:39 am
- Location: Barcelona, Spain
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:
My shaders are:
and:
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!
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
}
}
}
}
Code: Select all
varying vec4 ecPosition;
void main()
{
ecPosition = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = ftransform();
}
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);
}
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!
-
- Goblin
- Posts: 231
- Joined: Thu May 08, 2008 10:39 am
- Location: Barcelona, Spain
No advances yet...
My scene creation code is (two viewports, splitting the screen horizontally, the compositor and two elements, a plane and a sphere):
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!
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");
}
}
Any suggestions? Any idea would be usefull
Thanks!
-
- Goblin
- Posts: 231
- Joined: Thu May 08, 2008 10:39 am
- Location: Barcelona, Spain
[Solved] How to render the Z-buffer to a Texture
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:
This fragment shader for the depth map calculation:
The shaders's definitions:
The second shader for using the RTT:
And the compositor:
The code for the creation of the RTT applying the shader to the whole scene:
As the last step, add the code to add and enable the compositor and that's all
Cheers!
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
}
}
}
}
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);
}
Code: Select all
fragment_program FragmentDepthMap glsl
{
source depthmap.frag
}
fragment_program FragmentSampler glsl
{
source sampler.frag
default_params
{
param_named Depth int 0
}
}
Code: Select all
uniform sampler2D Depth;
void main()
{
gl_FragColor = texture2D(Depth, gl_TexCoord[0].xy);
}
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
}
}
}
}
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");
}
Cheers!
-
- Kobold
- Posts: 31
- Joined: Tue Jul 01, 2008 3:17 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.
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.
-
- Goblin
- Posts: 231
- Joined: Thu May 08, 2008 10:39 am
- Location: Barcelona, Spain
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
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
-
- Kobold
- Posts: 31
- Joined: Tue Jul 01, 2008 3:17 pm
Hi,
ray tracer works perfectly, the results are precisely what I needed.
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.
ray tracer works perfectly, the results are precisely what I needed.
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.
-
- Goblin
- Posts: 231
- Joined: Thu May 08, 2008 10:39 am
- Location: Barcelona, Spain
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
-
- Kobold
- Posts: 31
- Joined: Tue Jul 01, 2008 3:17 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 ) 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.
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 ) 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.
- nullsquared
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
-
- Goblin
- Posts: 231
- Joined: Thu May 08, 2008 10:39 am
- Location: Barcelona, Spain
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.I don't want to read into shader programming since I won't need it anymore
Edit: Sorry, I think I'm going a bit off-topic Forget this message...