Skip to content

Commit acdfd09

Browse files
committed
Use clipping distance for minimum LIDAR distance
Using Hlms custom pieces and a listener to implement it See changes to Ogre2GpuRays::Render for usage Update ogre2/src/media/Hlms/Pbs/GLSL/VertexShader_vs.glsl to latest upstream version Signed-off-by: Matias N. Goldberg <[email protected]>
1 parent 41dd82d commit acdfd09

8 files changed

+299
-2
lines changed

ogre2/include/ignition/rendering/ogre2/Ogre2RenderEngine.hh

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ namespace ignition
4848
//
4949
// forward declaration
5050
class Ogre2RenderEnginePrivate;
51+
class Ogre2IgnHlmsCustomizations;
5152

5253
/// \brief Plugin for loading ogre render engine
5354
class IGNITION_RENDERING_OGRE2_VISIBLE Ogre2RenderEnginePlugin :
@@ -163,6 +164,9 @@ namespace ignition
163164
/// \return a list of FSAA levels
164165
public: std::vector<unsigned int> FSAALevels() const;
165166

167+
/// \brief Retrieves Hlms customizations for tweaking them
168+
public: Ogre2IgnHlmsCustomizations& HlmsCustomizations();
169+
166170
/// \internal
167171
/// \brief Get a pointer to the Ogre overlay system.
168172
/// \return Pointer to the ogre overlay system.

ogre2/src/Ogre2GpuRays.cc

+8
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "ignition/rendering/ogre2/Ogre2Sensor.hh"
3535
#include "ignition/rendering/ogre2/Ogre2Visual.hh"
3636

37+
#include "Ogre2IgnHlmsCustomizations.hh"
3738
#include "Ogre2ParticleNoiseListener.hh"
3839

3940
namespace ignition
@@ -1090,8 +1091,15 @@ void Ogre2GpuRays::UpdateRenderTarget2ndPass()
10901091
//////////////////////////////////////////////////
10911092
void Ogre2GpuRays::Render()
10921093
{
1094+
auto engine = Ogre2RenderEngine::Instance();
1095+
Ogre2IgnHlmsCustomizations &hlmsCustomizations =
1096+
engine->HlmsCustomizations();
1097+
1098+
hlmsCustomizations.minDistanceClip =
1099+
static_cast<float>(this->NearClipPlane());
10931100
this->UpdateRenderTarget1stPass();
10941101
this->UpdateRenderTarget2ndPass();
1102+
hlmsCustomizations.minDistanceClip = -1;
10951103
}
10961104

10971105
//////////////////////////////////////////////////
+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (C) 2021 Open Source Robotics Foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
#include "Ogre2IgnHlmsCustomizations.hh"
19+
20+
#ifdef _MSC_VER
21+
#pragma warning(push, 0)
22+
#endif
23+
#include <OgreCamera.h>
24+
#include <OgreHlms.h>
25+
#include <OgreRenderTarget.h>
26+
#include <OgreSceneManager.h>
27+
#include <OgreViewport.h>
28+
#ifdef _MSC_VER
29+
#pragma warning(pop)
30+
#endif
31+
32+
using namespace ignition;
33+
using namespace rendering;
34+
35+
//////////////////////////////////////////////////
36+
void Ogre2IgnHlmsCustomizations::preparePassHash(
37+
const Ogre::CompositorShadowNode */*_shadowNode*/,
38+
bool _casterPass, bool /*_dualParaboloid*/,
39+
Ogre::SceneManager */*_sceneManager*/,
40+
Ogre::Hlms *_hlms)
41+
{
42+
this->needsWorldPos = false;
43+
if (!_casterPass && this->MinDistanceClipEnabled())
44+
{
45+
const Ogre::int32 numClipPlanes =
46+
_hlms->_getProperty("hlms_pso_clip_distances");
47+
_hlms->_setProperty( "ign_spherical_clip_min_distance", 1 );
48+
_hlms->_setProperty( "ign_spherical_clip_idx", numClipPlanes );
49+
_hlms->_setProperty( "hlms_pso_clip_distances", numClipPlanes + 1 );
50+
51+
if (_hlms->getType() == Ogre::HLMS_UNLIT)
52+
{
53+
if (_hlms->_getProperty("hlms_global_clip_planes") == 0)
54+
{
55+
this->needsWorldPos = true;
56+
_hlms->_setProperty( "ign_spherical_clip_needs_worldPos", 1 );
57+
}
58+
}
59+
}
60+
}
61+
62+
//////////////////////////////////////////////////
63+
Ogre::uint32 Ogre2IgnHlmsCustomizations::getPassBufferSize(
64+
const Ogre::CompositorShadowNode */*_shadowNode*/,
65+
bool _casterPass, bool /*_dualParaboloid*/,
66+
Ogre::SceneManager */*_sceneManager*/) const
67+
{
68+
if (_casterPass || !this->MinDistanceClipEnabled())
69+
return 0u;
70+
71+
Ogre::uint32 bufferSize = sizeof(float) * 4u;
72+
if (this->needsWorldPos)
73+
bufferSize += sizeof(float) * 16u;
74+
75+
return bufferSize;
76+
}
77+
78+
//////////////////////////////////////////////////
79+
float* Ogre2IgnHlmsCustomizations::preparePassBuffer(
80+
const Ogre::CompositorShadowNode */*_shadowNode*/,
81+
bool _casterPass, bool /*_dualParaboloid*/,
82+
Ogre::SceneManager *_sceneManager,
83+
float *_passBufferPtr)
84+
{
85+
if (!_casterPass && this->MinDistanceClipEnabled())
86+
{
87+
Ogre::Camera *camera = _sceneManager->getCameraInProgress();
88+
const Ogre::Vector3 &camPos = camera->getDerivedPosition();
89+
90+
// float4 ignMinClipDistance_ignCameraPos
91+
*_passBufferPtr++ = this->minDistanceClip;
92+
*_passBufferPtr++ = camPos.x;
93+
*_passBufferPtr++ = camPos.y;
94+
*_passBufferPtr++ = camPos.z;
95+
96+
if (this->needsWorldPos)
97+
{
98+
// TODO(dark_sylinc): Modify Ogre to access HlmsUnlit::mPreparedPass
99+
// so we get the view matrix that's going to be used instead of
100+
// recalculating everything again (which can get complex if VR is
101+
// being used)
102+
const Ogre::RenderTarget *renderTarget =
103+
_sceneManager->getCurrentViewport()->getTarget();
104+
Ogre::Matrix4 projectionMatrix =
105+
camera->getProjectionMatrixWithRSDepth();
106+
if( renderTarget->requiresTextureFlipping() )
107+
{
108+
projectionMatrix[1][0] = -projectionMatrix[1][0];
109+
projectionMatrix[1][1] = -projectionMatrix[1][1];
110+
projectionMatrix[1][2] = -projectionMatrix[1][2];
111+
projectionMatrix[1][3] = -projectionMatrix[1][3];
112+
}
113+
114+
Ogre::Matrix4 invViewProj = (projectionMatrix *
115+
camera->getViewMatrix(true)).inverse();
116+
for (size_t i = 0; i < 16u; ++i)
117+
*_passBufferPtr++ = static_cast<float>(invViewProj[0][i]);
118+
}
119+
}
120+
return _passBufferPtr;
121+
}
+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright (C) 2021 Open Source Robotics Foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
#ifndef IGNITION_RENDERING_OGRE2_OGRE2IGNHLMSCUSTOMIZATIONS_HH_
19+
#define IGNITION_RENDERING_OGRE2_OGRE2IGNHLMSCUSTOMIZATIONS_HH_
20+
21+
#include "ignition/rendering/config.hh"
22+
#include "ignition/rendering/ogre2/Export.hh"
23+
24+
#ifdef _MSC_VER
25+
#pragma warning(push, 0)
26+
#endif
27+
#include <OgreHlmsListener.h>
28+
#ifdef _MSC_VER
29+
#pragma warning(pop)
30+
#endif
31+
32+
namespace ignition
33+
{
34+
namespace rendering
35+
{
36+
inline namespace IGNITION_RENDERING_VERSION_NAMESPACE {
37+
//
38+
/// \brief Controls custom shader snippets of Hlms (both Pbs and Unlit):
39+
///
40+
/// - Toggles them on/off
41+
/// - Sends relevant data to the GPU buffers for shaders to use
42+
///
43+
/// This listener requires Hlms to have been created with the piece data
44+
/// files in ogre2/src/media/Hlms/Ignition registered
45+
///
46+
/// \internal
47+
/// \remark Public variables take effect immediately (i.e. for the
48+
/// next render)
49+
class IGNITION_RENDERING_OGRE2_VISIBLE Ogre2IgnHlmsCustomizations final :
50+
public Ogre::HlmsListener
51+
{
52+
public:
53+
virtual ~Ogre2IgnHlmsCustomizations() = default;
54+
55+
/// \brief
56+
/// \return Returns true if spherical clipping customizations should
57+
/// be active
58+
public: bool MinDistanceClipEnabled() const
59+
{
60+
return this->minDistanceClip >= 0.0f;
61+
}
62+
63+
/// \brief Determines which custom pieces we should activate
64+
/// \param _casterPass
65+
/// \param _hlms
66+
private: virtual void preparePassHash(
67+
const Ogre::CompositorShadowNode *_shadowNode,
68+
bool _casterPass, bool _dualParaboloid,
69+
Ogre::SceneManager *_sceneManager,
70+
Ogre::Hlms *_hlms) override;
71+
72+
/// \brief Tells Ogre the buffer data sent to GPU should be a little
73+
/// bigger to fit our data we need to send
74+
///
75+
/// This data is sent in Ogre2IgnHlmsCustomizations::preparePassBuffer
76+
/// \param _casterPass
77+
/// \param _hlms
78+
private: virtual Ogre::uint32 getPassBufferSize(
79+
const Ogre::CompositorShadowNode *_shadowNode,
80+
bool _casterPass, bool _dualParaboloid,
81+
Ogre::SceneManager *_sceneManager) const override;
82+
83+
/// \brief Sends our custom data to GPU buffers that our
84+
/// pieces activated in Ogre2IgnHlmsCustomizations::preparePassHash
85+
/// will need.
86+
///
87+
/// Bytes written must not exceed what we informed in getPassBufferSize
88+
/// \param _casterPass
89+
/// \param _sceneManager
90+
/// \param _passBufferPtr
91+
/// \return The pointer where Ogre should continue appending more data
92+
private: virtual float* preparePassBuffer(
93+
const Ogre::CompositorShadowNode *_shadowNode,
94+
bool _casterPass, bool _dualParaboloid,
95+
Ogre::SceneManager *_sceneManager,
96+
float *_passBufferPtr) override;
97+
98+
/// \brief Min distance to clip geometry against in a spherical manner
99+
/// (i.e. vertices that are too close to camera are clipped)
100+
/// Usually this means the min lidar distance
101+
///
102+
/// Regular near clip distance clips in a rectangular way, so
103+
/// it's not enough.
104+
///
105+
/// Set to a negative value to disable (0 does NOT disable it!)
106+
///
107+
/// See https://github.com/ignitionrobotics/ign-rendering/pull/356
108+
public: float minDistanceClip = -1.0f;
109+
110+
/// \brief When true, we're currently dealing with HlmsUnlit
111+
/// where we need to define and calculate `float3 worldPos`
112+
/// \internal
113+
private: bool needsWorldPos = false;
114+
};
115+
}
116+
}
117+
}
118+
#endif

ogre2/src/Ogre2RenderEngine.cc

+20
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "ignition/rendering/ogre2/Ogre2Scene.hh"
4141
#include "ignition/rendering/ogre2/Ogre2Storage.hh"
4242

43+
#include "Ogre2IgnHlmsCustomizations.hh"
4344

4445
class ignition::rendering::Ogre2RenderEnginePrivate
4546
{
@@ -49,6 +50,9 @@ class ignition::rendering::Ogre2RenderEnginePrivate
4950

5051
/// \brief A list of supported fsaa levels
5152
public: std::vector<unsigned int> fsaaLevels;
53+
54+
/// \brief Controls Hlms customizations for both PBS and Unlit
55+
public: ignition::rendering::Ogre2IgnHlmsCustomizations hlmsCustomizations;
5256
};
5357

5458
using namespace ignition;
@@ -612,6 +616,10 @@ void Ogre2RenderEngine::CreateResources()
612616

613617
Ogre::ArchiveManager &archiveManager = Ogre::ArchiveManager::getSingleton();
614618

619+
Ogre::Archive *customizationsArchiveLibrary =
620+
archiveManager.load( rootHlmsFolder + "Hlms/Ignition", "FileSystem",
621+
true );
622+
615623
{
616624
Ogre::HlmsUnlit *hlmsUnlit = 0;
617625
// Create & Register HlmsUnlit
@@ -631,13 +639,16 @@ void Ogre2RenderEngine::CreateResources()
631639
++libraryFolderPathIt;
632640
}
633641

642+
archiveUnlitLibraryFolders.push_back( customizationsArchiveLibrary );
643+
634644
// Create and register the unlit Hlms
635645
hlmsUnlit = OGRE_NEW Ogre::HlmsUnlit(archiveUnlit,
636646
&archiveUnlitLibraryFolders);
637647
Ogre::Root::getSingleton().getHlmsManager()->registerHlms(hlmsUnlit);
638648

639649
// disable writting debug output to disk
640650
hlmsUnlit->setDebugOutputPath(false, false);
651+
hlmsUnlit->setListener(&this->dataPtr->hlmsCustomizations);
641652
}
642653

643654
{
@@ -661,12 +672,15 @@ void Ogre2RenderEngine::CreateResources()
661672
++libraryFolderPathIt;
662673
}
663674

675+
archivePbsLibraryFolders.push_back( customizationsArchiveLibrary );
676+
664677
// Create and register
665678
hlmsPbs = OGRE_NEW Ogre::HlmsPbs(archivePbs, &archivePbsLibraryFolders);
666679
Ogre::Root::getSingleton().getHlmsManager()->registerHlms(hlmsPbs);
667680

668681
// disable writting debug output to disk
669682
hlmsPbs->setDebugOutputPath(false, false);
683+
hlmsPbs->setListener(&this->dataPtr->hlmsCustomizations);
670684
}
671685
}
672686

@@ -782,6 +796,12 @@ std::vector<unsigned int> Ogre2RenderEngine::FSAALevels() const
782796
return this->dataPtr->fsaaLevels;
783797
}
784798

799+
/////////////////////////////////////////////////
800+
Ogre2IgnHlmsCustomizations& Ogre2RenderEngine::HlmsCustomizations()
801+
{
802+
return this->dataPtr->hlmsCustomizations;
803+
}
804+
785805
/////////////////////////////////////////////////
786806
Ogre::v1::OverlaySystem *Ogre2RenderEngine::OverlaySystem() const
787807
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
@property( ign_spherical_clip_min_distance )
2+
@piece( custom_passBuffer )
3+
#define ignMinClipDistance ignMinClipDistance_ignCameraPos.x
4+
#define ignCameraPos ignMinClipDistance_ignCameraPos.yzw
5+
float4 ignMinClipDistance_ignCameraPos;
6+
7+
@property( ign_spherical_clip_needs_worldPos )
8+
float4x4 invViewProj;
9+
@end
10+
@end
11+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@property( ign_spherical_clip_min_distance )
2+
@piece( custom_vs_posExecution )
3+
@property( ign_spherical_clip_needs_worldPos )
4+
// Unlit didn't declare this
5+
float3 worldPos = (gl_Position * passBuf.invViewProj).xyz;
6+
@end
7+
8+
// Ogre 2.2 should use outVs_clipDistanceN for compatibility with all
9+
// APIs
10+
// Rare case of geometry without normals.
11+
gl_ClipDistance[@value(ign_spherical_clip_idx)] =
12+
distance( worldPos.xyz, passBuf.ignCameraPos.xyz ) -
13+
passBuf.ignMinClipDistance;
14+
@end
15+
@end

ogre2/src/media/Hlms/Pbs/GLSL/VertexShader_vs.glsl

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
out gl_PerVertex
55
{
66
vec4 gl_Position;
7-
@property( hlms_global_clip_planes )
8-
float gl_ClipDistance[@value(hlms_global_clip_planes)];
7+
@property( hlms_pso_clip_distances )
8+
float gl_ClipDistance[@value(hlms_pso_clip_distances)];
99
@end
1010
};
1111

0 commit comments

Comments
 (0)