diff --git a/docs/Materials.md.html b/docs/Materials.md.html index 85428dbba9c..753e3a6b2f5 100644 --- a/docs/Materials.md.html +++ b/docs/Materials.md.html @@ -1308,7 +1308,12 @@ declare a variable called `eyeDirection` you can access it in the fragment shader using `variable_eyeDirection`. In the vertex shader, the interpolant name is simply a member of the `MaterialVertexInputs` structure (`material.eyeDirection` in your example). Each - interpolant is of type `float4` (`vec4`) in the shaders. + interpolant is of type `float4` (`vec4`) in the shaders. By default the precision of the + interpolant is `highp` in *both* the vertex and fragment shaders. + An alternate syntax can be used to specify both the name and precision of the interpolant. + In this case the specified precision is used as-is in both fragment and vertex stages, in + particular if `default` is specified the default precision is used is the fragment shader + (`mediump`) and in the vertex shader (`highp`). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON material { @@ -1320,7 +1325,11 @@ } ], variables : [ - eyeDirection + eyeDirection, + { + name : eyeColor, + precision : medium + } ], vertexDomain : device, depthWrite : false, diff --git a/libs/filamat/include/filamat/MaterialBuilder.h b/libs/filamat/include/filamat/MaterialBuilder.h index 2587adba659..7a7e3ba2e2d 100644 --- a/libs/filamat/include/filamat/MaterialBuilder.h +++ b/libs/filamat/include/filamat/MaterialBuilder.h @@ -323,6 +323,9 @@ class UTILS_PUBLIC MaterialBuilder : public MaterialBuilderBase { //! Custom variables (all float4). MaterialBuilder& variable(Variable v, const char* name) noexcept; + MaterialBuilder& variable(Variable v, const char* name, + ParameterPrecision precision) noexcept; + /** * Require a specified attribute. * @@ -708,11 +711,17 @@ class UTILS_PUBLIC MaterialBuilder : public MaterialBuilderBase { ShaderStage stage; }; + struct CustomVariable { + utils::CString name; + Precision precision; + bool hasPrecision; + }; + static constexpr size_t MATERIAL_PROPERTIES_COUNT = filament::MATERIAL_PROPERTIES_COUNT; using Property = filament::Property; using PropertyList = bool[MATERIAL_PROPERTIES_COUNT]; - using VariableList = utils::CString[MATERIAL_VARIABLES_COUNT]; + using VariableList = CustomVariable[MATERIAL_VARIABLES_COUNT]; using OutputList = std::vector; static constexpr size_t MAX_COLOR_OUTPUT = filament::backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 35add4f503f..1905c86cc00 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -234,7 +234,21 @@ MaterialBuilder& MaterialBuilder::variable(Variable v, const char* name) noexcep case Variable::CUSTOM2: case Variable::CUSTOM3: assert(size_t(v) < MATERIAL_VARIABLES_COUNT); - mVariables[size_t(v)] = CString(name); + mVariables[size_t(v)] = { CString(name), Precision::DEFAULT, false }; + break; + } + return *this; +} + +MaterialBuilder& MaterialBuilder::variable(Variable v, + const char* name, ParameterPrecision precision) noexcept { + switch (v) { + case Variable::CUSTOM0: + case Variable::CUSTOM1: + case Variable::CUSTOM2: + case Variable::CUSTOM3: + assert(size_t(v) < MATERIAL_VARIABLES_COUNT); + mVariables[size_t(v)] = { CString(name), precision, true }; break; } return *this; @@ -1383,7 +1397,7 @@ bool MaterialBuilder::checkMaterialLevelFeatures(MaterialInfo const& info) const bool MaterialBuilder::hasCustomVaryings() const noexcept { for (const auto& variable : mVariables) { - if (!variable.empty()) { + if (!variable.name.empty()) { return true; } } diff --git a/libs/filamat/src/shaders/CodeGenerator.cpp b/libs/filamat/src/shaders/CodeGenerator.cpp index 1c74cbd7797..2b90c299410 100644 --- a/libs/filamat/src/shaders/CodeGenerator.cpp +++ b/libs/filamat/src/shaders/CodeGenerator.cpp @@ -451,15 +451,20 @@ io::sstream& CodeGenerator::generatePostProcessMain(io::sstream& out, ShaderStag } io::sstream& CodeGenerator::generateVariable(io::sstream& out, ShaderStage stage, - const CString& name, size_t index) { - + const MaterialBuilder::CustomVariable& variable, size_t index) { + auto const& name = variable.name; + const char* precisionString = getPrecisionQualifier(variable.precision); if (!name.empty()) { if (stage == ShaderStage::VERTEX) { out << "\n#define VARIABLE_CUSTOM" << index << " " << name.c_str() << "\n"; out << "\n#define VARIABLE_CUSTOM_AT" << index << " variable_" << name.c_str() << "\n"; - out << "LAYOUT_LOCATION(" << index << ") VARYING vec4 variable_" << name.c_str() << ";\n"; + out << "LAYOUT_LOCATION(" << index << ") VARYING " << precisionString << " vec4 variable_" << name.c_str() << ";\n"; } else if (stage == ShaderStage::FRAGMENT) { - out << "\nLAYOUT_LOCATION(" << index << ") VARYING highp vec4 variable_" << name.c_str() << ";\n"; + if (!variable.hasPrecision && variable.precision == Precision::DEFAULT) { + // for backward compatibility + precisionString = "highp"; + } + out << "\nLAYOUT_LOCATION(" << index << ") VARYING " << precisionString << " vec4 variable_" << name.c_str() << ";\n"; } } return out; diff --git a/libs/filamat/src/shaders/CodeGenerator.h b/libs/filamat/src/shaders/CodeGenerator.h index 233243f348c..f7bb4af5ebb 100644 --- a/libs/filamat/src/shaders/CodeGenerator.h +++ b/libs/filamat/src/shaders/CodeGenerator.h @@ -103,7 +103,7 @@ class UTILS_PRIVATE CodeGenerator { // generate declarations for custom interpolants static utils::io::sstream& generateVariable(utils::io::sstream& out, ShaderStage stage, - const utils::CString& name, size_t index); + const MaterialBuilder::CustomVariable& variable, size_t index); // generate declarations for non-custom "in" variables utils::io::sstream& generateShaderInputs(utils::io::sstream& out, ShaderStage type, diff --git a/tools/matc/src/matc/ParametersProcessor.cpp b/tools/matc/src/matc/ParametersProcessor.cpp index 828597e51a6..34bbc2d72a3 100644 --- a/tools/matc/src/matc/ParametersProcessor.cpp +++ b/tools/matc/src/matc/ParametersProcessor.cpp @@ -615,14 +615,51 @@ static bool processVariables(MaterialBuilder& builder, const JsonishValue& value } for (size_t i = 0; i < elements.size(); i++) { - auto elementValue = elements[i]; + ParameterPrecision precision = ParameterPrecision::DEFAULT; MaterialBuilder::Variable v = intToVariable(i); - if (elementValue->getType() != JsonishValue::Type::STRING) { + std::string nameString; + + auto elementValue = elements[i]; + if (elementValue->getType() == JsonishValue::Type::OBJECT) { + + JsonishObject const& jsonObject = *elementValue->toJsonObject(); + + const JsonishValue* nameValue = jsonObject.getValue("name"); + if (!nameValue) { + std::cerr << "variables: entry without 'name' key." << std::endl; + return false; + } + if (nameValue->getType() != JsonishValue::STRING) { + std::cerr << "variables: name value must be STRING." << std::endl; + return false; + } + + const JsonishValue* precisionValue = jsonObject.getValue("precision"); + if (precisionValue) { + if (precisionValue->getType() != JsonishValue::STRING) { + std::cerr << "variables: precision must be a STRING." << std::endl; + return false; + } + auto precisionString = precisionValue->toJsonString(); + if (!Enums::isValid(precisionString->getString())){ + return logEnumIssue("variables", *precisionString, Enums::map()); + } + } + + nameString = nameValue->toJsonString()->getString(); + if (precisionValue) { + precision = Enums::toEnum( + precisionValue->toJsonString()->getString()); + } + builder.variable(v, nameString.c_str(), precision); + } else if (elementValue->getType() == JsonishValue::Type::STRING) { + nameString = elementValue->toJsonString()->getString(); + builder.variable(v, nameString.c_str()); + } else { std::cerr << "variables: array index " << i << " is not a STRING. found:" << JsonishValue::typeToString(elementValue->getType()) << std::endl; return false; } - builder.variable(v, elementValue->toJsonString()->getString().c_str()); } return true;