mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-05-02 09:34:58 +00:00
stuff
This commit is contained in:
204
MaterialX/source/MaterialXGenShader/UnitSystem.cpp
Normal file
204
MaterialX/source/MaterialXGenShader/UnitSystem.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// Copyright Contributors to the MaterialX Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <MaterialXGenShader/UnitSystem.h>
|
||||
|
||||
#include <MaterialXGenShader/Exception.h>
|
||||
#include <MaterialXGenShader/GenContext.h>
|
||||
#include <MaterialXGenShader/ShaderStage.h>
|
||||
#include <MaterialXGenShader/Shader.h>
|
||||
|
||||
MATERIALX_NAMESPACE_BEGIN
|
||||
|
||||
class ScalarUnitNode : public ShaderNodeImpl
|
||||
{
|
||||
public:
|
||||
explicit ScalarUnitNode(LinearUnitConverterPtr scalarUnitConverter) :
|
||||
_scalarUnitConverter(scalarUnitConverter),
|
||||
_unitRatioFunctionName("mx_" + _scalarUnitConverter->getUnitType() + "_unit_ratio")
|
||||
{
|
||||
}
|
||||
|
||||
static ShaderNodeImplPtr create(LinearUnitConverterPtr scalarUnitConverter);
|
||||
|
||||
void initialize(const InterfaceElement& element, GenContext& context) override;
|
||||
void emitFunctionDefinition(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
|
||||
void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
|
||||
|
||||
protected:
|
||||
LinearUnitConverterPtr _scalarUnitConverter;
|
||||
const string _unitRatioFunctionName;
|
||||
};
|
||||
|
||||
ShaderNodeImplPtr ScalarUnitNode::create(LinearUnitConverterPtr scalarUnitConverter)
|
||||
{
|
||||
return std::make_shared<ScalarUnitNode>(scalarUnitConverter);
|
||||
}
|
||||
|
||||
void ScalarUnitNode::initialize(const InterfaceElement& element, GenContext& /*context*/)
|
||||
{
|
||||
_name = element.getName();
|
||||
|
||||
// Use the unit ratio function name has hash to make sure this function
|
||||
// is shared, and only emitted once, for all units of the same unit type.
|
||||
_hash = std::hash<string>{}(_unitRatioFunctionName);
|
||||
}
|
||||
|
||||
void ScalarUnitNode::emitFunctionDefinition(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
|
||||
{
|
||||
DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
|
||||
{
|
||||
// Emit the helper function mx_<unittype>_unit_ratio that embeds a look up table for unit scale
|
||||
vector<float> unitScales;
|
||||
unitScales.reserve(_scalarUnitConverter->getUnitScale().size());
|
||||
auto unitScaleMap = _scalarUnitConverter->getUnitScale();
|
||||
unitScales.resize(unitScaleMap.size());
|
||||
for (const auto& unitScale : unitScaleMap)
|
||||
{
|
||||
int location = _scalarUnitConverter->getUnitAsInteger(unitScale.first);
|
||||
unitScales[location] = unitScale.second;
|
||||
}
|
||||
// See stdlib/gen*/mx_<unittype>_unit. This helper function is called by these shaders.
|
||||
const string VAR_UNIT_SCALE = "u_" + _scalarUnitConverter->getUnitType() + "_unit_scales";
|
||||
VariableBlock unitLUT("unitLUT", EMPTY_STRING);
|
||||
ScopedFloatFormatting fmt(Value::FloatFormatFixed, 15);
|
||||
unitLUT.add(Type::FLOATARRAY, VAR_UNIT_SCALE, Value::createValue<vector<float>>(unitScales));
|
||||
|
||||
const ShaderGenerator& shadergen = context.getShaderGenerator();
|
||||
shadergen.emitLine("float " + _unitRatioFunctionName + "(int unit_from, int unit_to)", stage, false);
|
||||
shadergen.emitFunctionBodyBegin(node, context, stage);
|
||||
shadergen.emitVariableDeclarations(unitLUT, shadergen.getSyntax().getConstantQualifier(), ";", context, stage, true);
|
||||
shadergen.emitLine("return (" + VAR_UNIT_SCALE + "[unit_from] / " + VAR_UNIT_SCALE + "[unit_to])", stage);
|
||||
shadergen.emitFunctionBodyEnd(node, context, stage);
|
||||
}
|
||||
}
|
||||
|
||||
void ScalarUnitNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
|
||||
{
|
||||
DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
|
||||
{
|
||||
const ShaderGenerator& shadergen = context.getShaderGenerator();
|
||||
|
||||
const ShaderInput* in = node.getInput(0);
|
||||
const ShaderInput* from = node.getInput(1);
|
||||
const ShaderInput* to = node.getInput(2);
|
||||
|
||||
shadergen.emitLineBegin(stage);
|
||||
shadergen.emitOutput(node.getOutput(), true, false, context, stage);
|
||||
shadergen.emitString(" = ", stage);
|
||||
shadergen.emitInput(in, context, stage);
|
||||
shadergen.emitString(" * ", stage);
|
||||
shadergen.emitString(_unitRatioFunctionName + "(", stage);
|
||||
shadergen.emitInput(from, context, stage);
|
||||
shadergen.emitString(", ", stage);
|
||||
shadergen.emitInput(to, context, stage);
|
||||
shadergen.emitString(")", stage);
|
||||
shadergen.emitLineEnd(stage);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Unit transform methods
|
||||
//
|
||||
|
||||
UnitTransform::UnitTransform(const string& ss, const string& ts, TypeDesc t, const string& unittype) :
|
||||
sourceUnit(ss),
|
||||
targetUnit(ts),
|
||||
type(t),
|
||||
unitType(unittype)
|
||||
{
|
||||
if (type != Type::FLOAT && type != Type::VECTOR2 && type != Type::VECTOR3 && type != Type::VECTOR4)
|
||||
{
|
||||
throw ExceptionShaderGenError("Unit space transform can only be a float or vectors");
|
||||
}
|
||||
}
|
||||
|
||||
const string UnitSystem::UNITSYSTEM_NAME = "default_unit_system";
|
||||
|
||||
UnitSystem::UnitSystem(const string& target) :
|
||||
_target(createValidName(target))
|
||||
{
|
||||
}
|
||||
|
||||
void UnitSystem::loadLibrary(DocumentPtr document)
|
||||
{
|
||||
_document = document;
|
||||
}
|
||||
|
||||
void UnitSystem::setUnitConverterRegistry(UnitConverterRegistryPtr registry)
|
||||
{
|
||||
_unitRegistry = registry;
|
||||
}
|
||||
|
||||
UnitConverterRegistryPtr UnitSystem::getUnitConverterRegistry() const
|
||||
{
|
||||
return _unitRegistry;
|
||||
}
|
||||
|
||||
UnitSystemPtr UnitSystem::create(const string& language)
|
||||
{
|
||||
return UnitSystemPtr(new UnitSystem(language));
|
||||
}
|
||||
|
||||
NodeDefPtr UnitSystem::getNodeDef(const UnitTransform& transform) const
|
||||
{
|
||||
if (!_document)
|
||||
{
|
||||
throw ExceptionShaderGenError("No library loaded for unit system");
|
||||
}
|
||||
|
||||
const string MULTIPLY_NODE_NAME = "multiply";
|
||||
for (NodeDefPtr nodeDef : _document->getMatchingNodeDefs(MULTIPLY_NODE_NAME))
|
||||
{
|
||||
vector<InputPtr> nodeInputs = nodeDef->getInputs();
|
||||
if (nodeInputs.size() == 2 &&
|
||||
nodeInputs[0]->getType() == transform.type.getName() &&
|
||||
nodeInputs[1]->getType() == "float")
|
||||
{
|
||||
return nodeDef;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool UnitSystem::supportsTransform(const UnitTransform& transform) const
|
||||
{
|
||||
NodeDefPtr nodeDef = getNodeDef(transform);
|
||||
return nodeDef != nullptr;
|
||||
}
|
||||
|
||||
ShaderNodePtr UnitSystem::createNode(ShaderGraph* parent, const UnitTransform& transform, const string& name,
|
||||
GenContext& context) const
|
||||
{
|
||||
NodeDefPtr nodeDef = getNodeDef(transform);
|
||||
if (!nodeDef)
|
||||
{
|
||||
throw ExceptionShaderGenError("No nodedef found for transform: ('" + transform.sourceUnit + "', '" + transform.targetUnit + "').");
|
||||
}
|
||||
|
||||
// Scalar unit conversion
|
||||
UnitTypeDefPtr scalarTypeDef = _document->getUnitTypeDef(transform.unitType);
|
||||
if (!_unitRegistry || !_unitRegistry->getUnitConverter(scalarTypeDef))
|
||||
{
|
||||
throw ExceptionTypeError("Unit registry unavailable or undefined unit converter for: " + transform.unitType);
|
||||
}
|
||||
LinearUnitConverterPtr scalarConverter = std::dynamic_pointer_cast<LinearUnitConverter>(_unitRegistry->getUnitConverter(scalarTypeDef));
|
||||
|
||||
// Create the node.
|
||||
ShaderNodePtr shaderNode = ShaderNode::create(parent, name, *nodeDef, context);
|
||||
|
||||
// Set ports on the node.
|
||||
ShaderInput* in2 = shaderNode->getInput("in2");
|
||||
if (!in2)
|
||||
{
|
||||
throw ExceptionShaderGenError("Invalid node signature for unit transform: ('" + transform.sourceUnit + "', '" + transform.targetUnit + "').");
|
||||
}
|
||||
float conversionRatio = scalarConverter->conversionRatio(transform.sourceUnit, transform.targetUnit);
|
||||
in2->setValue(Value::createValue(conversionRatio));
|
||||
|
||||
return shaderNode;
|
||||
}
|
||||
|
||||
MATERIALX_NAMESPACE_END
|
||||
Reference in New Issue
Block a user