private void UpdateParameters(OutlineParameters parameters, Camera camera, bool editorCamera) { UpdateSharedParameters(parameters, camera, editorCamera); parameters.DepthTarget = RenderTargetUtility.ComposeTarget(parameters, BuiltinRenderTextureType.CameraTarget); var targetTexture = camera.targetTexture == null ? camera.activeTexture : camera.targetTexture; if (UnityEngine.XR.XRSettings.enabled && !parameters.IsEditorCamera && parameters.EyeMask != StereoTargetEyeMask.None) { var descriptor = UnityEngine.XR.XRSettings.eyeTextureDesc; parameters.TargetWidth = descriptor.width; parameters.TargetHeight = descriptor.height; } else { parameters.TargetWidth = targetTexture != null ? targetTexture.width : camera.scaledPixelWidth; parameters.TargetHeight = targetTexture != null ? targetTexture.height : camera.scaledPixelHeight; } parameters.Antialiasing = editorCamera ? (targetTexture == null ? 1 : targetTexture.antiAliasing) : CameraUtility.GetMSAA(targetCamera); parameters.Target = RenderTargetUtility.ComposeTarget(parameters, HasCutomRenderTarget && !editorCamera ? GetRenderTarget(parameters) : BuiltinRenderTextureType.CameraTarget); Outlinable.GetAllActiveOutlinables(parameters.Camera, parameters.OutlinablesToRender); RendererFilteringUtility.Filter(parameters.Camera, parameters); }
private void LateUpdate() { parameters.Layers.Clear(); Outlinable.GetAllActiveOutlinables(outlinables); foreach (var outlinable in outlinables) { parameters.Layers.Add(outlinable.Layer); } #if UNITY_EDITOR ReAddBufferToEditorCamera(); if (SceneView.lastActiveSceneView != null && SceneView.lastActiveSceneView.camera != null) { UpdateParameters(SceneView.lastActiveSceneView.camera, true); var targetTexture = SceneView.lastActiveSceneView.camera.targetTexture; var width = targetTexture == null ? Screen.width : targetTexture.width; var height = targetTexture == null ? Screen.height : targetTexture.height; SceneView.lastActiveSceneView.camera.forceIntoRenderTexture = true; OutlineEffect.SetupBuffer(parameters); } #endif { UpdateParameters(targetCamera, false); targetCamera.forceIntoRenderTexture = true; OutlineEffect.SetupBuffer(parameters); } }
public static void SetupBuffer(OutlineParameters parameters) { CheckIsPrepared(); outlinables.Clear(); Outlinable.GetAllActiveOutlinables(outlinables); parameters.Buffer.Clear(); if (outlinables.Count == 0 && !parameters.SustainedPerformanceMode) { return; } SetupDepth(parameters); if (parameters.SustainedPerformanceMode && parameters.Layers.Count == 0) { parameters.Layers.Add(int.MaxValue); } foreach (var layer in parameters.Layers) { var scaledWidth = (int)(parameters.Width * parameters.PrimaryRendererScale); var scaledHeight = (int)(parameters.Height * parameters.PrimaryRendererScale); GetTemporaryRT(parameters, temporaryRT, parameters.Width, parameters.Height, 0); parameters.ControlProvider.Blit(parameters.Target, temporaryRT, basicBlitMaterial, 0); parameters.ControlProvider.SetTarget(parameters.Target); parameters.Buffer.ClearRenderTarget(false, true, Color.clear); foreach (var outlinable in outlinables) { if (outlinable.Layer != layer) { continue; } if (!parameters.DrawPredicate(outlinable)) { continue; } var maskMaterialToUse = outlinable.MaskMaterial; parameters.Buffer.SetGlobalColor(colorHash, outlinable.OutlineColor); renderers.Clear(); outlinable.GetRenderers(renderers); foreach (var currentRenderer in renderers) { if (currentRenderer == null || !currentRenderer.enabled || !currentRenderer.gameObject.activeInHierarchy) { continue; } var submeshesCount = GetSubmeshCount(currentRenderer); for (var submesh = 0; submesh < submeshesCount; submesh++) { if (maskMaterialToUse != null) { parameters.ControlProvider.DrawRenderer(currentRenderer, maskMaterialToUse, submesh, false); } parameters.ControlProvider.DrawRenderer(currentRenderer, outlinable.OutlineMaterial, submesh, SetupCutout(parameters, currentRenderer)); if (maskMaterialToUse != null) { parameters.ControlProvider.DrawRenderer(currentRenderer, clearStencilMaterial, submesh, false); } } } } // Post processing GetTemporaryRT(parameters, postprocessRT, scaledWidth, scaledHeight, 0); GetTemporaryRT(parameters, secondaryPostprocessRT, scaledWidth, scaledHeight, 0); GetTemporaryRT(parameters, copySurface, parameters.Width, parameters.Height, 0); parameters.ControlProvider.Blit(parameters.Target, copySurface, addAlphaBlitMaterial, 0); parameters.ControlProvider.Blit(copySurface, postprocessRT, basicBlitMaterial, -1); parameters.ControlProvider.SetTarget(parameters.Target); parameters.Buffer.ClearRenderTarget(false, true, Color.clear); if (parameters.UsingInfoBuffer) { var scaledInfoWidth = (int)(parameters.Width * parameters.InfoBufferScale); var scaledInfoHeight = (int)(parameters.Height * parameters.InfoBufferScale); GetTemporaryRT(parameters, infoBuffer, scaledInfoWidth, scaledInfoHeight, 0); foreach (var outlinable in outlinables) { if (outlinable.Layer != layer) { continue; } if (!parameters.DrawPredicate(outlinable)) { continue; } var maskMaterialToUse = outlinable.MaskMaterial; parameters.Buffer.SetGlobalColor(colorHash, new Color(outlinable.BlurShift, outlinable.DilateShift, 0, 0)); outlinable.GetRenderers(renderers); foreach (var currentRenderer in renderers) { if (currentRenderer == null || !currentRenderer.enabled || !currentRenderer.gameObject.activeInHierarchy) { continue; } var submeshesCount = GetSubmeshCount(currentRenderer); for (var submesh = 0; submesh < submeshesCount; submesh++) { if (maskMaterialToUse != null) { parameters.ControlProvider.DrawRenderer(currentRenderer, maskMaterialToUse, submesh, false); } parameters.ControlProvider.DrawRenderer(currentRenderer, infoMaterial, submesh, false); if (maskMaterialToUse != null) { parameters.ControlProvider.DrawRenderer(currentRenderer, clearStencilMaterial, submesh, false); } } } } parameters.Buffer.SetGlobalTexture(infoBufferHash, infoBuffer); parameters.ControlProvider.Blit(parameters.Target, infoBuffer, basicBlitMaterial, -1); parameters.ControlProvider.SetTarget(parameters.Target); GetTemporaryRT(parameters, secondaryInfoBuffer, scaledInfoWidth, scaledInfoWidth, 0); var firstInfoBuffer = infoBuffer; var secondInfoBuffer = secondaryInfoBuffer; Postprocess(parameters.Buffer, parameters.ControlProvider, new Vector2(1.0f / scaledInfoWidth, 1.0f / scaledInfoHeight), parameters.BlurIterations + parameters.DilateIterations, ref firstInfoBuffer, ref secondInfoBuffer, outlinePostProcessMaterial, 1); } var firstTarget = postprocessRT; var secondTarget = secondaryPostprocessRT; Postprocess(parameters.Buffer, parameters.ControlProvider, new Vector2(parameters.DilateShift / scaledWidth, parameters.DilateShift / scaledHeight), parameters.DilateIterations, ref firstTarget, ref secondTarget, outlinePostProcessMaterial, parameters.UsingInfoBuffer ? 3 : 1); Postprocess(parameters.Buffer, parameters.ControlProvider, new Vector2(parameters.BlurShift / scaledWidth, parameters.BlurShift / scaledHeight), parameters.BlurIterations, ref firstTarget, ref secondTarget, outlinePostProcessMaterial, parameters.UsingInfoBuffer ? 2 : 0); parameters.ControlProvider.Blit(firstTarget, copySurface, blitMaterial, 0); parameters.Buffer.ReleaseTemporaryRT(postprocessRT); parameters.Buffer.ReleaseTemporaryRT(secondaryPostprocessRT); parameters.ControlProvider.SetTarget(copySurface); // Carving foreach (var outlinable in outlinables) { if (outlinable.Layer != layer) { continue; } if (!parameters.DrawPredicate(outlinable)) { continue; } outlinable.GetRenderers(renderers); foreach (var currentRenderer in renderers) { if (currentRenderer == null || !currentRenderer.enabled || !currentRenderer.gameObject.activeInHierarchy) { continue; } var submeshesCount = GetSubmeshCount(currentRenderer); for (var submesh = 0; submesh < submeshesCount; submesh++) { parameters.ControlProvider.DrawRenderer(currentRenderer, fillMaterial, submesh, SetupCutout(parameters, currentRenderer)); } } } parameters.ControlProvider.Blit(copySurface, temporaryRT, blitMaterial, -1); parameters.Buffer.ReleaseTemporaryRT(copySurface); parameters.ControlProvider.Blit(temporaryRT, parameters.Target, basicBlitMaterial, 0); parameters.Buffer.ReleaseTemporaryRT(temporaryRT); if (!parameters.UsingInfoBuffer) { continue; } parameters.Buffer.ReleaseTemporaryRT(infoBuffer); parameters.Buffer.ReleaseTemporaryRT(secondaryInfoBuffer); } }