d9cbc97ec0
ATOM-16273 Compiling SceneSRG before updating it can cause a gpu crash Changes include: 1. Removed Scene::SetShaderResourceGroupCallback() function and clean up code which use this function. 2. Moved SceneTimeSrg.azsli to RPI's DefaultSceneSrg folder and setup the constants in RPI::Scene 3. Add AZ::Event for Scene's update srg event which features and update scene srg at proper place 4. UpdateTransformServcie FP to use PrepareSceneSrg event handler. 5. Clean up shaders and srgs used in project templates. Signed-off-by: Qing Tao <qingtao@amazon.com>
90 lines
3.6 KiB
Plaintext
90 lines
3.6 KiB
Plaintext
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <scenesrg.srgi>
|
|
#include <viewsrg.srgi>
|
|
|
|
#include <Atom/RPI/Math.azsli>
|
|
#include "EyeAdaptationUtil.azsli"
|
|
|
|
ShaderResourceGroup PassSrg : SRG_PerPass
|
|
{
|
|
// This is a mip chain containing the scene luminance info
|
|
// x = min luminance
|
|
// y = average luminance
|
|
// z = max luminance
|
|
Texture2D<float4> m_sceneLuminance;
|
|
|
|
Sampler LinearSampler
|
|
{
|
|
MinFilter = Linear;
|
|
MagFilter = Linear;
|
|
MipFilter = Linear;
|
|
AddressU = Clamp;
|
|
AddressV = Clamp;
|
|
AddressW = Clamp;
|
|
};
|
|
|
|
// Contains the eye-adaptation feedback settings. This buffer will be updated in this pass.
|
|
RWStructuredBuffer<EyeAdaptation> m_eyeAdaptationData;
|
|
}
|
|
|
|
[numthreads(1, 1, 1)]
|
|
void MainCS(uint3 dispatch_id : SV_DispatchThreadID)
|
|
{
|
|
// Determine the goal exposure value in logarithmic(perceptual) space.
|
|
float goalExposureLog2 = 0.0; // default goal is no adjustment
|
|
|
|
if (ViewSrg::m_exposureControl.m_eyeAdaptationEnabled)
|
|
{
|
|
// Get the dimensions and mip levels from the luminance mip chain
|
|
uint2 inputDimensions;
|
|
uint numMipLevels = 1;
|
|
PassSrg::m_sceneLuminance.GetDimensions(0, inputDimensions.x, inputDimensions.y, numMipLevels);
|
|
|
|
// Use smallest 1x1 mip to get scene average luminance.
|
|
float luminanceAvg = PassSrg::m_sceneLuminance.SampleLevel(PassSrg::LinearSampler, float2(0.5f, 0.5f), numMipLevels - 1).y;
|
|
|
|
// Middle gray value is the half-tone between black and white in exposure control.
|
|
// Defining Middle Grey value to 0.18f as the typical value used in photography. Cf. https://en.wikipedia.org/wiki/Middle_gray
|
|
const float middleGray = 0.18f;
|
|
|
|
// Protection from NaNs getting in the frame buffer leading to NaN luminance.
|
|
if (isnan(luminanceAvg))
|
|
{
|
|
luminanceAvg = middleGray;
|
|
}
|
|
|
|
// This finds the exposure at which the lumininaceAvg would be equal to middleGray, ie perfectly neutral.
|
|
goalExposureLog2 = log2(luminanceAvg / middleGray);
|
|
|
|
// Clamp goal exposure by min / max.
|
|
float minExposure = ViewSrg::m_exposureControl.m_exposureMinLog2;
|
|
float maxExposure = ViewSrg::m_exposureControl.m_exposureMaxLog2;
|
|
goalExposureLog2 = clamp(goalExposureLog2, minExposure, maxExposure);
|
|
}
|
|
|
|
// Convert the previous frame linear exposure to a stop adjustment.
|
|
float previousFrameExposureLog2 = -log2(max(0.00000001, PassSrg::m_eyeAdaptationData[0].m_exposureValue));
|
|
|
|
float exposureDifference = goalExposureLog2 - previousFrameExposureLog2;
|
|
|
|
// Speed depends on if the exposure should be increased or decreased.
|
|
const float speed = exposureDifference > 0.0 ? ViewSrg::m_exposureControl.m_speedUp : ViewSrg::m_exposureControl.m_speedDown;
|
|
|
|
// Update the adjustment for this frame based on the frame deltaTime and speed
|
|
float deltaTime = clamp(SceneSrg::m_time - PassSrg::m_eyeAdaptationData[0].m_setValueTime, 0.0f, 1.0f);
|
|
float exposureAdjustment = exposureDifference * deltaTime * speed;
|
|
float newExposureLog2 = previousFrameExposureLog2 + exposureAdjustment;
|
|
|
|
// Store the linear exposure so it can be used by the look modification transform later.
|
|
// newExposureLog2 is negated because m_exposureValue is used to correct for a given exposure.
|
|
PassSrg::m_eyeAdaptationData[0].m_exposureValue = pow(2.0f, -newExposureLog2);
|
|
PassSrg::m_eyeAdaptationData[0].m_setValueTime = SceneSrg::m_time;
|
|
}
|