@@ -65,11 +65,21 @@ class ignition::gazebo::systems::ShaderParamPrivate
65
65
public: std::vector<std::string> args;
66
66
};
67
67
68
- // / \brief Path to vertex shader
69
- public: std::string vertexShaderUri;
68
+ // / \brief Data structure for storing shader files uri
69
+ public: class ShaderUri
70
+ {
71
+ // / \brief Shader language: glsl or metal
72
+ public: std::string language;
73
+
74
+ // / \brief Path to vertex shader
75
+ public: std::string vertexShaderUri;
70
76
71
- // / \brief Path to fragment shader
72
- public: std::string fragmentShaderUri;
77
+ // / \brief Path to fragment shader
78
+ public: std::string fragmentShaderUri;
79
+ };
80
+
81
+ // / \brief A map of shader language to shader program files
82
+ public: std::map<std::string, ShaderUri> shaders;
73
83
74
84
// / \brief Mutex to protect sim time updates.
75
85
public: std::mutex mutex;
@@ -179,9 +189,16 @@ void ShaderParam::Configure(const Entity &_entity,
179
189
}
180
190
181
191
// parse path to shaders
182
- if (sdf->HasElement (" shader" ))
192
+ if (!sdf->HasElement (" shader" ))
193
+ {
194
+ ignerr << " Unable to load shader param system. "
195
+ << " Missing <shader> SDF element." << std::endl;
196
+ return ;
197
+ }
198
+ // allow mulitple shader SDF element for different shader languages
199
+ sdf::ElementPtr shaderElem = sdf->GetElement (" shader" );
200
+ while (shaderElem)
183
201
{
184
- sdf::ElementPtr shaderElem = sdf->GetElement (" shader" );
185
202
if (!shaderElem->HasElement (" vertex" ) ||
186
203
!shaderElem->HasElement (" fragment" ))
187
204
{
@@ -190,16 +207,35 @@ void ShaderParam::Configure(const Entity &_entity,
190
207
}
191
208
else
192
209
{
210
+ // default to glsl
211
+ std::string api = " glsl" ;
212
+ if (shaderElem->HasAttribute (" language" ))
213
+ api = shaderElem->GetAttribute (" language" )->GetAsString ();
214
+
215
+ ShaderParamPrivate::ShaderUri shader;
216
+ shader.language = api;
217
+
193
218
sdf::ElementPtr vertexElem = shaderElem->GetElement (" vertex" );
194
- this -> dataPtr -> vertexShaderUri = common::findFile (
219
+ shader. vertexShaderUri = common::findFile (
195
220
asFullPath (vertexElem->Get <std::string>(),
196
221
this ->dataPtr ->modelPath ));
197
222
sdf::ElementPtr fragmentElem = shaderElem->GetElement (" fragment" );
198
- this -> dataPtr -> fragmentShaderUri = common::findFile (
223
+ shader. fragmentShaderUri = common::findFile (
199
224
asFullPath (fragmentElem->Get <std::string>(),
200
225
this ->dataPtr ->modelPath ));
226
+ this ->dataPtr ->shaders [api] = shader;
227
+
228
+ std::cerr << " api: " << api << " , " << shader.vertexShaderUri << std::endl;
229
+
230
+ shaderElem = shaderElem->GetNextElement (" shader" );
201
231
}
202
232
}
233
+ if (this ->dataPtr ->shaders .empty ())
234
+ {
235
+ ignerr << " Unable to load shader param system. "
236
+ << " No valid shaders." << std::endl;
237
+ return ;
238
+ }
203
239
204
240
this ->dataPtr ->entity = _entity;
205
241
auto nameComp = _ecm.Component <components::Name>(_entity);
@@ -272,8 +308,30 @@ void ShaderParamPrivate::OnUpdate()
272
308
if (!this ->material )
273
309
{
274
310
auto mat = scene->CreateMaterial ();
275
- mat->SetVertexShader (this ->vertexShaderUri );
276
- mat->SetFragmentShader (this ->fragmentShaderUri );
311
+
312
+ // default to glsl
313
+ auto it = this ->shaders .find (" glsl" );
314
+ if (it != this ->shaders .end ())
315
+ {
316
+ mat->SetVertexShader (it->second .vertexShaderUri );
317
+ mat->SetFragmentShader (it->second .fragmentShaderUri );
318
+ }
319
+ // prefer metal over glsl on macOS
320
+ // \todo(anyone) instead of using ifdef to check for macOS,
321
+ // expose add an accessor function to get the GraphicsApi
322
+ // from rendering::RenderEngine
323
+ #ifdef __APPLE__
324
+ auto metalIt = this ->shaders .find (" metal" );
325
+ if (metalIt != this ->shaders .end ())
326
+ {
327
+ mat->SetVertexShader (metalIt->second .vertexShaderUri );
328
+ mat->SetFragmentShader (metalIt->second .fragmentShaderUri );
329
+ // if both glsl and metal are specified, print a msg to inform that
330
+ // metal is used instead of glsl
331
+ if (it != this ->shaders .end ())
332
+ ignmsg << " Using metal shaders. " << std::endl
333
+ }
334
+ #endif
277
335
this ->visual ->SetMaterial (mat);
278
336
scene->DestroyMaterial (mat);
279
337
this ->material = this ->visual ->Material ();
0 commit comments