BITFALL/Assets/Plugins/_MK/MKGlow/Scripts/Effect.cs

1445 lines
73 KiB
C#

//////////////////////////////////////////////////////
// MK Glow Effect //
// //
// Created by Michael Kremmel //
// www.michaelkremmel.de //
// Copyright © 2021 All rights reserved. //
//////////////////////////////////////////////////////
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using System.Linq;
namespace MK.Glow
{
using ShaderProperties = PipelineProperties.ShaderProperties;
internal sealed class Effect
{
internal Effect()
{
//_cArgsComputeBuffer = new ComputeBuffer(_cArgBufferSize, 4, ComputeBufferType.Default);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Members
/////////////////////////////////////////////////////////////////////////////////////////////
//always needed parameters - static
private static MK.Glow.Resources _resources;
private static readonly Vector2 _referenceResolution = new Vector2(3840, 2160);
private static readonly float _referenceAspectRatio = 0.5625f;
private static readonly Vector2 _selectiveWorkflowThreshold = new Vector2(0.1f, 10);
private static readonly int _cArgBufferSize = 66;
private static readonly int _glareIterationsBase = 3;
private static readonly RenderDimension _directComputeSize = new RenderDimension(8, 7);
private static readonly float naturalIntensityMult = 0.1f;
//Selective rendering objects
private static readonly string _selectiveReplacementTag = "RenderType";
private static readonly string _selectiveGlowCameraObjectName = "selectiveGlowCameraObject";
private GameObject _selectiveGlowCameraObject;
private UnityEngine.Camera _selectiveGlowCamera;
//Compute Shader Feature Matrices
//Copy variant is always 0
//private ComputeShaderVariants _presampleComputeVariants = new ComputeShaderVariants(0);
//private ComputeShaderVariants _downsampleComputeVariants = new ComputeShaderVariants(240);
//private ComputeShaderVariants _upsampleComputeVariants = new ComputeShaderVariants(480);
//Debug and composite variants skipped for now because its always the final blit to show up the render context
//Renderbuffers
private CommandBuffer _commandBuffer;
private bool _finalBlit = true;
private RenderTarget _selectiveRenderTarget;
private MipBuffer _bloomDownsampleBuffer, _bloomUpsampleBuffer;
private MipBuffer _lensFlareDownsampleBuffer, _lensFlareUpsampleBuffer;
private MipBuffer _glareDownsampleBuffer0, _glareDownsampleBuffer1, _glareDownsampleBuffer2, _glareDownsampleBuffer3, _glareUpsampleBuffer0, _glareUpsampleBuffer1, _glareUpsampleBuffer2, _glareUpsampleBuffer3;
private RenderTarget _sourceFrameBuffer, _destinationFrameBuffer;
private RenderTarget sourceFrameBuffer
{
get
{
return _settings.GetWorkflow() == Workflow.Selective && _debugView != DebugView.None ? _selectiveRenderTarget : _sourceFrameBuffer;
}
}
//Runtime needed
private Keyword[] _shaderKeywords = new Keyword[]
{
new Keyword("_MK_BLOOM", false),
new Keyword("_MK_LENS_SURFACE", false),
new Keyword("_MK_LENS_FLARE", false),
new Keyword("_MK_GLARE_1", false),
new Keyword("_MK_DEBUG_RAW_BLOOM", false),
new Keyword("_MK_DEBUG_RAW_LENS_FLARE", false),
new Keyword("_MK_DEBUG_RAW_GLARE", false),
new Keyword("_MK_DEBUG_BLOOM", false), //No Keyword will be set
new Keyword("_MK_DEBUG_LENS_FLARE", false),
new Keyword("_MK_DEBUG_GLARE", false),
new Keyword("_MK_DEBUG_COMPOSITE", false),
new Keyword("_MK_LEGACY_BLIT", false),
new Keyword("_MK_RENDER_PRIORITY_QUALITY", false),
new Keyword("_MK_NATURAL", false),
new Keyword("_MK_GLARE_2", false),
new Keyword("_MK_GLARE_3", false),
new Keyword("_MK_GLARE_4", false),
new Keyword("", false),
new Keyword("_MK_RENDER_PRIORITY_BALANCED", false),
new Keyword("_MK_HQ_ANTI_FLICKER", false)
};
//Used features
private bool _useGeometryShaders, _useComputeShaders, _useLensSurface, _useLensFlare, _useGlare;
//Lists
private List<RenderTarget> _renderTargetsBundle;
private List<MaterialKeywords> _renderKeywordsBundle;
//Rendering dependent
private int _bloomIterations, _lensFlareIterations, _minIterations, _glareIterations, _currentRenderIndex;
internal int currentRenderIndex { get { return _currentRenderIndex; }}
private float bloomUpsampleSpread, _lensFlareUpsampleSpread, _glareScatteringMult;
private Vector2 _resolutionScale;
private Vector2[] glareAngles = new Vector2[4];
private RenderTextureFormat _renderTextureFormat;
internal RenderTextureFormat renderTextureFormat { get{ return _renderTextureFormat; } }
private ComputeShaderVariants.KeywordState computeShaderFeatures = new ComputeShaderVariants.KeywordState(0, 0, 0, 0, 0, 0);
private RenderContext[] _sourceContext, _renderContext;
private RenderContext _selectiveRenderContext;
private UnityEngine.Camera _renderingCamera;
private ICameraData _cameraData;
private RenderPipeline _renderPipeline;
private DebugView _debugView;
//Materials
private Material _renderMaterialNoGeometry;
internal Material renderMaterialNoGeometry { get { return _renderMaterialNoGeometry; } }
private Material _renderMaterialGeometry;
//Direct compute dependent
private float[] _cArgArray = new float[_cArgBufferSize];
private ComputeBuffer _cArgsComputeBuffer;
private RenderDimension _computeThreadGroups = new RenderDimension();
//Settings
private ISettings _settings;
/////////////////////////////////////////////////////////////////////////////////////////////
// Unity MonoBehavior Messages
/////////////////////////////////////////////////////////////////////////////////////////////
//shaderoverwrites should both null or referenced
internal void Enable(RenderPipeline renderPipeline)
{
_resources = MK.Glow.Resources.LoadResourcesAsset();
_renderTextureFormat = Compatibility.CheckSupportedRenderTextureFormat();
_renderPipeline = renderPipeline;
_sourceContext = new RenderContext[1]{new RenderContext()};
_renderContext = new RenderContext[PipelineProperties.renderBufferSize];
for(int i = 0; i < PipelineProperties.renderBufferSize; i++)
_renderContext[i] = new RenderContext();
_selectiveRenderContext = new RenderContext();
_renderMaterialNoGeometry = new Material(_resources.sm45Shader) { hideFlags = HideFlags.HideAndDontSave };
_renderMaterialGeometry = new Material(_resources.sm45Shader) { hideFlags = HideFlags.HideAndDontSave };
_renderTargetsBundle = new List<RenderTarget>();
_renderKeywordsBundle = new List<MaterialKeywords>();
//create buffers
_bloomDownsampleBuffer = new MipBuffer(PipelineProperties.CommandBufferProperties.bloomDownsampleBuffer, _renderPipeline);
_bloomUpsampleBuffer = new MipBuffer(PipelineProperties.CommandBufferProperties.bloomUpsampleBuffer, _renderPipeline);
_lensFlareDownsampleBuffer = new MipBuffer(PipelineProperties.CommandBufferProperties.lensFlareDownsampleBuffer, _renderPipeline);
_lensFlareUpsampleBuffer = new MipBuffer(PipelineProperties.CommandBufferProperties.lensFlareUpsampleBuffer, _renderPipeline);
_glareDownsampleBuffer0 = new MipBuffer(PipelineProperties.CommandBufferProperties.glareDownsampleBuffer0, _renderPipeline);
_glareDownsampleBuffer1 = new MipBuffer(PipelineProperties.CommandBufferProperties.glareDownsampleBuffer1, _renderPipeline);
_glareDownsampleBuffer2 = new MipBuffer(PipelineProperties.CommandBufferProperties.glareDownsampleBuffer2, _renderPipeline);
_glareDownsampleBuffer3 = new MipBuffer(PipelineProperties.CommandBufferProperties.glareDownsampleBuffer3, _renderPipeline);
_glareUpsampleBuffer0 = new MipBuffer(PipelineProperties.CommandBufferProperties.glareUpsampleBuffer0, _renderPipeline);
_glareUpsampleBuffer1 = new MipBuffer(PipelineProperties.CommandBufferProperties.glareUpsampleBuffer1, _renderPipeline);
_glareUpsampleBuffer2 = new MipBuffer(PipelineProperties.CommandBufferProperties.glareUpsampleBuffer2, _renderPipeline);
_glareUpsampleBuffer3 = new MipBuffer(PipelineProperties.CommandBufferProperties.glareUpsampleBuffer3, _renderPipeline);
}
~Effect()
{
//_cArgsComputeBuffer.Release();
_cArgsComputeBuffer = null;
}
internal void Disable()
{
_currentRenderIndex = 0;
_renderTargetsBundle.Clear();
_renderKeywordsBundle.Clear();
PipelineExtensions.Destroy(_selectiveGlowCamera);
PipelineExtensions.Destroy(_selectiveGlowCameraObject);
PipelineExtensions.Destroy(_renderMaterialNoGeometry);
PipelineExtensions.Destroy(_renderMaterialGeometry);
MK.Glow.Resources.UnLoadResourcesAsset(_resources);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// RenderBuffers
/////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Prepare Scattering parameters fora given Scattering value
/// </summary>
/// <param name="Scattering"></param>
/// <param name="scale"></param>
/// <param name="iterations"></param>
/// <param name="spread"></param>
private void PrepareScattering(float Scattering, float scale, ref int iterations, ref float spread)
{
/*
float lit = Mathf.Log(scale, 2f) + Mathf.Min(Scattering, 10f) - 10f;
int litF = Mathf.FloorToInt(lit);
iterations = Mathf.Clamp(litF, 1, 15);
spread = 0.5f + lit - litF;
*/
float scaledIterations = scale + Mathf.Clamp(Scattering, 1f, 10.0f) - 10.0f;
iterations = Mathf.Max(Mathf.FloorToInt(scaledIterations), 1);
spread = scaledIterations > 1 ? 0.5f + scaledIterations - iterations : 0.5f;
}
/// <summary>
/// Create renderbuffers
/// </summary>
private void UpdateRenderBuffers()
{
RenderDimension renderDimension = new RenderDimension(_cameraData.GetCameraWidth(), _cameraData.GetCameraHeight());
_sourceContext[0].UpdateRenderContext(_cameraData, _renderTextureFormat, 0, _useComputeShaders, renderDimension);
_sourceContext[0].SinglePassStereoAdjustWidth(_cameraData.GetStereoEnabled());
Vector2 anamorphic = new Vector2(_settings.GetAnamorphicRatio() < 0 ? -_settings.GetAnamorphicRatio() : 0f, _settings.GetAnamorphicRatio() > 0 ? _settings.GetAnamorphicRatio() : 0f);
switch(_settings.GetQuality())
{
case Quality.Ultra:
anamorphic *= 0.5f;
break;
case Quality.High:
//anamorphic *= 1.0f;
break;
case Quality.Medium:
anamorphic *= 2.0f;
break;
case Quality.Low:
anamorphic *= 4.0f;
break;
case Quality.VeryLow:
anamorphic *= 6.0f;
break;
}
renderDimension = new RenderDimension(Mathf.CeilToInt(_sourceContext[0].width / ((float)_settings.GetQuality() - anamorphic.x)), Mathf.CeilToInt(_sourceContext[0].height / ((float)_settings.GetQuality() - anamorphic.y)));
float sizeScale = Mathf.Log(Mathf.FloorToInt(Mathf.Max(renderDimension.width, renderDimension.height)), 2.0f);
//float sizeScale = Mathf.FloorToInt(Mathf.Max(renderDimension.width, renderDimension.height));
PrepareScattering(_settings.GetBloomScattering(), sizeScale, ref _bloomIterations, ref bloomUpsampleSpread);
_minIterations = _bloomIterations;
if(_useLensFlare)
{
PrepareScattering(_settings.GetLensFlareScattering(), sizeScale, ref _lensFlareIterations, ref _lensFlareUpsampleSpread);
if(_lensFlareIterations > _minIterations)
_minIterations = _lensFlareIterations;
}
if(_useGlare)
{
switch(_settings.GetQuality())
{
case Quality.High:
case Quality.Medium:
case Quality.Low:
_glareIterations = _glareIterationsBase;
_glareScatteringMult = 1;
break;
default:
_glareIterations = _glareIterationsBase;
_glareScatteringMult = 1;
break;
}
if(_glareIterations > _minIterations)
_minIterations = _glareIterations;
}
_cameraData.UpdateMipRenderContext(_renderContext, renderDimension, _minIterations + 1, _renderTextureFormat, 0, _useComputeShaders);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Selective glow setup
/////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// selective replacement shader rendering camera for the glow
/// </summary>
private GameObject selectiveGlowCameraObject
{
get
{
if(!_selectiveGlowCameraObject)
{
_selectiveGlowCameraObject = new GameObject(_selectiveGlowCameraObjectName);
_selectiveGlowCameraObject.AddComponent<UnityEngine.Camera>();
_selectiveGlowCameraObject.hideFlags = HideFlags.HideAndDontSave;
}
return _selectiveGlowCameraObject;
}
}
/// <summary>
/// selective replacement shader rendering camera forthe glow
/// </summary>
private UnityEngine.Camera selectiveGlowCamera
{
get
{
if(_selectiveGlowCamera == null)
{
_selectiveGlowCamera = selectiveGlowCameraObject.GetComponent<UnityEngine.Camera>();
_selectiveGlowCamera.hideFlags = HideFlags.HideAndDontSave;
_selectiveGlowCamera.enabled = false;
}
return _selectiveGlowCamera;
}
}
/// <summary>
/// Prepare replacement rendering camera forthe selective glow
/// </summary>
private void SetupSelectiveGlowCamera()
{
selectiveGlowCamera.CopyFrom(_renderingCamera);
selectiveGlowCamera.targetTexture = _selectiveRenderTarget.renderTexture;
selectiveGlowCamera.clearFlags = CameraClearFlags.SolidColor;
selectiveGlowCamera.rect = new Rect(0,0, 1,1);
selectiveGlowCamera.backgroundColor = new Color(0, 0, 0, 1);
selectiveGlowCamera.cullingMask = _settings.GetSelectiveRenderLayerMask();
selectiveGlowCamera.renderingPath = RenderingPath.VertexLit;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// CommandBuffer creation
/////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Enable or disable all supported / unsupported shaders based on the platform
/// </summary>
private void CheckFeatureSupport()
{
//Check iflens surface is set
if(_settings.GetAllowLensSurface())
_useLensSurface = true;
else
_useLensSurface = false;
//Check ifLensFlare is supported
if(_settings.GetAllowLensFlare() && Compatibility.CheckLensFlareFeatureSupport() && (int)_settings.GetQuality() <= 4)
_useLensFlare = true;
else
_useLensFlare = false;
//Check if Glare is supported
if(_settings.GetAllowGlare() && Compatibility.CheckGlareFeatureSupport() && (int)_settings.GetQuality() <= 4)
_useGlare = true;
else
_useGlare = false;
/*
//Check for geometry shader support
if(_settings.allowGeometryShaders && Compatibility.CheckGeometryShaderSupport())
_useGeometryShaders = true;
else
_useGeometryShaders = false;
//Check for compute shader support
//TODO: if single pass stereo enabled compute shaders are turning off because UCG variables are not defined
// -> more compute shader variants are needed
//dont allow compute shaders to do lens flare on gles and glcore - dynamic for loop combined with compute shader seems not to work
if(_settings.allowComputeShaders && Compatibility.CheckComputeShaderSupport() && !_cameraData.GetStereoEnabled())
_useComputeShaders = true;
else
_useComputeShaders = false;
*/
//If any debug view without depending feature is enabled fallback to default rendering
if(_debugView != DebugView.None)
{
if(!_useLensFlare && (_debugView == DebugView.LensFlare || _debugView == DebugView.RawLensFlare) ||
!_useGlare &&(_debugView == DebugView.Glare || _debugView == DebugView.RawGlare))
_debugView = DebugView.None;
}
_useComputeShaders = false;
_useGeometryShaders = false;
}
private void BeginProfileSample(string text)
{
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.BeginSample(text);
else
UnityEngine.Profiling.Profiler.BeginSample(text);
}
private void EndProfileSample(string text)
{
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.EndSample(text);
else
UnityEngine.Profiling.Profiler.EndSample();
}
//Camera is still required for backwards compatibility of selective glow, should be removed in the future
/// <summary>
/// Renders the effect from source into destination buffer
/// </summary>
/// <param name="source"></param>
/// <param name="destination"></param>
internal void Build(RenderTarget source, RenderTarget destination, ISettings settings, CommandBuffer cmd, ICameraData cameraData, UnityEngine.Camera renderingCamera = null, bool finalBlit = true)
{
_commandBuffer = cmd;
_finalBlit = finalBlit;
_settings = settings;
_renderingCamera = renderingCamera;
_cameraData = cameraData;
_debugView = settings.GetDebugView();
BeginProfileSample(PipelineProperties.CommandBufferProperties.samplePrepare);
CheckFeatureSupport();
_sourceFrameBuffer = source;
_destinationFrameBuffer = destination;
UpdateRenderBuffers();
EndProfileSample(PipelineProperties.CommandBufferProperties.samplePrepare);
//Prepare for selective glow
if(_settings.GetWorkflow() == Workflow.Selective)
{
BeginProfileSample(PipelineProperties.CommandBufferProperties.sampleReplacement);
_selectiveRenderContext.UpdateRenderContext(_cameraData, _renderTextureFormat, 16, false, _sourceContext[0].renderDimension);
//The allowVerticallyFlip flag seems to break sometimes orientation of the rendered glow map, therefore force the old way.
_selectiveRenderTarget.renderTexture = RenderTexture.GetTemporary(_cameraData.GetCameraWidth() / (int)_settings.GetQuality(), _cameraData.GetCameraHeight() / (int)_settings.GetQuality(), 16, _renderTextureFormat, RenderTextureReadWrite.Default, 1);//PipelineExtensions.GetTemporary(_selectiveRenderContext, _renderTextureFormat);
SetupSelectiveGlowCamera();
selectiveGlowCamera.RenderWithShader(_resources.selectiveRenderShader, _selectiveReplacementTag);
EndProfileSample(PipelineProperties.CommandBufferProperties.sampleReplacement);
}
BeginProfileSample(PipelineProperties.CommandBufferProperties.sampleSetup);
_resolutionScale = new Vector2(_renderContext[0].width / _referenceResolution.x * _renderContext[0].height / _renderContext[0].width / _referenceAspectRatio, _renderContext[0].height / _referenceResolution.y);
UpdateConstantBuffers();
EndProfileSample(PipelineProperties.CommandBufferProperties.sampleSetup);
PreSample();
Downsample();
Upsample();
Composite();
}
/// <summary>
/// Update the profile based on the user input
/// </summary>
private void UpdateConstantBuffers()
{
//Common
SetVector(PipelineProperties.ShaderProperties.screenSize, new Vector2(_cameraData.GetCameraWidth(), _cameraData.GetCameraHeight()), true);
SetFloat(PipelineProperties.ShaderProperties.singlePassStereoScale, PipelineProperties.singlePassStereoDoubleWideEnabled ? 2 : 1);
SetFloat(PipelineProperties.ShaderProperties.lumaScale, _settings.GetLumaScale());
SetFloat(PipelineProperties.ShaderProperties.blooming, _settings.GetBlooming(), true);
SetVector(PipelineProperties.ShaderProperties.resolutionScale, _resolutionScale);
SetVector(PipelineProperties.ShaderProperties.resolutionScale, _resolutionScale, true);
SetVector(PipelineProperties.ShaderProperties.renderTargetSize, new Vector2(_cameraData.GetCameraWidth(), _cameraData.GetCameraHeight()), true);
Matrix4x4 viewMatrix = _cameraData.GetWorldToCameraMatrix();
//Setting 4x4 matrix via vector rows
if(_useComputeShaders)
{
SetVector(ShaderProperties.viewMatrix, viewMatrix.GetRow(0), true);
SetVector(ShaderProperties.viewMatrix, viewMatrix.GetRow(1), true);
SetVector(ShaderProperties.viewMatrix, viewMatrix.GetRow(2), true);
SetVector(ShaderProperties.viewMatrix, viewMatrix.GetRow(3), true);
}
else
{
Shader.SetGlobalMatrix(ShaderProperties.viewMatrix.id, viewMatrix);
}
//Bloom
SetFloat(PipelineProperties.ShaderProperties.bloomIntensity, ConvertGammaValue(_settings.GetBloomIntensity() * (_settings.GetWorkflow() == Workflow.Natural ? naturalIntensityMult : 1f)), true);
SetFloat(PipelineProperties.ShaderProperties.bloomSpread, bloomUpsampleSpread);
SetFloat(PipelineProperties.ShaderProperties.bloomSpread, bloomUpsampleSpread, true);
SetVector(PipelineProperties.ShaderProperties.bloomThreshold, _settings.GetWorkflow() == Workflow.Selective ? _selectiveWorkflowThreshold : new Vector2(ConvertGammaValue(_settings.GetBloomThreshold().minValue), ConvertGammaValue(_settings.GetBloomThreshold().maxValue)), _debugView == DebugView.RawBloom ? true : false);
//LensSurface
if(_useLensSurface)
{
SetFloat(PipelineProperties.ShaderProperties.lensSurfaceDirtIntensity, ConvertGammaValue(_settings.GetLensSurfaceDirtIntensity() * (_settings.GetWorkflow() == Workflow.Natural ? naturalIntensityMult : 1f)), true);
SetFloat(PipelineProperties.ShaderProperties.lensSurfaceDiffractionIntensity, ConvertGammaValue(_settings.GetLensSurfaceDiffractionIntensity() * (_settings.GetWorkflow() == Workflow.Natural ? naturalIntensityMult : 1f)), true);
float dirtRatio = (float)(_settings.GetLensSurfaceDirtTexture() ? _settings.GetLensSurfaceDirtTexture().width : _resources.lensSurfaceDirtTextureDefault.width) /
(float)(_settings.GetLensSurfaceDirtTexture() ? _settings.GetLensSurfaceDirtTexture().height : _resources.lensSurfaceDirtTextureDefault.height);
float dsRatio = _cameraData.GetAspect() / dirtRatio;
float sdRatio = dirtRatio / _cameraData.GetAspect();
SetVector(PipelineProperties.ShaderProperties.lensSurfaceDirtTexST, dirtRatio > _cameraData.GetAspect() ?
new Vector4(dsRatio, 1, (1f - dsRatio) * 0.5f, 0) :
new Vector4(1, sdRatio, 0, (1f - sdRatio) * 0.5f), true);
}
//LensFlare
if(_useLensFlare)
{
Presets.SetLensFlarePreset(_settings.GetLensFlareStyle(), _settings);
SetVector(PipelineProperties.ShaderProperties.lensFlareThreshold, _settings.GetWorkflow() == Workflow.Selective ? _selectiveWorkflowThreshold : new Vector2(ConvertGammaValue(_settings.GetLensFlareThreshold().minValue), ConvertGammaValue(_settings.GetLensFlareThreshold().maxValue)), _debugView == DebugView.RawLensFlare ? true : false);
SetVector(PipelineProperties.ShaderProperties.lensFlareGhostParams, new Vector4(_settings.GetLensFlareGhostCount(), _settings.GetLensFlareGhostDispersal(), _settings.GetLensFlareGhostFade(), ConvertGammaValue(_settings.GetLensFlareGhostIntensity() * (_settings.GetWorkflow() == Workflow.Natural ? naturalIntensityMult : 1f))));
SetVector(PipelineProperties.ShaderProperties.lensFlareHaloParams, new Vector3(_settings.GetLensFlareHaloSize(), _settings.GetLensFlareHaloFade(), ConvertGammaValue(_settings.GetLensFlareHaloIntensity() * (_settings.GetWorkflow() == Workflow.Natural ? naturalIntensityMult : 1f))));
SetFloat(PipelineProperties.ShaderProperties.lensFlareSpread, _lensFlareUpsampleSpread);
SetFloat(PipelineProperties.ShaderProperties.lensFlareChromaticAberration, _settings.GetLensFlareChromaticAberration(), true);
}
//Glare
if(_useGlare)
{
Presets.SetGlarePreset(_settings.GetGlareStyle(), _settings);
SetVector(PipelineProperties.ShaderProperties.glareThreshold, _settings.GetWorkflow() == Workflow.Selective ? _selectiveWorkflowThreshold : new Vector2(ConvertGammaValue(_settings.GetGlareThreshold().minValue), ConvertGammaValue(_settings.GetGlareThreshold().maxValue)), _debugView == DebugView.RawGlare ? true : false);
SetFloat(PipelineProperties.ShaderProperties.glareBlend, _settings.GetGlareBlend(), true);
SetVector(PipelineProperties.ShaderProperties.glareIntensity, ConvertGammaValue(new Vector4(_settings.GetGlareSample0Intensity(), _settings.GetGlareSample1Intensity(), _settings.GetGlareSample2Intensity(), _settings.GetGlareSample3Intensity())), true);
Vector4 Scattering = new Vector4(_settings.GetGlareSample0Scattering() * _glareScatteringMult * _settings.GetGlareScattering(), _settings.GetGlareSample1Scattering() * _glareScatteringMult * _settings.GetGlareScattering(), _settings.GetGlareSample2Scattering() * _glareScatteringMult * _settings.GetGlareScattering(), _settings.GetGlareSample3Scattering() * _glareScatteringMult * _settings.GetGlareScattering());
glareAngles[0] = AngleToDirection(_settings.GetGlareSample0Angle() + _settings.GetGlareAngle());
glareAngles[1] = AngleToDirection(_settings.GetGlareSample1Angle() + _settings.GetGlareAngle());
glareAngles[2] = AngleToDirection(_settings.GetGlareSample2Angle() + _settings.GetGlareAngle());
glareAngles[3] = AngleToDirection(_settings.GetGlareSample3Angle() + _settings.GetGlareAngle());
Vector4 direction01 = new Vector4(glareAngles[0].x, glareAngles[0].y, glareAngles[1].x, glareAngles[1].y);
Vector4 direction02 = new Vector4(glareAngles[2].x, glareAngles[2].y, glareAngles[3].x, glareAngles[3].y);
Vector4 offset = new Vector4(_settings.GetGlareSample0Offset(), _settings.GetGlareSample1Offset(), _settings.GetGlareSample2Offset(), _settings.GetGlareSample3Offset());
SetVector(PipelineProperties.ShaderProperties.glareScattering, Scattering);
SetVector(PipelineProperties.ShaderProperties.glareDirection01, direction01);
SetVector(PipelineProperties.ShaderProperties.glareDirection23, direction02);
SetVector(PipelineProperties.ShaderProperties.glareOffset, offset);
SetVector(PipelineProperties.ShaderProperties.glareScattering, Scattering, true);
SetVector(PipelineProperties.ShaderProperties.glareDirection01, direction01, true);
SetVector(PipelineProperties.ShaderProperties.glareDirection23, direction02, true);
SetVector(PipelineProperties.ShaderProperties.glareOffset, offset, true);
SetFloat(PipelineProperties.ShaderProperties.glareGlobalIntensity, ConvertGammaValue(_settings.GetGlareIntensity()) * (_settings.GetWorkflow() == Workflow.Natural ? naturalIntensityMult : 1f), true);
}
if(_useComputeShaders)
_cArgsComputeBuffer.SetData(_cArgArray);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Commandbuffer helpers
/////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Set a specific keyword for the pixelshader
/// </summary>
/// <param name="keyword"></param>
/// <param name="enable"></param>
private void SetKeyword(MaterialKeywords keyword, bool enable)
{
//For now disable check if a keyword is already set
//to make sure the cmd is always correctly setuped
//if(_shaderKeywords[(int)keyword].enabled != enable)
{
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetKeyword(_shaderKeywords[(int)keyword].name, enable);
else
PipelineExtensions.SetKeyword(_shaderKeywords[(int)keyword].name, enable);
_shaderKeywords[(int)keyword].enabled = enable;
}
}
/// <summary>
/// Convert an angle (degree) to a Vector2 direction
/// </summary>
/// <returns></returns>
private Vector2 AngleToDirection(float angleDegree)
{
return new Vector2(Mathf.Sin(angleDegree * Mathf.Deg2Rad), Mathf.Cos(angleDegree * Mathf.Deg2Rad));
}
/// <summary>
/// get a threshold value based on current color space
/// </summary>
private float ConvertGammaValue(float gammaSpacedValue)
{
if(QualitySettings.activeColorSpace == ColorSpace.Linear)
{
return Mathf.GammaToLinearSpace(gammaSpacedValue);
}
else
return gammaSpacedValue;
}
/// <summary>
/// get a threshold value based on current color space
/// </summary>
private Vector4 ConvertGammaValue(Vector4 gammaSpacedVector)
{
if(QualitySettings.activeColorSpace == ColorSpace.Linear)
{
gammaSpacedVector.x = ConvertGammaValue(gammaSpacedVector.x);
gammaSpacedVector.y = ConvertGammaValue(gammaSpacedVector.y);
gammaSpacedVector.z = ConvertGammaValue(gammaSpacedVector.z);
gammaSpacedVector.w = ConvertGammaValue(gammaSpacedVector.w);
return gammaSpacedVector;
}
else
return gammaSpacedVector;
}
/// <summary>
/// Get the needed Threadgroups forcompute shaders
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
private void UpdateComputeShaderThreadGroups(RenderDimension renderDimension)
{
_computeThreadGroups.width = Mathf.Max(1, Mathf.FloorToInt((renderDimension.width + _directComputeSize.height) / _directComputeSize.width));
_computeThreadGroups.height = Mathf.Max(1, Mathf.FloorToInt((renderDimension.height + _directComputeSize.height) / _directComputeSize.width));
}
/// <summary>
/// Update the renderindex (pass) forthe next Draw
/// </summary>
/// <param name="v"></param>
private void UpdateRenderIndex(int v)
{
_currentRenderIndex = v;
}
/// <summary>
/// Update the renderindex (compute kernel) for the next Draw
/// </summary>
/// <param name="variants"></param>
/// <param name="features"></param>
private void UpdateRenderIndex(ComputeShaderVariants variants, ComputeShaderVariants.KeywordState features)
{
variants.GetVariantNumber(features, out _currentRenderIndex);
}
/// <summary>
/// Attach CArgs to currently used kernel
/// </summary>
private void AttachCArgBufferToComputeKernel()
{
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetComputeBufferParam(_resources.computeShader, _currentRenderIndex, ShaderProperties.cArgBuffer.id, _cArgsComputeBuffer);
else
_resources.computeShader.SetBuffer(_currentRenderIndex, ShaderProperties.cArgBuffer.id, _cArgsComputeBuffer);
}
/// <summary>
/// Auto set a float value on the renderpipeline
/// </summary>
/// <param name="property"></param>
/// <param name="value"></param>
private void SetFloat(ShaderProperties.CBufferProperty property, float value, bool forcePixelShader = false)
{
if(_useComputeShaders && !forcePixelShader)
_cArgArray[property.index] = value;
else
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetGlobalFloat(property.id, value);
else
Shader.SetGlobalFloat(property.id, value);
}
/// <summary>
/// Auto set a vector value on the renderpipeline
/// </summary>
/// <param name="property"></param>
/// <param name="value"></param>
private void SetVector(ShaderProperties.CBufferProperty property, Vector4 value, bool forcePixelShader = false)
{
if(_useComputeShaders && !forcePixelShader)
{
_cArgArray[property.index] = value.x;
_cArgArray[property.index + 1] = value.y;
_cArgArray[property.index + 2] = value.z;
_cArgArray[property.index + 3] = value.w;
}
else
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetGlobalVector(property.id, value);
else
Shader.SetGlobalVector(property.id, value);
}
/// <summary>
/// Auto set a vector value on the renderpipeline
/// </summary>
/// <param name="property"></param>
/// <param name="value"></param>
private void SetVector(ShaderProperties.CBufferProperty property, Vector3 value, bool forcePixelShader = false)
{
if(_useComputeShaders && !forcePixelShader)
{
_cArgArray[property.index] = value.x;
_cArgArray[property.index + 1] = value.y;
_cArgArray[property.index + 2] = value.z;
}
else
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetGlobalVector(property.id, value);
else
Shader.SetGlobalVector(property.id, value);
}
/// <summary>
/// Auto set a vector value on the renderpipeline
/// </summary>
/// <param name="property"></param>
/// <param name="value"></param>
private void SetVector(ShaderProperties.CBufferProperty property, Vector2 value, bool forcePixelShader = false)
{
if(_useComputeShaders && !forcePixelShader)
{
_cArgArray[property.index] = value.x;
_cArgArray[property.index + 1] = value.y;
}
else
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetGlobalVector(property.id, value);
else
Shader.SetGlobalVector(property.id, value);
}
/// <summary>
/// Auto set a texture on the renderpipeline,
/// always update the computeKernelIndexBuffer before using this to get the correct variant while using compute shaders
/// </summary>
/// <param name="property"></param>
/// <param name="rt"></param>
/// <param name="forcePixelShader"></param>
private void SetTexture(ShaderProperties.DefaultProperty property, RenderTarget rt, bool forcePixelShader = false)
{
if(_useComputeShaders && !forcePixelShader)
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetComputeTextureParam(_resources.computeShader, _currentRenderIndex, property.id, rt.renderTargetIdentifier);
else
_resources.computeShader.SetTexture(_currentRenderIndex, property.id, rt.renderTexture);
else
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetGlobalTexture(property.id, rt.renderTargetIdentifier);
else
Shader.SetGlobalTexture(property.id, rt.renderTexture);
}
private void SetTexture(ShaderProperties.DefaultProperty property, Texture tex, bool forcePixelShader = false)
{
if(_useComputeShaders && !forcePixelShader)
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetComputeTextureParam(_resources.computeShader, _currentRenderIndex, property.id, tex);
else
_resources.computeShader.SetTexture(_currentRenderIndex, property.id, tex);
else
if(_renderPipeline == RenderPipeline.SRP)
_commandBuffer.SetGlobalTexture(property.id, tex);
else
Shader.SetGlobalTexture(property.id, tex);
}
/// <summary>
/// Setup for the next draw command
/// </summary>
/// <param name="variant"></param>
/// <param name="renderDimension"></param>
/// <param name="forcePixelShader"></param>
private void PrepareDraw(int variant, RenderDimension renderDimension, bool forcePixelShader = false)
{
if(_useComputeShaders && !forcePixelShader)
{
UpdateRenderIndex(variant);
AttachCArgBufferToComputeKernel();
UpdateComputeShaderThreadGroups(renderDimension);
}
else
{
SetRenderPriority();
UpdateRenderIndex(variant);
DisableRenderKeywords();
foreach(MaterialKeywords kw in _renderKeywordsBundle)
SetKeyword(kw, true);
_renderKeywordsBundle.Clear();
}
}
/// <summary>
/// Setup for the next draw command
/// </summary>
/// <param name="materialPass"></param>
/// <param name="variants"></param>
/// <param name="features"></param>
/// <param name="renderDimension"></param>
private void PrepareDraw(int materialPass, ComputeShaderVariants variants, bool enableBloom, bool enableLensflare, bool enableGlare, RenderDimension renderDimension)
{
if(_useComputeShaders)
{
computeShaderFeatures.bloom = enableBloom ? 1 : 0;
computeShaderFeatures.lensSurface = _settings.GetAllowLensSurface() ? 1 : 0;
computeShaderFeatures.lensFlare = enableLensflare ? 1 : 0;
computeShaderFeatures.glare = enableGlare ? _settings.GetGlareStreaks() : 0;
computeShaderFeatures.natural = (int)_settings.GetWorkflow() == 2 ? 1 : 0;
computeShaderFeatures.renderPriority = (int)_settings.GetRenderPriority() <= 0 ? 0 : (int)_settings.GetRenderPriority() == 1 ? 1 : 2;
UpdateRenderIndex(variants, computeShaderFeatures);
AttachCArgBufferToComputeKernel();
UpdateComputeShaderThreadGroups(renderDimension);
}
else
{
SetRenderPriority();
UpdateRenderIndex(materialPass);
DisableRenderKeywords();
foreach(MaterialKeywords kw in _renderKeywordsBundle)
SetKeyword(kw, true);
_renderKeywordsBundle.Clear();
}
}
/// <summary>
/// Draw into a destination framebuffer based on shadertype
/// Always prepare for drawing using the PrepareDraw command
/// </summary>
/// <param name="forcePixelShader"></param>
private void Draw(RenderDimension dimension, bool forcePixelShader = false)
{
if(_renderPipeline == RenderPipeline.SRP)
{
if(_useComputeShaders && !forcePixelShader)
_commandBuffer.Draw(_renderTargetsBundle, _resources.computeShader, _currentRenderIndex, _computeThreadGroups);
else
_commandBuffer.Draw(_renderTargetsBundle, _useGeometryShaders ? _renderMaterialGeometry : _renderMaterialNoGeometry, _useGeometryShaders, _currentRenderIndex, new Rect(0, 0, dimension.width, dimension.height));
}
else
{
if(_useComputeShaders && !forcePixelShader)
PipelineExtensions.Draw(_renderTargetsBundle, _resources.computeShader, _currentRenderIndex, _computeThreadGroups);
else
PipelineExtensions.Draw(_renderTargetsBundle, _useGeometryShaders ? _renderMaterialGeometry : _renderMaterialNoGeometry, _useGeometryShaders, _currentRenderIndex);
}
_renderTargetsBundle.Clear();
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Sampling
/////////////////////////////////////////////////////////////////////////////////////////////
private MaterialKeywords GetGlareKeyword(int streaks)
{
switch(streaks)
{
case 1:
return MaterialKeywords.Glare1;
case 2:
return MaterialKeywords.Glare2;
case 3:
return MaterialKeywords.Glare3;
case 4:
return MaterialKeywords.Glare4;
default:
return MaterialKeywords.Null;
}
}
/// <summary>
/// Disable render Keywords
/// </summary>
private void DisableRenderKeywords()
{
SetKeyword(MaterialKeywords.Bloom, false);
SetKeyword(MaterialKeywords.LensSurface, false);
SetKeyword(MaterialKeywords.LensFlare, false);
SetKeyword(MaterialKeywords.Glare1, false);
SetKeyword(MaterialKeywords.Glare2, false);
SetKeyword(MaterialKeywords.Glare3, false);
SetKeyword(MaterialKeywords.Glare4, false);
SetKeyword(MaterialKeywords.RenderPriorityBalanced, false);
SetKeyword(MaterialKeywords.RenderPriorityQuality, false);
SetKeyword(MaterialKeywords.Natural, false);
SetKeyword(MaterialKeywords.HQAntiFlickerFilter, false);
}
/// <summary>
/// Disable debug Keywords
/// </summary>
private void DisableDebugKeywords()
{
SetKeyword(MaterialKeywords.DebugRawBloom, false);
SetKeyword(MaterialKeywords.DebugRawLensFlare, false);
SetKeyword(MaterialKeywords.DebugRawGlare, false);
SetKeyword(MaterialKeywords.DebugBloom, false);
SetKeyword(MaterialKeywords.DebugLensFlare, false);
SetKeyword(MaterialKeywords.DebugGlare, false);
SetKeyword(MaterialKeywords.DebugComposite, false);
}
private void SetRenderPriority()
{
if(_settings.GetRenderPriority() == RenderPriority.Quality)
{
_renderKeywordsBundle.Add(MaterialKeywords.RenderPriorityQuality);
}
else if(_settings.GetRenderPriority() == RenderPriority.Balanced)
{
_renderKeywordsBundle.Add(MaterialKeywords.RenderPriorityBalanced);
}
else
{
}
}
/// <summary>
/// Pre sample the glow map
/// </summary>
private void PreSample()
{
BeginProfileSample(PipelineProperties.CommandBufferProperties.samplePreSample);
_bloomDownsampleBuffer.CreateTemporary(_renderContext, 0, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
if(_settings.GetAntiFlickerMode() == AntiFlickerMode.Strong)
_renderKeywordsBundle.Add(MaterialKeywords.HQAntiFlickerFilter);
_renderKeywordsBundle.Add(MaterialKeywords.Bloom);
if(_settings.GetWorkflow() == Workflow.Natural)
_renderKeywordsBundle.Add(MaterialKeywords.Natural);
_renderTargetsBundle.Add(_bloomDownsampleBuffer.renderTargets[0]);
if(_useLensFlare)
{
_lensFlareDownsampleBuffer.CreateTemporary(_renderContext, 0, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderKeywordsBundle.Add(MaterialKeywords.LensFlare);
_renderTargetsBundle.Add(_lensFlareDownsampleBuffer.renderTargets[0]);
}
if(_useGlare)
{
_glareDownsampleBuffer0.CreateTemporary(_renderContext, 0, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_glareDownsampleBuffer1.CreateTemporary(_renderContext, 0, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_glareDownsampleBuffer2.CreateTemporary(_renderContext, 0, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_glareDownsampleBuffer3.CreateTemporary(_renderContext, 0, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderKeywordsBundle.Add(GetGlareKeyword(_settings.GetGlareStreaks()));
_renderTargetsBundle.Add(_glareDownsampleBuffer0.renderTargets[0]);
_renderTargetsBundle.Add(_glareDownsampleBuffer1.renderTargets[0]);
_renderTargetsBundle.Add(_glareDownsampleBuffer2.renderTargets[0]);
_renderTargetsBundle.Add(_glareDownsampleBuffer3.renderTargets[0]);
}
PrepareDraw
(
(int)ShaderRenderPass.Presample,
null, //_presampleComputeVariants,
true, _useLensFlare, _useGlare,
_renderContext[0].renderDimension
);
if(_useComputeShaders)
SetTexture(PipelineProperties.ShaderProperties.bloomTargetTex, _bloomDownsampleBuffer.renderTargets[0]);
if(_settings.GetWorkflow() == Workflow.Selective)
SetTexture(PipelineProperties.ShaderProperties.sourceTex, _selectiveRenderTarget.renderTexture);
else
SetTexture(PipelineProperties.ShaderProperties.sourceTex, sourceFrameBuffer);
//SetTexture(PipelineProperties.ShaderProperties.sourceTex, _settings.GetWorkflow() == Workflow.Threshold ? sourceFrameBuffer : _selectiveRenderTarget);
if(_useLensFlare)
{
SetTexture(PipelineProperties.ShaderProperties.lensFlareColorRamp, _settings.GetLensFlareColorRamp() ? _settings.GetLensFlareColorRamp() : _resources.lensFlareColorRampDefault);
if(_useComputeShaders)
SetTexture(PipelineProperties.ShaderProperties.lensFlareTargetTex, _lensFlareDownsampleBuffer.renderTargets[0]);
}
if(_useGlare)
{
if(_useComputeShaders)
{
SetTexture(PipelineProperties.ShaderProperties.glare0TargetTex, _glareDownsampleBuffer0.renderTargets[0]);
SetTexture(PipelineProperties.ShaderProperties.glare1TargetTex, _glareDownsampleBuffer1.renderTargets[0]);
SetTexture(PipelineProperties.ShaderProperties.glare2TargetTex, _glareDownsampleBuffer2.renderTargets[0]);
SetTexture(PipelineProperties.ShaderProperties.glare3TargetTex, _glareDownsampleBuffer3.renderTargets[0]);
}
}
Draw(_renderContext[0].renderDimension);
if(_settings.GetWorkflow() == Workflow.Selective)
RenderTexture.ReleaseTemporary(_selectiveRenderTarget.renderTexture);
EndProfileSample(PipelineProperties.CommandBufferProperties.samplePreSample);
}
/// <summary>
/// Downsample the glow map
/// </summary>
private void Downsample()
{
BeginProfileSample(PipelineProperties.CommandBufferProperties.sampleDownsample);
bool enableBloom, enableLensFlare, enableGlare;
for(int i = 0; i < _minIterations; i++)
{
enableBloom = i < _bloomIterations;
enableLensFlare = _useLensFlare && i < _lensFlareIterations;
enableGlare = _useGlare && i < _glareIterations;
if(enableBloom)
{
_bloomDownsampleBuffer.CreateTemporary(_renderContext, i + 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderKeywordsBundle.Add(MaterialKeywords.Bloom);
_renderTargetsBundle.Add(_bloomDownsampleBuffer.renderTargets[i + 1]);
}
if(enableLensFlare)
{
_lensFlareDownsampleBuffer.CreateTemporary(_renderContext, i + 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderKeywordsBundle.Add(MaterialKeywords.LensFlare);
_renderTargetsBundle.Add(_lensFlareDownsampleBuffer.renderTargets[i + 1]);
}
if(enableGlare)
{
_glareDownsampleBuffer0.CreateTemporary(_renderContext, i + 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_glareDownsampleBuffer1.CreateTemporary(_renderContext, i + 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_glareDownsampleBuffer2.CreateTemporary(_renderContext, i + 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_glareDownsampleBuffer3.CreateTemporary(_renderContext, i + 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderKeywordsBundle.Add(GetGlareKeyword(_settings.GetGlareStreaks()));
_renderTargetsBundle.Add(_glareDownsampleBuffer0.renderTargets[i + 1]);
_renderTargetsBundle.Add(_glareDownsampleBuffer1.renderTargets[i + 1]);
_renderTargetsBundle.Add(_glareDownsampleBuffer2.renderTargets[i + 1]);
_renderTargetsBundle.Add(_glareDownsampleBuffer3.renderTargets[i + 1]);
}
PrepareDraw
(
(int)ShaderRenderPass.Downsample,
null, //_downsampleComputeVariants,
enableBloom, enableLensFlare, enableGlare,
_renderContext[i + 1].renderDimension
);
if(enableBloom)
{
SetTexture(PipelineProperties.ShaderProperties.bloomTex, _bloomDownsampleBuffer.renderTargets[i]);
if(_useComputeShaders)
SetTexture(PipelineProperties.ShaderProperties.bloomTargetTex, _bloomDownsampleBuffer.renderTargets[i + 1]);
}
if(enableLensFlare)
{
SetTexture(PipelineProperties.ShaderProperties.lensFlareTex, _lensFlareDownsampleBuffer.renderTargets[i]);
if(_useComputeShaders)
SetTexture(PipelineProperties.ShaderProperties.lensFlareTargetTex, _lensFlareDownsampleBuffer.renderTargets[i + 1]);
}
if(enableGlare)
{
SetTexture(PipelineProperties.ShaderProperties.glare0Tex, _glareDownsampleBuffer0.renderTargets[i]);
SetTexture(PipelineProperties.ShaderProperties.glare1Tex, _glareDownsampleBuffer1.renderTargets[i]);
SetTexture(PipelineProperties.ShaderProperties.glare2Tex, _glareDownsampleBuffer2.renderTargets[i]);
SetTexture(PipelineProperties.ShaderProperties.glare3Tex, _glareDownsampleBuffer3.renderTargets[i]);
if(_useComputeShaders)
{
SetTexture(PipelineProperties.ShaderProperties.glare0TargetTex, _glareDownsampleBuffer0.renderTargets[i + 1]);
SetTexture(PipelineProperties.ShaderProperties.glare1TargetTex, _glareDownsampleBuffer1.renderTargets[i + 1]);
SetTexture(PipelineProperties.ShaderProperties.glare2TargetTex, _glareDownsampleBuffer2.renderTargets[i + 1]);
SetTexture(PipelineProperties.ShaderProperties.glare3TargetTex, _glareDownsampleBuffer3.renderTargets[i + 1]);
}
}
Draw(_renderContext[i + 1].renderDimension);
}
EndProfileSample(PipelineProperties.CommandBufferProperties.sampleDownsample);
}
/// <summary>
/// Upsample the glow map
/// </summary>
private void Upsample()
{
BeginProfileSample(PipelineProperties.CommandBufferProperties.sampleUpsample);
bool enableBloom, enableLensFlare, enableGlare;
for(int i = _minIterations; i > 0; i--)
{
enableBloom = i <= _bloomIterations;
enableLensFlare = _useLensFlare && i <= _lensFlareIterations;
enableGlare = _useGlare && i <= _glareIterations;
if(enableBloom)
{
_bloomUpsampleBuffer.CreateTemporary(_renderContext, i - 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderKeywordsBundle.Add(MaterialKeywords.Bloom);
_renderTargetsBundle.Add(_bloomUpsampleBuffer.renderTargets[i - 1]);
}
if(enableLensFlare)
{
_lensFlareUpsampleBuffer.CreateTemporary(_renderContext, i - 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderKeywordsBundle.Add(MaterialKeywords.LensFlare);
_renderTargetsBundle.Add(_lensFlareUpsampleBuffer.renderTargets[i - 1]);
}
if(enableGlare)
{
if(_settings.GetGlareStreaks() >= 1)
{
_glareUpsampleBuffer0.CreateTemporary(_renderContext, i - 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderTargetsBundle.Add(_glareUpsampleBuffer0.renderTargets[i - 1]);
}
if(_settings.GetGlareStreaks() >= 2)
{
_glareUpsampleBuffer1.CreateTemporary(_renderContext, i - 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderTargetsBundle.Add(_glareUpsampleBuffer1.renderTargets[i - 1]);
}
if(_settings.GetGlareStreaks() >= 3)
{
_glareUpsampleBuffer2.CreateTemporary(_renderContext, i - 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderTargetsBundle.Add(_glareUpsampleBuffer2.renderTargets[i - 1]);
}
if(_settings.GetGlareStreaks() >= 4)
{
_glareUpsampleBuffer3.CreateTemporary(_renderContext, i - 1, _commandBuffer, _renderTextureFormat, _useComputeShaders, _renderPipeline);
_renderTargetsBundle.Add(_glareUpsampleBuffer3.renderTargets[i - 1]);
}
_renderKeywordsBundle.Add(GetGlareKeyword(_settings.GetGlareStreaks()));
}
PrepareDraw
(
(int)ShaderRenderPass.Upsample,
null, //_upsampleComputeVariants,
enableBloom, enableLensFlare, enableGlare,
_renderContext[i - 1].renderDimension
);
if(enableBloom)
{
SetTexture(PipelineProperties.ShaderProperties.higherMipBloomTex, _bloomDownsampleBuffer.renderTargets[i - 1]);
SetTexture(PipelineProperties.ShaderProperties.bloomTex, (i >= _bloomIterations) ? _bloomDownsampleBuffer.renderTargets[i] : _bloomUpsampleBuffer.renderTargets[i]);
if(_useComputeShaders)
SetTexture(PipelineProperties.ShaderProperties.bloomTargetTex, _bloomUpsampleBuffer.renderTargets[i - 1]);
}
if(enableLensFlare)
{
SetTexture(PipelineProperties.ShaderProperties.lensFlareTex, (i >= _lensFlareIterations) ? _lensFlareDownsampleBuffer.renderTargets[i] : _lensFlareUpsampleBuffer.renderTargets[i]);
if(_useComputeShaders)
SetTexture(PipelineProperties.ShaderProperties.lensFlareTargetTex, _lensFlareUpsampleBuffer.renderTargets[i - 1]);
}
if(enableGlare)
{
if(_settings.GetGlareStreaks() >= 1)
SetTexture(PipelineProperties.ShaderProperties.glare0Tex, (i >= _glareIterations) ? _glareDownsampleBuffer0.renderTargets[i] : _glareUpsampleBuffer0.renderTargets[i]);
if(_settings.GetGlareStreaks() >= 2)
SetTexture(PipelineProperties.ShaderProperties.glare1Tex, (i >= _glareIterations) ? _glareDownsampleBuffer1.renderTargets[i] : _glareUpsampleBuffer1.renderTargets[i]);
if(_settings.GetGlareStreaks() >= 3)
SetTexture(PipelineProperties.ShaderProperties.glare2Tex, (i >= _glareIterations) ? _glareDownsampleBuffer2.renderTargets[i] : _glareUpsampleBuffer2.renderTargets[i]);
if(_settings.GetGlareStreaks() >= 4)
SetTexture(PipelineProperties.ShaderProperties.glare3Tex, (i >= _glareIterations) ? _glareDownsampleBuffer3.renderTargets[i] : _glareUpsampleBuffer3.renderTargets[i]);
if(_useComputeShaders)
{
if(_settings.GetGlareStreaks() >= 1)
SetTexture(PipelineProperties.ShaderProperties.glare0TargetTex, _glareUpsampleBuffer0.renderTargets[i - 1]);
if(_settings.GetGlareStreaks() >= 2)
SetTexture(PipelineProperties.ShaderProperties.glare1TargetTex, _glareUpsampleBuffer1.renderTargets[i - 1]);
if(_settings.GetGlareStreaks() >= 3)
SetTexture(PipelineProperties.ShaderProperties.glare2TargetTex, _glareUpsampleBuffer2.renderTargets[i - 1]);
if(_settings.GetGlareStreaks() >= 4)
SetTexture(PipelineProperties.ShaderProperties.glare3TargetTex, _glareUpsampleBuffer3.renderTargets[i - 1]);
}
}
Draw(_renderContext[i - 1].renderDimension);
if(enableBloom)
{
if(i >= _bloomIterations)
_bloomDownsampleBuffer.ClearTemporary(_commandBuffer, i, _renderPipeline);
else
{
_bloomDownsampleBuffer.ClearTemporary(_commandBuffer, i, _renderPipeline);
_bloomUpsampleBuffer.ClearTemporary(_commandBuffer, i, _renderPipeline);
}
}
if(enableLensFlare)
{
if(i >= _lensFlareIterations)
_lensFlareDownsampleBuffer.ClearTemporary(_commandBuffer, i, _renderPipeline);
else
{
_lensFlareDownsampleBuffer.ClearTemporary(_commandBuffer, i, _renderPipeline);
_lensFlareUpsampleBuffer.ClearTemporary(_commandBuffer, i, _renderPipeline);
}
}
if(enableGlare)
{
if(i >= _glareIterations)
{
_glareDownsampleBuffer0.ClearTemporary(_commandBuffer, i, _renderPipeline);
_glareDownsampleBuffer1.ClearTemporary(_commandBuffer, i, _renderPipeline);
_glareDownsampleBuffer2.ClearTemporary(_commandBuffer, i, _renderPipeline);
_glareDownsampleBuffer3.ClearTemporary(_commandBuffer, i, _renderPipeline);
}
else
{
_glareDownsampleBuffer0.ClearTemporary(_commandBuffer, i, _renderPipeline);
_glareDownsampleBuffer1.ClearTemporary(_commandBuffer, i, _renderPipeline);
_glareDownsampleBuffer2.ClearTemporary(_commandBuffer, i, _renderPipeline);
_glareDownsampleBuffer3.ClearTemporary(_commandBuffer, i, _renderPipeline);
if(_settings.GetGlareStreaks() >= 1)
_glareUpsampleBuffer0.ClearTemporary(_commandBuffer, i, _renderPipeline);
if(_settings.GetGlareStreaks() >= 2)
_glareUpsampleBuffer1.ClearTemporary(_commandBuffer, i, _renderPipeline);
if(_settings.GetGlareStreaks() >= 3)
_glareUpsampleBuffer2.ClearTemporary(_commandBuffer, i, _renderPipeline);
if(_settings.GetGlareStreaks() >= 4)
_glareUpsampleBuffer3.ClearTemporary(_commandBuffer, i, _renderPipeline);
}
}
}
_bloomDownsampleBuffer.ClearTemporary(_commandBuffer, 0, _renderPipeline);
if(_useLensFlare)
_lensFlareDownsampleBuffer.ClearTemporary(_commandBuffer, 0, _renderPipeline);
if(_useGlare)
{
_glareDownsampleBuffer0.ClearTemporary(_commandBuffer, 0, _renderPipeline);
_glareDownsampleBuffer1.ClearTemporary(_commandBuffer, 0, _renderPipeline);
_glareDownsampleBuffer2.ClearTemporary(_commandBuffer, 0, _renderPipeline);
_glareDownsampleBuffer3.ClearTemporary(_commandBuffer, 0, _renderPipeline);
}
EndProfileSample(PipelineProperties.CommandBufferProperties.sampleUpsample);
}
/// <summary>
/// Precomposite of the glow map
/// </summary>
private void Composite()
{
BeginProfileSample(PipelineProperties.CommandBufferProperties.sampleComposite);
int renderpass;
switch(_debugView)
{
case DebugView.RawBloom:
_renderKeywordsBundle.Add(MaterialKeywords.DebugRawBloom);
renderpass = (int)ShaderRenderPass.Debug;
break;
case DebugView.RawLensFlare:
_renderKeywordsBundle.Add(MaterialKeywords.DebugRawLensFlare);
renderpass = (int)ShaderRenderPass.Debug;
break;
case DebugView.RawGlare:
_renderKeywordsBundle.Add(MaterialKeywords.DebugRawGlare);
renderpass = (int)ShaderRenderPass.Debug;
break;
case DebugView.Bloom:
_renderKeywordsBundle.Add(MaterialKeywords.DebugBloom);
renderpass = (int)ShaderRenderPass.Debug;
break;
case DebugView.LensFlare:
_renderKeywordsBundle.Add(MaterialKeywords.DebugLensFlare);
renderpass = (int)ShaderRenderPass.Debug;
break;
case DebugView.Glare:
_renderKeywordsBundle.Add(MaterialKeywords.DebugGlare);
_renderKeywordsBundle.Add(GetGlareKeyword(_settings.GetGlareStreaks()));
renderpass = (int)ShaderRenderPass.Debug;
break;
case DebugView.Composite:
if(_settings.GetWorkflow() == Workflow.Natural)
_renderKeywordsBundle.Add(MaterialKeywords.Natural);
if(_useLensSurface)
{
_renderKeywordsBundle.Add(MaterialKeywords.LensSurface);
}
if(_useLensFlare)
{
_renderKeywordsBundle.Add(MaterialKeywords.LensFlare);
}
if(_useGlare)
{
_renderKeywordsBundle.Add(GetGlareKeyword(_settings.GetGlareStreaks()));
}
_renderKeywordsBundle.Add(MaterialKeywords.DebugComposite);
renderpass = (int)ShaderRenderPass.Debug;
break;
default:
if(_settings.GetWorkflow() == Workflow.Natural)
_renderKeywordsBundle.Add(MaterialKeywords.Natural);
if(_useLensSurface)
{
_renderKeywordsBundle.Add(MaterialKeywords.LensSurface);
}
if(_useLensFlare)
{
_renderKeywordsBundle.Add(MaterialKeywords.LensFlare);
}
if(_useGlare)
{
_renderKeywordsBundle.Add(GetGlareKeyword(_settings.GetGlareStreaks()));
}
renderpass = (int)ShaderRenderPass.Composite;
break;
}
if(_settings.GetWorkflow() == Workflow.Natural)
_renderKeywordsBundle.Add(MaterialKeywords.Natural);
PrepareDraw
(
renderpass,
_sourceContext[0].renderDimension,
true
);
if(_settings.GetWorkflow() == Workflow.Selective && (_debugView == DebugView.RawBloom || _debugView == DebugView.RawLensFlare || _debugView == DebugView.RawGlare))
SetTexture(PipelineProperties.ShaderProperties.sourceTex, sourceFrameBuffer.renderTexture, true);
else
{
SetTexture(PipelineProperties.ShaderProperties.sourceTex, _sourceFrameBuffer, true);
SetTexture(PipelineProperties.ShaderProperties.bloomTex, _bloomUpsampleBuffer.renderTargets[0], true);
}
if(_useLensSurface)
{
SetTexture(PipelineProperties.ShaderProperties.lensSurfaceDirtTex, _settings.GetLensSurfaceDirtTexture() ? _settings.GetLensSurfaceDirtTexture() : _resources.lensSurfaceDirtTextureDefault, true);
SetTexture(PipelineProperties.ShaderProperties.lensSurfaceDiffractionTex, _settings.GetLensSurfaceDiffractionTexture() ? _settings.GetLensSurfaceDiffractionTexture() : _resources.lensSurfaceDiffractionTextureDefault, true);
}
if(_useLensFlare)
{
SetTexture(PipelineProperties.ShaderProperties.lensFlareTex, _lensFlareUpsampleBuffer.renderTargets[0], true);
}
if(_useGlare)
{
if(_settings.GetGlareStreaks() >= 1)
SetTexture(PipelineProperties.ShaderProperties.glare0Tex, _glareUpsampleBuffer0.renderTargets[0], true);
if(_settings.GetGlareStreaks() >= 2)
SetTexture(PipelineProperties.ShaderProperties.glare1Tex, _glareUpsampleBuffer1.renderTargets[0], true);
if(_settings.GetGlareStreaks() >= 3)
SetTexture(PipelineProperties.ShaderProperties.glare2Tex, _glareUpsampleBuffer2.renderTargets[0], true);
if(_settings.GetGlareStreaks() >= 4)
SetTexture(PipelineProperties.ShaderProperties.glare3Tex, _glareUpsampleBuffer3.renderTargets[0], true);
}
//Dont draw when using legacy render pipeline
if(_finalBlit)
{
_renderTargetsBundle.Add(_destinationFrameBuffer);
Draw(_sourceContext[0].renderDimension, true);
AfterCompositeCleanup();
}
else
{
PipelineExtensions.SetKeyword(_shaderKeywords[(int)MaterialKeywords.LegacyBlit].name, true);
_renderTargetsBundle.Clear();
}
EndProfileSample(PipelineProperties.CommandBufferProperties.sampleComposite);
}
/// <summary>
/// This cleans up the final render step
/// </summary>
internal void AfterCompositeCleanup()
{
_bloomUpsampleBuffer.ClearTemporary(_commandBuffer, 0, _renderPipeline);
if(_useLensFlare)
_lensFlareUpsampleBuffer.ClearTemporary(_commandBuffer, 0, _renderPipeline);
if(_useGlare)
{
if(_settings.GetGlareStreaks() >= 1)
_glareUpsampleBuffer0.ClearTemporary(_commandBuffer, 0, _renderPipeline);
if(_settings.GetGlareStreaks() >= 2)
_glareUpsampleBuffer1.ClearTemporary(_commandBuffer, 0, _renderPipeline);
if(_settings.GetGlareStreaks() >= 3)
_glareUpsampleBuffer2.ClearTemporary(_commandBuffer, 0, _renderPipeline);
if(_settings.GetGlareStreaks() >= 4)
_glareUpsampleBuffer3.ClearTemporary(_commandBuffer, 0, _renderPipeline);
}
DisableDebugKeywords();
DisableRenderKeywords();
if(_renderPipeline == RenderPipeline.Legacy)
PipelineExtensions.SetKeyword(_shaderKeywords[(int)MaterialKeywords.LegacyBlit].name, false);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Enum / structs used for rendering
/////////////////////////////////////////////////////////////////////////////////////////////
///
/// <summary>
/// Rendering passes for shaders
/// </summary>
internal enum ShaderRenderPass
{
//Copy = 0,
Presample = 0,
Downsample = 1,
Upsample = 2,
Composite = 3,
Debug = 4
}
/// <summary>
/// Material keywords represented in the keyword holder
/// </summary>
internal enum MaterialKeywords
{
Bloom = 0,
LensSurface = 1,
LensFlare = 2,
Glare1 = 3,
DebugRawBloom = 4,
DebugRawLensFlare = 5,
DebugRawGlare = 6,
DebugBloom = 7,
DebugLensFlare = 8,
DebugGlare = 9,
DebugComposite = 10,
LegacyBlit = 11,
RenderPriorityQuality = 12,
Natural = 13,
Glare2 = 14,
Glare3 = 15,
Glare4 = 16,
Null = 17,
RenderPriorityBalanced = 18,
HQAntiFlickerFilter = 19
}
/// <summary>
/// Keyword represented as with state
/// </summary>
internal struct Keyword
{
internal string name;
internal bool enabled;
internal Keyword(string name, bool enabled)
{
this.name = name;
this.enabled = enabled;
}
}
}
}