Skip to content

Commit 2908969

Browse files
authored
Respect vertex shader from low level materials in sensor passes (#544) (#578)
* Respect vertex shader from low level materials in sensor passes (#544) clone the material while overriding the pixel shader while keeping the vertex shader Signed-off-by: Matias N. Goldberg <[email protected]>
1 parent 11197df commit 2908969

5 files changed

+202
-30
lines changed

ogre2/src/Ogre2GpuRays.cc

+20-4
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,27 @@ void Ogre2LaserRetroMaterialSwitcher::passPreExecute(
309309

310310
if (!subItem->getMaterial().isNull())
311311
{
312-
// TODO(anyone): We need to keep the material's vertex shader
313-
// to keep vertex deformation consistent. See
314-
// https://github.com/ignitionrobotics/ign-rendering/issues/544
315312
this->materialMap.push_back({ subItem, subItem->getMaterial() });
316-
subItem->setDatablock(defaultPbs);
313+
314+
// We need to keep the material's vertex shader
315+
// to keep vertex deformation consistent; so we use
316+
// a cloned material with a different pixel shader
317+
// https://github.com/ignitionrobotics/ign-rendering/issues/544
318+
auto material = Ogre::MaterialManager::getSingleton().getByName(
319+
subItem->getMaterial()->getName() + "_solid",
320+
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
321+
if (material->getNumSupportedTechniques() > 0u)
322+
{
323+
subItem->setMaterial(material);
324+
}
325+
else
326+
{
327+
// The supplied vertex shader could not pair with the
328+
// pixel shader we provide. Try to salvage the situation
329+
// using PBS shader. Custom deformation won't work but
330+
// if we're lucky that won't matter
331+
subItem->setDatablock(defaultPbs);
332+
}
317333
}
318334
else
319335
{

ogre2/src/Ogre2Material.cc

+102-10
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,22 @@ class ignition::rendering::Ogre2MaterialPrivate
6868
/// \brief Parameters to be bound to the fragment shader
6969
public: ShaderParamsPtr fragmentShaderParams;
7070

71+
/// \brief Material to be used when rendering to special
72+
/// cameras (e.g. sensors) like Ogre2GpuRays,
73+
/// Ogre2LaserRetroMaterialSwitcher, etc
74+
///
75+
/// It shares the same Vertex Shader, but uses a different
76+
/// Pixel Shader
77+
public: Ogre::MaterialPtr ogreSolidColorMat;
78+
79+
/// \brief A clone of plaincolor_fs. We need a clone
80+
/// because some Metal needs to pair with the vertex shader they're
81+
/// going to be used and Vulkan needs to have the same or a compatible
82+
/// Root Layout profile.
83+
///
84+
/// Used in ogreSolidColorMat
85+
public: Ogre::HighLevelGpuProgramPtr ogreSolidColorShader;
86+
7187
/// \brief Returns the shader language code.
7288
/// \param[in] _graphicsAPI The graphic API.
7389
/// \return The shader language code string.
@@ -77,6 +93,8 @@ class ignition::rendering::Ogre2MaterialPrivate
7793
{
7894
case GraphicsAPI::OPENGL:
7995
return "glsl";
96+
case GraphicsAPI::VULKAN:
97+
return "glslvk";
8098
case GraphicsAPI::METAL:
8199
return "metal";
82100
default:
@@ -125,6 +143,13 @@ void Ogre2Material::Destroy()
125143
Ogre::MaterialManager &matManager = Ogre::MaterialManager::getSingleton();
126144
matManager.remove(this->ogreMaterial);
127145
this->ogreMaterial.reset();
146+
147+
matManager.remove(this->dataPtr->ogreSolidColorMat);
148+
this->dataPtr->ogreSolidColorMat.reset();
149+
150+
Ogre::HighLevelGpuProgramManager::getSingleton().remove(
151+
this->dataPtr->ogreSolidColorShader);
152+
this->dataPtr->ogreSolidColorShader.reset();
128153
}
129154

130155
Ogre::Root *root = Ogre2RenderEngine::Instance()->OgreRoot();
@@ -630,11 +655,15 @@ void Ogre2Material::UpdateShaderParams()
630655
if (this->dataPtr->vertexShaderParams &&
631656
this->dataPtr->vertexShaderParams->IsDirty())
632657
{
633-
Ogre::GpuProgramParametersSharedPtr ogreParams;
634-
auto mat = this->Material();
635-
auto pass = mat->getTechnique(0u)->getPass(0);
636-
ogreParams = pass->getVertexProgramParameters();
637-
this->UpdateShaderParams(this->dataPtr->vertexShaderParams, ogreParams);
658+
Ogre::MaterialPtr mat[2] = { this->Material(),
659+
this->dataPtr->ogreSolidColorMat };
660+
for (int i = 0; i < 2; ++i)
661+
{
662+
Ogre::GpuProgramParametersSharedPtr ogreParams;
663+
auto pass = mat[i]->getTechnique(0u)->getPass(0);
664+
ogreParams = pass->getVertexProgramParameters();
665+
this->UpdateShaderParams(this->dataPtr->vertexShaderParams, ogreParams);
666+
}
638667
this->dataPtr->vertexShaderParams->ClearDirty();
639668
}
640669
if (this->dataPtr->fragmentShaderParams &&
@@ -802,6 +831,43 @@ Ogre::MaterialPtr Ogre2Material::Material()
802831
Ogre::MaterialManager &matManager = Ogre::MaterialManager::getSingleton();
803832
this->ogreMaterial = matManager.create(this->name,
804833
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
834+
835+
this->dataPtr->ogreSolidColorMat = matManager.create(
836+
this->name + "_solid",
837+
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
838+
839+
const auto graphicsApi = Ogre2RenderEngine::Instance()->GraphicsAPI();
840+
841+
this->dataPtr->ogreSolidColorShader =
842+
Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(
843+
"_ign_" + this->name + "_solid_fs",
844+
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
845+
this->dataPtr->shaderLanguageCode(graphicsApi),
846+
Ogre::GpuProgramType::GPT_FRAGMENT_PROGRAM);
847+
848+
switch (graphicsApi)
849+
{
850+
case GraphicsAPI::OPENGL:
851+
case GraphicsAPI::VULKAN:
852+
this->dataPtr->ogreSolidColorShader->setSourceFile("plain_color_fs.glsl");
853+
break;
854+
case GraphicsAPI::DIRECT3D11:
855+
this->dataPtr->ogreSolidColorShader->setSourceFile("plain_color_fs.hlsl");
856+
break;
857+
case GraphicsAPI::METAL:
858+
this->dataPtr->ogreSolidColorShader->setSourceFile(
859+
"plain_color_fs.metal");
860+
break;
861+
default:
862+
IGN_ASSERT(false, "Impossible path!");
863+
}
864+
865+
auto mat = this->dataPtr->ogreSolidColorMat;
866+
auto pass = mat->getTechnique(0u)->getPass(0);
867+
pass->setFragmentProgram(this->dataPtr->ogreSolidColorShader->getName());
868+
auto psParams = pass->getFragmentProgramParameters();
869+
psParams->setNamedAutoConstant("inColor",
870+
Ogre::GpuProgramParameters::ACT_CUSTOM, 1u);
805871
}
806872

807873
return this->ogreMaterial;
@@ -1136,11 +1202,37 @@ void Ogre2Material::SetVertexShader(const std::string &_path)
11361202
assert(!(vertexShader->hasCompileError()));
11371203
assert(vertexShader->isSupported());
11381204

1139-
auto mat = this->Material();
1140-
auto pass = mat->getTechnique(0u)->getPass(0);
1141-
pass->setVertexProgram(vertexShader->getName());
1142-
mat->compile();
1143-
mat->load();
1205+
// Call it now to ensure ogreSolidColorShader is created
1206+
auto mainMat = this->Material();
1207+
1208+
// We can set this setting now for the solid pixel shader
1209+
// Metal needs this. Other APIs will ignore it.
1210+
this->dataPtr->ogreSolidColorShader->setParameter(
1211+
"shader_reflection_pair_hint", vertexShader->getName());
1212+
1213+
Ogre::MaterialPtr mat[2] = { mainMat, this->dataPtr->ogreSolidColorMat };
1214+
1215+
for (int i = 0; i < 2; ++i)
1216+
{
1217+
auto pass = mat[i]->getTechnique(0u)->getPass(0);
1218+
pass->setVertexProgram(vertexShader->getName());
1219+
mat[i]->compile();
1220+
mat[i]->load();
1221+
}
1222+
1223+
if(this->dataPtr->ogreSolidColorMat->getNumSupportedTechniques() == 0u)
1224+
{
1225+
ignwarn
1226+
<< "Material '" << this->Name()
1227+
<< "' could not be paired with special pixel shader '"
1228+
<< this->dataPtr->ogreSolidColorShader->getSourceFile()
1229+
<< "' See Ogre.log for details. This shader is used for special "
1230+
"rendering in sensors (e.g. Lidar, Thermal). Your vertex shader "
1231+
"must have a compatible signature if you want it to work.\n"
1232+
"See https://github.com/ignitionrobotics/ign-rendering/issues/544\n"
1233+
"If this issue isn't fixed, sensor rendering MIGHT not be correct"
1234+
"if your vertex shader performs custom geometry deformation";
1235+
}
11441236

11451237
this->dataPtr->vertexShaderPath = _path;
11461238
this->dataPtr->vertexShaderParams.reset(new ShaderParams);

ogre2/src/Ogre2MaterialSwitcher.cc

+20-4
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,27 @@ void Ogre2MaterialSwitcher::cameraPreRenderScene(
9797

9898
if (!subItem->getMaterial().isNull())
9999
{
100-
// TODO(anyone): We need to keep the material's vertex shader
101-
// to keep vertex deformation consistent. See
102-
// https://github.com/ignitionrobotics/ign-rendering/issues/544
103100
this->materialMap.push_back({ subItem, subItem->getMaterial() });
104-
subItem->setDatablock(defaultPbs);
101+
102+
// We need to keep the material's vertex shader
103+
// to keep vertex deformation consistent; so we use
104+
// a cloned material with a different pixel shader
105+
// https://github.com/ignitionrobotics/ign-rendering/issues/544
106+
auto material = Ogre::MaterialManager::getSingleton().getByName(
107+
subItem->getMaterial()->getName() + "_solid",
108+
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
109+
if (material->getNumSupportedTechniques() > 0u)
110+
{
111+
subItem->setMaterial(material);
112+
}
113+
else
114+
{
115+
// The supplied vertex shader could not pair with the
116+
// pixel shader we provide. Try to salvage the situation
117+
// using PBS shader. Custom deformation won't work but
118+
// if we're lucky that won't matter
119+
subItem->setDatablock(defaultPbs);
120+
}
105121
}
106122
else
107123
{

ogre2/src/Ogre2SegmentationMaterialSwitcher.cc

+20-4
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,27 @@ void Ogre2SegmentationMaterialSwitcher::cameraPreRenderScene(
301301

302302
if (!subItem->getMaterial().isNull())
303303
{
304-
// TODO(anyone): We need to keep the material's vertex shader
305-
// to keep vertex deformation consistent. See
306-
// https://github.com/ignitionrobotics/ign-rendering/issues/544
307304
this->materialMap.push_back({ subItem, subItem->getMaterial() });
308-
subItem->setDatablock(defaultPbs);
305+
306+
// We need to keep the material's vertex shader
307+
// to keep vertex deformation consistent; so we use
308+
// a cloned material with a different pixel shader
309+
// https://github.com/ignitionrobotics/ign-rendering/issues/544
310+
auto material = Ogre::MaterialManager::getSingleton().getByName(
311+
subItem->getMaterial()->getName() + "_solid",
312+
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
313+
if (material->getNumSupportedTechniques() > 0u)
314+
{
315+
subItem->setMaterial(material);
316+
}
317+
else
318+
{
319+
// The supplied vertex shader could not pair with the
320+
// pixel shader we provide. Try to salvage the situation
321+
// using PBS shader. Custom deformation won't work but
322+
// if we're lucky that won't matter
323+
subItem->setDatablock(defaultPbs);
324+
}
309325
}
310326
else
311327
{

ogre2/src/Ogre2ThermalCamera.cc

+40-8
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,27 @@ void Ogre2ThermalCameraMaterialSwitcher::cameraPreRenderScene(
341341

342342
if (!subItem->getMaterial().isNull())
343343
{
344-
// TODO(anyone): We need to keep the material's vertex shader
345-
// to keep vertex deformation consistent. See
346-
// https://github.com/ignitionrobotics/ign-rendering/issues/544
347344
this->materialMap.push_back({ subItem, subItem->getMaterial() });
348-
subItem->setDatablock(defaultPbs);
345+
346+
// We need to keep the material's vertex shader
347+
// to keep vertex deformation consistent; so we use
348+
// a cloned material with a different pixel shader
349+
// https://github.com/ignitionrobotics/ign-rendering/issues/544
350+
auto material = Ogre::MaterialManager::getSingleton().getByName(
351+
subItem->getMaterial()->getName() + "_solid",
352+
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
353+
if (material->getNumSupportedTechniques() > 0u)
354+
{
355+
subItem->setMaterial(material);
356+
}
357+
else
358+
{
359+
// The supplied vertex shader could not pair with the
360+
// pixel shader we provide. Try to salvage the situation
361+
// using PBS shader. Custom deformation won't work but
362+
// if we're lucky that won't matter
363+
subItem->setDatablock(defaultPbs);
364+
}
349365
}
350366
else
351367
{
@@ -473,11 +489,27 @@ void Ogre2ThermalCameraMaterialSwitcher::cameraPreRenderScene(
473489

474490
if (!subItem->getMaterial().isNull())
475491
{
476-
// TODO(anyone): We need to keep the material's vertex shader
477-
// to keep vertex deformation consistent. See
478-
// https://github.com/ignitionrobotics/ign-rendering/issues/544
479492
this->materialMap.push_back({ subItem, subItem->getMaterial() });
480-
subItem->setDatablock(defaultPbs);
493+
494+
// We need to keep the material's vertex shader
495+
// to keep vertex deformation consistent; so we use
496+
// a cloned material with a different pixel shader
497+
// https://github.com/ignitionrobotics/ign-rendering/issues/544
498+
auto material = Ogre::MaterialManager::getSingleton().getByName(
499+
subItem->getMaterial()->getName() + "_solid",
500+
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
501+
if (material->getNumSupportedTechniques() > 0u)
502+
{
503+
subItem->setMaterial(material);
504+
}
505+
else
506+
{
507+
// The supplied vertex shader could not pair with the
508+
// pixel shader we provide. Try to salvage the situation
509+
// using PBS shader. Custom deformation won't work but
510+
// if we're lucky that won't matter
511+
subItem->setDatablock(defaultPbs);
512+
}
481513
}
482514
else
483515
{

0 commit comments

Comments
 (0)