[SOLVED] Ogre3d World, View, Projection Matrices

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
Post Reply
nickygs
Gnoblar
Posts: 15
Joined: Wed Jul 20, 2016 7:55 pm

[SOLVED] Ogre3d World, View, Projection Matrices

Post by nickygs »

I am trying to access the World, view and projection matrices in the ogre code.

I think the projection matrix is obtained by

Code: Select all

 mCamera->getProjectionMatrix();
and the view matrix by

Code: Select all

mCamera->getViewMatrix();
In the doc these are specified as the projection/view matrices of the frustum respectively.

I absolutely do not know how to get the world matrix.

Can someone please confirm that the projection/view matrix is the same as the projection/view matrix of the frustum. A hint at how I can get the world view matrix would be appreciated.
Last edited by nickygs on Wed Mar 01, 2017 7:26 pm, edited 1 time in total.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Ogre3d World, View, Projection Matrices

Post by dark_sylinc »

Ogre 1.x you get the World transform via Renderable::getWorldTransforms
Ogre 2.1 you get the World transform via Node::_getFullTransform
Can someone please confirm that the projection/view matrix is the same as the projection/view matrix of the frustum
I don't know what you mean by this.
Projection matrices may have different variants though, depending on whether you want one using Ogre conventions, or one specific to the RenderSystem you're rendering to (getProjectionMatrixRS, getProjectionMatrixWithRSDepth).
nickygs
Gnoblar
Posts: 15
Joined: Wed Jul 20, 2016 7:55 pm

Re: Ogre3d World, View, Projection Matrices

Post by nickygs »

Thanks for the reply @dark_sylic, well really I am asking these questions for a bigger problem I am tackling.

What I mean by:
Can someone please confirm that the projection/view matrix is the same as the projection/view matrix of the frustum
is that generally when reading online about the projection matrix and the view matrix it does not ever specify it belonging to a frustum. I believe that the quoted question is somewhat stupid :P

The real thing I am after is reconstructing points from a sampled depth map. This query can however be seen in a separate post if you wish to have a look :)
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Ogre3d World, View, Projection Matrices

Post by dark_sylinc »

nickygs wrote:The real thing I am after is reconstructing points from a sampled depth map. This query can however be seen in a separate post if you wish to have a look :)

Code: Select all

Matrix4 projMat = camera->getProjectionMatrixRS();
Matrix4 viewMat = camera->getViewMatrix();

Matrix4 wvp = projMat * viewMat * worldMat;
Matrix4 inverseWvp = wvp.inverse();

// x & y are in range [-1; 1]; depthFromDepthBuffer is the value you got from the depth buffer.
Vector4 clipSpaceValue( x, y, depthFromDepthBuffer, 1.0f );
Vector4 worldPos = inverseWvp * clipSpaceValue;
worldPos /= worldPos.w;
//Now worldPos has the value you were looking for.
nickygs
Gnoblar
Posts: 15
Joined: Wed Jul 20, 2016 7:55 pm

Re: Ogre3d World, View, Projection Matrices

Post by nickygs »

In fact my code is quite similar, I have made it slightly cleaner after seeing yours :)

ok so I am creating my depth texture using

Code: Select all

//-----------------------------------------------------------------------------------
// Vertex shader
//-----------------------------------------------------------------------------------
void mainVP( 
   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; 
}

//-----------------------------------------------------------------------------------
// Fragment shader
//-----------------------------------------------------------------------------------
void mainFP( 
   float2 depth      : TEXCOORD0, 
   out float4 result : COLOR) 
    
{ 
   float finalDepth = depth.x; 
   result = float4(finalDepth, finalDepth, finalDepth, 1); 
} 
parameters set are

Code: Select all

 vertexParams->setNamedAutoConstant("worldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); // Must be same name as in pu_depth.hlsl
      vertexParams->setNamedAutoConstant("texelOffsets", Ogre::GpuProgramParameters::ACT_TEXEL_OFFSETS); // Must be same name as in pu_depth.hlsl
      vertexParams->setNamedAutoConstant("depthRange", Ogre::GpuProgramParameters::ACT_SCENE_DEPTH_RANGE); // Must be same name as in pu_depth.hlsl
After I get the depth image I try to reconstruct some sampled points from sampled depth values using the following code

Code: Select all

Ogre::ColourValue depth = pb.getColourAt(sampledX, sampledY,0);
	Ogre::Real alpha = 1;//must be added to do matrix multplication with vector 4x4 time 4x1
	Ogre::Real texCoordx = sampledX / (mDepthMap->getWidth()-1);
	Ogre::Real texCoordy = sampledY / (mDepthMap->getHeight()-1);


        Ogre::Real remappedX = (texCoordx *2) -1;
	Ogre::Real remappedY = (texCoordy * 2) - 1;
	Ogre::Real depthZ = depth.g;

	Ogre::Vector4 clipSpaceValue(remappedX, remappedY, depthZ, alpha);
	//matrices represented as column vectors, evaluation right to left, standard math convention

	Ogre::Matrix4 perspProj= createPerspProjMatrix();//using this because it has to be done manually since a shader is not being used http://www.codinglabs.net/article_world_view_projection_matrix.aspx
	Ogre::Matrix4  projectionMat = mCamera->getProjectionMatrixRS();//frustrum projection matrix
	Ogre::Matrix4 viewMat = mCamera->getViewMatrix();//frustrum view matrix
	Ogre::Matrix4 worldMat = depthMapNode->_getFullTransform();

	Ogre::Matrix4 worldViewProjPersp = perspProj*projectionMat*viewMat*worldMat;
	Ogre::Matrix4 inverseWorldViewProjPersp = worldViewProjPersp.inverse();

	Ogre::Vector4 position = inverseWorldViewProjPersp * clipSpaceValue;
	position/= position.w;
Since I am using direct3D9 the depth values are between [0,1], the projection matrix should be keeping this in mind since the rendering system is the same.
I think the problem is with some calculation I am not taking care of due to the way the shader is implemented.
nickygs
Gnoblar
Posts: 15
Joined: Wed Jul 20, 2016 7:55 pm

Re: Ogre3d World, View, Projection Matrices

Post by nickygs »

I seem to have figured out why my approach is not working, the shader is using linear depth which requires a different process to get back the position. Some help with this would be appreciated as I am slightly lost.


Shader source code used.

Code: Select all

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);
 
    // fix pixel / texel alignment
    outPos.xy += texelOffsets.zw * outPos.w;
    // linear depth storage
    // offset / scale range output
#if LINEAR_RANGE
    outDepth.x = (outPos.z - depthRange.x) * depthRange.w;
#else
    outDepth.x = outPos.z;
#endif
    outDepth.y = outPos.w;
}
 
// Shadow caster fragment program for high-precision single-channel textures    
void casterFP(
    float2 depth            : TEXCOORD0,
    out float4 result        : COLOR)
 
{
#if LINEAR_RANGE
    float finalDepth = depth.x;
#else
    float finalDepth = depth.x / depth.y;
#endif
    // just smear across all components 
    // therefore this one needs high individual channel precision
    result = float4(finalDepth, finalDepth, finalDepth, 1);
}
I managed to get it to work using "basic" depth by changing the shader slightly and not using the perspective Matrix. However, I would like to get it to work using Linear Depth as it will give me more precision when reconstructing the positions.
arkeon
Goblin
Posts: 272
Joined: Fri Dec 04, 2009 6:02 pm
x 38

Re: [SOLVED] Ogre3d World, View, Projection Matrices

Post by arkeon »

Hello,

could you please provide a complete working code ?
I'm also trying to reconstruct the 3D position from the depth pixel value, but I keep the viewspace and use a ray to get the source position.
It's almost working but I hate maths and I don't really understand why the precision is perfect on the middle of the screen but loose on the sides.
I think I have to manage the perspective matrix but I don't understand what your "createPerspProjMatrix" do.

here my shader code (I use MRT for subentity selection) :

Code: Select all


float4 pack(float value)
{
  float4 shift = float4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
  float4 mask = float4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
  float4 ret = frac(value * shift);
  ret -= ret.xxyz * mask;
  return ret.wzyx;
}

 // vertex shader main entry
void main_plain_color_vp(
  float4 position: POSITION,
  out float4 oPos: POSITION,
  out float4 oColor: TEXCOORD0,
  out float2 oDepth: TEXCOORD1,
	uniform float4x4 worldViewProj,
  uniform float4 texelOffsets,
  uniform float4 inColor
	)
{
  oPos = mul(worldViewProj, position); // calculate output coords
  oPos.xy += texelOffsets.zw * oPos.w;
  oDepth = oPos.zw;
  
  oColor = inColor;
}
 
void main_plain_color_fp(
  float4 position: POSITION,
  float4 iColor: TEXCOORD0,
  float2 iDepth: TEXCOORD1,
  out float4 Colour0 : COLOR0,
	out float4 Colour1 : COLOR1
  )
{
  Colour0 = iColor;
  
  //depth mrt
  float fdepth = iDepth.x / iDepth.y;
  Colour1 = pack(fdepth);
}
part that retrieve the depth pixel value (it's a 1x1 texture for performances)

Code: Select all

      Ogre::Pass* pickerPass = pickerTech->getPass(0);
      Ogre::GpuProgramParametersSharedPtr fparams = pickerPass->getFragmentProgramParameters();
      fparams->setNamedConstant("inMouse", mousePos);

      pickerPass->getTextureUnitState(0)->setTexture(mOgreDepthTexture);

      mOgrePickerRenderTexture->update();
      mOgrePickerRenderTexture->copyContentsToMemory(Ogre::Box(0, 0, 1, 1), *mOgrePixelBox, Ogre::RenderTarget::FB_AUTO);

      ogreColour = mOgrePixelBox->getColourAt(0, 0, 0);

      //unpack RGBA to float
      Ogre::Vector4 shift(1.0f / (256.0f * 256.0f * 256.0f), 1.0f / (256.0f * 256.0f), 1.0f / 256.0f, 1.0f);
      zpos = Ogre::Vector4(ogreColour.a, ogreColour.b, ogreColour.g, ogreColour.r).dotProduct(shift);
and finally my fail code to reconstruct

Code: Select all

          Ogre::Matrix4 wvp = camera->getProjectionMatrixRS();

          // x & y are in range [-1; 1]; zdepth is the value you got from the depth buffer.
          Ogre::Vector4 clipSpaceValue(xR * 2.0f - 1.0f, yR * 2.0f - 1.0f, zdepth, 1.0f);
          Ogre::Vector4 viewPos = wvp.inverse() * clipSpaceValue;
          viewPos /= viewPos.w;

          Ogre::Ray ray = camera->getCameraToViewportRay(xR, yR);
          pos = ray.getOrigin() + (ray.getDirection() * viewPos.z);
OpenSpace 3D Project manager
http://www.openspace3d.com
arkeon
Goblin
Posts: 272
Joined: Fri Dec 04, 2009 6:02 pm
x 38

Re: [SOLVED] Ogre3d World, View, Projection Matrices

Post by arkeon »

I finally found the correct way to get the world position from linear depth

Shader code

Code: Select all

float4 pack(float value)
{
  float4 shift = float4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
  float4 mask = float4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
  float4 ret = frac(value * shift);
  ret -= ret.xxyz * mask;
  return ret.wzyx;
}

 // vertex shader main entry
void main_plain_color_vp(
  float4 position: POSITION,
  out float4 oPos: POSITION,
  out float4 oColor: TEXCOORD0,
  out float oDepth: TEXCOORD1,
  uniform float4x4 worldViewProj,
  uniform float4 texelOffsets,
  uniform float4 inColor
	)
{
  oPos = mul(worldViewProj, position); // calculate output coords
  oPos.xy += texelOffsets.zw * oPos.w;
  oDepth = oPos.z;
  
  oColor = inColor;
}
 
void main_plain_color_fp(
  float4 position: POSITION,
  float4 iColor: TEXCOORD0,
  float iDepth: TEXCOORD1,
  uniform float nearclip,
  uniform float farclip,
  out float4 Colour0 : COLOR0,
  out float4 Colour1 : COLOR1
  )
{
  Colour0 = iColor;
  
  //depth mrt
  Colour1 = pack((iDepth - nearclip.x) / (farclip - nearclip));
}
Get the depth pixel value

Code: Select all

      Ogre::Pass* pickerPass = pickerTech->getPass(0);
      Ogre::GpuProgramParametersSharedPtr fparams = pickerPass->getFragmentProgramParameters();
      fparams->setNamedConstant("inMouse", mousePos);

      pickerPass->getTextureUnitState(0)->setTexture(mOgreDepthTexture);

      mOgrePickerRenderTexture->update();
      mOgrePickerRenderTexture->copyContentsToMemory(Ogre::Box(0, 0, 1, 1), *mOgrePixelBox, Ogre::RenderTarget::FB_AUTO);

      ogreColour = mOgrePixelBox->getColourAt(0, 0, 0);

      //unpack RGBA to float
      Ogre::Vector4 shift(1.0f / (256.0f * 256.0f * 256.0f), 1.0f / (256.0f * 256.0f), 1.0f / 256.0f, 1.0f);
      zpos = Ogre::Vector4(ogreColour.a, ogreColour.b, ogreColour.g, ogreColour.r).dotProduct(shift);
convert to world pos

Code: Select all

          //restore view distance from linear depth
          zdepth *= camera->getFarClipDistance() - camera->getNearClipDistance();
          zdepth += camera->getNearClipDistance();
          
          // x & y are in range [-1; 1];
          Ogre::Real nx = (2.0f * xR) - 1.0f;
          Ogre::Real ny = 1.0f - (2.0f * yR);
          Ogre::Vector3 nearPoint(nx, ny, -1.0f);
          Ogre::Vector3 midPoint(nx, ny, 0.0f);
          
          //get ray world position and direction
          Ogre::Matrix4 invViewMat = (camera->getProjectionMatrix() * camera->getViewMatrix(true)).inverse();
          Ogre::Vector3 rayOrigin = invViewMat * nearPoint;
          Ogre::Vector3 rayDirection = (invViewMat * midPoint) - rayOrigin;
          rayDirection.normalise();
          
          // get new distance for ray direction
          // A B C triangle : tan(fov / 2) gives AB : AC is depth : then use pythagore to get hypotenuse BC
          double ylenght = Ogre::Math::Tan(camera->getFOVy().valueRadians() * 0.5);
          double xlenght = ylenght * camera->getAspectRatio();
          double opx = zdepth * abs(xlenght * nx);
          double opy = zdepth * abs(ylenght * ny);
          zdepth = Ogre::Math::Sqrt((zdepth * zdepth) + (opx * opx) + (opy * opy));
          pos = rayOrigin + (rayDirection * zdepth);
OpenSpace 3D Project manager
http://www.openspace3d.com
arkeon
Goblin
Posts: 272
Joined: Fri Dec 04, 2009 6:02 pm
x 38

Re: [SOLVED] Ogre3d World, View, Projection Matrices

Post by arkeon »

Any idea how to manage orthographic camera the same way ?
OpenSpace 3D Project manager
http://www.openspace3d.com
Post Reply