Another batch of GetValues() overrides. (#6915)

* Another batch of GetValues() overrides.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Added missing headers.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>

* Addressed PR feedback.

Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>
This commit is contained in:
Mike Balfour
2022-01-18 15:05:17 -06:00
committed by GitHub
parent 3a3aa20545
commit 4b9e53e623
18 changed files with 386 additions and 126 deletions
@@ -257,62 +257,80 @@ namespace GradientSignal
float MixedGradientComponent::GetValue(const GradientSampleParams& sampleParams) const
{
AZ_PROFILE_FUNCTION(Entity);
//accumulate the mixed/combined result of all layers and operations
float result = 0.0f;
float operationResult = 0.0f;
for (const auto& layer : m_configuration.m_layers)
{
// added check to prevent opacity of 0.0, which will bust when we unpremultiply the alpha out
if (layer.m_enabled && layer.m_gradientSampler.m_opacity != 0.0f)
{
// Precalculate the inverse opacity that we'll use for blending the current accumulated value with.
// In the one case of "Initialize" blending, force this value to 0 so that we erase any accumulated values.
const float inverseOpacity = (layer.m_operation == MixedGradientLayer::MixingOperation::Initialize)
? 0.0f
: (1.0f - layer.m_gradientSampler.m_opacity);
// this includes leveling and opacity result, we need unpremultiplied opacity to combine properly
float current = layer.m_gradientSampler.GetValue(sampleParams);
// unpremultiplied alpha (we clamp the end result)
float currentUnpremultiplied = current / layer.m_gradientSampler.m_opacity;
switch (layer.m_operation)
{
default:
case MixedGradientLayer::MixingOperation::Initialize:
//reset the result of the mixed/combined layers to the current value
result = 0.0f;
operationResult = currentUnpremultiplied;
break;
case MixedGradientLayer::MixingOperation::Multiply:
operationResult = result * currentUnpremultiplied;
break;
case MixedGradientLayer::MixingOperation::Add:
operationResult = result + currentUnpremultiplied;
break;
case MixedGradientLayer::MixingOperation::Subtract:
operationResult = result - currentUnpremultiplied;
break;
case MixedGradientLayer::MixingOperation::Min:
operationResult = AZStd::min(currentUnpremultiplied, result);
break;
case MixedGradientLayer::MixingOperation::Max:
operationResult = AZStd::max(currentUnpremultiplied, result);
break;
case MixedGradientLayer::MixingOperation::Average:
operationResult = (result + currentUnpremultiplied) / 2.0f;
break;
case MixedGradientLayer::MixingOperation::Normal:
operationResult = currentUnpremultiplied;
break;
case MixedGradientLayer::MixingOperation::Overlay:
operationResult = (result >= 0.5f) ? (1.0f - (2.0f * (1.0f - result) * (1.0f - currentUnpremultiplied))) : (2.0f * result * currentUnpremultiplied);
break;
}
const float currentUnpremultiplied = current / layer.m_gradientSampler.m_opacity;
const float operationResult = PerformMixingOperation(layer.m_operation, result, currentUnpremultiplied);
// blend layers (re-applying opacity, which is why we needed to use unpremultiplied)
result = (result * (1.0f - layer.m_gradientSampler.m_opacity)) + (operationResult * layer.m_gradientSampler.m_opacity);
result = (result * inverseOpacity) + (operationResult * layer.m_gradientSampler.m_opacity);
}
}
return AZ::GetClamp(result, 0.0f, 1.0f);
}
void MixedGradientComponent::GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const
{
if (positions.size() != outValues.size())
{
AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size());
return;
}
// Initialize all of our output data to 0.0f. Layer blends will combine with this, so we need it to have an initial value.
AZStd::fill(outValues.begin(), outValues.end(), 0.0f);
AZStd::vector<float> layerValues(positions.size());
// accumulate the mixed/combined result of all layers and operations
for (const auto& layer : m_configuration.m_layers)
{
// added check to prevent opacity of 0.0, which will bust when we unpremultiply the alpha out
if (layer.m_enabled && layer.m_gradientSampler.m_opacity != 0.0f)
{
// Precalculate the inverse opacity that we'll use for blending the current accumulated value with.
// In the one case of "Initialize" blending, force this value to 0 so that we erase any accumulated values.
const float inverseOpacity = (layer.m_operation == MixedGradientLayer::MixingOperation::Initialize)
? 0.0f
: (1.0f - layer.m_gradientSampler.m_opacity);
// this includes leveling and opacity result, we need unpremultiplied opacity to combine properly
layer.m_gradientSampler.GetValues(positions, layerValues);
for (size_t index = 0; index < outValues.size(); index++)
{
// unpremultiplied alpha (we clamp the end result)
const float currentUnpremultiplied = layerValues[index] / layer.m_gradientSampler.m_opacity;
const float operationResult = PerformMixingOperation(layer.m_operation, outValues[index], currentUnpremultiplied);
// blend layers (re-applying opacity, which is why we needed to use unpremultiplied)
outValues[index] = (outValues[index] * inverseOpacity) + (operationResult * layer.m_gradientSampler.m_opacity);
}
}
}
for (auto& outValue : outValues)
{
outValue = AZ::GetClamp(outValue, 0.0f, 1.0f);
}
}
bool MixedGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const
{
for (const auto& layer : m_configuration.m_layers)