Skip to content

Commit da879bb

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 da879bb

8 files changed

+308
-3
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ namespace ignition
4444
{
4545
namespace rendering
4646
{
47+
class Ogre2IgnHlmsCustomizations;
4748
inline namespace IGNITION_RENDERING_VERSION_NAMESPACE {
4849
//
4950
// forward declaration
@@ -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

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

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

40+
#include "OgreHlmsListener.h"
41+
3942
namespace ignition
4043
{
4144
namespace rendering
@@ -1090,8 +1093,15 @@ void Ogre2GpuRays::UpdateRenderTarget2ndPass()
10901093
//////////////////////////////////////////////////
10911094
void Ogre2GpuRays::Render()
10921095
{
1096+
auto engine = Ogre2RenderEngine::Instance();
1097+
Ogre2IgnHlmsCustomizations &hlmsCustomizations =
1098+
engine->HlmsCustomizations();
1099+
1100+
hlmsCustomizations.minDistanceClip =
1101+
static_cast<float>(this->NearClipPlane());
10931102
this->UpdateRenderTarget1stPass();
10941103
this->UpdateRenderTarget2ndPass();
1104+
hlmsCustomizations.minDistanceClip = -1;
10951105
}
10961106

10971107
//////////////////////////////////////////////////
+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+
}
+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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/ogre2/Export.hh"
22+
23+
#ifdef _MSC_VER
24+
#pragma warning(push, 0)
25+
#endif
26+
#include <OgreHlmsListener.h>
27+
#ifdef _MSC_VER
28+
#pragma warning(pop)
29+
#endif
30+
31+
namespace ignition
32+
{
33+
namespace rendering
34+
{
35+
// TODO(anyone) Can't use inline namespace here. At runtime it will complain
36+
// vtable for ignition::rendering::v4::Ogre2IgnHlmsCustomizations
37+
// was not found
38+
// inline namespace IGNITION_RENDERING_VERSION_NAMESPACE {
39+
//
40+
/// \brief Controls custom shader snippets of Hlms (both Pbs and Unlit):
41+
///
42+
/// - Toggles them on/off
43+
/// - Sends relevant data to the GPU buffers for shaders to use
44+
///
45+
/// This listener requires Hlms to have been created with the piece data
46+
/// files in ogre2/src/media/Hlms/Ignition registered
47+
///
48+
/// \internal
49+
/// \remark Public variables take effect immediately (i.e. for the
50+
/// next render)
51+
class IGNITION_RENDERING_OGRE2_HIDDEN Ogre2IgnHlmsCustomizations final :
52+
public Ogre::HlmsListener
53+
{
54+
/// \brief
55+
/// \return Returns true if spherical clipping customizations should
56+
/// be active
57+
public: bool MinDistanceClipEnabled() const
58+
{
59+
return this->minDistanceClip >= 0.0f;
60+
}
61+
62+
/// \brief Determines which custom pieces we should activate
63+
/// \param _casterPass
64+
/// \param _hlms
65+
public: void preparePassHash(const Ogre::CompositorShadowNode *_shadowNode,
66+
bool _casterPass, bool _dualParaboloid,
67+
Ogre::SceneManager *_sceneManager,
68+
Ogre::Hlms *_hlms) override;
69+
70+
/// \brief Tells Ogre the buffer data sent to GPU should be a little
71+
/// bigger to fit our data we need to send
72+
///
73+
/// This data is sent in Ogre2IgnHlmsCustomizations::preparePassBuffer
74+
/// \param _casterPass
75+
/// \param _hlms
76+
public: Ogre::uint32 getPassBufferSize(
77+
const Ogre::CompositorShadowNode *_shadowNode,
78+
bool _casterPass, bool _dualParaboloid,
79+
Ogre::SceneManager *_sceneManager) const override;
80+
81+
/// \brief Sends our custom data to GPU buffers that our
82+
/// pieces activated in Ogre2IgnHlmsCustomizations::preparePassHash
83+
/// will need.
84+
///
85+
/// Bytes written must not exceed what we informed in getPassBufferSize
86+
/// \param _casterPass
87+
/// \param _sceneManager
88+
/// \param _passBufferPtr
89+
/// \return The pointer where Ogre should continue appending more data
90+
public: float* preparePassBuffer(
91+
const Ogre::CompositorShadowNode *_shadowNode,
92+
bool _casterPass, bool _dualParaboloid,
93+
Ogre::SceneManager *_sceneManager,
94+
float *_passBufferPtr) override;
95+
96+
/// \brief Min distance to clip geometry against in a spherical manner
97+
/// (i.e. vertices that are too close to camera are clipped)
98+
/// Usually this means the min lidar distance
99+
///
100+
/// Regular near clip distance clips in a rectangular way, so
101+
/// it's not enough.
102+
///
103+
/// Set to a negative value to disable (0 does NOT disable it!)
104+
///
105+
/// See https://github.com/ignitionrobotics/ign-rendering/pull/356
106+
public: float minDistanceClip = -1.0f;
107+
108+
/// \brief When true, we're currently dealing with HlmsUnlit
109+
/// where we need to define and calculate `float3 worldPos`
110+
/// \internal
111+
private: bool needsWorldPos = false;
112+
};
113+
// }
114+
}
115+
}
116+
#endif

ogre2/src/Ogre2RenderEngine.cc

+29-1
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,28 @@
4040
#include "ignition/rendering/ogre2/Ogre2Scene.hh"
4141
#include "ignition/rendering/ogre2/Ogre2Storage.hh"
4242

43+
#include "Ogre2IgnHlmsCustomizations.hh"
4344

44-
class ignition::rendering::Ogre2RenderEnginePrivate
45+
namespace ignition
46+
{
47+
namespace rendering
48+
{
49+
inline namespace IGNITION_RENDERING_VERSION_NAMESPACE {
50+
class Ogre2RenderEnginePrivate
4551
{
4652
#if !defined(__APPLE__) && !defined(_WIN32)
4753
public: XVisualInfo *dummyVisual = nullptr;
4854
#endif
4955

5056
/// \brief A list of supported fsaa levels
5157
public: std::vector<unsigned int> fsaaLevels;
58+
59+
/// \brief Controls Hlms customizations for both PBS and Unlit
60+
public: Ogre2IgnHlmsCustomizations hlmsCustomizations;
5261
};
62+
}
63+
}
64+
}
5365

5466
using namespace ignition;
5567
using namespace rendering;
@@ -612,6 +624,10 @@ void Ogre2RenderEngine::CreateResources()
612624

613625
Ogre::ArchiveManager &archiveManager = Ogre::ArchiveManager::getSingleton();
614626

627+
Ogre::Archive *customizationsArchiveLibrary =
628+
archiveManager.load( rootHlmsFolder + "Hlms/Ignition", "FileSystem",
629+
true );
630+
615631
{
616632
Ogre::HlmsUnlit *hlmsUnlit = 0;
617633
// Create & Register HlmsUnlit
@@ -631,13 +647,16 @@ void Ogre2RenderEngine::CreateResources()
631647
++libraryFolderPathIt;
632648
}
633649

650+
archiveUnlitLibraryFolders.push_back( customizationsArchiveLibrary );
651+
634652
// Create and register the unlit Hlms
635653
hlmsUnlit = OGRE_NEW Ogre::HlmsUnlit(archiveUnlit,
636654
&archiveUnlitLibraryFolders);
637655
Ogre::Root::getSingleton().getHlmsManager()->registerHlms(hlmsUnlit);
638656

639657
// disable writting debug output to disk
640658
hlmsUnlit->setDebugOutputPath(false, false);
659+
hlmsUnlit->setListener(&this->dataPtr->hlmsCustomizations);
641660
}
642661

643662
{
@@ -661,12 +680,15 @@ void Ogre2RenderEngine::CreateResources()
661680
++libraryFolderPathIt;
662681
}
663682

683+
archivePbsLibraryFolders.push_back( customizationsArchiveLibrary );
684+
664685
// Create and register
665686
hlmsPbs = OGRE_NEW Ogre::HlmsPbs(archivePbs, &archivePbsLibraryFolders);
666687
Ogre::Root::getSingleton().getHlmsManager()->registerHlms(hlmsPbs);
667688

668689
// disable writting debug output to disk
669690
hlmsPbs->setDebugOutputPath(false, false);
691+
hlmsPbs->setListener(&this->dataPtr->hlmsCustomizations);
670692
}
671693
}
672694

@@ -782,6 +804,12 @@ std::vector<unsigned int> Ogre2RenderEngine::FSAALevels() const
782804
return this->dataPtr->fsaaLevels;
783805
}
784806

807+
/////////////////////////////////////////////////
808+
Ogre2IgnHlmsCustomizations& Ogre2RenderEngine::HlmsCustomizations()
809+
{
810+
return this->dataPtr->hlmsCustomizations;
811+
}
812+
785813
/////////////////////////////////////////////////
786814
Ogre::v1::OverlaySystem *Ogre2RenderEngine::OverlaySystem() const
787815
{
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

0 commit comments

Comments
 (0)