private void DoDepthOfField(RenderTexture source, RenderTexture destination) { float radiusAdjustement = source.height / 720f; float textureBokehScale = radiusAdjustement; float textureBokehMaxRadius = textureBokehScale * 30f; float nearBlurRadius = 40 * radiusAdjustement; float maxBlurRadius = nearBlurRadius; maxBlurRadius *= 1.2f; if (maxBlurRadius < 0.5f) { Graphics.Blit(source, destination); return; } // Quarter resolution int rtW = source.width / 2; int rtH = source.height / 2; var blurrinessCoe = new Vector4(nearBlurRadius * 0.5f, nearBlurRadius * 0.5f, 0f, 0f); var colorAndCoc = m_RTU.GetTemporaryRenderTexture(rtW, rtH); var colorAndCoc2 = m_RTU.GetTemporaryRenderTexture(rtW, rtH); // Downsample to Color + COC buffer Vector4 cocParam; Vector4 cocCoe; ComputeCocParameters(out cocParam, out cocCoe); filmicDepthOfFieldMaterial.SetVector(m_BlurParams, cocParam); filmicDepthOfFieldMaterial.SetVector(m_BlurCoe, cocCoe); Graphics.Blit(source, colorAndCoc2, filmicDepthOfFieldMaterial, (int)Passes.CaptureCocExplicit); var src = colorAndCoc2; var dst = colorAndCoc; // Collect texture bokeh candidates and replace with a darker pixel if (shouldPerformBokeh) { // Blur a bit so we can do a frequency check var blurred = m_RTU.GetTemporaryRenderTexture(rtW, rtH); Graphics.Blit(src, blurred, filmicDepthOfFieldMaterial, (int)Passes.BoxBlur); filmicDepthOfFieldMaterial.SetVector(m_Offsets, new Vector4(0f, 1.5f, 0f, 1.5f)); Graphics.Blit(blurred, dst, filmicDepthOfFieldMaterial, (int)Passes.BlurAlphaWeighted); filmicDepthOfFieldMaterial.SetVector(m_Offsets, new Vector4(1.5f, 0f, 0f, 1.5f)); Graphics.Blit(dst, blurred, filmicDepthOfFieldMaterial, (int)Passes.BlurAlphaWeighted); // Collect texture bokeh candidates and replace with a darker pixel textureBokehMaterial.SetTexture(m_BlurredColor, blurred); textureBokehMaterial.SetFloat(m_SpawnHeuristic, bokehTexture.spawnHeuristic); textureBokehMaterial.SetVector(m_BokehParams, new Vector4(bokehTexture.scale * textureBokehScale, bokehTexture.intensity, bokehTexture.threshold, textureBokehMaxRadius)); Graphics.SetRandomWriteTarget(1, computeBufferPoints); Graphics.Blit(src, dst, textureBokehMaterial, (int)BokehTexturesPasses.Collect); Graphics.ClearRandomWriteTargets(); SwapRenderTexture(ref src, ref dst); m_RTU.ReleaseTemporaryRenderTexture(blurred); } filmicDepthOfFieldMaterial.SetVector(m_BlurParams, cocParam); filmicDepthOfFieldMaterial.SetVector(m_BlurCoe, blurrinessCoe); // Dilate near blur factor RenderTexture blurredFgCoc = null; var blurredFgCoc2 = m_RTU.GetTemporaryRenderTexture(rtW, rtH, 0, RenderTextureFormat.RGHalf); blurredFgCoc = m_RTU.GetTemporaryRenderTexture(rtW, rtH, 0, RenderTextureFormat.RGHalf); filmicDepthOfFieldMaterial.SetVector(m_Offsets, new Vector4(0f, nearBlurRadius * 0.75f, 0f, 0f)); Graphics.Blit(src, blurredFgCoc2, filmicDepthOfFieldMaterial, (int)Passes.DilateFgCocFromColor); filmicDepthOfFieldMaterial.SetVector(m_Offsets, new Vector4(nearBlurRadius * 0.75f, 0f, 0f, 0f)); Graphics.Blit(blurredFgCoc2, blurredFgCoc, filmicDepthOfFieldMaterial, (int)Passes.DilateFgCoc); m_RTU.ReleaseTemporaryRenderTexture(blurredFgCoc2); blurredFgCoc.filterMode = FilterMode.Point; Graphics.Blit(src, dst, filmicDepthOfFieldMaterial, (int)Passes.CocPrefilter); SwapRenderTexture(ref src, ref dst); DoHexagonalBlur(blurredFgCoc, ref src, ref dst, maxBlurRadius); // Smooth result Graphics.Blit(src, dst, medianFilterMaterial, (int)MedianPasses.Median3X3); SwapRenderTexture(ref src, ref dst); // Merge to full resolution (with boost) + upsampling (linear or bicubic) filmicDepthOfFieldMaterial.SetVector(m_BlurCoe, blurrinessCoe); filmicDepthOfFieldMaterial.SetVector(m_Convolved_TexelSize, new Vector4(src.width, src.height, 1f / src.width, 1f / src.height)); filmicDepthOfFieldMaterial.SetTexture(m_SecondTex, src); int mergePass = (int)Passes.MergeExplicit; // Apply texture bokeh if (shouldPerformBokeh) { var tmp = m_RTU.GetTemporaryRenderTexture(source.height, source.width, 0, source.format); Graphics.Blit(source, tmp, filmicDepthOfFieldMaterial, mergePass); Graphics.SetRenderTarget(tmp); ComputeBuffer.CopyCount(computeBufferPoints, computeBufferDrawArgs, 0); textureBokehMaterial.SetBuffer(pointBuffer, computeBufferPoints); textureBokehMaterial.SetTexture(m_MainTex, bokehTexture.texture); textureBokehMaterial.SetVector(m_Screen, new Vector3(1f / (1f * source.width), 1f / (1f * source.height), textureBokehMaxRadius)); textureBokehMaterial.SetPass((int)BokehTexturesPasses.Apply); Graphics.DrawProceduralIndirect(MeshTopology.Points, computeBufferDrawArgs, 0); Graphics.Blit(tmp, destination); // Hackaround for DX11 flipfun (OPTIMIZEME) } else { Graphics.Blit(source, destination, filmicDepthOfFieldMaterial, mergePass); } }
private void OnRenderImage(RenderTexture source, RenderTexture destination) { if (!this.enabled) { Graphics.Blit(source, destination); return; } material.shaderKeywords = null; if (this.enabled) { material.SetColor("_VignetteColor", this.color); if (this.blur > 0f) { // Downscale + gaussian blur (2 passes) int w = source.width / 2; int h = source.height / 2; var rt1 = m_RTU.GetTemporaryRenderTexture(w, h, 0, source.format); var rt2 = m_RTU.GetTemporaryRenderTexture(w, h, 0, source.format); material.SetVector("_BlurPass", new Vector2(1f / w, 0f)); Graphics.Blit(source, rt1, material, (int)Pass.BlurPrePass); material.SetVector("_BlurPass", new Vector2(0f, 1f / h)); Graphics.Blit(rt1, rt2, material, (int)Pass.BlurPrePass); material.SetVector("_BlurPass", new Vector2(1f / w, 0f)); Graphics.Blit(rt2, rt1, material, (int)Pass.BlurPrePass); material.SetVector("_BlurPass", new Vector2(0f, 1f / h)); Graphics.Blit(rt1, rt2, material, (int)Pass.BlurPrePass); material.SetTexture("_BlurTex", rt2); material.SetFloat("_VignetteBlur", this.blur * 3f); material.EnableKeyword("VIGNETTE_BLUR"); } if (this.desaturate > 0f) { material.EnableKeyword("VIGNETTE_DESAT"); material.SetFloat("_VignetteDesat", 1f - this.desaturate); } material.SetVector("_VignetteCenter", this.center); if (Mathf.Approximately(this.roundness, 1f)) { material.EnableKeyword("VIGNETTE_CLASSIC"); material.SetVector("_VignetteSettings", new Vector2(this.intensity, this.smoothness)); } else { material.EnableKeyword("VIGNETTE_FILMIC"); float roundness = (1f - this.roundness) * 6f + this.roundness; material.SetVector("_VignetteSettings", new Vector3(this.intensity, this.smoothness, roundness)); } } Graphics.Blit(source, destination, material, 1); m_RTU.ReleaseAllTemporaryRenderTextures(); }