Initial
This commit is contained in:
commit
36a53f343e
32 changed files with 300431 additions and 0 deletions
|
|
@ -0,0 +1,185 @@
|
|||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
using DebugMode = BuiltinDebugViewsModel.Mode;
|
||||
|
||||
public sealed class AmbientOcclusionComponent : PostProcessingComponentCommandBuffer<AmbientOcclusionModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _Intensity = Shader.PropertyToID("_Intensity");
|
||||
internal static readonly int _Radius = Shader.PropertyToID("_Radius");
|
||||
internal static readonly int _FogParams = Shader.PropertyToID("_FogParams");
|
||||
internal static readonly int _Downsample = Shader.PropertyToID("_Downsample");
|
||||
internal static readonly int _SampleCount = Shader.PropertyToID("_SampleCount");
|
||||
internal static readonly int _OcclusionTexture1 = Shader.PropertyToID("_OcclusionTexture1");
|
||||
internal static readonly int _OcclusionTexture2 = Shader.PropertyToID("_OcclusionTexture2");
|
||||
internal static readonly int _OcclusionTexture = Shader.PropertyToID("_OcclusionTexture");
|
||||
internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
|
||||
internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
|
||||
}
|
||||
|
||||
const string k_BlitShaderString = "Hidden/Post FX/Blit";
|
||||
const string k_ShaderString = "Hidden/Post FX/Ambient Occlusion";
|
||||
|
||||
readonly RenderTargetIdentifier[] m_MRT =
|
||||
{
|
||||
BuiltinRenderTextureType.GBuffer0, // Albedo, Occ
|
||||
BuiltinRenderTextureType.CameraTarget // Ambient
|
||||
};
|
||||
|
||||
enum OcclusionSource
|
||||
{
|
||||
DepthTexture,
|
||||
DepthNormalsTexture,
|
||||
GBuffer
|
||||
}
|
||||
|
||||
OcclusionSource occlusionSource
|
||||
{
|
||||
get
|
||||
{
|
||||
if (context.isGBufferAvailable && !model.settings.forceForwardCompatibility)
|
||||
return OcclusionSource.GBuffer;
|
||||
|
||||
if (model.settings.highPrecision && (!context.isGBufferAvailable || model.settings.forceForwardCompatibility))
|
||||
return OcclusionSource.DepthTexture;
|
||||
|
||||
return OcclusionSource.DepthNormalsTexture;
|
||||
}
|
||||
}
|
||||
|
||||
bool ambientOnlySupported
|
||||
{
|
||||
get { return context.isHdr && model.settings.ambientOnly && context.isGBufferAvailable && !model.settings.forceForwardCompatibility; }
|
||||
}
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& model.settings.intensity > 0f
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
public override DepthTextureMode GetCameraFlags()
|
||||
{
|
||||
var flags = DepthTextureMode.None;
|
||||
|
||||
if (occlusionSource == OcclusionSource.DepthTexture)
|
||||
flags |= DepthTextureMode.Depth;
|
||||
|
||||
if (occlusionSource != OcclusionSource.GBuffer)
|
||||
flags |= DepthTextureMode.DepthNormals;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
{
|
||||
return "Ambient Occlusion";
|
||||
}
|
||||
|
||||
public override CameraEvent GetCameraEvent()
|
||||
{
|
||||
return ambientOnlySupported && !context.profile.debugViews.IsModeActive(DebugMode.AmbientOcclusion)
|
||||
? CameraEvent.BeforeReflections
|
||||
: CameraEvent.BeforeImageEffectsOpaque;
|
||||
}
|
||||
|
||||
public override void PopulateCommandBuffer(CommandBuffer cb)
|
||||
{
|
||||
var settings = model.settings;
|
||||
|
||||
// Material setup
|
||||
var blitMaterial = context.materialFactory.Get(k_BlitShaderString);
|
||||
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
material.shaderKeywords = null;
|
||||
material.SetFloat(Uniforms._Intensity, settings.intensity);
|
||||
material.SetFloat(Uniforms._Radius, settings.radius);
|
||||
material.SetFloat(Uniforms._Downsample, settings.downsampling ? 0.5f : 1f);
|
||||
material.SetInt(Uniforms._SampleCount, (int)settings.sampleCount);
|
||||
|
||||
if (!context.isGBufferAvailable && RenderSettings.fog)
|
||||
{
|
||||
material.SetVector(Uniforms._FogParams, new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance));
|
||||
|
||||
switch (RenderSettings.fogMode)
|
||||
{
|
||||
case FogMode.Linear:
|
||||
material.EnableKeyword("FOG_LINEAR");
|
||||
break;
|
||||
case FogMode.Exponential:
|
||||
material.EnableKeyword("FOG_EXP");
|
||||
break;
|
||||
case FogMode.ExponentialSquared:
|
||||
material.EnableKeyword("FOG_EXP2");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
material.EnableKeyword("FOG_OFF");
|
||||
}
|
||||
|
||||
int tw = context.width;
|
||||
int th = context.height;
|
||||
int ts = settings.downsampling ? 2 : 1;
|
||||
const RenderTextureFormat kFormat = RenderTextureFormat.ARGB32;
|
||||
const RenderTextureReadWrite kRWMode = RenderTextureReadWrite.Linear;
|
||||
const FilterMode kFilter = FilterMode.Bilinear;
|
||||
|
||||
// AO buffer
|
||||
var rtMask = Uniforms._OcclusionTexture1;
|
||||
cb.GetTemporaryRT(rtMask, tw / ts, th / ts, 0, kFilter, kFormat, kRWMode);
|
||||
|
||||
// AO estimation
|
||||
cb.Blit((Texture)null, rtMask, material, (int)occlusionSource);
|
||||
|
||||
// Blur buffer
|
||||
var rtBlur = Uniforms._OcclusionTexture2;
|
||||
|
||||
// Separable blur (horizontal pass)
|
||||
cb.GetTemporaryRT(rtBlur, tw, th, 0, kFilter, kFormat, kRWMode);
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, rtMask);
|
||||
cb.Blit(rtMask, rtBlur, material, occlusionSource == OcclusionSource.GBuffer ? 4 : 3);
|
||||
cb.ReleaseTemporaryRT(rtMask);
|
||||
|
||||
// Separable blur (vertical pass)
|
||||
rtMask = Uniforms._OcclusionTexture;
|
||||
cb.GetTemporaryRT(rtMask, tw, th, 0, kFilter, kFormat, kRWMode);
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, rtBlur);
|
||||
cb.Blit(rtBlur, rtMask, material, 5);
|
||||
cb.ReleaseTemporaryRT(rtBlur);
|
||||
|
||||
if (context.profile.debugViews.IsModeActive(DebugMode.AmbientOcclusion))
|
||||
{
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, rtMask);
|
||||
cb.Blit(rtMask, BuiltinRenderTextureType.CameraTarget, material, 8);
|
||||
context.Interrupt();
|
||||
}
|
||||
else if (ambientOnlySupported)
|
||||
{
|
||||
cb.SetRenderTarget(m_MRT, BuiltinRenderTextureType.CameraTarget);
|
||||
cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fbFormat = context.isHdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default;
|
||||
|
||||
int tempRT = Uniforms._TempRT;
|
||||
cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Bilinear, fbFormat);
|
||||
cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, blitMaterial, 0);
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, tempRT);
|
||||
cb.Blit(tempRT, BuiltinRenderTextureType.CameraTarget, material, 6);
|
||||
cb.ReleaseTemporaryRT(tempRT);
|
||||
}
|
||||
|
||||
cb.ReleaseTemporaryRT(rtMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c6e33ce72d3776b408121f946283403d
|
||||
timeCreated: 1467275948
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
public sealed class BloomComponent : PostProcessingComponentRenderTexture<BloomModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _AutoExposure = Shader.PropertyToID("_AutoExposure");
|
||||
internal static readonly int _Threshold = Shader.PropertyToID("_Threshold");
|
||||
internal static readonly int _Curve = Shader.PropertyToID("_Curve");
|
||||
internal static readonly int _PrefilterOffs = Shader.PropertyToID("_PrefilterOffs");
|
||||
internal static readonly int _SampleScale = Shader.PropertyToID("_SampleScale");
|
||||
internal static readonly int _BaseTex = Shader.PropertyToID("_BaseTex");
|
||||
internal static readonly int _BloomTex = Shader.PropertyToID("_BloomTex");
|
||||
internal static readonly int _Bloom_Settings = Shader.PropertyToID("_Bloom_Settings");
|
||||
internal static readonly int _Bloom_DirtTex = Shader.PropertyToID("_Bloom_DirtTex");
|
||||
internal static readonly int _Bloom_DirtIntensity = Shader.PropertyToID("_Bloom_DirtIntensity");
|
||||
}
|
||||
|
||||
const int k_MaxPyramidBlurLevel = 16;
|
||||
readonly RenderTexture[] m_BlurBuffer1 = new RenderTexture[k_MaxPyramidBlurLevel];
|
||||
readonly RenderTexture[] m_BlurBuffer2 = new RenderTexture[k_MaxPyramidBlurLevel];
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& model.settings.bloom.intensity > 0f
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
public void Prepare(RenderTexture source, Material uberMaterial, Texture autoExposure)
|
||||
{
|
||||
var bloom = model.settings.bloom;
|
||||
var lensDirt = model.settings.lensDirt;
|
||||
var material = context.materialFactory.Get("Hidden/Post FX/Bloom");
|
||||
material.shaderKeywords = null;
|
||||
|
||||
// Apply auto exposure before the prefiltering pass
|
||||
material.SetTexture(Uniforms._AutoExposure, autoExposure);
|
||||
|
||||
// Do bloom on a half-res buffer, full-res doesn't bring much and kills performances on
|
||||
// fillrate limited platforms
|
||||
var tw = context.width / 2;
|
||||
var th = context.height / 2;
|
||||
|
||||
// Blur buffer format
|
||||
// TODO: Extend the use of RGBM to the whole chain for mobile platforms
|
||||
var useRGBM = Application.isMobilePlatform;
|
||||
var rtFormat = useRGBM
|
||||
? RenderTextureFormat.Default
|
||||
: RenderTextureFormat.DefaultHDR;
|
||||
|
||||
// Determine the iteration count
|
||||
float logh = Mathf.Log(th, 2f) + bloom.radius - 8f;
|
||||
int logh_i = (int)logh;
|
||||
int iterations = Mathf.Clamp(logh_i, 1, k_MaxPyramidBlurLevel);
|
||||
|
||||
// Uupdate the shader properties
|
||||
float lthresh = bloom.thresholdLinear;
|
||||
material.SetFloat(Uniforms._Threshold, lthresh);
|
||||
|
||||
float knee = lthresh * bloom.softKnee + 1e-5f;
|
||||
var curve = new Vector3(lthresh - knee, knee * 2f, 0.25f / knee);
|
||||
material.SetVector(Uniforms._Curve, curve);
|
||||
|
||||
material.SetFloat(Uniforms._PrefilterOffs, bloom.antiFlicker ? -0.5f : 0f);
|
||||
|
||||
float sampleScale = 0.5f + logh - logh_i;
|
||||
material.SetFloat(Uniforms._SampleScale, sampleScale);
|
||||
|
||||
// TODO: Probably can disable antiFlicker if TAA is enabled - need to do some testing
|
||||
if (bloom.antiFlicker)
|
||||
material.EnableKeyword("ANTI_FLICKER");
|
||||
|
||||
// Prefilter pass
|
||||
var prefiltered = context.renderTextureFactory.Get(tw, th, 0, rtFormat);
|
||||
Graphics.Blit(source, prefiltered, material, 0);
|
||||
|
||||
// Construct a mip pyramid
|
||||
var last = prefiltered;
|
||||
|
||||
for (int level = 0; level < iterations; level++)
|
||||
{
|
||||
m_BlurBuffer1[level] = context.renderTextureFactory.Get(
|
||||
last.width / 2, last.height / 2, 0, rtFormat
|
||||
);
|
||||
|
||||
int pass = (level == 0) ? 1 : 2;
|
||||
Graphics.Blit(last, m_BlurBuffer1[level], material, pass);
|
||||
|
||||
last = m_BlurBuffer1[level];
|
||||
}
|
||||
|
||||
// Upsample and combine loop
|
||||
for (int level = iterations - 2; level >= 0; level--)
|
||||
{
|
||||
var baseTex = m_BlurBuffer1[level];
|
||||
material.SetTexture(Uniforms._BaseTex, baseTex);
|
||||
|
||||
m_BlurBuffer2[level] = context.renderTextureFactory.Get(
|
||||
baseTex.width, baseTex.height, 0, rtFormat
|
||||
);
|
||||
|
||||
Graphics.Blit(last, m_BlurBuffer2[level], material, 3);
|
||||
last = m_BlurBuffer2[level];
|
||||
}
|
||||
|
||||
var bloomTex = last;
|
||||
|
||||
// Release the temporary buffers
|
||||
for (int i = 0; i < k_MaxPyramidBlurLevel; i++)
|
||||
{
|
||||
if (m_BlurBuffer1[i] != null)
|
||||
context.renderTextureFactory.Release(m_BlurBuffer1[i]);
|
||||
|
||||
if (m_BlurBuffer2[i] != null && m_BlurBuffer2[i] != bloomTex)
|
||||
context.renderTextureFactory.Release(m_BlurBuffer2[i]);
|
||||
|
||||
m_BlurBuffer1[i] = null;
|
||||
m_BlurBuffer2[i] = null;
|
||||
}
|
||||
|
||||
context.renderTextureFactory.Release(prefiltered);
|
||||
|
||||
// Push everything to the uber material
|
||||
uberMaterial.SetTexture(Uniforms._BloomTex, bloomTex);
|
||||
uberMaterial.SetVector(Uniforms._Bloom_Settings, new Vector2(sampleScale, bloom.intensity));
|
||||
|
||||
if (lensDirt.intensity > 0f && lensDirt.texture != null)
|
||||
{
|
||||
uberMaterial.SetTexture(Uniforms._Bloom_DirtTex, lensDirt.texture);
|
||||
uberMaterial.SetFloat(Uniforms._Bloom_DirtIntensity, lensDirt.intensity);
|
||||
uberMaterial.EnableKeyword("BLOOM_LENS_DIRT");
|
||||
}
|
||||
else
|
||||
{
|
||||
uberMaterial.EnableKeyword("BLOOM");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
using Mode = BuiltinDebugViewsModel.Mode;
|
||||
|
||||
public sealed class BuiltinDebugViewsComponent : PostProcessingComponentCommandBuffer<BuiltinDebugViewsModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _DepthScale = Shader.PropertyToID("_DepthScale");
|
||||
internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
|
||||
internal static readonly int _Opacity = Shader.PropertyToID("_Opacity");
|
||||
internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
|
||||
internal static readonly int _TempRT2 = Shader.PropertyToID("_TempRT2");
|
||||
internal static readonly int _Amplitude = Shader.PropertyToID("_Amplitude");
|
||||
internal static readonly int _Scale = Shader.PropertyToID("_Scale");
|
||||
}
|
||||
|
||||
const string k_ShaderString = "Hidden/Post FX/Builtin Debug Views";
|
||||
|
||||
enum Pass
|
||||
{
|
||||
Depth,
|
||||
Normals,
|
||||
MovecOpacity,
|
||||
MovecImaging,
|
||||
MovecArrows
|
||||
}
|
||||
|
||||
ArrowArray m_Arrows;
|
||||
|
||||
class ArrowArray
|
||||
{
|
||||
public Mesh mesh { get; private set; }
|
||||
|
||||
public int columnCount { get; private set; }
|
||||
public int rowCount { get; private set; }
|
||||
|
||||
public void BuildMesh(int columns, int rows)
|
||||
{
|
||||
// Base shape
|
||||
var arrow = new Vector3[6]
|
||||
{
|
||||
new Vector3(0f, 0f, 0f),
|
||||
new Vector3(0f, 1f, 0f),
|
||||
new Vector3(0f, 1f, 0f),
|
||||
new Vector3(-1f, 1f, 0f),
|
||||
new Vector3(0f, 1f, 0f),
|
||||
new Vector3(1f, 1f, 0f)
|
||||
};
|
||||
|
||||
// make the vertex array
|
||||
int vcount = 6 * columns * rows;
|
||||
var vertices = new List<Vector3>(vcount);
|
||||
var uvs = new List<Vector2>(vcount);
|
||||
|
||||
for (int iy = 0; iy < rows; iy++)
|
||||
{
|
||||
for (int ix = 0; ix < columns; ix++)
|
||||
{
|
||||
var uv = new Vector2(
|
||||
(0.5f + ix) / columns,
|
||||
(0.5f + iy) / rows
|
||||
);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
vertices.Add(arrow[i]);
|
||||
uvs.Add(uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make the index array
|
||||
var indices = new int[vcount];
|
||||
|
||||
for (int i = 0; i < vcount; i++)
|
||||
indices[i] = i;
|
||||
|
||||
// initialize the mesh object
|
||||
mesh = new Mesh { hideFlags = HideFlags.DontSave };
|
||||
mesh.SetVertices(vertices);
|
||||
mesh.SetUVs(0, uvs);
|
||||
mesh.SetIndices(indices, MeshTopology.Lines, 0);
|
||||
mesh.UploadMeshData(true);
|
||||
|
||||
// update the properties
|
||||
columnCount = columns;
|
||||
rowCount = rows;
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
GraphicsUtils.Destroy(mesh);
|
||||
mesh = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.IsModeActive(Mode.Depth)
|
||||
|| model.IsModeActive(Mode.Normals)
|
||||
|| model.IsModeActive(Mode.MotionVectors);
|
||||
}
|
||||
}
|
||||
|
||||
public override DepthTextureMode GetCameraFlags()
|
||||
{
|
||||
var mode = model.settings.mode;
|
||||
var flags = DepthTextureMode.None;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case Mode.Normals:
|
||||
flags |= DepthTextureMode.DepthNormals;
|
||||
break;
|
||||
case Mode.MotionVectors:
|
||||
flags |= DepthTextureMode.MotionVectors | DepthTextureMode.Depth;
|
||||
break;
|
||||
case Mode.Depth:
|
||||
flags |= DepthTextureMode.Depth;
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public override CameraEvent GetCameraEvent()
|
||||
{
|
||||
return model.settings.mode == Mode.MotionVectors
|
||||
? CameraEvent.BeforeImageEffects
|
||||
: CameraEvent.BeforeImageEffectsOpaque;
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
{
|
||||
return "Builtin Debug Views";
|
||||
}
|
||||
|
||||
public override void PopulateCommandBuffer(CommandBuffer cb)
|
||||
{
|
||||
var settings = model.settings;
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
material.shaderKeywords = null;
|
||||
|
||||
if (context.isGBufferAvailable)
|
||||
material.EnableKeyword("SOURCE_GBUFFER");
|
||||
|
||||
switch (settings.mode)
|
||||
{
|
||||
case Mode.Depth:
|
||||
DepthPass(cb);
|
||||
break;
|
||||
case Mode.Normals:
|
||||
DepthNormalsPass(cb);
|
||||
break;
|
||||
case Mode.MotionVectors:
|
||||
MotionVectorsPass(cb);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Interrupt();
|
||||
}
|
||||
|
||||
void DepthPass(CommandBuffer cb)
|
||||
{
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
var settings = model.settings.depth;
|
||||
|
||||
cb.SetGlobalFloat(Uniforms._DepthScale, 1f / settings.scale);
|
||||
cb.Blit((Texture)null, BuiltinRenderTextureType.CameraTarget, material, (int)Pass.Depth);
|
||||
}
|
||||
|
||||
void DepthNormalsPass(CommandBuffer cb)
|
||||
{
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
cb.Blit((Texture)null, BuiltinRenderTextureType.CameraTarget, material, (int)Pass.Normals);
|
||||
}
|
||||
|
||||
void MotionVectorsPass(CommandBuffer cb)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// Don't render motion vectors preview when the editor is not playing as it can in some
|
||||
// cases results in ugly artifacts (i.e. when resizing the game view).
|
||||
if (!Application.isPlaying)
|
||||
return;
|
||||
#endif
|
||||
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
var settings = model.settings.motionVectors;
|
||||
|
||||
// Blit the original source image
|
||||
int tempRT = Uniforms._TempRT;
|
||||
cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Bilinear);
|
||||
cb.SetGlobalFloat(Uniforms._Opacity, settings.sourceOpacity);
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget);
|
||||
cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, material, (int)Pass.MovecOpacity);
|
||||
|
||||
// Motion vectors (imaging)
|
||||
if (settings.motionImageOpacity > 0f && settings.motionImageAmplitude > 0f)
|
||||
{
|
||||
int tempRT2 = Uniforms._TempRT2;
|
||||
cb.GetTemporaryRT(tempRT2, context.width, context.height, 0, FilterMode.Bilinear);
|
||||
cb.SetGlobalFloat(Uniforms._Opacity, settings.motionImageOpacity);
|
||||
cb.SetGlobalFloat(Uniforms._Amplitude, settings.motionImageAmplitude);
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, tempRT);
|
||||
cb.Blit(tempRT, tempRT2, material, (int)Pass.MovecImaging);
|
||||
cb.ReleaseTemporaryRT(tempRT);
|
||||
tempRT = tempRT2;
|
||||
}
|
||||
|
||||
// Motion vectors (arrows)
|
||||
if (settings.motionVectorsOpacity > 0f && settings.motionVectorsAmplitude > 0f)
|
||||
{
|
||||
PrepareArrows();
|
||||
|
||||
float sy = 1f / settings.motionVectorsResolution;
|
||||
float sx = sy * context.height / context.width;
|
||||
|
||||
cb.SetGlobalVector(Uniforms._Scale, new Vector2(sx, sy));
|
||||
cb.SetGlobalFloat(Uniforms._Opacity, settings.motionVectorsOpacity);
|
||||
cb.SetGlobalFloat(Uniforms._Amplitude, settings.motionVectorsAmplitude);
|
||||
cb.DrawMesh(m_Arrows.mesh, Matrix4x4.identity, material, 0, (int)Pass.MovecArrows);
|
||||
}
|
||||
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, tempRT);
|
||||
cb.Blit(tempRT, BuiltinRenderTextureType.CameraTarget);
|
||||
cb.ReleaseTemporaryRT(tempRT);
|
||||
}
|
||||
|
||||
void PrepareArrows()
|
||||
{
|
||||
int row = model.settings.motionVectors.motionVectorsResolution;
|
||||
int col = row * Screen.width / Screen.height;
|
||||
|
||||
if (m_Arrows == null)
|
||||
m_Arrows = new ArrowArray();
|
||||
|
||||
if (m_Arrows.columnCount != col || m_Arrows.rowCount != row)
|
||||
{
|
||||
m_Arrows.Release();
|
||||
m_Arrows.BuildMesh(col, row);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
if (m_Arrows != null)
|
||||
m_Arrows.Release();
|
||||
|
||||
m_Arrows = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
using Mode = BuiltinDebugViewsModel.Mode;
|
||||
|
||||
public sealed class BuiltinDebugViewsComponent : PostProcessingComponentCommandBuffer<BuiltinDebugViewsModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _DepthScale = Shader.PropertyToID("_DepthScale");
|
||||
internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
|
||||
internal static readonly int _Opacity = Shader.PropertyToID("_Opacity");
|
||||
internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
|
||||
internal static readonly int _TempRT2 = Shader.PropertyToID("_TempRT2");
|
||||
internal static readonly int _Amplitude = Shader.PropertyToID("_Amplitude");
|
||||
internal static readonly int _Scale = Shader.PropertyToID("_Scale");
|
||||
}
|
||||
|
||||
const string k_ShaderString = "Hidden/Post FX/Builtin Debug Views";
|
||||
|
||||
enum Pass
|
||||
{
|
||||
Depth,
|
||||
Normals,
|
||||
MovecOpacity,
|
||||
MovecImaging,
|
||||
MovecArrows
|
||||
}
|
||||
|
||||
ArrowArray m_Arrows;
|
||||
|
||||
class ArrowArray
|
||||
{
|
||||
public Mesh mesh { get; private set; }
|
||||
|
||||
public int columnCount { get; private set; }
|
||||
public int rowCount { get; private set; }
|
||||
|
||||
public void BuildMesh(int columns, int rows)
|
||||
{
|
||||
// Base shape
|
||||
var arrow = new Vector3[6]
|
||||
{
|
||||
new Vector3(0f, 0f, 0f),
|
||||
new Vector3(0f, 1f, 0f),
|
||||
new Vector3(0f, 1f, 0f),
|
||||
new Vector3(-1f, 1f, 0f),
|
||||
new Vector3(0f, 1f, 0f),
|
||||
new Vector3(1f, 1f, 0f)
|
||||
};
|
||||
|
||||
// make the vertex array
|
||||
int vcount = 6 * columns * rows;
|
||||
var vertices = new List<Vector3>(vcount);
|
||||
var uvs = new List<Vector2>(vcount);
|
||||
|
||||
for (int iy = 0; iy < rows; iy++)
|
||||
{
|
||||
for (int ix = 0; ix < columns; ix++)
|
||||
{
|
||||
var uv = new Vector2(
|
||||
(0.5f + ix) / columns,
|
||||
(0.5f + iy) / rows
|
||||
);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
vertices.Add(arrow[i]);
|
||||
uvs.Add(uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make the index array
|
||||
var indices = new int[vcount];
|
||||
|
||||
for (int i = 0; i < vcount; i++)
|
||||
indices[i] = i;
|
||||
|
||||
// initialize the mesh object
|
||||
mesh = new Mesh { hideFlags = HideFlags.DontSave };
|
||||
mesh.SetVertices(vertices);
|
||||
mesh.SetUVs(0, uvs);
|
||||
mesh.SetIndices(indices, MeshTopology.Lines, 0);
|
||||
mesh.UploadMeshData(true);
|
||||
|
||||
// update the properties
|
||||
columnCount = columns;
|
||||
rowCount = rows;
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
GraphicsUtils.Destroy(mesh);
|
||||
mesh = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.IsModeActive(Mode.Depth)
|
||||
|| model.IsModeActive(Mode.Normals)
|
||||
|| model.IsModeActive(Mode.MotionVectors);
|
||||
}
|
||||
}
|
||||
|
||||
public override DepthTextureMode GetCameraFlags()
|
||||
{
|
||||
var mode = model.settings.mode;
|
||||
var flags = DepthTextureMode.None;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case Mode.Normals:
|
||||
flags |= DepthTextureMode.DepthNormals;
|
||||
break;
|
||||
case Mode.MotionVectors:
|
||||
flags |= DepthTextureMode.MotionVectors | DepthTextureMode.Depth;
|
||||
break;
|
||||
case Mode.Depth:
|
||||
flags |= DepthTextureMode.Depth;
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public override CameraEvent GetCameraEvent()
|
||||
{
|
||||
return model.settings.mode == Mode.MotionVectors
|
||||
? CameraEvent.BeforeImageEffects
|
||||
: CameraEvent.BeforeImageEffectsOpaque;
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
{
|
||||
return "Builtin Debug Views";
|
||||
}
|
||||
|
||||
public override void PopulateCommandBuffer(CommandBuffer cb)
|
||||
{
|
||||
var settings = model.settings;
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
material.shaderKeywords = null;
|
||||
|
||||
if (context.isGBufferAvailable)
|
||||
material.EnableKeyword("SOURCE_GBUFFER");
|
||||
|
||||
switch (settings.mode)
|
||||
{
|
||||
case Mode.Depth:
|
||||
DepthPass(cb);
|
||||
break;
|
||||
case Mode.Normals:
|
||||
DepthNormalsPass(cb);
|
||||
break;
|
||||
case Mode.MotionVectors:
|
||||
MotionVectorsPass(cb);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Interrupt();
|
||||
}
|
||||
|
||||
void DepthPass(CommandBuffer cb)
|
||||
{
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
var settings = model.settings.depth;
|
||||
|
||||
cb.SetGlobalFloat(Uniforms._DepthScale, 1f / settings.scale);
|
||||
cb.Blit((Texture)null, BuiltinRenderTextureType.CameraTarget, material, (int)Pass.Depth);
|
||||
}
|
||||
|
||||
void DepthNormalsPass(CommandBuffer cb)
|
||||
{
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
cb.Blit((Texture)null, BuiltinRenderTextureType.CameraTarget, material, (int)Pass.Normals);
|
||||
}
|
||||
|
||||
void MotionVectorsPass(CommandBuffer cb)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// Don't render motion vectors preview when the editor is not playing as it can in some
|
||||
// cases results in ugly artifacts (i.e. when resizing the game view).
|
||||
if (!Application.isPlaying)
|
||||
return;
|
||||
#endif
|
||||
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
var settings = model.settings.motionVectors;
|
||||
|
||||
// Blit the original source image
|
||||
int tempRT = Uniforms._TempRT;
|
||||
cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Bilinear);
|
||||
cb.SetGlobalFloat(Uniforms._Opacity, settings.sourceOpacity);
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget);
|
||||
cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, material, (int)Pass.MovecOpacity);
|
||||
|
||||
// Motion vectors (imaging)
|
||||
if (settings.motionImageOpacity > 0f && settings.motionImageAmplitude > 0f)
|
||||
{
|
||||
int tempRT2 = Uniforms._TempRT2;
|
||||
cb.GetTemporaryRT(tempRT2, context.width, context.height, 0, FilterMode.Bilinear);
|
||||
cb.SetGlobalFloat(Uniforms._Opacity, settings.motionImageOpacity);
|
||||
cb.SetGlobalFloat(Uniforms._Amplitude, settings.motionImageAmplitude);
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, tempRT);
|
||||
cb.Blit(tempRT, tempRT2, material, (int)Pass.MovecImaging);
|
||||
cb.ReleaseTemporaryRT(tempRT);
|
||||
tempRT = tempRT2;
|
||||
}
|
||||
|
||||
// Motion vectors (arrows)
|
||||
if (settings.motionVectorsOpacity > 0f && settings.motionVectorsAmplitude > 0f)
|
||||
{
|
||||
PrepareArrows();
|
||||
|
||||
float sy = 1f / settings.motionVectorsResolution;
|
||||
float sx = sy * context.height / context.width;
|
||||
|
||||
cb.SetGlobalVector(Uniforms._Scale, new Vector2(sx, sy));
|
||||
cb.SetGlobalFloat(Uniforms._Opacity, settings.motionVectorsOpacity);
|
||||
cb.SetGlobalFloat(Uniforms._Amplitude, settings.motionVectorsAmplitude);
|
||||
cb.DrawMesh(m_Arrows.mesh, Matrix4x4.identity, material, 0, (int)Pass.MovecArrows);
|
||||
}
|
||||
|
||||
cb.SetGlobalTexture(Uniforms._MainTex, tempRT);
|
||||
cb.Blit(tempRT, BuiltinRenderTextureType.CameraTarget);
|
||||
cb.ReleaseTemporaryRT(tempRT);
|
||||
}
|
||||
|
||||
void PrepareArrows()
|
||||
{
|
||||
int row = model.settings.motionVectors.motionVectorsResolution;
|
||||
int col = row * Screen.width / Screen.height;
|
||||
|
||||
if (m_Arrows == null)
|
||||
m_Arrows = new ArrowArray();
|
||||
|
||||
if (m_Arrows.columnCount != col || m_Arrows.rowCount != row)
|
||||
{
|
||||
m_Arrows.Release();
|
||||
m_Arrows.BuildMesh(col, row);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
if (m_Arrows != null)
|
||||
m_Arrows.Release();
|
||||
|
||||
m_Arrows = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fd834b6165e82e64f9da2d4ed9f4e236
|
||||
timeCreated: 1473163679
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
public sealed class ChromaticAberrationComponent : PostProcessingComponentRenderTexture<ChromaticAberrationModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _ChromaticAberration_Amount = Shader.PropertyToID("_ChromaticAberration_Amount");
|
||||
internal static readonly int _ChromaticAberration_Spectrum = Shader.PropertyToID("_ChromaticAberration_Spectrum");
|
||||
}
|
||||
|
||||
Texture2D m_SpectrumLut;
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& model.settings.intensity > 0f
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
GraphicsUtils.Destroy(m_SpectrumLut);
|
||||
m_SpectrumLut = null;
|
||||
}
|
||||
|
||||
public override void Prepare(Material uberMaterial)
|
||||
{
|
||||
var settings = model.settings;
|
||||
var spectralLut = settings.spectralTexture;
|
||||
|
||||
if (spectralLut == null)
|
||||
{
|
||||
if (m_SpectrumLut == null)
|
||||
{
|
||||
m_SpectrumLut = new Texture2D(3, 1, TextureFormat.RGB24, false)
|
||||
{
|
||||
name = "Chromatic Aberration Spectrum Lookup",
|
||||
filterMode = FilterMode.Bilinear,
|
||||
wrapMode = TextureWrapMode.Clamp,
|
||||
anisoLevel = 0,
|
||||
hideFlags = HideFlags.DontSave
|
||||
};
|
||||
|
||||
var pixels = new Color[3];
|
||||
pixels[0] = new Color(1f, 0f, 0f);
|
||||
pixels[1] = new Color(0f, 1f, 0f);
|
||||
pixels[2] = new Color(0f, 0f, 1f);
|
||||
m_SpectrumLut.SetPixels(pixels);
|
||||
m_SpectrumLut.Apply();
|
||||
}
|
||||
|
||||
spectralLut = m_SpectrumLut;
|
||||
}
|
||||
|
||||
uberMaterial.EnableKeyword("CHROMATIC_ABERRATION");
|
||||
uberMaterial.SetFloat(Uniforms._ChromaticAberration_Amount, settings.intensity * 0.03f);
|
||||
uberMaterial.SetTexture(Uniforms._ChromaticAberration_Spectrum, spectralLut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b9c65642df654a84d84ded1b07448a4c
|
||||
timeCreated: 1473085971
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,436 @@
|
|||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
using DebugMode = BuiltinDebugViewsModel.Mode;
|
||||
|
||||
public sealed class ColorGradingComponent : PostProcessingComponentRenderTexture<ColorGradingModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _LutParams = Shader.PropertyToID("_LutParams");
|
||||
internal static readonly int _NeutralTonemapperParams1 = Shader.PropertyToID("_NeutralTonemapperParams1");
|
||||
internal static readonly int _NeutralTonemapperParams2 = Shader.PropertyToID("_NeutralTonemapperParams2");
|
||||
internal static readonly int _HueShift = Shader.PropertyToID("_HueShift");
|
||||
internal static readonly int _Saturation = Shader.PropertyToID("_Saturation");
|
||||
internal static readonly int _Contrast = Shader.PropertyToID("_Contrast");
|
||||
internal static readonly int _Balance = Shader.PropertyToID("_Balance");
|
||||
internal static readonly int _Lift = Shader.PropertyToID("_Lift");
|
||||
internal static readonly int _InvGamma = Shader.PropertyToID("_InvGamma");
|
||||
internal static readonly int _Gain = Shader.PropertyToID("_Gain");
|
||||
internal static readonly int _Slope = Shader.PropertyToID("_Slope");
|
||||
internal static readonly int _Power = Shader.PropertyToID("_Power");
|
||||
internal static readonly int _Offset = Shader.PropertyToID("_Offset");
|
||||
internal static readonly int _ChannelMixerRed = Shader.PropertyToID("_ChannelMixerRed");
|
||||
internal static readonly int _ChannelMixerGreen = Shader.PropertyToID("_ChannelMixerGreen");
|
||||
internal static readonly int _ChannelMixerBlue = Shader.PropertyToID("_ChannelMixerBlue");
|
||||
internal static readonly int _Curves = Shader.PropertyToID("_Curves");
|
||||
internal static readonly int _LogLut = Shader.PropertyToID("_LogLut");
|
||||
internal static readonly int _LogLut_Params = Shader.PropertyToID("_LogLut_Params");
|
||||
internal static readonly int _ExposureEV = Shader.PropertyToID("_ExposureEV");
|
||||
}
|
||||
|
||||
const int k_InternalLogLutSize = 32;
|
||||
const int k_CurvePrecision = 128;
|
||||
const float k_CurveStep = 1f / k_CurvePrecision;
|
||||
|
||||
Texture2D m_GradingCurves;
|
||||
Color[] m_pixels = new Color[k_CurvePrecision * 2];
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
// An analytical model of chromaticity of the standard illuminant, by Judd et al.
|
||||
// http://en.wikipedia.org/wiki/Standard_illuminant#Illuminant_series_D
|
||||
// Slightly modifed to adjust it with the D65 white point (x=0.31271, y=0.32902).
|
||||
float StandardIlluminantY(float x)
|
||||
{
|
||||
return 2.87f * x - 3f * x * x - 0.27509507f;
|
||||
}
|
||||
|
||||
// CIE xy chromaticity to CAT02 LMS.
|
||||
// http://en.wikipedia.org/wiki/LMS_color_space#CAT02
|
||||
Vector3 CIExyToLMS(float x, float y)
|
||||
{
|
||||
float Y = 1f;
|
||||
float X = Y * x / y;
|
||||
float Z = Y * (1f - x - y) / y;
|
||||
|
||||
float L = 0.7328f * X + 0.4296f * Y - 0.1624f * Z;
|
||||
float M = -0.7036f * X + 1.6975f * Y + 0.0061f * Z;
|
||||
float S = 0.0030f * X + 0.0136f * Y + 0.9834f * Z;
|
||||
|
||||
return new Vector3(L, M, S);
|
||||
}
|
||||
|
||||
Vector3 CalculateColorBalance(float temperature, float tint)
|
||||
{
|
||||
// Range ~[-1.8;1.8] ; using higher ranges is unsafe
|
||||
float t1 = temperature / 55f;
|
||||
float t2 = tint / 55f;
|
||||
|
||||
// Get the CIE xy chromaticity of the reference white point.
|
||||
// Note: 0.31271 = x value on the D65 white point
|
||||
float x = 0.31271f - t1 * (t1 < 0f ? 0.1f : 0.05f);
|
||||
float y = StandardIlluminantY(x) + t2 * 0.05f;
|
||||
|
||||
// Calculate the coefficients in the LMS space.
|
||||
var w1 = new Vector3(0.949237f, 1.03542f, 1.08728f); // D65 white point
|
||||
var w2 = CIExyToLMS(x, y);
|
||||
return new Vector3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);
|
||||
}
|
||||
|
||||
static Color NormalizeColor(Color c)
|
||||
{
|
||||
float sum = (c.r + c.g + c.b) / 3f;
|
||||
|
||||
if (Mathf.Approximately(sum, 0f))
|
||||
return new Color(1f, 1f, 1f, c.a);
|
||||
|
||||
return new Color
|
||||
{
|
||||
r = c.r / sum,
|
||||
g = c.g / sum,
|
||||
b = c.b / sum,
|
||||
a = c.a
|
||||
};
|
||||
}
|
||||
|
||||
static Vector3 ClampVector(Vector3 v, float min, float max)
|
||||
{
|
||||
return new Vector3(
|
||||
Mathf.Clamp(v.x, min, max),
|
||||
Mathf.Clamp(v.y, min, max),
|
||||
Mathf.Clamp(v.z, min, max)
|
||||
);
|
||||
}
|
||||
|
||||
public static Vector3 GetLiftValue(Color lift)
|
||||
{
|
||||
const float kLiftScale = 0.1f;
|
||||
|
||||
var nLift = NormalizeColor(lift);
|
||||
float avgLift = (nLift.r + nLift.g + nLift.b) / 3f;
|
||||
|
||||
// Getting some artifacts when going into the negatives using a very low offset (lift.a) with non ACES-tonemapping
|
||||
float liftR = (nLift.r - avgLift) * kLiftScale + lift.a;
|
||||
float liftG = (nLift.g - avgLift) * kLiftScale + lift.a;
|
||||
float liftB = (nLift.b - avgLift) * kLiftScale + lift.a;
|
||||
|
||||
return ClampVector(new Vector3(liftR, liftG, liftB), -1f, 1f);
|
||||
}
|
||||
|
||||
public static Vector3 GetGammaValue(Color gamma)
|
||||
{
|
||||
const float kGammaScale = 0.5f;
|
||||
const float kMinGamma = 0.01f;
|
||||
|
||||
var nGamma = NormalizeColor(gamma);
|
||||
float avgGamma = (nGamma.r + nGamma.g + nGamma.b) / 3f;
|
||||
|
||||
gamma.a *= gamma.a < 0f ? 0.8f : 5f;
|
||||
float gammaR = Mathf.Pow(2f, (nGamma.r - avgGamma) * kGammaScale) + gamma.a;
|
||||
float gammaG = Mathf.Pow(2f, (nGamma.g - avgGamma) * kGammaScale) + gamma.a;
|
||||
float gammaB = Mathf.Pow(2f, (nGamma.b - avgGamma) * kGammaScale) + gamma.a;
|
||||
|
||||
float invGammaR = 1f / Mathf.Max(kMinGamma, gammaR);
|
||||
float invGammaG = 1f / Mathf.Max(kMinGamma, gammaG);
|
||||
float invGammaB = 1f / Mathf.Max(kMinGamma, gammaB);
|
||||
|
||||
return ClampVector(new Vector3(invGammaR, invGammaG, invGammaB), 0f, 5f);
|
||||
}
|
||||
|
||||
public static Vector3 GetGainValue(Color gain)
|
||||
{
|
||||
const float kGainScale = 0.5f;
|
||||
|
||||
var nGain = NormalizeColor(gain);
|
||||
float avgGain = (nGain.r + nGain.g + nGain.b) / 3f;
|
||||
|
||||
gain.a *= gain.a > 0f ? 3f : 1f;
|
||||
float gainR = Mathf.Pow(2f, (nGain.r - avgGain) * kGainScale) + gain.a;
|
||||
float gainG = Mathf.Pow(2f, (nGain.g - avgGain) * kGainScale) + gain.a;
|
||||
float gainB = Mathf.Pow(2f, (nGain.b - avgGain) * kGainScale) + gain.a;
|
||||
|
||||
return ClampVector(new Vector3(gainR, gainG, gainB), 0f, 4f);
|
||||
}
|
||||
|
||||
public static void CalculateLiftGammaGain(Color lift, Color gamma, Color gain, out Vector3 outLift, out Vector3 outGamma, out Vector3 outGain)
|
||||
{
|
||||
outLift = GetLiftValue(lift);
|
||||
outGamma = GetGammaValue(gamma);
|
||||
outGain = GetGainValue(gain);
|
||||
}
|
||||
|
||||
public static Vector3 GetSlopeValue(Color slope)
|
||||
{
|
||||
const float kSlopeScale = 0.1f;
|
||||
|
||||
var nSlope = NormalizeColor(slope);
|
||||
float avgSlope = (nSlope.r + nSlope.g + nSlope.b) / 3f;
|
||||
|
||||
slope.a *= 0.5f;
|
||||
float slopeR = (nSlope.r - avgSlope) * kSlopeScale + slope.a + 1f;
|
||||
float slopeG = (nSlope.g - avgSlope) * kSlopeScale + slope.a + 1f;
|
||||
float slopeB = (nSlope.b - avgSlope) * kSlopeScale + slope.a + 1f;
|
||||
|
||||
return ClampVector(new Vector3(slopeR, slopeG, slopeB), 0f, 2f);
|
||||
}
|
||||
|
||||
public static Vector3 GetPowerValue(Color power)
|
||||
{
|
||||
const float kPowerScale = 0.1f;
|
||||
const float minPower = 0.01f;
|
||||
|
||||
var nPower = NormalizeColor(power);
|
||||
float avgPower = (nPower.r + nPower.g + nPower.b) / 3f;
|
||||
|
||||
power.a *= 0.5f;
|
||||
float powerR = (nPower.r - avgPower) * kPowerScale + power.a + 1f;
|
||||
float powerG = (nPower.g - avgPower) * kPowerScale + power.a + 1f;
|
||||
float powerB = (nPower.b - avgPower) * kPowerScale + power.a + 1f;
|
||||
|
||||
float invPowerR = 1f / Mathf.Max(minPower, powerR);
|
||||
float invPowerG = 1f / Mathf.Max(minPower, powerG);
|
||||
float invPowerB = 1f / Mathf.Max(minPower, powerB);
|
||||
|
||||
return ClampVector(new Vector3(invPowerR, invPowerG, invPowerB), 0.5f, 2.5f);
|
||||
}
|
||||
|
||||
public static Vector3 GetOffsetValue(Color offset)
|
||||
{
|
||||
const float kOffsetScale = 0.05f;
|
||||
|
||||
var nOffset = NormalizeColor(offset);
|
||||
float avgOffset = (nOffset.r + nOffset.g + nOffset.b) / 3f;
|
||||
|
||||
offset.a *= 0.5f;
|
||||
float offsetR = (nOffset.r - avgOffset) * kOffsetScale + offset.a;
|
||||
float offsetG = (nOffset.g - avgOffset) * kOffsetScale + offset.a;
|
||||
float offsetB = (nOffset.b - avgOffset) * kOffsetScale + offset.a;
|
||||
|
||||
return ClampVector(new Vector3(offsetR, offsetG, offsetB), -0.8f, 0.8f);
|
||||
}
|
||||
|
||||
public static void CalculateSlopePowerOffset(Color slope, Color power, Color offset, out Vector3 outSlope, out Vector3 outPower, out Vector3 outOffset)
|
||||
{
|
||||
outSlope = GetSlopeValue(slope);
|
||||
outPower = GetPowerValue(power);
|
||||
outOffset = GetOffsetValue(offset);
|
||||
}
|
||||
|
||||
TextureFormat GetCurveFormat()
|
||||
{
|
||||
if (SystemInfo.SupportsTextureFormat(TextureFormat.RGBAHalf))
|
||||
return TextureFormat.RGBAHalf;
|
||||
|
||||
return TextureFormat.RGBA32;
|
||||
}
|
||||
|
||||
Texture2D GetCurveTexture()
|
||||
{
|
||||
if (m_GradingCurves == null)
|
||||
{
|
||||
m_GradingCurves = new Texture2D(k_CurvePrecision, 2, GetCurveFormat(), false, true)
|
||||
{
|
||||
name = "Internal Curves Texture",
|
||||
hideFlags = HideFlags.DontSave,
|
||||
anisoLevel = 0,
|
||||
wrapMode = TextureWrapMode.Clamp,
|
||||
filterMode = FilterMode.Bilinear
|
||||
};
|
||||
}
|
||||
|
||||
var curves = model.settings.curves;
|
||||
curves.hueVShue.Cache();
|
||||
curves.hueVSsat.Cache();
|
||||
|
||||
for (int i = 0; i < k_CurvePrecision; i++)
|
||||
{
|
||||
float t = i * k_CurveStep;
|
||||
|
||||
// HSL
|
||||
float x = curves.hueVShue.Evaluate(t);
|
||||
float y = curves.hueVSsat.Evaluate(t);
|
||||
float z = curves.satVSsat.Evaluate(t);
|
||||
float w = curves.lumVSsat.Evaluate(t);
|
||||
m_pixels[i] = new Color(x, y, z, w);
|
||||
|
||||
// YRGB
|
||||
float m = curves.master.Evaluate(t);
|
||||
float r = curves.red.Evaluate(t);
|
||||
float g = curves.green.Evaluate(t);
|
||||
float b = curves.blue.Evaluate(t);
|
||||
m_pixels[i + k_CurvePrecision] = new Color(r, g, b, m);
|
||||
}
|
||||
|
||||
m_GradingCurves.SetPixels(m_pixels);
|
||||
m_GradingCurves.Apply(false, false);
|
||||
|
||||
return m_GradingCurves;
|
||||
}
|
||||
|
||||
bool IsLogLutValid(RenderTexture lut)
|
||||
{
|
||||
return lut != null && lut.IsCreated() && lut.height == k_InternalLogLutSize;
|
||||
}
|
||||
|
||||
RenderTextureFormat GetLutFormat()
|
||||
{
|
||||
if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf))
|
||||
return RenderTextureFormat.ARGBHalf;
|
||||
|
||||
return RenderTextureFormat.ARGB32;
|
||||
}
|
||||
|
||||
void GenerateLut()
|
||||
{
|
||||
var settings = model.settings;
|
||||
|
||||
if (!IsLogLutValid(model.bakedLut))
|
||||
{
|
||||
GraphicsUtils.Destroy(model.bakedLut);
|
||||
|
||||
model.bakedLut = new RenderTexture(k_InternalLogLutSize * k_InternalLogLutSize, k_InternalLogLutSize, 0, GetLutFormat())
|
||||
{
|
||||
name = "Color Grading Log LUT",
|
||||
hideFlags = HideFlags.DontSave,
|
||||
filterMode = FilterMode.Bilinear,
|
||||
wrapMode = TextureWrapMode.Clamp,
|
||||
anisoLevel = 0
|
||||
};
|
||||
}
|
||||
|
||||
var lutMaterial = context.materialFactory.Get("Hidden/Post FX/Lut Generator");
|
||||
lutMaterial.SetVector(Uniforms._LutParams, new Vector4(
|
||||
k_InternalLogLutSize,
|
||||
0.5f / (k_InternalLogLutSize * k_InternalLogLutSize),
|
||||
0.5f / k_InternalLogLutSize,
|
||||
k_InternalLogLutSize / (k_InternalLogLutSize - 1f))
|
||||
);
|
||||
|
||||
// Tonemapping
|
||||
lutMaterial.shaderKeywords = null;
|
||||
|
||||
var tonemapping = settings.tonemapping;
|
||||
switch (tonemapping.tonemapper)
|
||||
{
|
||||
case ColorGradingModel.Tonemapper.Neutral:
|
||||
{
|
||||
lutMaterial.EnableKeyword("TONEMAPPING_NEUTRAL");
|
||||
|
||||
const float scaleFactor = 20f;
|
||||
const float scaleFactorHalf = scaleFactor * 0.5f;
|
||||
|
||||
float inBlack = tonemapping.neutralBlackIn * scaleFactor + 1f;
|
||||
float outBlack = tonemapping.neutralBlackOut * scaleFactorHalf + 1f;
|
||||
float inWhite = tonemapping.neutralWhiteIn / scaleFactor;
|
||||
float outWhite = 1f - tonemapping.neutralWhiteOut / scaleFactor;
|
||||
float blackRatio = inBlack / outBlack;
|
||||
float whiteRatio = inWhite / outWhite;
|
||||
|
||||
const float a = 0.2f;
|
||||
float b = Mathf.Max(0f, Mathf.LerpUnclamped(0.57f, 0.37f, blackRatio));
|
||||
float c = Mathf.LerpUnclamped(0.01f, 0.24f, whiteRatio);
|
||||
float d = Mathf.Max(0f, Mathf.LerpUnclamped(0.02f, 0.20f, blackRatio));
|
||||
const float e = 0.02f;
|
||||
const float f = 0.30f;
|
||||
|
||||
lutMaterial.SetVector(Uniforms._NeutralTonemapperParams1, new Vector4(a, b, c, d));
|
||||
lutMaterial.SetVector(Uniforms._NeutralTonemapperParams2, new Vector4(e, f, tonemapping.neutralWhiteLevel, tonemapping.neutralWhiteClip / scaleFactorHalf));
|
||||
break;
|
||||
}
|
||||
|
||||
case ColorGradingModel.Tonemapper.ACES:
|
||||
{
|
||||
lutMaterial.EnableKeyword("TONEMAPPING_FILMIC");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Color balance & basic grading settings
|
||||
lutMaterial.SetFloat(Uniforms._HueShift, settings.basic.hueShift / 360f);
|
||||
lutMaterial.SetFloat(Uniforms._Saturation, settings.basic.saturation);
|
||||
lutMaterial.SetFloat(Uniforms._Contrast, settings.basic.contrast);
|
||||
lutMaterial.SetVector(Uniforms._Balance, CalculateColorBalance(settings.basic.temperature, settings.basic.tint));
|
||||
|
||||
// Lift / Gamma / Gain
|
||||
Vector3 lift, gamma, gain;
|
||||
CalculateLiftGammaGain(
|
||||
settings.colorWheels.linear.lift,
|
||||
settings.colorWheels.linear.gamma,
|
||||
settings.colorWheels.linear.gain,
|
||||
out lift, out gamma, out gain
|
||||
);
|
||||
|
||||
lutMaterial.SetVector(Uniforms._Lift, lift);
|
||||
lutMaterial.SetVector(Uniforms._InvGamma, gamma);
|
||||
lutMaterial.SetVector(Uniforms._Gain, gain);
|
||||
|
||||
// Slope / Power / Offset
|
||||
Vector3 slope, power, offset;
|
||||
CalculateSlopePowerOffset(
|
||||
settings.colorWheels.log.slope,
|
||||
settings.colorWheels.log.power,
|
||||
settings.colorWheels.log.offset,
|
||||
out slope, out power, out offset
|
||||
);
|
||||
|
||||
lutMaterial.SetVector(Uniforms._Slope, slope);
|
||||
lutMaterial.SetVector(Uniforms._Power, power);
|
||||
lutMaterial.SetVector(Uniforms._Offset, offset);
|
||||
|
||||
// Channel mixer
|
||||
lutMaterial.SetVector(Uniforms._ChannelMixerRed, settings.channelMixer.red);
|
||||
lutMaterial.SetVector(Uniforms._ChannelMixerGreen, settings.channelMixer.green);
|
||||
lutMaterial.SetVector(Uniforms._ChannelMixerBlue, settings.channelMixer.blue);
|
||||
|
||||
// Selective grading & YRGB curves
|
||||
lutMaterial.SetTexture(Uniforms._Curves, GetCurveTexture());
|
||||
|
||||
// Generate the lut
|
||||
Graphics.Blit(null, model.bakedLut, lutMaterial, 0);
|
||||
}
|
||||
|
||||
public override void Prepare(Material uberMaterial)
|
||||
{
|
||||
if (model.isDirty || !IsLogLutValid(model.bakedLut))
|
||||
{
|
||||
GenerateLut();
|
||||
model.isDirty = false;
|
||||
}
|
||||
|
||||
uberMaterial.EnableKeyword(
|
||||
context.profile.debugViews.IsModeActive(DebugMode.PreGradingLog)
|
||||
? "COLOR_GRADING_LOG_VIEW"
|
||||
: "COLOR_GRADING"
|
||||
);
|
||||
|
||||
var bakedLut = model.bakedLut;
|
||||
uberMaterial.SetTexture(Uniforms._LogLut, bakedLut);
|
||||
uberMaterial.SetVector(Uniforms._LogLut_Params, new Vector3(1f / bakedLut.width, 1f / bakedLut.height, bakedLut.height - 1f));
|
||||
|
||||
float ev = Mathf.Exp(model.settings.basic.postExposure * 0.69314718055994530941723212145818f);
|
||||
uberMaterial.SetFloat(Uniforms._ExposureEV, ev);
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
var bakedLut = model.bakedLut;
|
||||
var rect = new Rect(context.viewport.x * Screen.width + 8f, 8f, bakedLut.width, bakedLut.height);
|
||||
GUI.DrawTexture(rect, bakedLut);
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
GraphicsUtils.Destroy(m_GradingCurves);
|
||||
GraphicsUtils.Destroy(model.bakedLut);
|
||||
m_GradingCurves = null;
|
||||
model.bakedLut = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9baf73db7c9fc1b478f4a0a1000c86f5
|
||||
timeCreated: 1473086520
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
using DebugMode = BuiltinDebugViewsModel.Mode;
|
||||
|
||||
public sealed class DepthOfFieldComponent : PostProcessingComponentRenderTexture<DepthOfFieldModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _DepthOfFieldTex = Shader.PropertyToID("_DepthOfFieldTex");
|
||||
internal static readonly int _DepthOfFieldCoCTex = Shader.PropertyToID("_DepthOfFieldCoCTex");
|
||||
internal static readonly int _Distance = Shader.PropertyToID("_Distance");
|
||||
internal static readonly int _LensCoeff = Shader.PropertyToID("_LensCoeff");
|
||||
internal static readonly int _MaxCoC = Shader.PropertyToID("_MaxCoC");
|
||||
internal static readonly int _RcpMaxCoC = Shader.PropertyToID("_RcpMaxCoC");
|
||||
internal static readonly int _RcpAspect = Shader.PropertyToID("_RcpAspect");
|
||||
internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
|
||||
internal static readonly int _CoCTex = Shader.PropertyToID("_CoCTex");
|
||||
internal static readonly int _TaaParams = Shader.PropertyToID("_TaaParams");
|
||||
internal static readonly int _DepthOfFieldParams = Shader.PropertyToID("_DepthOfFieldParams");
|
||||
}
|
||||
|
||||
const string k_ShaderString = "Hidden/Post FX/Depth Of Field";
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
public override DepthTextureMode GetCameraFlags()
|
||||
{
|
||||
return DepthTextureMode.Depth;
|
||||
}
|
||||
|
||||
RenderTexture m_CoCHistory;
|
||||
|
||||
// Height of the 35mm full-frame format (36mm x 24mm)
|
||||
const float k_FilmHeight = 0.024f;
|
||||
|
||||
float CalculateFocalLength()
|
||||
{
|
||||
var settings = model.settings;
|
||||
|
||||
if (!settings.useCameraFov)
|
||||
return settings.focalLength / 1000f;
|
||||
|
||||
float fov = context.camera.fieldOfView * Mathf.Deg2Rad;
|
||||
return 0.5f * k_FilmHeight / Mathf.Tan(0.5f * fov);
|
||||
}
|
||||
|
||||
float CalculateMaxCoCRadius(int screenHeight)
|
||||
{
|
||||
// Estimate the allowable maximum radius of CoC from the kernel
|
||||
// size (the equation below was empirically derived).
|
||||
float radiusInPixels = (float)model.settings.kernelSize * 4f + 6f;
|
||||
|
||||
// Applying a 5% limit to the CoC radius to keep the size of
|
||||
// TileMax/NeighborMax small enough.
|
||||
return Mathf.Min(0.05f, radiusInPixels / screenHeight);
|
||||
}
|
||||
|
||||
bool CheckHistory(int width, int height)
|
||||
{
|
||||
return m_CoCHistory != null && m_CoCHistory.IsCreated() &&
|
||||
m_CoCHistory.width == width && m_CoCHistory.height == height;
|
||||
}
|
||||
|
||||
RenderTextureFormat SelectFormat(RenderTextureFormat primary, RenderTextureFormat secondary)
|
||||
{
|
||||
if (SystemInfo.SupportsRenderTextureFormat(primary)) return primary;
|
||||
if (SystemInfo.SupportsRenderTextureFormat(secondary)) return secondary;
|
||||
return RenderTextureFormat.Default;
|
||||
}
|
||||
|
||||
public void Prepare(RenderTexture source, Material uberMaterial, bool antialiasCoC, Vector2 taaJitter, float taaBlending)
|
||||
{
|
||||
var settings = model.settings;
|
||||
var colorFormat = RenderTextureFormat.DefaultHDR;
|
||||
var cocFormat = SelectFormat(RenderTextureFormat.R8, RenderTextureFormat.RHalf);
|
||||
|
||||
// Avoid using R8 on OSX with Metal. #896121, https://goo.gl/MgKqu6
|
||||
#if (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX) && !UNITY_2017_1_OR_NEWER
|
||||
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
|
||||
cocFormat = SelectFormat(RenderTextureFormat.RHalf, RenderTextureFormat.Default);
|
||||
#endif
|
||||
|
||||
// Material setup
|
||||
var f = CalculateFocalLength();
|
||||
var s1 = Mathf.Max(settings.focusDistance, f);
|
||||
var aspect = (float)source.width / source.height;
|
||||
var coeff = f * f / (settings.aperture * (s1 - f) * k_FilmHeight * 2);
|
||||
var maxCoC = CalculateMaxCoCRadius(source.height);
|
||||
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
material.SetFloat(Uniforms._Distance, s1);
|
||||
material.SetFloat(Uniforms._LensCoeff, coeff);
|
||||
material.SetFloat(Uniforms._MaxCoC, maxCoC);
|
||||
material.SetFloat(Uniforms._RcpMaxCoC, 1f / maxCoC);
|
||||
material.SetFloat(Uniforms._RcpAspect, 1f / aspect);
|
||||
|
||||
// CoC calculation pass
|
||||
var rtCoC = context.renderTextureFactory.Get(context.width, context.height, 0, cocFormat, RenderTextureReadWrite.Linear);
|
||||
Graphics.Blit(null, rtCoC, material, 0);
|
||||
|
||||
if (antialiasCoC)
|
||||
{
|
||||
// CoC temporal filter pass
|
||||
material.SetTexture(Uniforms._CoCTex, rtCoC);
|
||||
|
||||
var blend = CheckHistory(context.width, context.height) ? taaBlending : 0f;
|
||||
material.SetVector(Uniforms._TaaParams, new Vector3(taaJitter.x, taaJitter.y, blend));
|
||||
|
||||
var rtFiltered = RenderTexture.GetTemporary(context.width, context.height, 0, cocFormat);
|
||||
Graphics.Blit(m_CoCHistory, rtFiltered, material, 1);
|
||||
|
||||
context.renderTextureFactory.Release(rtCoC);
|
||||
if (m_CoCHistory != null) RenderTexture.ReleaseTemporary(m_CoCHistory);
|
||||
|
||||
m_CoCHistory = rtCoC = rtFiltered;
|
||||
}
|
||||
|
||||
// Downsampling and prefiltering pass
|
||||
var rt1 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, colorFormat);
|
||||
material.SetTexture(Uniforms._CoCTex, rtCoC);
|
||||
Graphics.Blit(source, rt1, material, 2);
|
||||
|
||||
// Bokeh simulation pass
|
||||
var rt2 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, colorFormat);
|
||||
Graphics.Blit(rt1, rt2, material, 3 + (int)settings.kernelSize);
|
||||
|
||||
// Postfilter pass
|
||||
Graphics.Blit(rt2, rt1, material, 7);
|
||||
|
||||
// Give the results to the uber shader.
|
||||
uberMaterial.SetVector(Uniforms._DepthOfFieldParams, new Vector3(s1, coeff, maxCoC));
|
||||
|
||||
if (context.profile.debugViews.IsModeActive(DebugMode.FocusPlane))
|
||||
{
|
||||
uberMaterial.EnableKeyword("DEPTH_OF_FIELD_COC_VIEW");
|
||||
context.Interrupt();
|
||||
}
|
||||
else
|
||||
{
|
||||
uberMaterial.SetTexture(Uniforms._DepthOfFieldTex, rt1);
|
||||
uberMaterial.SetTexture(Uniforms._DepthOfFieldCoCTex, rtCoC);
|
||||
uberMaterial.EnableKeyword("DEPTH_OF_FIELD");
|
||||
}
|
||||
|
||||
context.renderTextureFactory.Release(rt2);
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
if (m_CoCHistory != null)
|
||||
RenderTexture.ReleaseTemporary(m_CoCHistory);
|
||||
|
||||
m_CoCHistory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
using DebugMode = BuiltinDebugViewsModel.Mode;
|
||||
|
||||
public sealed class DepthOfFieldComponent : PostProcessingComponentRenderTexture<DepthOfFieldModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _DepthOfFieldTex = Shader.PropertyToID("_DepthOfFieldTex");
|
||||
internal static readonly int _DepthOfFieldCoCTex = Shader.PropertyToID("_DepthOfFieldCoCTex");
|
||||
internal static readonly int _Distance = Shader.PropertyToID("_Distance");
|
||||
internal static readonly int _LensCoeff = Shader.PropertyToID("_LensCoeff");
|
||||
internal static readonly int _MaxCoC = Shader.PropertyToID("_MaxCoC");
|
||||
internal static readonly int _RcpMaxCoC = Shader.PropertyToID("_RcpMaxCoC");
|
||||
internal static readonly int _RcpAspect = Shader.PropertyToID("_RcpAspect");
|
||||
internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
|
||||
internal static readonly int _CoCTex = Shader.PropertyToID("_CoCTex");
|
||||
internal static readonly int _TaaParams = Shader.PropertyToID("_TaaParams");
|
||||
internal static readonly int _DepthOfFieldParams = Shader.PropertyToID("_DepthOfFieldParams");
|
||||
}
|
||||
|
||||
const string k_ShaderString = "Hidden/Post FX/Depth Of Field";
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
public override DepthTextureMode GetCameraFlags()
|
||||
{
|
||||
return DepthTextureMode.Depth;
|
||||
}
|
||||
|
||||
RenderTexture m_CoCHistory;
|
||||
|
||||
// Height of the 35mm full-frame format (36mm x 24mm)
|
||||
const float k_FilmHeight = 0.024f;
|
||||
|
||||
float CalculateFocalLength()
|
||||
{
|
||||
var settings = model.settings;
|
||||
|
||||
if (!settings.useCameraFov)
|
||||
return settings.focalLength / 1000f;
|
||||
|
||||
float fov = context.camera.fieldOfView * Mathf.Deg2Rad;
|
||||
return 0.5f * k_FilmHeight / Mathf.Tan(0.5f * fov);
|
||||
}
|
||||
|
||||
float CalculateMaxCoCRadius(int screenHeight)
|
||||
{
|
||||
// Estimate the allowable maximum radius of CoC from the kernel
|
||||
// size (the equation below was empirically derived).
|
||||
float radiusInPixels = (float)model.settings.kernelSize * 4f + 6f;
|
||||
|
||||
// Applying a 5% limit to the CoC radius to keep the size of
|
||||
// TileMax/NeighborMax small enough.
|
||||
return Mathf.Min(0.05f, radiusInPixels / screenHeight);
|
||||
}
|
||||
|
||||
bool CheckHistory(int width, int height)
|
||||
{
|
||||
return m_CoCHistory != null && m_CoCHistory.IsCreated() &&
|
||||
m_CoCHistory.width == width && m_CoCHistory.height == height;
|
||||
}
|
||||
|
||||
RenderTextureFormat SelectFormat(RenderTextureFormat primary, RenderTextureFormat secondary)
|
||||
{
|
||||
if (SystemInfo.SupportsRenderTextureFormat(primary)) return primary;
|
||||
if (SystemInfo.SupportsRenderTextureFormat(secondary)) return secondary;
|
||||
return RenderTextureFormat.Default;
|
||||
}
|
||||
|
||||
public void Prepare(RenderTexture source, Material uberMaterial, bool antialiasCoC, Vector2 taaJitter, float taaBlending)
|
||||
{
|
||||
var settings = model.settings;
|
||||
var colorFormat = RenderTextureFormat.DefaultHDR;
|
||||
var cocFormat = SelectFormat(RenderTextureFormat.R8, RenderTextureFormat.RHalf);
|
||||
|
||||
// Avoid using R8 on OSX with Metal. #896121, https://goo.gl/MgKqu6
|
||||
#if (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX) && !UNITY_2017_1_OR_NEWER
|
||||
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
|
||||
cocFormat = SelectFormat(RenderTextureFormat.RHalf, RenderTextureFormat.Default);
|
||||
#endif
|
||||
|
||||
// Material setup
|
||||
var f = CalculateFocalLength();
|
||||
var s1 = Mathf.Max(settings.focusDistance, f);
|
||||
var aspect = (float)source.width / source.height;
|
||||
var coeff = f * f / (settings.aperture * (s1 - f) * k_FilmHeight * 2);
|
||||
var maxCoC = CalculateMaxCoCRadius(source.height);
|
||||
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
material.SetFloat(Uniforms._Distance, s1);
|
||||
material.SetFloat(Uniforms._LensCoeff, coeff);
|
||||
material.SetFloat(Uniforms._MaxCoC, maxCoC);
|
||||
material.SetFloat(Uniforms._RcpMaxCoC, 1f / maxCoC);
|
||||
material.SetFloat(Uniforms._RcpAspect, 1f / aspect);
|
||||
|
||||
// CoC calculation pass
|
||||
var rtCoC = context.renderTextureFactory.Get(context.width, context.height, 0, cocFormat, RenderTextureReadWrite.Linear);
|
||||
Graphics.Blit(null, rtCoC, material, 0);
|
||||
|
||||
if (antialiasCoC)
|
||||
{
|
||||
// CoC temporal filter pass
|
||||
material.SetTexture(Uniforms._CoCTex, rtCoC);
|
||||
|
||||
var blend = CheckHistory(context.width, context.height) ? taaBlending : 0f;
|
||||
material.SetVector(Uniforms._TaaParams, new Vector3(taaJitter.x, taaJitter.y, blend));
|
||||
|
||||
var rtFiltered = RenderTexture.GetTemporary(context.width, context.height, 0, cocFormat);
|
||||
Graphics.Blit(m_CoCHistory, rtFiltered, material, 1);
|
||||
|
||||
context.renderTextureFactory.Release(rtCoC);
|
||||
if (m_CoCHistory != null) RenderTexture.ReleaseTemporary(m_CoCHistory);
|
||||
|
||||
m_CoCHistory = rtCoC = rtFiltered;
|
||||
}
|
||||
|
||||
// Downsampling and prefiltering pass
|
||||
var rt1 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, colorFormat);
|
||||
material.SetTexture(Uniforms._CoCTex, rtCoC);
|
||||
Graphics.Blit(source, rt1, material, 2);
|
||||
|
||||
// Bokeh simulation pass
|
||||
var rt2 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, colorFormat);
|
||||
Graphics.Blit(rt1, rt2, material, 3 + (int)settings.kernelSize);
|
||||
|
||||
// Postfilter pass
|
||||
Graphics.Blit(rt2, rt1, material, 7);
|
||||
|
||||
// Give the results to the uber shader.
|
||||
uberMaterial.SetVector(Uniforms._DepthOfFieldParams, new Vector3(s1, coeff, maxCoC));
|
||||
|
||||
if (context.profile.debugViews.IsModeActive(DebugMode.FocusPlane))
|
||||
{
|
||||
uberMaterial.EnableKeyword("DEPTH_OF_FIELD_COC_VIEW");
|
||||
context.Interrupt();
|
||||
}
|
||||
else
|
||||
{
|
||||
uberMaterial.SetTexture(Uniforms._DepthOfFieldTex, rt1);
|
||||
uberMaterial.SetTexture(Uniforms._DepthOfFieldCoCTex, rtCoC);
|
||||
uberMaterial.EnableKeyword("DEPTH_OF_FIELD");
|
||||
}
|
||||
|
||||
context.renderTextureFactory.Release(rt2);
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
if (m_CoCHistory != null)
|
||||
RenderTexture.ReleaseTemporary(m_CoCHistory);
|
||||
|
||||
m_CoCHistory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
public sealed class DitheringComponent : PostProcessingComponentRenderTexture<DitheringModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _DitheringTex = Shader.PropertyToID("_DitheringTex");
|
||||
internal static readonly int _DitheringCoords = Shader.PropertyToID("_DitheringCoords");
|
||||
}
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
// Holds 64 64x64 Alpha8 textures (256kb total)
|
||||
Texture2D[] noiseTextures;
|
||||
int textureIndex = 0;
|
||||
|
||||
const int k_TextureCount = 64;
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
noiseTextures = null;
|
||||
}
|
||||
|
||||
void LoadNoiseTextures()
|
||||
{
|
||||
noiseTextures = new Texture2D[k_TextureCount];
|
||||
|
||||
for (int i = 0; i < k_TextureCount; i++)
|
||||
noiseTextures[i] = Resources.Load<Texture2D>("Bluenoise64/LDR_LLL1_" + i);
|
||||
}
|
||||
|
||||
public override void Prepare(Material uberMaterial)
|
||||
{
|
||||
float rndOffsetX;
|
||||
float rndOffsetY;
|
||||
|
||||
#if POSTFX_DEBUG_STATIC_DITHERING
|
||||
textureIndex = 0;
|
||||
rndOffsetX = 0f;
|
||||
rndOffsetY = 0f;
|
||||
#else
|
||||
if (++textureIndex >= k_TextureCount)
|
||||
textureIndex = 0;
|
||||
|
||||
rndOffsetX = Random.value;
|
||||
rndOffsetY = Random.value;
|
||||
#endif
|
||||
|
||||
if (noiseTextures == null)
|
||||
LoadNoiseTextures();
|
||||
|
||||
var noiseTex = noiseTextures[textureIndex];
|
||||
|
||||
uberMaterial.EnableKeyword("DITHERING");
|
||||
uberMaterial.SetTexture(Uniforms._DitheringTex, noiseTex);
|
||||
uberMaterial.SetVector(Uniforms._DitheringCoords, new Vector4(
|
||||
(float)context.width / (float)noiseTex.width,
|
||||
(float)context.height / (float)noiseTex.height,
|
||||
rndOffsetX,
|
||||
rndOffsetY
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 35ceb4b3cfab56d43a3f0efeb9d68c43
|
||||
timeCreated: 1485179235
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
public sealed class EyeAdaptationComponent : PostProcessingComponentRenderTexture<EyeAdaptationModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _Params = Shader.PropertyToID("_Params");
|
||||
internal static readonly int _Speed = Shader.PropertyToID("_Speed");
|
||||
internal static readonly int _ScaleOffsetRes = Shader.PropertyToID("_ScaleOffsetRes");
|
||||
internal static readonly int _ExposureCompensation = Shader.PropertyToID("_ExposureCompensation");
|
||||
internal static readonly int _AutoExposure = Shader.PropertyToID("_AutoExposure");
|
||||
internal static readonly int _DebugWidth = Shader.PropertyToID("_DebugWidth");
|
||||
}
|
||||
|
||||
ComputeShader m_EyeCompute;
|
||||
ComputeBuffer m_HistogramBuffer;
|
||||
|
||||
readonly RenderTexture[] m_AutoExposurePool = new RenderTexture[2];
|
||||
int m_AutoExposurePingPing;
|
||||
RenderTexture m_CurrentAutoExposure;
|
||||
|
||||
RenderTexture m_DebugHistogram;
|
||||
|
||||
static uint[] s_EmptyHistogramBuffer;
|
||||
|
||||
bool m_FirstFrame = true;
|
||||
|
||||
// Don't forget to update 'EyeAdaptation.cginc' if you change these values !
|
||||
const int k_HistogramBins = 64;
|
||||
const int k_HistogramThreadX = 16;
|
||||
const int k_HistogramThreadY = 16;
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& SystemInfo.supportsComputeShaders
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetHistory()
|
||||
{
|
||||
m_FirstFrame = true;
|
||||
}
|
||||
|
||||
public override void OnEnable()
|
||||
{
|
||||
m_FirstFrame = true;
|
||||
}
|
||||
|
||||
public override void OnDisable()
|
||||
{
|
||||
foreach (var rt in m_AutoExposurePool)
|
||||
GraphicsUtils.Destroy(rt);
|
||||
|
||||
if (m_HistogramBuffer != null)
|
||||
m_HistogramBuffer.Release();
|
||||
|
||||
m_HistogramBuffer = null;
|
||||
|
||||
if (m_DebugHistogram != null)
|
||||
m_DebugHistogram.Release();
|
||||
|
||||
m_DebugHistogram = null;
|
||||
}
|
||||
|
||||
Vector4 GetHistogramScaleOffsetRes()
|
||||
{
|
||||
var settings = model.settings;
|
||||
float diff = settings.logMax - settings.logMin;
|
||||
float scale = 1f / diff;
|
||||
float offset = -settings.logMin * scale;
|
||||
return new Vector4(scale, offset, Mathf.Floor(context.width / 2f), Mathf.Floor(context.height / 2f));
|
||||
}
|
||||
|
||||
public Texture Prepare(RenderTexture source, Material uberMaterial)
|
||||
{
|
||||
var settings = model.settings;
|
||||
|
||||
// Setup compute
|
||||
if (m_EyeCompute == null)
|
||||
m_EyeCompute = Resources.Load<ComputeShader>("Shaders/EyeHistogram");
|
||||
|
||||
var material = context.materialFactory.Get("Hidden/Post FX/Eye Adaptation");
|
||||
material.shaderKeywords = null;
|
||||
|
||||
if (m_HistogramBuffer == null)
|
||||
m_HistogramBuffer = new ComputeBuffer(k_HistogramBins, sizeof(uint));
|
||||
|
||||
if (s_EmptyHistogramBuffer == null)
|
||||
s_EmptyHistogramBuffer = new uint[k_HistogramBins];
|
||||
|
||||
// Downscale the framebuffer, we don't need an absolute precision for auto exposure and it
|
||||
// helps making it more stable
|
||||
var scaleOffsetRes = GetHistogramScaleOffsetRes();
|
||||
|
||||
var rt = context.renderTextureFactory.Get((int)scaleOffsetRes.z, (int)scaleOffsetRes.w, 0, source.format);
|
||||
Graphics.Blit(source, rt);
|
||||
|
||||
if (m_AutoExposurePool[0] == null || !m_AutoExposurePool[0].IsCreated())
|
||||
m_AutoExposurePool[0] = new RenderTexture(1, 1, 0, RenderTextureFormat.RFloat);
|
||||
|
||||
if (m_AutoExposurePool[1] == null || !m_AutoExposurePool[1].IsCreated())
|
||||
m_AutoExposurePool[1] = new RenderTexture(1, 1, 0, RenderTextureFormat.RFloat);
|
||||
|
||||
// Clears the buffer on every frame as we use it to accumulate luminance values on each frame
|
||||
m_HistogramBuffer.SetData(s_EmptyHistogramBuffer);
|
||||
|
||||
// Gets a log histogram
|
||||
int kernel = m_EyeCompute.FindKernel("KEyeHistogram");
|
||||
m_EyeCompute.SetBuffer(kernel, "_Histogram", m_HistogramBuffer);
|
||||
m_EyeCompute.SetTexture(kernel, "_Source", rt);
|
||||
m_EyeCompute.SetVector("_ScaleOffsetRes", scaleOffsetRes);
|
||||
m_EyeCompute.Dispatch(kernel, Mathf.CeilToInt(rt.width / (float)k_HistogramThreadX), Mathf.CeilToInt(rt.height / (float)k_HistogramThreadY), 1);
|
||||
|
||||
// Cleanup
|
||||
context.renderTextureFactory.Release(rt);
|
||||
|
||||
// Make sure filtering values are correct to avoid apocalyptic consequences
|
||||
const float minDelta = 1e-2f;
|
||||
settings.highPercent = Mathf.Clamp(settings.highPercent, 1f + minDelta, 99f);
|
||||
settings.lowPercent = Mathf.Clamp(settings.lowPercent, 1f, settings.highPercent - minDelta);
|
||||
|
||||
// Compute auto exposure
|
||||
material.SetBuffer("_Histogram", m_HistogramBuffer); // No (int, buffer) overload for SetBuffer ?
|
||||
material.SetVector(Uniforms._Params, new Vector4(settings.lowPercent * 0.01f, settings.highPercent * 0.01f, Mathf.Exp(settings.minLuminance * 0.69314718055994530941723212145818f), Mathf.Exp(settings.maxLuminance * 0.69314718055994530941723212145818f)));
|
||||
material.SetVector(Uniforms._Speed, new Vector2(settings.speedDown, settings.speedUp));
|
||||
material.SetVector(Uniforms._ScaleOffsetRes, scaleOffsetRes);
|
||||
material.SetFloat(Uniforms._ExposureCompensation, settings.keyValue);
|
||||
|
||||
if (settings.dynamicKeyValue)
|
||||
material.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];
|
||||
Graphics.Blit(null, m_CurrentAutoExposure, material, (int)EyeAdaptationModel.EyeAdaptationType.Fixed);
|
||||
|
||||
// Copy current exposure to the other pingpong target to avoid adapting from black
|
||||
Graphics.Blit(m_AutoExposurePool[0], m_AutoExposurePool[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pp = m_AutoExposurePingPing;
|
||||
var src = m_AutoExposurePool[++pp % 2];
|
||||
var dst = m_AutoExposurePool[++pp % 2];
|
||||
Graphics.Blit(src, dst, material, (int)settings.adaptationType);
|
||||
m_AutoExposurePingPing = ++pp % 2;
|
||||
m_CurrentAutoExposure = dst;
|
||||
}
|
||||
|
||||
// Generate debug histogram
|
||||
if (context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.EyeAdaptation))
|
||||
{
|
||||
if (m_DebugHistogram == null || !m_DebugHistogram.IsCreated())
|
||||
{
|
||||
m_DebugHistogram = new RenderTexture(256, 128, 0, RenderTextureFormat.ARGB32)
|
||||
{
|
||||
filterMode = FilterMode.Point,
|
||||
wrapMode = TextureWrapMode.Clamp
|
||||
};
|
||||
}
|
||||
|
||||
material.SetFloat(Uniforms._DebugWidth, m_DebugHistogram.width);
|
||||
Graphics.Blit(null, m_DebugHistogram, material, 2);
|
||||
}
|
||||
|
||||
m_FirstFrame = false;
|
||||
return m_CurrentAutoExposure;
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
if (m_DebugHistogram == null || !m_DebugHistogram.IsCreated())
|
||||
return;
|
||||
|
||||
var rect = new Rect(context.viewport.x * Screen.width + 8f, 8f, m_DebugHistogram.width, m_DebugHistogram.height);
|
||||
GUI.DrawTexture(rect, m_DebugHistogram);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c227d71a4040d304c943c26e0914bdeb
|
||||
timeCreated: 1473088756
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
public sealed class FogComponent : PostProcessingComponentCommandBuffer<FogModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _FogColor = Shader.PropertyToID("_FogColor");
|
||||
internal static readonly int _Density = Shader.PropertyToID("_Density");
|
||||
internal static readonly int _Start = Shader.PropertyToID("_Start");
|
||||
internal static readonly int _End = Shader.PropertyToID("_End");
|
||||
internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
|
||||
}
|
||||
|
||||
const string k_ShaderString = "Hidden/Post FX/Fog";
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& context.isGBufferAvailable // In forward fog is already done at shader level
|
||||
&& RenderSettings.fog
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
{
|
||||
return "Fog";
|
||||
}
|
||||
|
||||
public override DepthTextureMode GetCameraFlags()
|
||||
{
|
||||
return DepthTextureMode.Depth;
|
||||
}
|
||||
|
||||
public override CameraEvent GetCameraEvent()
|
||||
{
|
||||
return CameraEvent.AfterImageEffectsOpaque;
|
||||
}
|
||||
|
||||
public override void PopulateCommandBuffer(CommandBuffer cb)
|
||||
{
|
||||
var settings = model.settings;
|
||||
|
||||
var material = context.materialFactory.Get(k_ShaderString);
|
||||
material.shaderKeywords = null;
|
||||
var fogColor = GraphicsUtils.isLinearColorSpace ? RenderSettings.fogColor.linear : RenderSettings.fogColor;
|
||||
material.SetColor(Uniforms._FogColor, fogColor);
|
||||
material.SetFloat(Uniforms._Density, RenderSettings.fogDensity);
|
||||
material.SetFloat(Uniforms._Start, RenderSettings.fogStartDistance);
|
||||
material.SetFloat(Uniforms._End, RenderSettings.fogEndDistance);
|
||||
|
||||
switch (RenderSettings.fogMode)
|
||||
{
|
||||
case FogMode.Linear:
|
||||
material.EnableKeyword("FOG_LINEAR");
|
||||
break;
|
||||
case FogMode.Exponential:
|
||||
material.EnableKeyword("FOG_EXP");
|
||||
break;
|
||||
case FogMode.ExponentialSquared:
|
||||
material.EnableKeyword("FOG_EXP2");
|
||||
break;
|
||||
}
|
||||
|
||||
var fbFormat = context.isHdr
|
||||
? RenderTextureFormat.DefaultHDR
|
||||
: RenderTextureFormat.Default;
|
||||
|
||||
cb.GetTemporaryRT(Uniforms._TempRT, context.width, context.height, 24, FilterMode.Bilinear, fbFormat);
|
||||
cb.Blit(BuiltinRenderTextureType.CameraTarget, Uniforms._TempRT);
|
||||
cb.Blit(Uniforms._TempRT, BuiltinRenderTextureType.CameraTarget, material, settings.excludeSkybox ? 1 : 0);
|
||||
cb.ReleaseTemporaryRT(Uniforms._TempRT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d0363c1cc7de62b4989190994103f5e2
|
||||
timeCreated: 1487334918
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
namespace UnityEngine.PostProcessing
|
||||
{
|
||||
public sealed class FxaaComponent : PostProcessingComponentRenderTexture<AntialiasingModel>
|
||||
{
|
||||
static class Uniforms
|
||||
{
|
||||
internal static readonly int _QualitySettings = Shader.PropertyToID("_QualitySettings");
|
||||
internal static readonly int _ConsoleSettings = Shader.PropertyToID("_ConsoleSettings");
|
||||
}
|
||||
|
||||
public override bool active
|
||||
{
|
||||
get
|
||||
{
|
||||
return model.enabled
|
||||
&& model.settings.method == AntialiasingModel.Method.Fxaa
|
||||
&& !context.interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
public void Render(RenderTexture source, RenderTexture destination)
|
||||
{
|
||||
var settings = model.settings.fxaaSettings;
|
||||
var material = context.materialFactory.Get("Hidden/Post FX/FXAA");
|
||||
var qualitySettings = AntialiasingModel.FxaaQualitySettings.presets[(int)settings.preset];
|
||||
var consoleSettings = AntialiasingModel.FxaaConsoleSettings.presets[(int)settings.preset];
|
||||
|
||||
material.SetVector(Uniforms._QualitySettings,
|
||||
new Vector3(
|
||||
qualitySettings.subpixelAliasingRemovalAmount,
|
||||
qualitySettings.edgeDetectionThreshold,
|
||||
qualitySettings.minimumRequiredLuminance
|
||||
)
|
||||
);
|
||||
|
||||
material.SetVector(Uniforms._ConsoleSettings,
|
||||
new Vector4(
|
||||
consoleSettings.subpixelSpreadAmount,
|
||||
consoleSettings.edgeSharpnessAmount,
|
||||
consoleSettings.edgeDetectionThreshold,
|
||||
consoleSettings.minimumRequiredLuminance
|
||||
)
|
||||
);
|
||||
|
||||
Graphics.Blit(source, destination, material, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d4e1109c5030ca04e9a28243a35155ff
|
||||
timeCreated: 1473088423
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue