#include "RuntimeShaderParams.h" #include "Std140Buffer.h" #include namespace { ShaderParameterValue DefaultValueForDefinition(const ShaderParameterDefinition& definition) { ShaderParameterValue value; switch (definition.type) { case ShaderParameterType::Float: value.numberValues = definition.defaultNumbers.empty() ? std::vector{ 0.0 } : definition.defaultNumbers; break; case ShaderParameterType::Vec2: value.numberValues = definition.defaultNumbers.size() == 2 ? definition.defaultNumbers : std::vector{ 0.0, 0.0 }; break; case ShaderParameterType::Color: value.numberValues = definition.defaultNumbers.size() == 4 ? definition.defaultNumbers : std::vector{ 1.0, 1.0, 1.0, 1.0 }; break; case ShaderParameterType::Boolean: value.booleanValue = definition.defaultBoolean; break; case ShaderParameterType::Enum: value.enumValue = definition.defaultEnumValue; break; case ShaderParameterType::Text: value.textValue = definition.defaultTextValue; break; case ShaderParameterType::Trigger: value.numberValues = { 0.0, -1000000.0 }; break; } return value; } int EnumIndexForDefault(const ShaderParameterDefinition& definition, const ShaderParameterValue& value) { for (std::size_t optionIndex = 0; optionIndex < definition.enumOptions.size(); ++optionIndex) { if (definition.enumOptions[optionIndex].value == value.enumValue) return static_cast(optionIndex); } return 0; } double UtcSecondsOfDay() { const auto now = std::chrono::system_clock::now(); const auto seconds = std::chrono::duration_cast(now.time_since_epoch()).count(); const long long secondsPerDay = 24 * 60 * 60; long long daySeconds = seconds % secondsPerDay; if (daySeconds < 0) daySeconds += secondsPerDay; return static_cast(daySeconds); } } std::vector BuildRuntimeShaderGlobalParamsStd140( const RuntimeShaderArtifact& artifact, uint64_t frameIndex, unsigned width, unsigned height) { std::vector buffer; buffer.reserve(512); AppendStd140Float(buffer, static_cast(frameIndex) / 60.0f); AppendStd140Vec2(buffer, static_cast(width), static_cast(height)); AppendStd140Vec2(buffer, static_cast(width), static_cast(height)); AppendStd140Float(buffer, static_cast(UtcSecondsOfDay())); AppendStd140Float(buffer, 0.0f); AppendStd140Float(buffer, 0.37f); AppendStd140Float(buffer, static_cast(frameIndex)); AppendStd140Float(buffer, 1.0f); AppendStd140Float(buffer, 0.0f); AppendStd140Int(buffer, 0); AppendStd140Int(buffer, 0); AppendStd140Int(buffer, 0); for (const ShaderParameterDefinition& definition : artifact.parameterDefinitions) { const auto valueIt = artifact.parameterValues.find(definition.id); const ShaderParameterValue value = valueIt == artifact.parameterValues.end() ? DefaultValueForDefinition(definition) : valueIt->second; switch (definition.type) { case ShaderParameterType::Float: AppendStd140Float(buffer, value.numberValues.empty() ? 0.0f : static_cast(value.numberValues[0])); break; case ShaderParameterType::Vec2: AppendStd140Vec2(buffer, value.numberValues.size() > 0 ? static_cast(value.numberValues[0]) : 0.0f, value.numberValues.size() > 1 ? static_cast(value.numberValues[1]) : 0.0f); break; case ShaderParameterType::Color: AppendStd140Vec4(buffer, value.numberValues.size() > 0 ? static_cast(value.numberValues[0]) : 1.0f, value.numberValues.size() > 1 ? static_cast(value.numberValues[1]) : 1.0f, value.numberValues.size() > 2 ? static_cast(value.numberValues[2]) : 1.0f, value.numberValues.size() > 3 ? static_cast(value.numberValues[3]) : 1.0f); break; case ShaderParameterType::Boolean: AppendStd140Int(buffer, value.booleanValue ? 1 : 0); break; case ShaderParameterType::Enum: AppendStd140Int(buffer, EnumIndexForDefault(definition, value)); break; case ShaderParameterType::Text: break; case ShaderParameterType::Trigger: AppendStd140Int(buffer, value.numberValues.empty() ? 0 : static_cast(value.numberValues[0])); AppendStd140Float(buffer, value.numberValues.size() > 1 ? static_cast(value.numberValues[1]) : -1000000.0f); break; } } buffer.resize(AlignStd140(buffer.size(), 16), 0); return buffer; }