public override void Render(PostProcessRenderContext context) { var cmd = context.command; cmd.BeginSample("ScanLine"); RenderTextureDescriptor desc = new RenderTextureDescriptor(context.width, context.height); desc.enableRandomWrite = true; //cmd.GetTemporaryRT(tempCanvas, desc); desc.graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.R32G32B32A32_SFloat; cmd.GetTemporaryRT(tempRTID1, desc); cmd.GetTemporaryRT(tempRTID2, desc); cmd.GetTemporaryRT(tempRTID3, desc); Matrix4x4 V = Camera.main.worldToCameraMatrix; Matrix4x4 P = GL.GetGPUProjectionMatrix(Camera.main.projectionMatrix, true); Matrix4x4 VP = P * V; Matrix4x4 InvMVP = VP.inverse; // depth edge cmd.SetComputeIntParam(depthEdgeShader, "Width", context.width - 1); cmd.SetComputeIntParam(depthEdgeShader, "Height", context.height - 1); cmd.SetComputeFloatParam(depthEdgeShader, "EdgeStrength", settings.DepthEdgeStrength.value); cmd.SetComputeTextureParam(depthEdgeShader, sobelForDepthKernelID, "Source", BuiltinRenderTextureType.Depth);// or ResolvedDepth cmd.SetComputeTextureParam(depthEdgeShader, sobelForDepthKernelID, "Result", tempRTID1); cmd.DispatchCompute(depthEdgeShader, sobelForDepthKernelID, context.width, context.height, 1); // distance field cmd.SetComputeIntParam(distanceFieldShader, "Width", context.width - 1); cmd.SetComputeIntParam(distanceFieldShader, "Height", context.height - 1); cmd.SetComputeFloatParam(distanceFieldShader, "DistanceScale", settings.DistanceScale.value); cmd.SetComputeMatrixParam(distanceFieldShader, "InvVPMatrix", InvMVP); var tar = settings.Target.value; cmd.SetComputeFloatParams(distanceFieldShader, "Target", new float[3] { tar.x, tar.y, tar.z }); cmd.SetComputeTextureParam(distanceFieldShader, distanceFromTargetKernelID, "Source", BuiltinRenderTextureType.Depth);// or ResolvedDepth cmd.SetComputeTextureParam(distanceFieldShader, distanceFromTargetKernelID, "Result", tempRTID2); cmd.DispatchCompute(distanceFieldShader, distanceFromTargetKernelID, context.width, context.height, 1); // distance field edge cmd.SetComputeFloatParam(depthEdgeShader, "EdgeStrength", settings.DistanceEdgeStrength.value); cmd.SetComputeFloatParam(depthEdgeShader, "DistanceThresold", settings.DistanceThresold.value); cmd.SetComputeTextureParam(depthEdgeShader, sobelForDisatnceKernelID, "Source", tempRTID2);// or ResolvedDepth cmd.SetComputeTextureParam(depthEdgeShader, sobelForDisatnceKernelID, "Result", tempRTID3); cmd.DispatchCompute(depthEdgeShader, sobelForDisatnceKernelID, context.width, context.height, 1); // mix color var depthColor = settings.DepthEdgeColor.value; cmd.SetComputeFloatParams(colorMixerShader, "DepthEdgeColor", new float[3] { depthColor.r, depthColor.g, depthColor.b }); var distanceColor = settings.DistanceEdgeColor.value; cmd.SetComputeFloatParams(colorMixerShader, "DistanceEdgeColor", new float[3] { distanceColor.r, distanceColor.g, distanceColor.b }); cmd.SetComputeTextureParam(colorMixerShader, colroMixerKernelID, "ColorSource", context.source); cmd.SetComputeTextureParam(colorMixerShader, colroMixerKernelID, "DepthSource", tempRTID1); cmd.SetComputeTextureParam(colorMixerShader, colroMixerKernelID, "DistanceSource", tempRTID3); cmd.SetComputeTextureParam(colorMixerShader, colroMixerKernelID, "Result", tempRTID2); cmd.DispatchCompute(colorMixerShader, colroMixerKernelID, context.width, context.height, 1); cmd.Blit(tempRTID2, context.destination); cmd.ReleaseTemporaryRT(tempRTID1); cmd.ReleaseTemporaryRT(tempRTID2); cmd.ReleaseTemporaryRT(tempRTID3); cmd.EndSample("ScanLine"); }
// HDR color pipeline is rendered to a 2D strip lut (works on HDR platforms without compute // and 3D texture support). Precision is sliiiiiiightly lower than when using a 3D texture // LUT (33^3 -> 32^3) but most of the time it's imperceptible. void RenderHDRPipeline2D(PostProcessRenderContext context) { // For the same reasons as in RenderHDRPipeline3D, regen LUT on evey frame { CheckInternalStripLut(); // Lut setup var lutSheet = context.propertySheets.Get(context.resources.shaders.lut2DBaker); lutSheet.ClearKeywords(); lutSheet.properties.SetVector(ShaderIDs.Lut2D_Params, new Vector4(k_Lut2DSize, 0.5f / (k_Lut2DSize * k_Lut2DSize), 0.5f / k_Lut2DSize, k_Lut2DSize / (k_Lut2DSize - 1f))); var colorBalance = ColorUtilities.ComputeColorBalance(settings.temperature.value, settings.tint.value); lutSheet.properties.SetVector(ShaderIDs.ColorBalance, colorBalance); lutSheet.properties.SetVector(ShaderIDs.ColorFilter, settings.colorFilter.value); float hue = settings.hueShift.value / 360f; // Remap to [-0.5;0.5] float sat = settings.saturation.value / 100f + 1f; // Remap to [0;2] float con = settings.contrast.value / 100f + 1f; // Remap to [0;2] lutSheet.properties.SetVector(ShaderIDs.HueSatCon, new Vector3(hue, sat, con)); var channelMixerR = new Vector3(settings.mixerRedOutRedIn, settings.mixerRedOutGreenIn, settings.mixerRedOutBlueIn); var channelMixerG = new Vector3(settings.mixerGreenOutRedIn, settings.mixerGreenOutGreenIn, settings.mixerGreenOutBlueIn); var channelMixerB = new Vector3(settings.mixerBlueOutRedIn, settings.mixerBlueOutGreenIn, settings.mixerBlueOutBlueIn); lutSheet.properties.SetVector(ShaderIDs.ChannelMixerRed, channelMixerR / 100f); // Remap to [-2;2] lutSheet.properties.SetVector(ShaderIDs.ChannelMixerGreen, channelMixerG / 100f); lutSheet.properties.SetVector(ShaderIDs.ChannelMixerBlue, channelMixerB / 100f); var lift = ColorUtilities.ColorToLift(settings.lift.value * 0.2f); var gain = ColorUtilities.ColorToGain(settings.gain.value * 0.8f); var invgamma = ColorUtilities.ColorToInverseGamma(settings.gamma.value * 0.8f); lutSheet.properties.SetVector(ShaderIDs.Lift, lift); lutSheet.properties.SetVector(ShaderIDs.InvGamma, invgamma); lutSheet.properties.SetVector(ShaderIDs.Gain, gain); lutSheet.properties.SetTexture(ShaderIDs.Curves, GetCurveTexture(false)); var tonemapper = settings.tonemapper.value; if (tonemapper == Tonemapper.Custom) { lutSheet.EnableKeyword("TONEMAPPING_CUSTOM"); m_HableCurve.Init( settings.toneCurveToeStrength.value, settings.toneCurveToeLength.value, settings.toneCurveShoulderStrength.value, settings.toneCurveShoulderLength.value, settings.toneCurveShoulderAngle.value, settings.toneCurveGamma.value ); lutSheet.properties.SetVector(ShaderIDs.CustomToneCurve, m_HableCurve.uniforms.curve); lutSheet.properties.SetVector(ShaderIDs.ToeSegmentA, m_HableCurve.uniforms.toeSegmentA); lutSheet.properties.SetVector(ShaderIDs.ToeSegmentB, m_HableCurve.uniforms.toeSegmentB); lutSheet.properties.SetVector(ShaderIDs.MidSegmentA, m_HableCurve.uniforms.midSegmentA); lutSheet.properties.SetVector(ShaderIDs.MidSegmentB, m_HableCurve.uniforms.midSegmentB); lutSheet.properties.SetVector(ShaderIDs.ShoSegmentA, m_HableCurve.uniforms.shoSegmentA); lutSheet.properties.SetVector(ShaderIDs.ShoSegmentB, m_HableCurve.uniforms.shoSegmentB); } else if (tonemapper == Tonemapper.ACES) { lutSheet.EnableKeyword("TONEMAPPING_ACES"); } else if (tonemapper == Tonemapper.Neutral) { lutSheet.EnableKeyword("TONEMAPPING_NEUTRAL"); } // Generate the lut context.command.BeginSample("HdrColorGradingLut2D"); context.command.BlitFullscreenTriangle(BuiltinRenderTextureType.None, m_InternalLdrLut, lutSheet, (int)Pass.LutGenHDR2D); context.command.EndSample("HdrColorGradingLut2D"); } var lut = m_InternalLdrLut; var uberSheet = context.uberSheet; uberSheet.EnableKeyword("COLOR_GRADING_HDR_2D"); uberSheet.properties.SetVector(ShaderIDs.Lut2D_Params, new Vector3(1f / lut.width, 1f / lut.height, lut.height - 1f)); uberSheet.properties.SetTexture(ShaderIDs.Lut2D, lut); uberSheet.properties.SetFloat(ShaderIDs.PostExposure, RuntimeUtilities.Exp2(settings.postExposure.value)); }
/// <summary> /// Returns <c>true</c> if the effect is currently enabled and supported. /// </summary> /// <param name="context">The current post-processing render context</param> /// <returns><c>true</c> if the effect is currently enabled and supported</returns> public override bool IsEnabledAndSupported(PostProcessRenderContext context) { return(enabled.value && intensity.value > 0f); }
public override void Render(PostProcessRenderContext context) { var cmd = context.command; cmd.BeginSample("AutoExposureLookup"); // Prepare autoExpo texture pool CheckTexture(context.xrActiveEye, 0); CheckTexture(context.xrActiveEye, 1); // Make sure filtering values are correct to avoid apocalyptic consequences float lowPercent = settings.filtering.value.x; float highPercent = settings.filtering.value.y; const float kMinDelta = 1e-2f; highPercent = Mathf.Clamp(highPercent, 1f + kMinDelta, 99f); lowPercent = Mathf.Clamp(lowPercent, 1f, highPercent - kMinDelta); // Clamp min/max adaptation values as well float minLum = settings.minLuminance.value; float maxLum = settings.maxLuminance.value; settings.minLuminance.value = Mathf.Min(minLum, maxLum); settings.maxLuminance.value = Mathf.Max(minLum, maxLum); // Compute average luminance & auto exposure bool isStatic = m_ResetHistory || !Application.isPlaying; string adaptation = null; if (isStatic) { adaptation = "KAutoExposureAvgLuminance_fixed"; } else if (settings.eyeAdaptation.value == EyeAdaptation.Progressive) { adaptation = "KAutoExposureAvgLuminance_progressive"; } var compute = context.resources.computeShaders.autoExposure; int kernel = compute.FindKernel(adaptation); cmd.SetComputeBufferParam(compute, kernel, "_HistogramBuffer", context.logHistogram.data); cmd.SetComputeVectorParam(compute, "_Params1", new Vector4(lowPercent * 0.01f, highPercent * 0.01f, RuntimeUtilities.Exp2(settings.minLuminance.value), RuntimeUtilities.Exp2(settings.maxLuminance.value))); cmd.SetComputeVectorParam(compute, "_Params2", new Vector4(settings.speedDown.value, settings.speedUp.value, settings.keyValue.value, Time.deltaTime)); cmd.SetComputeVectorParam(compute, "_ScaleOffsetRes", context.logHistogram.GetHistogramScaleOffsetRes(context)); if (isStatic) { // 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[context.xrActiveEye][0]; cmd.SetComputeTextureParam(compute, kernel, "_Destination", m_CurrentAutoExposure); cmd.DispatchCompute(compute, kernel, 1, 1, 1); // Copy current exposure to the other pingpong target to avoid adapting from black RuntimeUtilities.CopyTexture(cmd, m_AutoExposurePool[context.xrActiveEye][0], m_AutoExposurePool[context.xrActiveEye][1]); m_ResetHistory = false; } else { int pp = m_AutoExposurePingPong[context.xrActiveEye]; var src = m_AutoExposurePool[context.xrActiveEye][++pp % 2]; var dst = m_AutoExposurePool[context.xrActiveEye][++pp % 2]; cmd.SetComputeTextureParam(compute, kernel, "_Source", src); cmd.SetComputeTextureParam(compute, kernel, "_Destination", dst); cmd.DispatchCompute(compute, kernel, 1, 1, 1); m_AutoExposurePingPong[context.xrActiveEye] = ++pp % 2; m_CurrentAutoExposure = dst; } cmd.EndSample("AutoExposureLookup"); context.autoExposureTexture = m_CurrentAutoExposure; context.autoExposure = settings; }
public override void Render(PostProcessRenderContext context) { var cmd = context.command; cmd.BeginSample("BloomPyramid"); var sheet = context.propertySheets.Get(context.resources.shaders.bloom); // Apply auto exposure adjustment in the prefiltering pass sheet.properties.SetTexture(ShaderIDs.AutoExposureTex, context.autoExposureTexture); // Negative anamorphic ratio values distort vertically - positive is horizontal float ratio = Mathf.Clamp(settings.anamorphicRatio, -1, 1); float rw = ratio < 0 ? -ratio : 0f; float rh = ratio > 0 ? ratio : 0f; // Do bloom on a half-res buffer, full-res doesn't bring much and kills performances on // fillrate limited platforms int tw = Mathf.FloorToInt(context.screenWidth / (2f - rw)); int th = Mathf.FloorToInt(context.screenHeight / (2f - rh)); bool singlePassDoubleWide = (context.stereoActive && (context.stereoRenderingMode == PostProcessRenderContext.StereoRenderingMode.SinglePass) && (context.camera.stereoTargetEye == StereoTargetEyeMask.Both)); int tw_stereo = singlePassDoubleWide ? tw * 2 : tw; // Determine the iteration count int s = Mathf.Max(tw, th); float logs = Mathf.Log(s, 2f) + Mathf.Min(settings.diffusion.value, 10f) - 10f; int logs_i = Mathf.FloorToInt(logs); int iterations = Mathf.Clamp(logs_i, 1, k_MaxPyramidSize); float sampleScale = 0.5f + logs - logs_i; sheet.properties.SetFloat(ShaderIDs.SampleScale, sampleScale); // Prefiltering parameters float lthresh = Mathf.GammaToLinearSpace(settings.threshold.value); float knee = lthresh * settings.softKnee.value + 1e-5f; var threshold = new Vector4(lthresh, lthresh - knee, knee * 2f, 0.25f / knee); sheet.properties.SetVector(ShaderIDs.Threshold, threshold); float lclamp = Mathf.GammaToLinearSpace(settings.clamp.value); sheet.properties.SetVector(ShaderIDs.Params, new Vector4(lclamp, 0f, 0f, 0f)); int qualityOffset = settings.fastMode ? 1 : 0; // Downsample var lastDown = context.source; for (int i = 0; i < iterations; i++) { int mipDown = m_Pyramid[i].down; int mipUp = m_Pyramid[i].up; int pass = i == 0 ? (int)Pass.Prefilter13 + qualityOffset : (int)Pass.Downsample13 + qualityOffset; context.GetScreenSpaceTemporaryRT(cmd, mipDown, 0, context.sourceFormat, RenderTextureReadWrite.Default, FilterMode.Bilinear, tw_stereo, th); context.GetScreenSpaceTemporaryRT(cmd, mipUp, 0, context.sourceFormat, RenderTextureReadWrite.Default, FilterMode.Bilinear, tw_stereo, th); cmd.BlitFullscreenTriangle(lastDown, mipDown, sheet, pass); lastDown = mipDown; tw_stereo = (singlePassDoubleWide && ((tw_stereo / 2) % 2 > 0)) ? 1 + tw_stereo / 2 : tw_stereo / 2; tw_stereo = Mathf.Max(tw_stereo, 1); th = Mathf.Max(th / 2, 1); } // Upsample int lastUp = m_Pyramid[iterations - 1].down; for (int i = iterations - 2; i >= 0; i--) { int mipDown = m_Pyramid[i].down; int mipUp = m_Pyramid[i].up; cmd.SetGlobalTexture(ShaderIDs.BloomTex, mipDown); cmd.BlitFullscreenTriangle(lastUp, mipUp, sheet, (int)Pass.UpsampleTent + qualityOffset); lastUp = mipUp; } var linearColor = settings.color.value.linear; float intensity = RuntimeUtilities.Exp2(settings.intensity.value / 10f) - 1f; var shaderSettings = new Vector4(sampleScale, intensity, settings.dirtIntensity.value, iterations); // Debug overlays if (context.IsDebugOverlayEnabled(DebugOverlay.BloomThreshold)) { context.PushDebugOverlay(cmd, context.source, sheet, (int)Pass.DebugOverlayThreshold); } else if (context.IsDebugOverlayEnabled(DebugOverlay.BloomBuffer)) { sheet.properties.SetVector(ShaderIDs.ColorIntensity, new Vector4(linearColor.r, linearColor.g, linearColor.b, intensity)); context.PushDebugOverlay(cmd, m_Pyramid[0].up, sheet, (int)Pass.DebugOverlayTent + qualityOffset); } // Lens dirtiness // Keep the aspect ratio correct & center the dirt texture, we don't want it to be // stretched or squashed var dirtTexture = settings.dirtTexture.value == null ? RuntimeUtilities.blackTexture : settings.dirtTexture.value; var dirtRatio = (float)dirtTexture.width / (float)dirtTexture.height; var screenRatio = (float)context.screenWidth / (float)context.screenHeight; var dirtTileOffset = new Vector4(1f, 1f, 0f, 0f); if (dirtRatio > screenRatio) { dirtTileOffset.x = screenRatio / dirtRatio; dirtTileOffset.z = (1f - dirtTileOffset.x) * 0.5f; } else if (screenRatio > dirtRatio) { dirtTileOffset.y = dirtRatio / screenRatio; dirtTileOffset.w = (1f - dirtTileOffset.y) * 0.5f; } // Shader properties var uberSheet = context.uberSheet; if (settings.fastMode) { uberSheet.EnableKeyword("BLOOM_LOW"); } else { uberSheet.EnableKeyword("BLOOM"); } uberSheet.properties.SetVector(ShaderIDs.Bloom_DirtTileOffset, dirtTileOffset); uberSheet.properties.SetVector(ShaderIDs.Bloom_Settings, shaderSettings); uberSheet.properties.SetColor(ShaderIDs.Bloom_Color, linearColor); uberSheet.properties.SetTexture(ShaderIDs.Bloom_DirtTex, dirtTexture); cmd.SetGlobalTexture(ShaderIDs.BloomTex, lastUp); // Cleanup for (int i = 0; i < iterations; i++) { if (m_Pyramid[i].down != lastUp) { cmd.ReleaseTemporaryRT(m_Pyramid[i].down); } if (m_Pyramid[i].up != lastUp) { cmd.ReleaseTemporaryRT(m_Pyramid[i].up); } } cmd.EndSample("BloomPyramid"); context.bloomBufferNameID = lastUp; }
public bool HasOpaqueOnlyEffects(PostProcessRenderContext context) { return(HasActiveEffects(PostProcessEvent.BeforeTransparent, context)); }
void RenderList(List <SerializedBundleRef> list, PostProcessRenderContext context, string marker) { var cmd = context.command; cmd.BeginSample(marker); // First gather active effects - we need this to manage render targets more efficiently m_ActiveEffects.Clear(); for (int i = 0; i < list.Count; i++) { var effect = list[i].bundle; if (effect.settings.IsEnabledAndSupported(context)) { if (!context.isSceneView || (context.isSceneView && effect.attribute.allowInSceneView)) { m_ActiveEffects.Add(effect.renderer); } } } int count = m_ActiveEffects.Count; // If there's only one active effect, we can simply execute it and skip the rest if (count == 1) { m_ActiveEffects[0].Render(context); } else { // Else create the target chain m_Targets.Clear(); m_Targets.Add(context.source); // First target is always source int tempTarget1 = m_TargetPool.Get(); int tempTarget2 = m_TargetPool.Get(); for (int i = 0; i < count - 1; i++) { m_Targets.Add(i % 2 == 0 ? tempTarget1 : tempTarget2); } m_Targets.Add(context.destination); // Last target is always destination // Render context.GetScreenSpaceTemporaryRT(cmd, tempTarget1, 24, context.sourceFormat); if (count > 2) { context.GetScreenSpaceTemporaryRT(cmd, tempTarget2, 24, context.sourceFormat); } for (int i = 0; i < count; i++) { context.source = m_Targets[i]; context.destination = m_Targets[i + 1]; m_ActiveEffects[i].Render(context); } cmd.ReleaseTemporaryRT(tempTarget1); if (count > 2) { cmd.ReleaseTemporaryRT(tempTarget2); } } cmd.EndSample(marker); }
public override bool IsEnabledAndSupported(PostProcessRenderContext context) { return((bool)enabled && context.camera.actualRenderingPath == RenderingPath.DeferredShading && SystemInfo.supportsMotionVectors && SystemInfo.supportsComputeShaders && SystemInfo.copyTextureSupport > CopyTextureSupport.None && (bool)context.resources.shaders.screenSpaceReflections && context.resources.shaders.screenSpaceReflections.isSupported && (bool)context.resources.computeShaders.gaussianDownsample); }
internal override bool ShaderResourcesAvailable(PostProcessRenderContext context) { return(context.resources.shaders.lightMeter && context.resources.shaders.lightMeter.isSupported); }
// Token: 0x06000989 RID: 2441 RVA: 0x00030144 File Offset: 0x0002E344 public override void Render(PostProcessRenderContext context) { CommandBuffer command = context.command; command.BeginSample("Screen-space Reflections"); if (base.settings.preset.value != ScreenSpaceReflectionPreset.Custom) { int value = (int)base.settings.preset.value; base.settings.maximumIterationCount.value = this.m_Presets[value].maximumIterationCount; base.settings.thickness.value = this.m_Presets[value].thickness; base.settings.resolution.value = this.m_Presets[value].downsampling; } base.settings.maximumMarchDistance.value = Mathf.Max(0f, base.settings.maximumMarchDistance.value); int num = Mathf.ClosestPowerOfTwo(Mathf.Min(context.width, context.height)); if (base.settings.resolution.value == ScreenSpaceReflectionResolution.Downsampled) { num >>= 1; } else if (base.settings.resolution.value == ScreenSpaceReflectionResolution.Supersampled) { num <<= 1; } int num2 = Mathf.FloorToInt(Mathf.Log((float)num, 2f) - 3f); num2 = Mathf.Min(num2, 12); this.CheckRT(ref this.m_Resolve, num, num, context.sourceFormat, FilterMode.Trilinear, true); Texture2D texture2D = context.resources.blueNoise256[0]; PropertySheet propertySheet = context.propertySheets.Get(Shader.Find("Hidden/PostProcessing/HopooSSR")); propertySheet.properties.SetTexture(Shader.PropertyToID("_Noise"), texture2D); Matrix4x4 matrix4x = default(Matrix4x4); matrix4x.SetRow(0, new Vector4((float)num * 0.5f, 0f, 0f, (float)num * 0.5f)); matrix4x.SetRow(1, new Vector4(0f, (float)num * 0.5f, 0f, (float)num * 0.5f)); matrix4x.SetRow(2, new Vector4(0f, 0f, 1f, 0f)); matrix4x.SetRow(3, new Vector4(0f, 0f, 0f, 1f)); Matrix4x4 gpuprojectionMatrix = GL.GetGPUProjectionMatrix(context.camera.projectionMatrix, false); matrix4x *= gpuprojectionMatrix; propertySheet.properties.SetMatrix(Shader.PropertyToID("_ViewMatrix"), context.camera.worldToCameraMatrix); propertySheet.properties.SetMatrix(Shader.PropertyToID("_InverseViewMatrix"), context.camera.worldToCameraMatrix.inverse); propertySheet.properties.SetMatrix(Shader.PropertyToID("_InverseProjectionMatrix"), gpuprojectionMatrix.inverse); propertySheet.properties.SetMatrix(Shader.PropertyToID("_ScreenSpaceProjectionMatrix"), matrix4x); propertySheet.properties.SetVector(Shader.PropertyToID("_Params"), new Vector4(base.settings.vignette.value, base.settings.distanceFade.value, base.settings.maximumMarchDistance.value, (float)num2)); propertySheet.properties.SetVector(Shader.PropertyToID("_Params2"), new Vector4((float)context.width / (float)context.height, (float)num / (float)texture2D.width, base.settings.thickness.value, (float)base.settings.maximumIterationCount.value)); command.GetTemporaryRT(Shader.PropertyToID("_Test"), num, num, 0, FilterMode.Point, context.sourceFormat); command.BlitFullscreenTriangle(context.source, Shader.PropertyToID("_Test"), propertySheet, 0, false, null); if (context.isSceneView) { command.BlitFullscreenTriangle(context.source, this.m_Resolve, propertySheet, 1, false, null); } else { this.CheckRT(ref this.m_History, num, num, context.sourceFormat, FilterMode.Bilinear, false); if (this.m_ResetHistory) { context.command.BlitFullscreenTriangle(context.source, this.m_History, false, null); this.m_ResetHistory = false; } command.GetTemporaryRT(Shader.PropertyToID("_SSRResolveTemp"), num, num, 0, FilterMode.Bilinear, context.sourceFormat); command.BlitFullscreenTriangle(context.source, Shader.PropertyToID("_SSRResolveTemp"), propertySheet, 1, false, null); propertySheet.properties.SetTexture(Shader.PropertyToID("_History"), this.m_History); command.BlitFullscreenTriangle(Shader.PropertyToID("_SSRResolveTemp"), this.m_Resolve, propertySheet, 2, false, null); command.CopyTexture(this.m_Resolve, 0, 0, this.m_History, 0, 0); command.ReleaseTemporaryRT(Shader.PropertyToID("_SSRResolveTemp")); } command.ReleaseTemporaryRT(Shader.PropertyToID("_Test")); if (this.m_MipIDs == null || this.m_MipIDs.Length == 0) { this.m_MipIDs = new int[12]; for (int i = 0; i < 12; i++) { this.m_MipIDs[i] = Shader.PropertyToID("_SSRGaussianMip" + i); } } ComputeShader gaussianDownsample = context.resources.computeShaders.gaussianDownsample; int kernelIndex = gaussianDownsample.FindKernel("KMain"); RenderTargetIdentifier rt = new RenderTargetIdentifier(this.m_Resolve); for (int j = 0; j < num2; j++) { num >>= 1; command.GetTemporaryRT(this.m_MipIDs[j], num, num, 0, FilterMode.Bilinear, context.sourceFormat, RenderTextureReadWrite.Default, 1, true); command.SetComputeTextureParam(gaussianDownsample, kernelIndex, "_Source", rt); command.SetComputeTextureParam(gaussianDownsample, kernelIndex, "_Result", this.m_MipIDs[j]); command.SetComputeVectorParam(gaussianDownsample, "_Size", new Vector4((float)num, (float)num, 1f / (float)num, 1f / (float)num)); command.DispatchCompute(gaussianDownsample, kernelIndex, num / 8, num / 8, 1); command.CopyTexture(this.m_MipIDs[j], 0, 0, this.m_Resolve, 0, j + 1); rt = this.m_MipIDs[j]; } for (int k = 0; k < num2; k++) { command.ReleaseTemporaryRT(this.m_MipIDs[k]); } propertySheet.properties.SetTexture(Shader.PropertyToID("_Resolve"), this.m_Resolve); command.BlitFullscreenTriangle(context.source, context.destination, propertySheet, 3, false, null); command.EndSample("Screen-space Reflections"); }
// Unused public override void Render(PostProcessRenderContext context) { }
// LDR color pipeline is rendered to a 2D strip lut (works on every platform) void RenderLDRPipeline2D(PostProcessRenderContext context) { // For the same reasons as in RenderHDRPipeline3D, regen LUT on every frame { CheckInternalStripLut(); // Lut setup var lutSheet = context.propertySheets.Get(context.resources.shaders.lut2DBaker); lutSheet.ClearKeywords(); lutSheet.properties.SetVector(ShaderIDs.Lut2D_Params, new Vector4(k_Lut2DSize, 0.5f / (k_Lut2DSize * k_Lut2DSize), 0.5f / k_Lut2DSize, k_Lut2DSize / (k_Lut2DSize - 1f))); var colorBalance = ColorUtilities.ComputeColorBalance(settings.temperature.value, settings.tint.value); lutSheet.properties.SetVector(ShaderIDs.ColorBalance, colorBalance); lutSheet.properties.SetVector(ShaderIDs.ColorFilter, settings.colorFilter.value); float hue = settings.hueShift.value / 360f; // Remap to [-0.5;0.5] float sat = settings.saturation.value / 100f + 1f; // Remap to [0;2] float con = settings.contrast.value / 100f + 1f; // Remap to [0;2] lutSheet.properties.SetVector(ShaderIDs.HueSatCon, new Vector3(hue, sat, con)); var channelMixerR = new Vector3(settings.mixerRedOutRedIn, settings.mixerRedOutGreenIn, settings.mixerRedOutBlueIn); var channelMixerG = new Vector3(settings.mixerGreenOutRedIn, settings.mixerGreenOutGreenIn, settings.mixerGreenOutBlueIn); var channelMixerB = new Vector3(settings.mixerBlueOutRedIn, settings.mixerBlueOutGreenIn, settings.mixerBlueOutBlueIn); lutSheet.properties.SetVector(ShaderIDs.ChannelMixerRed, channelMixerR / 100f); // Remap to [-2;2] lutSheet.properties.SetVector(ShaderIDs.ChannelMixerGreen, channelMixerG / 100f); lutSheet.properties.SetVector(ShaderIDs.ChannelMixerBlue, channelMixerB / 100f); var lift = ColorUtilities.ColorToLift(settings.lift.value); var gain = ColorUtilities.ColorToGain(settings.gain.value); var invgamma = ColorUtilities.ColorToInverseGamma(settings.gamma.value); lutSheet.properties.SetVector(ShaderIDs.Lift, lift); lutSheet.properties.SetVector(ShaderIDs.InvGamma, invgamma); lutSheet.properties.SetVector(ShaderIDs.Gain, gain); lutSheet.properties.SetFloat(ShaderIDs.Brightness, (settings.brightness.value + 100f) / 100f); lutSheet.properties.SetTexture(ShaderIDs.Curves, GetCurveTexture(false)); // Generate the lut context.command.BeginSample("LdrColorGradingLut2D"); var userLut = settings.ldrLut.value; if (userLut == null) { context.command.BlitFullscreenTriangle(BuiltinRenderTextureType.None, m_InternalLdrLut, lutSheet, (int)Pass.LutGenLDRFromScratch); } else { lutSheet.properties.SetVector(ShaderIDs.UserLut2D_Params, new Vector4(1f / userLut.width, 1f / userLut.height, userLut.height - 1f, settings.ldrLutContribution)); context.command.BlitFullscreenTriangle(userLut, m_InternalLdrLut, lutSheet, (int)Pass.LutGenLDR); } context.command.EndSample("LdrColorGradingLut2D"); } var lut = m_InternalLdrLut; var uberSheet = context.uberSheet; uberSheet.EnableKeyword("COLOR_GRADING_LDR_2D", context.command); uberSheet.properties.SetVector(ShaderIDs.Lut2D_Params, new Vector3(1f / lut.width, 1f / lut.height, lut.height - 1f)); uberSheet.properties.SetTexture(ShaderIDs.Lut2D, lut); }
internal override bool ShaderResourcesAvailable(PostProcessRenderContext context) { return(context.resources.computeShaders.gammaHistogram); }
public override void Render(PostProcessRenderContext context) { var sheet = context.propertySheets.Get(Shader.Find("Hidden/Custom/EdgeEnhance3")); context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0); }
public static Matrix4x4 GenerateJitteredProjectionMatrixFromOriginal(PostProcessRenderContext context, Matrix4x4 origProj, Vector2 jitter) { #if UNITY_2017_2_OR_NEWER var planes = origProj.decomposeProjection; float vertFov = Math.Abs(planes.top) + Math.Abs(planes.bottom); float horizFov = Math.Abs(planes.left) + Math.Abs(planes.right); var planeJitter = new Vector2(jitter.x * horizFov / context.screenWidth, jitter.y * vertFov / context.screenHeight); planes.left += planeJitter.x; planes.right += planeJitter.x; planes.top += planeJitter.y; planes.bottom += planeJitter.y; var jitteredMatrix = Matrix4x4.Frustum(planes); return(jitteredMatrix); #else var rTan = (1.0f + origProj[0, 2]) / origProj[0, 0]; var lTan = (-1.0f + origProj[0, 2]) / origProj[0, 0]; var tTan = (1.0f + origProj[1, 2]) / origProj[1, 1]; var bTan = (-1.0f + origProj[1, 2]) / origProj[1, 1]; float tanVertFov = Math.Abs(tTan) + Math.Abs(bTan); float tanHorizFov = Math.Abs(lTan) + Math.Abs(rTan); jitter.x *= tanHorizFov / context.screenWidth; jitter.y *= tanVertFov / context.screenHeight; float left = jitter.x + lTan; float right = jitter.x + rTan; float top = jitter.y + tTan; float bottom = jitter.y + bTan; var jitteredMatrix = new Matrix4x4(); jitteredMatrix[0, 0] = 2f / (right - left); jitteredMatrix[0, 1] = 0f; jitteredMatrix[0, 2] = (right + left) / (right - left); jitteredMatrix[0, 3] = 0f; jitteredMatrix[1, 0] = 0f; jitteredMatrix[1, 1] = 2f / (top - bottom); jitteredMatrix[1, 2] = (top + bottom) / (top - bottom); jitteredMatrix[1, 3] = 0f; jitteredMatrix[2, 0] = 0f; jitteredMatrix[2, 1] = 0f; jitteredMatrix[2, 2] = origProj[2, 2]; jitteredMatrix[2, 3] = origProj[2, 3]; jitteredMatrix[3, 0] = 0f; jitteredMatrix[3, 1] = 0f; jitteredMatrix[3, 2] = -1f; jitteredMatrix[3, 3] = 0f; return(jitteredMatrix); #endif }
public override bool IsEnabledAndSupported(PostProcessRenderContext context) { return(enabled.value && SystemInfo.supportsComputeShaders && SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RFloat)); }
public override void Render(PostProcessRenderContext context) { var cmd = context.command; cmd.BeginSample("Screen-space Reflections"); // Get quality settings if (settings.preset.value != ScreenSpaceReflectionPreset.Custom) { int id = (int)settings.preset.value; settings.maximumIterationCount.value = m_Presets[id].maximumIterationCount; settings.thickness.value = m_Presets[id].thickness; settings.resolution.value = m_Presets[id].downsampling; } settings.maximumMarchDistance.value = Mathf.Max(0f, settings.maximumMarchDistance.value); // Square POT target int size = Mathf.ClosestPowerOfTwo(Mathf.Min(context.width, context.height)); if (settings.resolution.value == ScreenSpaceReflectionResolution.Downsampled) { size >>= 1; } else if (settings.resolution.value == ScreenSpaceReflectionResolution.Supersampled) { size <<= 1; } // The gaussian pyramid compute works in blocks of 8x8 so make sure the last lod has a // minimum size of 8x8 const int kMaxLods = 12; int lodCount = Mathf.FloorToInt(Mathf.Log(size, 2f) - 3f); lodCount = Mathf.Min(lodCount, kMaxLods); CheckRT(ref m_Resolve, size, size, FilterMode.Trilinear, true); var noiseTex = context.resources.blueNoise256[0]; var sheet = context.propertySheets.Get(context.resources.shaders.screenSpaceReflections); sheet.properties.SetTexture(ShaderIDs.Noise, noiseTex); var screenSpaceProjectionMatrix = new Matrix4x4(); screenSpaceProjectionMatrix.SetRow(0, new Vector4(size * 0.5f, 0f, 0f, size * 0.5f)); screenSpaceProjectionMatrix.SetRow(1, new Vector4(0f, size * 0.5f, 0f, size * 0.5f)); screenSpaceProjectionMatrix.SetRow(2, new Vector4(0f, 0f, 1f, 0f)); screenSpaceProjectionMatrix.SetRow(3, new Vector4(0f, 0f, 0f, 1f)); var projectionMatrix = GL.GetGPUProjectionMatrix(context.camera.projectionMatrix, false); screenSpaceProjectionMatrix *= projectionMatrix; sheet.properties.SetMatrix(ShaderIDs.ViewMatrix, context.camera.worldToCameraMatrix); sheet.properties.SetMatrix(ShaderIDs.InverseViewMatrix, context.camera.worldToCameraMatrix.inverse); sheet.properties.SetMatrix(ShaderIDs.InverseProjectionMatrix, projectionMatrix.inverse); sheet.properties.SetMatrix(ShaderIDs.ScreenSpaceProjectionMatrix, screenSpaceProjectionMatrix); sheet.properties.SetVector(ShaderIDs.Params, new Vector4((float)settings.vignette.value, settings.distanceFade.value, settings.maximumMarchDistance.value, lodCount)); sheet.properties.SetVector(ShaderIDs.Params2, new Vector4((float)context.width / (float)context.height, (float)size / (float)noiseTex.width, settings.thickness.value, settings.maximumIterationCount.value)); cmd.GetTemporaryRT(ShaderIDs.Test, size, size, 0, FilterMode.Point, context.sourceFormat); cmd.BlitFullscreenTriangle(context.source, ShaderIDs.Test, sheet, (int)Pass.Test); if (context.isSceneView) { cmd.BlitFullscreenTriangle(context.source, m_Resolve, sheet, (int)Pass.Resolve); } else { CheckRT(ref m_History, size, size, FilterMode.Bilinear, false); if (m_ResetHistory) { context.command.BlitFullscreenTriangle(context.source, m_History); m_ResetHistory = false; } cmd.GetTemporaryRT(ShaderIDs.SSRResolveTemp, size, size, 0, FilterMode.Bilinear, context.sourceFormat); cmd.BlitFullscreenTriangle(context.source, ShaderIDs.SSRResolveTemp, sheet, (int)Pass.Resolve); sheet.properties.SetTexture(ShaderIDs.History, m_History); cmd.BlitFullscreenTriangle(ShaderIDs.SSRResolveTemp, m_Resolve, sheet, (int)Pass.Reproject); cmd.CopyTexture(m_Resolve, 0, 0, m_History, 0, 0); cmd.ReleaseTemporaryRT(ShaderIDs.SSRResolveTemp); } cmd.ReleaseTemporaryRT(ShaderIDs.Test); // Pre-cache mipmaps ids if (m_MipIDs == null || m_MipIDs.Length == 0) { m_MipIDs = new int[kMaxLods]; for (int i = 0; i < kMaxLods; i++) { m_MipIDs[i] = Shader.PropertyToID("_SSRGaussianMip" + i); } } var compute = context.resources.computeShaders.gaussianDownsample; int kernel = compute.FindKernel("KMain"); var mipFormat = RuntimeUtilities.defaultHDRRenderTextureFormat; var last = new RenderTargetIdentifier(m_Resolve); for (int i = 0; i < lodCount; i++) { size >>= 1; Assert.IsTrue(size > 0); cmd.GetTemporaryRT(m_MipIDs[i], size, size, 0, FilterMode.Bilinear, mipFormat, RenderTextureReadWrite.Default, 1, true); cmd.SetComputeTextureParam(compute, kernel, "_Source", last); cmd.SetComputeTextureParam(compute, kernel, "_Result", m_MipIDs[i]); cmd.SetComputeVectorParam(compute, "_Size", new Vector4(size, size, 1f / size, 1f / size)); cmd.DispatchCompute(compute, kernel, size / 8, size / 8, 1); cmd.CopyTexture(m_MipIDs[i], 0, 0, m_Resolve, 0, i + 1); last = m_MipIDs[i]; } for (int i = 0; i < lodCount; i++) { cmd.ReleaseTemporaryRT(m_MipIDs[i]); } sheet.properties.SetTexture(ShaderIDs.Resolve, m_Resolve); cmd.BlitFullscreenTriangle(context.source, context.destination, sheet, (int)Pass.Composite); cmd.EndSample("Screen-space Reflections"); }
public override void Render(PostProcessRenderContext context) { var sheet = context.uberSheet; Matrix4x4 frustumCorners = Matrix4x4.identity; context.camera.depthTextureMode |= DepthTextureMode.Depth; sheet.EnableKeyword("FOGWITHNOISE"); float fov = context.camera.fieldOfView; float near = context.camera.nearClipPlane; float aspect = context.camera.aspect; float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); Vector3 toRight = context.camera.transform.right * halfHeight * aspect; Vector3 toTop = context.camera.transform.up * halfHeight; Vector3 topLeft = context.camera.transform.forward * near + toTop - toRight; float scale = topLeft.magnitude / near; topLeft.Normalize(); topLeft *= scale; Vector3 topRight = context.camera.transform.forward * near + toRight + toTop; topRight.Normalize(); topRight *= scale; Vector3 bottomLeft = context.camera.transform.forward * near - toTop - toRight; bottomLeft.Normalize(); bottomLeft *= scale; Vector3 bottomRight = context.camera.transform.forward * near + toRight - toTop; bottomRight.Normalize(); bottomRight *= scale; if (settings.inArea > settings.area) { settings.inArea = settings.area; } frustumCorners.SetRow(0, bottomLeft); frustumCorners.SetRow(1, bottomRight); frustumCorners.SetRow(2, topRight); frustumCorners.SetRow(3, topLeft); sheet.properties.SetMatrix(ShaderIDs.FrustumCornersRay, frustumCorners); sheet.properties.SetFloat(ShaderIDs.FogDensity, settings.fogDensity * 2); sheet.properties.SetColor(ShaderIDs.FogColor1, settings.fogColor); sheet.properties.SetFloat(ShaderIDs.FogStart, settings.fogStart + context.camera.transform.position.y + 128); sheet.properties.SetFloat(ShaderIDs.FogEnd, settings.fogEnd + context.camera.transform.position.y + 128); if (settings.noiseTexture.value != null) { sheet.properties.SetTexture(ShaderIDs.NoiseTex, settings.noiseTexture.value); } sheet.properties.SetFloat(ShaderIDs.FogXSpeed, settings.fogXSpeed); sheet.properties.SetFloat(ShaderIDs.FogYSpeed, settings.fogYSpeed); sheet.properties.SetFloat(ShaderIDs.NoiseAmount, settings.noiseAmount); //material.SetFloat(ShaderIDs.WeakFactor", weakFactor); sheet.properties.SetFloat(ShaderIDs.OutArea, settings.area * 2); sheet.properties.SetFloat(ShaderIDs.InArea, settings.inArea / 2); sheet.properties.SetFloat(ShaderIDs.CenterX, settings.centerX); sheet.properties.SetFloat(ShaderIDs.CenterY, settings.centerY); }
// Renders everything not opaque-only // // Current order of operation is as following: // 1. Pre-stack // 2. Built-in stack // 3. Post-stack // 4. Built-in final pass // // Final pass should be skipped when outputting to a HDR display. public void Render(PostProcessRenderContext context) { if (RuntimeUtilities.scriptableRenderPipelineActive) { SetupContext(context); } TextureLerper.instance.BeginFrame(context); var cmd = context.command; // Update & override layer settings first (volume blending) if the opaque only pass // hasn't been called this frame. UpdateSettingsIfNeeded(context); // Do a NaN killing pass if needed int lastTarget = -1; if (stopNaNPropagation && !m_NaNKilled) { lastTarget = m_TargetPool.Get(); context.GetScreenSpaceTemporaryRT(cmd, lastTarget, 24, context.sourceFormat); cmd.BlitFullscreenTriangle(context.source, lastTarget, RuntimeUtilities.copySheet, 1); context.source = lastTarget; m_NaNKilled = true; } // Do temporal anti-aliasing first if (context.IsTemporalAntialiasingActive()) { if (!RuntimeUtilities.scriptableRenderPipelineActive) { if (context.stereoActive) { // We only need to configure all of this once for stereo, during OnPreCull if (context.camera.stereoActiveEye != Camera.MonoOrStereoscopicEye.Right) { temporalAntialiasing.ConfigureStereoJitteredProjectionMatrices(context); } } else { temporalAntialiasing.ConfigureJitteredProjectionMatrix(context); } } var taaTarget = m_TargetPool.Get(); var finalDestination = context.destination; context.GetScreenSpaceTemporaryRT(cmd, taaTarget, 24, context.sourceFormat); context.destination = taaTarget; temporalAntialiasing.Render(context); context.source = taaTarget; context.destination = finalDestination; if (lastTarget > -1) { cmd.ReleaseTemporaryRT(lastTarget); } lastTarget = taaTarget; } bool hasBeforeStackEffects = HasActiveEffects(PostProcessEvent.BeforeStack, context); bool hasAfterStackEffects = HasActiveEffects(PostProcessEvent.AfterStack, context) && !breakBeforeColorGrading; bool needsFinalPass = (hasAfterStackEffects || (antialiasingMode == Antialiasing.FastApproximateAntialiasing) || (antialiasingMode == Antialiasing.SubpixelMorphologicalAntialiasing && subpixelMorphologicalAntialiasing.IsSupported())) && !breakBeforeColorGrading; // Right before the builtin stack if (hasBeforeStackEffects) { lastTarget = RenderInjectionPoint(PostProcessEvent.BeforeStack, context, "BeforeStack", lastTarget); } // Builtin stack lastTarget = RenderBuiltins(context, !needsFinalPass, lastTarget); // After the builtin stack but before the final pass (before FXAA & Dithering) if (hasAfterStackEffects) { lastTarget = RenderInjectionPoint(PostProcessEvent.AfterStack, context, "AfterStack", lastTarget); } // And close with the final pass if (needsFinalPass) { RenderFinalPass(context, lastTarget); } // Render debug monitors & overlay if requested debugLayer.RenderSpecialOverlays(context); debugLayer.RenderMonitors(context); // End frame cleanup TextureLerper.instance.EndFrame(); debugLayer.EndFrame(); m_SettingsUpdateNeeded = true; m_NaNKilled = false; }
/// <summary> /// Returns <c>true</c> if the effect is currently enabled and supported. /// </summary> /// <param name="context">The current post-processing render context</param> /// <returns><c>true</c> if the effect is currently enabled and supported</returns> public override bool IsEnabledAndSupported(PostProcessRenderContext context) { return(enabled.value && ((mode.value == VignetteMode.Classic && intensity.value > 0f) || (mode.value == VignetteMode.Masked && opacity.value > 0f && mask.value != null))); }
int RenderBuiltins(PostProcessRenderContext context, bool isFinalPass, int releaseTargetAfterUse = -1) { var uberSheet = context.propertySheets.Get(context.resources.shaders.uber); uberSheet.ClearKeywords(); uberSheet.properties.Clear(); context.uberSheet = uberSheet; context.autoExposureTexture = RuntimeUtilities.whiteTexture; context.bloomBufferNameID = -1; var cmd = context.command; cmd.BeginSample("BuiltinStack"); int tempTarget = -1; var finalDestination = context.destination; if (!isFinalPass) { // Render to an intermediate target as this won't be the final pass tempTarget = m_TargetPool.Get(); context.GetScreenSpaceTemporaryRT(cmd, tempTarget, 24, context.sourceFormat); context.destination = tempTarget; // Handle FXAA's keep alpha mode if (antialiasingMode == Antialiasing.FastApproximateAntialiasing && !fastApproximateAntialiasing.keepAlpha) { uberSheet.properties.SetFloat(ShaderIDs.LumaInAlpha, 1f); } } // Depth of field final combination pass used to be done in Uber which led to artifacts // when used at the same time as Bloom (because both effects used the same source, so // the stronger bloom was, the more DoF was eaten away in out of focus areas) int depthOfFieldTarget = RenderEffect <DepthOfField>(context, true); // Motion blur is a separate pass - could potentially be done after DoF depending on the // kind of results you're looking for... int motionBlurTarget = RenderEffect <MotionBlur>(context, true); // Prepare exposure histogram if needed if (ShouldGenerateLogHistogram(context)) { m_LogHistogram.Generate(context); } // Uber effects RenderEffect <AutoExposure>(context); uberSheet.properties.SetTexture(ShaderIDs.AutoExposureTex, context.autoExposureTexture); RenderEffect <ChromaticAberration>(context); RenderEffect <Bloom>(context); RenderEffect <Vignette>(context); RenderEffect <Grain>(context); if (!breakBeforeColorGrading) { RenderEffect <ColorGrading>(context); } int pass = 0; if (isFinalPass) { uberSheet.EnableKeyword("FINALPASS"); dithering.Render(context); if (context.flip && !context.isSceneView) { pass = 1; } } cmd.BlitFullscreenTriangle(context.source, context.destination, uberSheet, pass); context.source = context.destination; context.destination = finalDestination; if (releaseTargetAfterUse > -1) { cmd.ReleaseTemporaryRT(releaseTargetAfterUse); } if (motionBlurTarget > -1) { cmd.ReleaseTemporaryRT(motionBlurTarget); } if (depthOfFieldTarget > -1) { cmd.ReleaseTemporaryRT(motionBlurTarget); } if (context.bloomBufferNameID > -1) { cmd.ReleaseTemporaryRT(context.bloomBufferNameID); } cmd.EndSample("BuiltinStack"); return(tempTarget); }
public override void Render(PostProcessRenderContext context) { // The coc is stored in alpha so we need a 4 channels target. Note that using ARGB32 // will result in a very weak near-blur. var colorFormat = context.camera.allowHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; var cocFormat = SelectFormat(RenderTextureFormat.R8, RenderTextureFormat.RHalf); // Material setup float scaledFilmHeight = k_FilmHeight * (context.height / 1080f); var f = settings.focalLength.value / 1000f; var s1 = Mathf.Max(settings.focusDistance.value, f); var aspect = (float)context.screenWidth / (float)context.screenHeight; var coeff = f * f / (settings.aperture.value * (s1 - f) * scaledFilmHeight * 2f); var maxCoC = CalculateMaxCoCRadius(context.screenHeight); var sheet = context.propertySheets.Get(context.resources.shaders.depthOfField); sheet.properties.Clear(); sheet.properties.SetFloat(ShaderIDs.Distance, s1); sheet.properties.SetFloat(ShaderIDs.LensCoeff, coeff); sheet.properties.SetFloat(ShaderIDs.MaxCoC, maxCoC); sheet.properties.SetFloat(ShaderIDs.RcpMaxCoC, 1f / maxCoC); sheet.properties.SetFloat(ShaderIDs.RcpAspect, 1f / aspect); sheet.properties.SetFloat(Shader.PropertyToID("_NoNearBlur"), settings.noNearBlur); var cmd = context.command; cmd.BeginSample("DepthOfField"); // CoC calculation pass context.GetScreenSpaceTemporaryRT(cmd, ShaderIDs.CoCTex, 0, cocFormat, RenderTextureReadWrite.Linear); cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, ShaderIDs.CoCTex, sheet, (int)Pass.CoCCalculation); // CoC temporal filter pass when TAA is enabled if (context.IsTemporalAntialiasingActive()) { float motionBlending = context.temporalAntialiasing.motionBlending; float blend = m_ResetHistory ? 0f : motionBlending; // Handles first frame blending var jitter = context.temporalAntialiasing.jitter; sheet.properties.SetVector(ShaderIDs.TaaParams, new Vector3(jitter.x, jitter.y, blend)); int pp = m_HistoryPingPong[context.xrActiveEye]; var historyRead = CheckHistory(context.xrActiveEye, ++pp % 2, context, cocFormat); var historyWrite = CheckHistory(context.xrActiveEye, ++pp % 2, context, cocFormat); m_HistoryPingPong[context.xrActiveEye] = ++pp % 2; cmd.BlitFullscreenTriangle(historyRead, historyWrite, sheet, (int)Pass.CoCTemporalFilter); cmd.ReleaseTemporaryRT(ShaderIDs.CoCTex); cmd.SetGlobalTexture(ShaderIDs.CoCTex, historyWrite); } // Downsampling and prefiltering pass context.GetScreenSpaceTemporaryRT(cmd, ShaderIDs.DepthOfFieldTex, 0, colorFormat, RenderTextureReadWrite.Default, FilterMode.Bilinear, context.width / 2, context.height / 2); cmd.BlitFullscreenTriangle(context.source, ShaderIDs.DepthOfFieldTex, sheet, (int)Pass.DownsampleAndPrefilter); // Bokeh simulation pass context.GetScreenSpaceTemporaryRT(cmd, ShaderIDs.DepthOfFieldTemp, 0, colorFormat, RenderTextureReadWrite.Default, FilterMode.Bilinear, context.width / 2, context.height / 2); cmd.BlitFullscreenTriangle(ShaderIDs.DepthOfFieldTex, ShaderIDs.DepthOfFieldTemp, sheet, (int)Pass.BokehSmallKernel + (int)settings.kernelSize.value); // Postfilter pass cmd.BlitFullscreenTriangle(ShaderIDs.DepthOfFieldTemp, ShaderIDs.DepthOfFieldTex, sheet, (int)Pass.PostFilter); cmd.ReleaseTemporaryRT(ShaderIDs.DepthOfFieldTemp); // Debug overlay pass if (context.IsDebugOverlayEnabled(DebugOverlay.DepthOfField)) { context.PushDebugOverlay(cmd, context.source, sheet, (int)Pass.DebugOverlay); } // Combine pass cmd.BlitFullscreenTriangle(context.source, context.destination, sheet, (int)Pass.Combine); cmd.ReleaseTemporaryRT(ShaderIDs.DepthOfFieldTex); if (!context.IsTemporalAntialiasingActive()) { cmd.ReleaseTemporaryRT(ShaderIDs.CoCTex); } cmd.EndSample("DepthOfField"); m_ResetHistory = false; }
public override void Render(PostProcessRenderContext context) { 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 == UnityEngine.Rendering.GraphicsDeviceType.Metal) { cocFormat = SelectFormat(RenderTextureFormat.RHalf, RenderTextureFormat.Default); } #endif // Material setup var f = settings.focalLength.value / 1000f; var s1 = Mathf.Max(settings.focusDistance.value, f); var aspect = (float)context.width / (float)context.height; var coeff = f * f / (settings.aperture.value * (s1 - f) * k_FilmHeight * 2); var maxCoC = CalculateMaxCoCRadius(context.height); var sheet = context.propertySheets.Get(context.resources.shaders.depthOfField); sheet.properties.Clear(); sheet.properties.SetFloat(ShaderIDs.Distance, s1); sheet.properties.SetFloat(ShaderIDs.LensCoeff, coeff); sheet.properties.SetFloat(ShaderIDs.MaxCoC, maxCoC); sheet.properties.SetFloat(ShaderIDs.RcpMaxCoC, 1f / maxCoC); sheet.properties.SetFloat(ShaderIDs.RcpAspect, 1f / aspect); var cmd = context.command; cmd.BeginSample("DepthOfField"); // CoC calculation pass cmd.GetTemporaryRT(ShaderIDs.CoCTex, context.width, context.height, 0, FilterMode.Bilinear, cocFormat, RenderTextureReadWrite.Linear); cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, ShaderIDs.CoCTex, sheet, (int)Pass.CoCCalculation); // CoC temporal filter pass when TAA is enabled if (context.IsTemporalAntialiasingActive()) { float motionBlending = context.temporalAntialiasing.motionBlending; float blend = m_ResetHistory ? 0f : motionBlending; // Handles first frame blending var jitter = context.temporalAntialiasing.jitter; sheet.properties.SetVector(ShaderIDs.TaaParams, new Vector3(jitter.x, jitter.y, blend)); int pp = m_HistoryPingPong; var historyRead = CheckHistory(++pp % 2, context.width, context.height, cocFormat); var historyWrite = CheckHistory(++pp % 2, context.width, context.height, cocFormat); m_HistoryPingPong = ++pp % 2; cmd.BlitFullscreenTriangle(historyRead, historyWrite, sheet, (int)Pass.CoCTemporalFilter); cmd.ReleaseTemporaryRT(ShaderIDs.CoCTex); cmd.SetGlobalTexture(ShaderIDs.CoCTex, historyWrite); } // Downsampling and prefiltering pass cmd.GetTemporaryRT(ShaderIDs.DepthOfFieldTex, context.width / 2, context.height / 2, 0, FilterMode.Bilinear, colorFormat); cmd.BlitFullscreenTriangle(context.source, ShaderIDs.DepthOfFieldTex, sheet, (int)Pass.DownsampleAndPrefilter); // Bokeh simulation pass cmd.GetTemporaryRT(ShaderIDs.DepthOfFieldTemp, context.width / 2, context.height / 2, 0, FilterMode.Bilinear, colorFormat); cmd.BlitFullscreenTriangle(ShaderIDs.DepthOfFieldTex, ShaderIDs.DepthOfFieldTemp, sheet, (int)Pass.BokehSmallKernel + (int)settings.kernelSize.value); // Postfilter pass cmd.BlitFullscreenTriangle(ShaderIDs.DepthOfFieldTemp, ShaderIDs.DepthOfFieldTex, sheet, (int)Pass.PostFilter); cmd.ReleaseTemporaryRT(ShaderIDs.DepthOfFieldTemp); // Combine pass cmd.BlitFullscreenTriangle(context.source, context.destination, sheet, (int)Pass.Combine); cmd.ReleaseTemporaryRT(ShaderIDs.DepthOfFieldTex); if (!context.IsTemporalAntialiasingActive()) { cmd.ReleaseTemporaryRT(ShaderIDs.CoCTex); } cmd.EndSample("DepthOfField"); m_ResetHistory = false; }
/// <summary> /// Returns <c>true</c> if the effect is currently enabled and supported. /// </summary> /// <param name="context">The current post-processing render context</param> /// <returns><c>true</c> if the effect is currently enabled and supported</returns> public override bool IsEnabledAndSupported(PostProcessRenderContext context) { return(enabled.value && SystemInfo.graphicsShaderLevel >= 35); }
// HDR color pipeline is rendered to a 3D lut; it requires Texture3D & compute shaders // support - Desktop / Consoles / Some high-end mobiles // TODO: Use ShaderIDs for compute once the compatible APIs go in void RenderHDRPipeline3D(PostProcessRenderContext context) { // Unfortunately because AnimationCurve doesn't implement GetHashCode and we don't have // any reliable way to figure out if a curve data is different from another one we can't // skip regenerating the Lut if nothing has changed. So it has to be done on every // frame... // It's not a very expensive operation anyway (we're talking about filling a 33x33x33 // Lut on the GPU) but every little thing helps, especially on mobile. { CheckInternalLogLut(); // Lut setup var compute = context.resources.computeShaders.lut3DBaker; int kernel = 0; switch (settings.tonemapper.value) { case Tonemapper.None: kernel = compute.FindKernel("KGenLut3D_NoTonemap"); break; case Tonemapper.Neutral: kernel = compute.FindKernel("KGenLut3D_NeutralTonemap"); break; case Tonemapper.ACES: kernel = compute.FindKernel("KGenLut3D_AcesTonemap"); break; case Tonemapper.Custom: kernel = compute.FindKernel("KGenLut3D_CustomTonemap"); break; } int groupSizeXY = Mathf.CeilToInt(k_Lut3DSize / 8f); int groupSizeZ = Mathf.CeilToInt(k_Lut3DSize / (RuntimeUtilities.isAndroidOpenGL ? 2f : 8f)); var cmd = context.command; cmd.SetComputeTextureParam(compute, kernel, "_Output", m_InternalLogLut); cmd.SetComputeVectorParam(compute, "_Size", new Vector4(k_Lut3DSize, 1f / (k_Lut3DSize - 1f), 0f, 0f)); var colorBalance = ColorUtilities.ComputeColorBalance(settings.temperature.value, settings.tint.value); cmd.SetComputeVectorParam(compute, "_ColorBalance", colorBalance); cmd.SetComputeVectorParam(compute, "_ColorFilter", settings.colorFilter.value); float hue = settings.hueShift.value / 360f; // Remap to [-0.5;0.5] float sat = settings.saturation.value / 100f + 1f; // Remap to [0;2] float con = settings.contrast.value / 100f + 1f; // Remap to [0;2] cmd.SetComputeVectorParam(compute, "_HueSatCon", new Vector4(hue, sat, con, 0f)); var channelMixerR = new Vector4(settings.mixerRedOutRedIn, settings.mixerRedOutGreenIn, settings.mixerRedOutBlueIn, 0f); var channelMixerG = new Vector4(settings.mixerGreenOutRedIn, settings.mixerGreenOutGreenIn, settings.mixerGreenOutBlueIn, 0f); var channelMixerB = new Vector4(settings.mixerBlueOutRedIn, settings.mixerBlueOutGreenIn, settings.mixerBlueOutBlueIn, 0f); cmd.SetComputeVectorParam(compute, "_ChannelMixerRed", channelMixerR / 100f); // Remap to [-2;2] cmd.SetComputeVectorParam(compute, "_ChannelMixerGreen", channelMixerG / 100f); cmd.SetComputeVectorParam(compute, "_ChannelMixerBlue", channelMixerB / 100f); var lift = ColorUtilities.ColorToLift(settings.lift.value * 0.2f); var gain = ColorUtilities.ColorToGain(settings.gain.value * 0.8f); var invgamma = ColorUtilities.ColorToInverseGamma(settings.gamma.value * 0.8f); cmd.SetComputeVectorParam(compute, "_Lift", new Vector4(lift.x, lift.y, lift.z, 0f)); cmd.SetComputeVectorParam(compute, "_InvGamma", new Vector4(invgamma.x, invgamma.y, invgamma.z, 0f)); cmd.SetComputeVectorParam(compute, "_Gain", new Vector4(gain.x, gain.y, gain.z, 0f)); cmd.SetComputeTextureParam(compute, kernel, "_Curves", GetCurveTexture(true)); if (settings.tonemapper.value == Tonemapper.Custom) { m_HableCurve.Init( settings.toneCurveToeStrength.value, settings.toneCurveToeLength.value, settings.toneCurveShoulderStrength.value, settings.toneCurveShoulderLength.value, settings.toneCurveShoulderAngle.value, settings.toneCurveGamma.value ); cmd.SetComputeVectorParam(compute, "_CustomToneCurve", m_HableCurve.uniforms.curve); cmd.SetComputeVectorParam(compute, "_ToeSegmentA", m_HableCurve.uniforms.toeSegmentA); cmd.SetComputeVectorParam(compute, "_ToeSegmentB", m_HableCurve.uniforms.toeSegmentB); cmd.SetComputeVectorParam(compute, "_MidSegmentA", m_HableCurve.uniforms.midSegmentA); cmd.SetComputeVectorParam(compute, "_MidSegmentB", m_HableCurve.uniforms.midSegmentB); cmd.SetComputeVectorParam(compute, "_ShoSegmentA", m_HableCurve.uniforms.shoSegmentA); cmd.SetComputeVectorParam(compute, "_ShoSegmentB", m_HableCurve.uniforms.shoSegmentB); } // Generate the lut context.command.BeginSample("HdrColorGradingLut3D"); cmd.DispatchCompute(compute, kernel, groupSizeXY, groupSizeXY, groupSizeZ); context.command.EndSample("HdrColorGradingLut3D"); } var lut = m_InternalLogLut; var uberSheet = context.uberSheet; uberSheet.EnableKeyword("COLOR_GRADING_HDR_3D"); uberSheet.properties.SetTexture(ShaderIDs.Lut3D, lut); uberSheet.properties.SetVector(ShaderIDs.Lut3D_Params, new Vector2(1f / lut.width, lut.width - 1f)); uberSheet.properties.SetFloat(ShaderIDs.PostExposure, RuntimeUtilities.Exp2(settings.postExposure.value)); context.logLut = lut; }
public virtual bool IsEnabledAndSupported(PostProcessRenderContext context) { return(enabled.value); }
public bool IsSupported(PostProcessRenderContext context) { return(intensity > 0f && !RuntimeUtilities.scriptableRenderPipelineActive); }
internal void BeginFrame(PostProcessRenderContext context) { m_Command = context.command; m_PropertySheets = context.propertySheets; m_Resources = context.resources; }
public override void Render(PostProcessRenderContext context) { var cmd = context.command; if (m_ResetHistory) { cmd.BlitFullscreenTriangle(context.source, context.destination); m_ResetHistory = false; return; } const float kMaxBlurRadius = 5f; var vectorRTFormat = RenderTextureFormat.RGHalf; var packedRTFormat = RenderTextureFormat.ARGB2101010.IsSupported() ? RenderTextureFormat.ARGB2101010 : RenderTextureFormat.ARGB32; var sheet = context.propertySheets.Get(context.resources.shaders.motionBlur); cmd.BeginSample("MotionBlur"); // Calculate the maximum blur radius in pixels. int maxBlurPixels = (int)(kMaxBlurRadius * context.height / 100); // Calculate the TileMax size. // It should be a multiple of 8 and larger than maxBlur. int tileSize = ((maxBlurPixels - 1) / 8 + 1) * 8; // Pass 1 - Velocity/depth packing var velocityScale = settings.shutterAngle / 360f; sheet.properties.SetFloat(ShaderIDs.VelocityScale, velocityScale); sheet.properties.SetFloat(ShaderIDs.MaxBlurRadius, maxBlurPixels); sheet.properties.SetFloat(ShaderIDs.RcpMaxBlurRadius, 1f / maxBlurPixels); int vbuffer = ShaderIDs.VelocityTex; CreateTemporaryRT(context, vbuffer, context.width, context.height, packedRTFormat); cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, vbuffer, sheet, (int)Pass.VelocitySetup); // Pass 2 - First TileMax filter (1/2 downsize) int tile2 = ShaderIDs.Tile2RT; CreateTemporaryRT(context, tile2, context.width / 2, context.height / 2, vectorRTFormat); cmd.BlitFullscreenTriangle(vbuffer, tile2, sheet, (int)Pass.TileMax1); // Pass 3 - Second TileMax filter (1/2 downsize) int tile4 = ShaderIDs.Tile4RT; CreateTemporaryRT(context, tile4, context.width / 4, context.height / 4, vectorRTFormat); cmd.BlitFullscreenTriangle(tile2, tile4, sheet, (int)Pass.TileMax2); cmd.ReleaseTemporaryRT(tile2); // Pass 4 - Third TileMax filter (1/2 downsize) int tile8 = ShaderIDs.Tile8RT; CreateTemporaryRT(context, tile8, context.width / 8, context.height / 8, vectorRTFormat); cmd.BlitFullscreenTriangle(tile4, tile8, sheet, (int)Pass.TileMax2); cmd.ReleaseTemporaryRT(tile4); // Pass 5 - Fourth TileMax filter (reduce to tileSize) var tileMaxOffs = Vector2.one * (tileSize / 8f - 1f) * -0.5f; sheet.properties.SetVector(ShaderIDs.TileMaxOffs, tileMaxOffs); sheet.properties.SetFloat(ShaderIDs.TileMaxLoop, (int)(tileSize / 8f)); int tile = ShaderIDs.TileVRT; CreateTemporaryRT(context, tile, context.width / tileSize, context.height / tileSize, vectorRTFormat); cmd.BlitFullscreenTriangle(tile8, tile, sheet, (int)Pass.TileMaxV); cmd.ReleaseTemporaryRT(tile8); // Pass 6 - NeighborMax filter int neighborMax = ShaderIDs.NeighborMaxTex; CreateTemporaryRT(context, neighborMax, context.width / tileSize, context.height / tileSize, vectorRTFormat); cmd.BlitFullscreenTriangle(tile, neighborMax, sheet, (int)Pass.NeighborMax); cmd.ReleaseTemporaryRT(tile); // Pass 7 - Reconstruction pass sheet.properties.SetFloat(ShaderIDs.LoopCount, Mathf.Clamp(settings.sampleCount / 2, 1, 64)); cmd.BlitFullscreenTriangle(context.source, context.destination, sheet, (int)Pass.Reconstruction); cmd.ReleaseTemporaryRT(vbuffer); cmd.ReleaseTemporaryRT(neighborMax); cmd.EndSample("MotionBlur"); }
public override void Render(PostProcessRenderContext context) { var sheet = context.propertySheets.Get(_shader); context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 4); }