Ejemplo n.º 1
0
        public override void Render(PostProcessRenderContext context)
        {
            var cmd = context.command;

            cmd.BeginSample("AutoExposureLookup");

            var sheet = context.propertySheets.Get(context.resources.shaders.autoExposure);

            sheet.ClearKeywords();

            // Prepare autoExpo texture pool
            CheckTexture(0);
            CheckTexture(1);

            // Make sure filtering values are correct to avoid apocalyptic consequences
            float       lowPercent  = settings.filtering.value.x;
            float       highPercent = settings.filtering.value.y;
            const float kMinDelta   = 1e-2f;

            highPercent = Mathf.Clamp(highPercent, 1f + kMinDelta, 99f);
            lowPercent  = Mathf.Clamp(lowPercent, 1f, highPercent - kMinDelta);

            // Compute auto exposure
            sheet.properties.SetBuffer(Uniforms._HistogramBuffer, context.logHistogram.data);
            sheet.properties.SetVector(Uniforms._Params, new Vector4(lowPercent * 0.01f, highPercent * 0.01f, RuntimeUtilities.Exp2(settings.minLuminance.value), RuntimeUtilities.Exp2(settings.maxLuminance.value)));
            sheet.properties.SetVector(Uniforms._Speed, new Vector2(settings.speedDown.value, settings.speedUp.value));
            sheet.properties.SetVector(Uniforms._ScaleOffsetRes, context.logHistogram.GetHistogramScaleOffsetRes(context));
            sheet.properties.SetFloat(Uniforms._ExposureCompensation, settings.keyValue.value);

            if (m_FirstFrame || !Application.isPlaying)
            {
                // We don't want eye adaptation when not in play mode because the GameView isn't
                // animated, thus making it harder to tweak. Just use the final audo exposure value.
                m_CurrentAutoExposure = m_AutoExposurePool[0];
                cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, m_CurrentAutoExposure, sheet, (int)EyeAdaptation.Fixed);

                // Copy current exposure to the other pingpong target to avoid adapting from black
                RuntimeUtilities.CopyTexture(cmd, m_AutoExposurePool[0], m_AutoExposurePool[1]);
            }
            else
            {
                int pp  = m_AutoExposurePingPong;
                var src = m_AutoExposurePool[++pp % 2];
                var dst = m_AutoExposurePool[++pp % 2];
                cmd.BlitFullscreenTriangle(src, dst, sheet, (int)settings.eyeAdaptation.value);
                m_AutoExposurePingPong = ++pp % 2;
                m_CurrentAutoExposure  = dst;
            }

            cmd.EndSample("AutoExposureLookup");

            context.autoExposureTexture = m_CurrentAutoExposure;
            context.autoExposure        = settings;
            m_FirstFrame = false;
        }
Ejemplo n.º 2
0
        public override void Render(PostProcessRenderContext context)
        {
            // Setup compute
            if (m_EyeCompute == null)
            {
                m_EyeCompute = Resources.Load <ComputeShader>("Shaders/Builtins/ExposureHistogram");
            }

            var cmd = context.command;

            cmd.BeginSample("AutoExposureLookup");

            var sheet = context.propertySheets.Get("Hidden/PostProcessing/AutoExposure");

            sheet.ClearKeywords();

            if (m_HistogramBuffer == null)
            {
                m_HistogramBuffer = new ComputeBuffer(k_HistogramBins, sizeof(uint));
            }

            // Downscale the framebuffer, we don't need an absolute precision for auto exposure and it
            // helps making it more stable
            var scaleOffsetRes = GetHistogramScaleOffsetRes(context);

            cmd.GetTemporaryRT(Uniforms._AutoExposureCopyTex,
                               (int)scaleOffsetRes.z,
                               (int)scaleOffsetRes.w,
                               0,
                               FilterMode.Bilinear,
                               context.sourceFormat);
            cmd.BlitFullscreenTriangle(context.source, Uniforms._AutoExposureCopyTex);

            // Prepare autoExpo texture pool
            CheckTexture(0);
            CheckTexture(1);

            // Clear the buffer on every frame as we use it to accumulate luminance values on each frame
            m_HistogramBuffer.SetData(s_EmptyHistogramBuffer);

            // Get a log histogram
            int kernel = m_EyeCompute.FindKernel("KEyeHistogram");

            cmd.SetComputeBufferParam(m_EyeCompute, kernel, "_HistogramBuffer", m_HistogramBuffer);
            cmd.SetComputeTextureParam(m_EyeCompute, kernel, "_Source", Uniforms._AutoExposureCopyTex);
            cmd.SetComputeVectorParam(m_EyeCompute, "_ScaleOffsetRes", scaleOffsetRes);
            cmd.DispatchCompute(m_EyeCompute, kernel,
                                Mathf.CeilToInt(scaleOffsetRes.z / (float)k_HistogramThreadX),
                                Mathf.CeilToInt(scaleOffsetRes.w / (float)k_HistogramThreadY),
                                1);

            // Cleanup
            cmd.ReleaseTemporaryRT(Uniforms._AutoExposureCopyTex);

            // Make sure filtering values are correct to avoid apocalyptic consequences
            float       lowPercent  = settings.filtering.value.x;
            float       highPercent = settings.filtering.value.y;
            const float kMinDelta   = 1e-2f;

            highPercent = Mathf.Clamp(highPercent, 1f + kMinDelta, 99f);
            lowPercent  = Mathf.Clamp(lowPercent, 1f, highPercent - kMinDelta);

            // Compute auto exposure
            sheet.properties.SetBuffer(Uniforms._HistogramBuffer, m_HistogramBuffer);
            sheet.properties.SetVector(Uniforms._Params, new Vector4(lowPercent * 0.01f, highPercent * 0.01f, RuntimeUtilities.Exp2(settings.minLuminance.value), RuntimeUtilities.Exp2(settings.maxLuminance.value)));
            sheet.properties.SetVector(Uniforms._Speed, new Vector2(settings.speedDown.value, settings.speedUp.value));
            sheet.properties.SetVector(Uniforms._ScaleOffsetRes, scaleOffsetRes);
            sheet.properties.SetFloat(Uniforms._ExposureCompensation, settings.keyValue.value);

            if (settings.dynamicKeyValue)
            {
                sheet.EnableKeyword("AUTO_KEY_VALUE");
            }

            if (m_FirstFrame || !Application.isPlaying)
            {
                // We don't want eye adaptation when not in play mode because the GameView isn't
                // animated, thus making it harder to tweak. Just use the final audo exposure value.
                m_CurrentAutoExposure = m_AutoExposurePool[0];
                cmd.BlitFullscreenTriangle((Texture)null, m_CurrentAutoExposure, sheet, (int)EyeAdaptation.Fixed);

                // Copy current exposure to the other pingpong target to avoid adapting from black
                RuntimeUtilities.CopyTexture(cmd, m_AutoExposurePool[0], m_AutoExposurePool[1]);
            }
            else
            {
                int pp  = m_AutoExposurePingPong;
                var src = m_AutoExposurePool[++pp % 2];
                var dst = m_AutoExposurePool[++pp % 2];
                cmd.BlitFullscreenTriangle(src, dst, sheet, (int)settings.eyeAdaptation.value);
                m_AutoExposurePingPong = ++pp % 2;
                m_CurrentAutoExposure  = dst;
            }

            cmd.EndSample("AutoExposureLookup");

            context.autoExposureTexture = m_CurrentAutoExposure;
            m_FirstFrame = false;
        }