Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend ShaderParam system to support textures #1310

Merged
merged 16 commits into from
Feb 9, 2022
Merged
40 changes: 10 additions & 30 deletions examples/worlds/shader_param.sdf
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ ShaderParam visual plugin over time.
<scene>
<ambient>1.0 1.0 1.0</ambient>
<background>0.8 0.8 0.8</background>
<sky></sky>
<grid>false</grid>
</scene>

<light type="directional" name="sun">
Expand All @@ -177,43 +179,21 @@ ShaderParam visual plugin over time.
<direction>-0.5 0.1 -0.9</direction>
</light>

<model name="ground_plane">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
</collision>
<visual name="visual">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
<material>
<ambient>0.8 0.8 0.8 1</ambient>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.8 0.8 0.8 1</specular>
</material>
</visual>
</link>
</model>

<include>
<pose>0 0.0 0.5 0 0 0</pose>
<name>deformable_sphere</name>
<pose>3 0 0 0 0 0</pose>
<pose>0 0 1.5 0 0 0</pose>
<uri>https://fuel.ignitionrobotics.org/1.0/openrobotics/models/deformable_sphere</uri>
</include>

<include>
<name>waves</name>
<pose>0 0 0 0 0 0</pose>
<uri>https://fuel.ignitionrobotics.org/1.0/openrobotics/models/waves</uri>
</include>

<model name="camera">
<static>true</static>
<pose>2.5 0 0.5 0 0.0 3.14</pose>
<pose>2.5 0 1.5 0 0.0 3.14</pose>
<link name="link">
<pose>0.05 0.05 0.05 0 0 0</pose>
<collision name="collision">
Expand Down
198 changes: 121 additions & 77 deletions src/systems/shader_param/ShaderParam.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,18 @@ class ignition::gazebo::systems::ShaderParamPrivate
/// \brief shader type: vertex or fragment
public: std::string shader;

/// \brief variable type: int, float, float_array, int_array
/// \todo(anyone) support samplers
/// \brief variable type: int, float, float_array, int_array,
/// texture, texture_cube
public: std::string type;

/// \brief variable name of param
public: std::string name;

/// \brief param value
public: std::string value;

/// \brief Any additional arguments
public: std::vector<std::string> args;
};

/// \brief Path to vertex shader
Expand Down Expand Up @@ -98,6 +101,9 @@ class ignition::gazebo::systems::ShaderParamPrivate
/// \brief Current sim time
public: std::chrono::steady_clock::duration currentSimTime;

/// \brief Path to model
public: std::string modelPath;

/// \brief All rendering operations must happen within this call
public: void OnUpdate();
};
Expand Down Expand Up @@ -149,11 +155,29 @@ void ShaderParam::Configure(const Entity &_entity,
spv.name = paramName;
spv.value = value;
spv.type = type;

if (paramElem->HasElement("arg"))
{
sdf::ElementPtr argElem = paramElem->GetElement("arg");
while (argElem)
{
spv.args.push_back(argElem->Get<std::string>());
argElem = argElem->GetNextElement("arg");
}
}

this->dataPtr->shaderParams.push_back(spv);
paramElem = paramElem->GetNextElement("param");
}
}

if (this->dataPtr->modelPath.empty())
{
auto modelEntity = topLevelModel(_entity, _ecm);
this->dataPtr->modelPath =
_ecm.ComponentData<components::SourceFilePath>(modelEntity).value();
}

// parse path to shaders
if (sdf->HasElement("shader"))
{
Expand All @@ -166,15 +190,14 @@ void ShaderParam::Configure(const Entity &_entity,
}
else
{
auto modelEntity = topLevelModel(_entity, _ecm);
auto modelPath =
_ecm.ComponentData<components::SourceFilePath>(modelEntity);
sdf::ElementPtr vertexElem = shaderElem->GetElement("vertex");
this->dataPtr->vertexShaderUri = common::findFile(
asFullPath(vertexElem->Get<std::string>(), modelPath.value()));
asFullPath(vertexElem->Get<std::string>(),
this->dataPtr->modelPath));
sdf::ElementPtr fragmentElem = shaderElem->GetElement("fragment");
this->dataPtr->fragmentShaderUri = common::findFile(
asFullPath(fragmentElem->Get<std::string>(), modelPath.value()));
asFullPath(fragmentElem->Get<std::string>(),
this->dataPtr->modelPath));
}
}

Expand Down Expand Up @@ -263,14 +286,12 @@ void ShaderParamPrivate::OnUpdate()
// this is only done once
for (const auto & spv : this->shaderParams)
{
std::vector<std::string> values = common::split(spv.value, " ");

int intValue = 0;
float floatValue = 0;
std::vector<float> floatArrayValue;

rendering::ShaderParam::ParamType paramType =
rendering::ShaderParam::PARAM_NONE;
// TIME is reserved keyword for sim time
if (spv.value == "TIME")
{
this->timeParams.push_back(spv);
continue;
}

rendering::ShaderParamsPtr params;
if (spv.shader == "fragment")
Expand All @@ -283,92 +304,115 @@ void ShaderParamPrivate::OnUpdate()
}

// if no <value> is specified, this could be a constant
if (values.empty())
if (spv.value.empty())
{
// \todo handle args for constants in ign-rendering
(*params)[spv.name] = 1;
continue;
}

// handle texture params
if (spv.type == "texture")
{
// \todo handle args for constants
(*params)[spv.name] = intValue;
unsigned int uvSetIndex = spv.args.empty() ? 0u :
static_cast<unsigned int>(std::stoul(spv.args[0]));
std::string texPath = common::findFile(
asFullPath(spv.value, this->modelPath));
(*params)[spv.name].SetTexture(texPath,
rendering::ShaderParam::ParamType::PARAM_TEXTURE, uvSetIndex);
}
// float / int
else if (values.size() == 1u)
else if (spv.type == "texture_cube")
{
unsigned int uvSetIndex = spv.args.empty() ? 0u :
static_cast<unsigned int>(std::stoul(spv.args[0]));
std::string texPath = common::findFile(
asFullPath(spv.value, this->modelPath));
(*params)[spv.name].SetTexture(texPath,
rendering::ShaderParam::ParamType::PARAM_TEXTURE_CUBE, uvSetIndex);
}
// handle int, float, int_array, and float_array params
else
{
std::string str = values[0];
std::vector<std::string> values = common::split(spv.value, " ");

// TIME is reserved keyword for sim time
if (str == "TIME")
{
this->timeParams.push_back(spv);
continue;
}
int intValue = 0;
float floatValue = 0;
std::vector<float> floatArrayValue;

// if <type> is not empty, respect the specified type
if (!spv.type.empty())
rendering::ShaderParam::ParamType paramType =
rendering::ShaderParam::PARAM_NONE;

// float / int
if (values.size() == 1u)
{
if (spv.type == "int")
{
intValue = std::stoi(str);
paramType = rendering::ShaderParam::PARAM_INT;
}
else if (spv.type == "float")
std::string str = values[0];

// if <type> is not empty, respect the specified type
if (!spv.type.empty())
{
floatValue = std::stof(str);
paramType = rendering::ShaderParam::PARAM_FLOAT;
if (spv.type == "int")
{
intValue = std::stoi(str);
paramType = rendering::ShaderParam::PARAM_INT;
}
else if (spv.type == "float")
{
floatValue = std::stof(str);
paramType = rendering::ShaderParam::PARAM_FLOAT;
}
}
// else do our best guess at what the type is
else
{
// \todo(anyone) support texture samplers
std::string::size_type sz;
int n = std::stoi(str, &sz);
if ( sz == str.size())
{
intValue = n;
paramType = rendering::ShaderParam::PARAM_INT;
}
else
{
floatValue = std::stof(str);
paramType = rendering::ShaderParam::PARAM_FLOAT;
}
}
}
// else do our best guess at what the type is
// arrays
else
{
std::string::size_type sz;
int n = std::stoi(str, &sz);
if ( sz == str.size())
// int array
if (!spv.type.empty() && spv.type == "int_array")
{
intValue = n;
paramType = rendering::ShaderParam::PARAM_INT;
for (const auto &v : values)
floatArrayValue.push_back(std::stoi(v));
paramType = rendering::ShaderParam::PARAM_INT_BUFFER;
}
// treat everything else as float_array
else
{
floatValue = std::stof(str);
paramType = rendering::ShaderParam::PARAM_FLOAT;
for (const auto &v : values)
floatArrayValue.push_back(std::stof(v));
paramType = rendering::ShaderParam::PARAM_FLOAT_BUFFER;
}
}
}
// arrays
else
{
// int array
if (!spv.type.empty() && spv.type == "int_array")

// set the params
if (paramType == rendering::ShaderParam::PARAM_INT)
{
for (const auto &v : values)
floatArrayValue.push_back(std::stoi(v));
paramType = rendering::ShaderParam::PARAM_INT_BUFFER;
(*params)[spv.name] = intValue;
}
// treat everything else as float_array
else
else if (paramType == rendering::ShaderParam::PARAM_FLOAT)
{
for (const auto &v : values)
floatArrayValue.push_back(std::stof(v));
paramType = rendering::ShaderParam::PARAM_FLOAT_BUFFER;
(*params)[spv.name] = floatValue;
}
else if (paramType == rendering::ShaderParam::PARAM_INT_BUFFER ||
paramType == rendering::ShaderParam::PARAM_FLOAT_BUFFER)
{
(*params)[spv.name].InitializeBuffer(floatArrayValue.size());
float *fv = &floatArrayValue[0];
(*params)[spv.name].UpdateBuffer(fv);
}
}

// set the params
if (paramType == rendering::ShaderParam::PARAM_INT)
{
(*params)[spv.name] = intValue;
}
else if (paramType == rendering::ShaderParam::PARAM_FLOAT)
{
(*params)[spv.name] = floatValue;
}
else if (paramType == rendering::ShaderParam::PARAM_INT_BUFFER ||
paramType == rendering::ShaderParam::PARAM_FLOAT_BUFFER)
{
(*params)[spv.name].InitializeBuffer(floatArrayValue.size());
float *fv = &floatArrayValue[0];
(*params)[spv.name].UpdateBuffer(fv);
}
}
this->shaderParams.clear();
Expand Down