Radium Engine  1.5.0
RenderParameters.hpp
1 #pragma once
2 
3 #include <Engine/RaEngine.hpp>
4 
5 #include <vector>
6 
7 #include <nlohmann/json.hpp>
8 
9 #include <Core/Types.hpp>
10 #include <Core/Utils/Color.hpp>
11 #include <Core/Utils/EnumConverter.hpp>
12 #include <Core/Utils/Log.hpp>
13 #include <Core/Utils/StdOptional.hpp>
14 
15 #include <Core/Containers/VariableSet.hpp>
16 
17 #include <Engine/Data/ShaderProgram.hpp>
18 
19 namespace Ra {
20 namespace Engine {
21 namespace Data {
22 
23 class Texture;
24 
35 class RA_ENGINE_API RenderParameters final
36 {
37  public:
41  using TextureInfo = std::pair<Data::Texture*, int>;
42 
45 
47  using BindableTypes = Core::Utils::TypeList<bool,
49  int,
50  uint,
51  Scalar,
53  std::vector<int>,
54  std::vector<uint>,
55  std::vector<Scalar>,
56  Core::Vector2,
57  Core::Vector3,
58  Core::Vector4,
59  Core::Matrix2,
60  Core::Matrix3,
61  Core::Matrix4,
62  std::reference_wrapper<RenderParameters>,
63  std::reference_wrapper<const RenderParameters>>;
64 
71  template <typename T>
73 
79  template <typename T>
82 
89  template <typename EnumBaseType>
90  void addEnumConverter( const std::string& name,
91  std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>> converter );
92 
99  template <typename EnumBaseType>
100  Core::Utils::optional<std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>>>
101  getEnumConverter( const std::string& name );
102 
110  template <typename Enum, typename std::enable_if<std::is_enum<Enum> {}, bool>::type = true>
111  std::string getEnumString( const std::string& name, Enum value );
112 
121  template <typename EnumBaseType>
122  std::string
123  getEnumString( const std::string& name,
124  EnumBaseType value,
125  typename std::enable_if<!std::is_enum<EnumBaseType> {}, bool>::type = true );
126 
137  template <typename T>
138  void addParameter( const std::string& name,
139  T value,
140  typename std::enable_if<!std::is_class<T> {}, bool>::type = true );
141 
148  template <typename T, typename std::enable_if<std::is_class<T> {}, bool>::type = true>
149  void addParameter( const std::string& name, const T& value );
150 
161  template <typename T,
162  typename std::enable_if<std::is_base_of<Data::Texture, T>::value, bool>::type = true>
163  void addParameter( const std::string& name, T* tex, int texUnit = -1 );
164 
172  void addParameter( const std::string& name, const std::string& value );
173  void addParameter( const std::string& name, const char* value );
174 
180  void addParameter( const std::string& name, RenderParameters& value );
181 
182  void addParameter( const std::string& name, const RenderParameters& value );
183 
192  template <typename T>
193  bool removeParameter( const std::string& name );
194 
201  void mergeKeepParameters( const RenderParameters& params );
202 
209  void mergeReplaceParameters( const RenderParameters& params );
210 
215  void bind( const Data::ShaderProgram* shader ) const;
216 
223  template <typename T>
224  const UniformBindableSet<T>& getParameterSet() const;
225  template <typename T>
226  UniformBindableSet<T>& getParameterSet();
228 
236  template <typename T>
237  Core::Utils::optional<UniformBindableSet<T>*> hasParameterSet() const;
238 
245  template <typename T>
246  Core::Utils::optional<UniformVariable<T>> containsParameter( const std::string& name ) const;
247 
256  template <typename T>
257  const T& getParameter( const std::string& name ) const;
258  template <typename T>
259  T& getParameter( const std::string& name );
261 
264  template <typename V>
265  void visit( V&& visitor ) const;
266 
267  template <typename V, typename T>
268  void visit( V&& visitor, T& userParams ) const;
269 
270  template <typename V, typename T>
271  void visit( V&& visitor, T&& userParams ) const;
272 
276  const Core::VariableSet& getStorage() const { return m_parameterSets; }
277  Core::VariableSet& getStorage() { return m_parameterSets; }
279  private:
285  class StaticParameterBinder
286  {
287  public:
289  using types = BindableTypes;
290 
294  void operator()( const std::string& name,
295  const Ra::Core::Utils::Color& p,
296  const Data::ShaderProgram* shader ) {
297  shader->setUniform( name.c_str(), Ra::Core::Utils::Color::VectorType( p ) );
298  }
299 
303  void operator()( const std::string& name,
305  const Data::ShaderProgram* shader ) {
306  auto [tex, texUnit] = p;
307  if ( texUnit == -1 ) { shader->setUniformTexture( name.c_str(), tex ); }
308  else { shader->setUniform( name.c_str(), tex, texUnit ); }
309  }
310 
315  template <typename T>
316  void operator()( const std::string& /*name*/,
317  const std::reference_wrapper<T>& p,
318  const Data::ShaderProgram* shader ) {
319  p.get().bind( shader );
320  }
321 
325  template <typename T>
326  void operator()( const std::string& name, const T& p, const Data::ShaderProgram* shader ) {
327  shader->setUniform( name.c_str(), p );
328  }
329  };
330 
334  static StaticParameterBinder s_binder;
335 
339  Core::VariableSet m_parameterSets;
340 };
341 
345 class RA_ENGINE_API ParameterSetEditingInterface
346 {
347  public:
348  virtual ~ParameterSetEditingInterface() = default;
349 
355  virtual nlohmann::json getParametersMetadata() const = 0;
356 
358  static void loadMetaData( const std::string& basename, nlohmann::json& destination );
359 };
360 
368 class RA_ENGINE_API ShaderParameterProvider
369 {
370  public:
371  virtual ~ShaderParameterProvider() = default;
372  virtual RenderParameters& getParameters() { return m_renderParameters; }
373  virtual const RenderParameters& getParameters() const { return m_renderParameters; }
380  virtual void updateGL() = 0;
381 
386  virtual void updateFromParameters() {};
387 
397  virtual std::list<std::string> getPropertyList() const { return {}; };
398 
399  private:
402  RenderParameters m_renderParameters;
403 };
404 
405 /* --------------- enum parameter management --------------- */
406 
407 template <typename EnumBaseType>
409  const std::string& name,
410  std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>> converter ) {
411  auto converterHandle = m_parameterSets.insertOrAssignVariable( name, converter );
412  std::function<void( Core::VariableSet&, const std::string&, const std::string& )>
413  convertingFunction = [converter = converterHandle.first]( Core::VariableSet& vs,
414  const std::string& nm,
415  const std::string& vl ) {
416  vs.insertOrAssignVariable( nm, converter->second->getEnumerator( vl ) );
417  };
418  m_parameterSets.insertOrAssignVariable( name, convertingFunction );
419 }
420 
421 template <typename EnumBaseType>
422 Core::Utils::optional<std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>>>
423 RenderParameters::getEnumConverter( const std::string& name ) {
424  auto storedConverter =
425  m_parameterSets.existsVariable<std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>>>(
426  name );
427  if ( storedConverter ) { return ( *storedConverter )->second; }
428  return {};
429 }
430 
431 template <typename EnumBaseType>
433  const std::string& name,
434  EnumBaseType value,
435  typename std::enable_if<!std::is_enum<EnumBaseType> {}, bool>::type ) {
436  auto storedConverter =
437  m_parameterSets.existsVariable<std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>>>(
438  name );
439  if ( storedConverter ) { return ( *storedConverter )->second->getEnumerator( value ); }
440  LOG( Ra::Core::Utils::logWARNING ) << name + " is not a registered Enum with underlying type " +
441  Ra::Core::Utils::demangleType<EnumBaseType>() + ".";
442  return "";
443 }
444 
445 template <typename Enum, typename std::enable_if<std::is_enum<Enum> {}, bool>::type>
446 std::string RenderParameters::getEnumString( const std::string& name, Enum value ) {
447  using EnumBaseType = typename std::underlying_type_t<Enum>;
448  return getEnumString( name, EnumBaseType( value ) );
449 }
450 
451 /* --------------- enum parameter management --------------- */
452 
453 template <typename T>
454 inline void
455 RenderParameters::addParameter( const std::string& name,
456  T value,
457  typename std::enable_if<!std::is_class<T> {}, bool>::type ) {
458  if constexpr ( std::is_enum<T>::value ) {
459  auto v = static_cast<typename std::underlying_type<T>::type>( value );
460  m_parameterSets.insertOrAssignVariable( name, v );
461  }
462  else { m_parameterSets.insertOrAssignVariable( name, value ); }
463 }
464 
465 template <typename T, typename std::enable_if<std::is_class<T> {}, bool>::type>
466 inline void RenderParameters::addParameter( const std::string& name, const T& value ) {
467  m_parameterSets.insertOrAssignVariable( name, value );
468 }
469 
470 template <typename T, typename std::enable_if<std::is_base_of<Data::Texture, T>::value, bool>::type>
471 inline void RenderParameters::addParameter( const std::string& name, T* tex, int texUnit ) {
472  addParameter( name, TextureInfo { tex, texUnit } );
473 }
474 
475 inline void RenderParameters::addParameter( const std::string& name, RenderParameters& value ) {
476  m_parameterSets.insertOrAssignVariable( name, std::ref( value ) );
477 }
478 
479 inline void RenderParameters::addParameter( const std::string& name,
480  const RenderParameters& value ) {
481  m_parameterSets.insertOrAssignVariable( name, std::cref( value ) );
482 }
483 
484 template <typename T>
485 bool RenderParameters::removeParameter( const std::string& name ) {
486  return m_parameterSets.deleteVariable<T>( name );
487 }
488 
489 template <typename T>
491  return m_parameterSets.getAllVariables<T>();
492 }
493 
494 template <typename T>
496  return m_parameterSets.getAllVariables<T>();
497 }
498 
499 template <typename T>
500 inline Core::Utils::optional<RenderParameters::UniformBindableSet<T>*>
502  if constexpr ( std::is_enum<T>::value ) {
503  // Do not return
504  // m_parameterSets.existsVariableType< typename std::underlying_type< T >::type >();
505  // to prevent misuse of this function. The user should infer this with another logic.
506  return {};
507  }
508  else { return m_parameterSets.existsVariableType<T>(); }
509 }
510 
511 template <typename T>
512 inline Core::Utils::optional<RenderParameters::UniformVariable<T>>
513 RenderParameters::containsParameter( const std::string& name ) const {
514  if constexpr ( std::is_enum<T>::value ) {
515  return m_parameterSets.existsVariable<typename std::underlying_type<T>::type>( name );
516  }
517  else { return m_parameterSets.existsVariable<T>( name ); }
518 }
519 
520 template <typename T>
521 inline const T& RenderParameters::getParameter( const std::string& name ) const {
522  if constexpr ( std::is_enum<T>::value ) {
523  // need to cast to take into account the way enums are managed in the RenderParameters
524  return reinterpret_cast<const T&>(
525  m_parameterSets.getVariable<typename std::underlying_type<T>::type>( name ) );
526  }
527  else { return m_parameterSets.getVariable<T>( name ); }
528 }
529 
530 template <typename T>
531 inline T& RenderParameters::getParameter( const std::string& name ) {
532  return const_cast<T&>( const_cast<const RenderParameters*>( this )->getParameter<T>( name ) );
533 }
534 
535 template <typename V>
536 inline void RenderParameters::visit( V&& visitor ) const {
537  m_parameterSets.visit( visitor );
538 }
539 
540 template <typename V, typename T>
541 inline void RenderParameters::visit( V&& visitor, T& userParams ) const {
542  m_parameterSets.visit( visitor, std::forward<T&>( userParams ) );
543 }
544 
545 template <typename V, typename T>
546 inline void RenderParameters::visit( V&& visitor, T&& userParams ) const {
547  m_parameterSets.visit( visitor, std::forward<T&&>( userParams ) );
548 }
549 
550 } // namespace Data
551 } // namespace Engine
552 } // namespace Ra
This class manage the bijective association between string and integral representation of an enumerat...
Heterogeneous container storing "Variables", that maps a name (std::string) to a value (of any type T...
Definition: VariableSet.hpp:72
auto getVariable(const std::string &name) const -> T &
get the value of the given variable
typename VariableContainer< T >::iterator VariableHandle
Handle of a variable A handle on a variable with type T is an iterator into the BaseContainer....
Definition: VariableSet.hpp:92
auto insertOrAssignVariable(const std::string &name, const T &value) -> std::pair< VariableHandle< T >, bool >
reset (or set if the variable does not exist yet) the value of the variable.
auto existsVariable(const std::string &name) const -> Utils::optional< VariableHandle< T >>
test the existence of the given variable
bool deleteVariable(const std::string &name)
Remove a variable, i.e. a name->value association.
auto getAllVariables() const -> VariableContainer< T > &
Get the whole container for variables of a given type.
std::map< std::string, T > VariableContainer
Container type for the mapping name->value of variables with type T.
Definition: VariableSet.hpp:76
auto existsVariableType() const -> Utils::optional< VariableContainer< T > * >
Test if the storage supports a given variable type.
void visit(F &&visitor) const
Visit the container using a user defined visitor.
virtual nlohmann::json getParametersMetadata() const =0
Get a json containing metadata about the parameters.
void addParameter(const std::string &name, T value, typename std::enable_if<!std::is_class< T > {}, bool >::type=true)
Add a parameter by value.
const T & getParameter(const std::string &name) const
Get a typed parameter.
void addEnumConverter(const std::string &name, std::shared_ptr< Core::Utils::EnumConverter< EnumBaseType >> converter)
Associate a converter for enumerated type to the given parameter name.
bool removeParameter(const std::string &name)
Remove the given parameter from the parameterSet.
std::pair< Data::Texture *, int > TextureInfo
Special type for Texture parameter.
const Core::VariableSet & getStorage() const
Get access to the parameter storage.
Core::Utils::TypeList< bool, Core::Utils::Color, int, uint, Scalar, TextureInfo, std::vector< int >, std::vector< uint >, std::vector< Scalar >, Core::Vector2, Core::Vector3, Core::Vector4, Core::Matrix2, Core::Matrix3, Core::Matrix4, std::reference_wrapper< RenderParameters >, std::reference_wrapper< const RenderParameters > > BindableTypes
Aliases for bindable parameter types.
Core::VariableSet::VariableContainer< T > UniformBindableSet
Core::Utils::optional< UniformVariable< T > > containsParameter(const std::string &name) const
Core::Utils::optional< std::shared_ptr< Core::Utils::EnumConverter< EnumBaseType > > > getEnumConverter(const std::string &name)
Search for a converter associated with an enumeration parameter.
const UniformBindableSet< T > & getParameterSet() const
Get a typed parameter set.
Core::Utils::optional< UniformBindableSet< T > * > hasParameterSet() const
Test if parameters of type T are stored.
std::string getEnumString(const std::string &name, Enum value)
Return the string associated to the actual value of a parameter.
Core::VariableSet::VariableHandle< T > UniformVariable
virtual void updateFromParameters()
Update the attributes of the ShaderParameterProvider to their actual values stored in the renderParam...
virtual void updateGL()=0
Update the OpenGL states used by the ShaderParameterProvider. These state could be the ones from an a...
virtual std::list< std::string > getPropertyList() const
Get the list of properties the provider might use in a shader. Each property will be added to the sha...
void setUniform(const char *name, const T &value) const
Uniform setters.
void setUniformTexture(const char *name, Texture *tex) const
Definition: Cage.cpp:3