private void RenderVPassBlend(OutlineResources resources, IOutlineSettings settings) { // Setup shader parameter overrides. var props = resources.VPassBlendProperties; props.SetFloat(resources.WidthId, settings.OutlineWidth); props.SetColor(resources.ColorId, settings.OutlineColor); if (settings.OutlineMode == OutlineMode.Solid) { props.SetFloat(resources.IntensityId, SolidIntensity); } else { props.SetFloat(resources.IntensityId, settings.OutlineIntensity); } // Set source texture as _MainTex to match Blit behavior. _commandBuffer.SetGlobalTexture(_mainRtId, _source); // Set destination texture as render target. #if UNITY_2018_2_OR_NEWER _commandBuffer.SetRenderTarget(_destination, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); #else _commandBuffer.SetRenderTarget(_destination); #endif // Blit fullscreen triangle. _commandBuffer.DrawMesh(resources.FullscreenTriangleMesh, Matrix4x4.identity, resources.VPassBlendMaterial, 0, 0, props); }
/// <summary> /// Initializes a new instance of the <see cref="OutlineRenderer"/> struct. /// </summary> /// <param name="cmd">A <see cref="CommandBuffer"/> to render the effect to. It should be cleared manually (if needed) before passing to this method.</param> /// <param name="resources">Outline resources.</param> /// <param name="dst">Render target.</param> /// <param name="depth">Depth dexture to use.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="cmd"/> is <see langword="null"/>.</exception> public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst, RenderTargetIdentifier depth, Vector2Int rtSize) { if (cmd is null) { throw new ArgumentNullException(nameof(cmd)); } if (resources is null) { throw new ArgumentNullException(nameof(resources)); } if (rtSize.x <= 0) { rtSize.x = -1; } if (rtSize.y <= 0) { rtSize.y = -1; } cmd.GetTemporaryRT(_maskRtId, rtSize.x, rtSize.y, 0, FilterMode.Bilinear, _rtFormat); cmd.GetTemporaryRT(_hPassRtId, rtSize.x, rtSize.y, 0, FilterMode.Bilinear, _rtFormat); _rt = dst; _depth = depth; _commandBuffer = cmd; _resources = resources; }
internal void SetResources(OutlineResources resources) { if (resources != _resources) { _resources = resources; _changed = true; } }
private void Awake() { OutlineResources.LogSrpNotSupported(this); OutlineResources.LogPpNotSupported(this); CreateRenderersIfNeeded(); CreateSettingsIfNeeded(); }
/// <summary> /// Renders all layers. /// </summary> public void Render(OutlineRenderer renderer, OutlineResources resources) { UpdateSortedLayersIfNeeded(); foreach (var layer in _sortedLayers) { layer.Render(renderer, resources); } }
internal void Render(OutlineRenderer renderer, OutlineResources resources) { _settings.SetResources(resources); foreach (var kvp in _outlineObjects) { if (kvp.Key) { renderer.RenderSingleObject(kvp.Value, _settings.OutlineMaterials); } } }
/// <summary> /// Renders the layers. /// </summary> public void Render(OutlineRenderer renderer, OutlineResources resources) { if (_enabled) { _settings.SetResources(resources); foreach (var kvp in _outlineObjects) { if (kvp.Key && kvp.Key.activeInHierarchy) { renderer.Render(kvp.Value, _settings.OutlineResources, _settings); } } } }
/// <summary> /// Initializes a new instance of the <see cref="OutlineRenderer"/> struct. /// </summary> /// <param name="cmd">A <see cref="CommandBuffer"/> to render the effect to. It should be cleared manually (if needed) before passing to this method.</param> /// <param name="resources">Outline resources.</param> /// <param name="dst">Render target.</param> /// <param name="depth">Depth dexture to use.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="cmd"/> is <see langword="null"/>.</exception> public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst, RenderTargetIdentifier depth, Vector2Int rtSize) { if (cmd is null) { throw new ArgumentNullException(nameof(cmd)); } if (resources is null) { throw new ArgumentNullException(nameof(resources)); } if (rtSize.x <= 0) { rtSize.x = -1; } if (rtSize.y <= 0) { rtSize.y = -1; } if (XRSettings.enabled) { var rtDesc = XRSettings.eyeTextureDesc; rtDesc.shadowSamplingMode = ShadowSamplingMode.None; rtDesc.depthBufferBits = 0; rtDesc.colorFormat = RtFormat; cmd.GetTemporaryRT(resources.MaskTexId, rtDesc, FilterMode.Bilinear); cmd.GetTemporaryRT(resources.TempTexId, rtDesc, FilterMode.Bilinear); _rtDimention = rtDesc.dimension; } else { cmd.GetTemporaryRT(resources.MaskTexId, rtSize.x, rtSize.y, 0, FilterMode.Bilinear, RtFormat); cmd.GetTemporaryRT(resources.TempTexId, rtSize.x, rtSize.y, 0, FilterMode.Bilinear, RtFormat); _rtDimention = TextureDimension.Tex2D; } _rt = dst; _depth = depth; _commandBuffer = cmd; _resources = resources; }
/// <summary> /// Initializes a new instance of the <see cref="OutlineMaterialSet"/> class. /// </summary> internal OutlineMaterialSet(OutlineResources resources, Material renderMaterial) { Debug.Assert(resources); Debug.Assert(resources.IsValid); Debug.Assert(renderMaterial); _outlineResources = resources; _renderMaterial = renderMaterial; _hPassMaterial = new Material(resources.HPassShader); _vPassMaterial = new Material(resources.VPassBlendShader); _hPassMaterial.SetInt(WidthNameId, _width); _vPassMaterial.SetInt(WidthNameId, _width); _vPassMaterial.SetColor(ColorNameId, _color); _vPassMaterial.SetFloat(IntensityNameId, OutlineRenderer.SolidIntensity); }
private void RenderObject(OutlineResources resources, IOutlineSettings settings, Renderer renderer) { RenderObjectClear((settings.OutlineRenderMode & OutlineRenderFlags.EnableDepthTesting) != 0); if (renderer && renderer.gameObject.activeInHierarchy && renderer.enabled) { // NOTE: Accessing Renderer.sharedMaterials triggers GC.Alloc. That's why we use a temporary // list of materials, cached with the outline resources. renderer.GetSharedMaterials(resources.TmpMaterials); for (var i = 0; i < resources.TmpMaterials.Count; ++i) { _commandBuffer.DrawRenderer(renderer, resources.RenderMaterial, i); } } }
/// <summary> /// Initializes a new instance of the <see cref="OutlineMaterialSet"/> class. /// </summary> /// <remarks> /// The preferred way of creating instances of <see cref="OutlineMaterialSet"/> is calling <see cref="OutlineResources.CreateMaterialSet"/> method. /// </remarks> public OutlineMaterialSet(OutlineResources resources) { if (resources == null) { throw new ArgumentNullException("resources"); } _outlineResources = resources; _renderMaterial = new Material(resources.RenderShader); _hPassMaterial = new Material(resources.HPassShader); _vPassMaterial = new Material(resources.VPassBlendShader); _hPassMaterial.SetInt(WidthNameId, _width); _vPassMaterial.SetInt(WidthNameId, _width); _vPassMaterial.SetColor(ColorNameId, _color); _vPassMaterial.SetFloat(IntensityNameId, OutlineRenderer.SolidIntensity); }
internal void SetResources(OutlineResources resources) { if (resources == null) { if (_materials != null) { _materials.Dispose(); _materials = null; } } else if (_materials == null || _materials.OutlineResources != resources) { _materials = resources.CreateMaterialSet(); _materials.Reset(this); _changed = true; } }
private void RenderHPass(OutlineResources resources, IOutlineSettings settings) { // Setup shader parameter overrides. var props = resources.HPassProperties; props.SetFloat(resources.WidthId, settings.OutlineWidth); // Set source texture as _MainTex to match Blit behavior. _commandBuffer.SetGlobalTexture(_mainRtId, _maskRtId); // Set destination texture as render target. #if UNITY_2018_2_OR_NEWER _commandBuffer.SetRenderTarget(_hPassRtId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); #else _commandBuffer.SetRenderTarget(_hPassRtId); #endif // Blit fullscreen triangle. _commandBuffer.DrawMesh(resources.FullscreenTriangleMesh, Matrix4x4.identity, resources.HPassMaterial, 0, 0, props); }
private void RenderObject(OutlineResources resources, IOutlineSettings settings, IEnumerable <Renderer> renderers) { RenderObjectClear((settings.OutlineRenderMode & OutlineRenderFlags.EnableDepthTesting) != 0); // NOTE: Calling IEnumerable.GetEnumerator() triggers GC.Alloc. foreach (var r in renderers) { if (r && r.enabled && r.gameObject.activeInHierarchy) { // NOTE: Accessing Renderer.sharedMaterials triggers GC.Alloc. That's why we use a temporary // list of materials, cached with the outline resources. r.GetSharedMaterials(resources.TmpMaterials); for (var j = 0; j < resources.TmpMaterials.Count; ++j) { _commandBuffer.DrawRenderer(r, resources.RenderMaterial, j); } } } }
/// <summary> /// Initializes a new instance of the <see cref="OutlineRenderer"/> struct. /// </summary> /// <param name="cmd">A <see cref="CommandBuffer"/> to render the effect to. It should be cleared manually (if needed) before passing to this method.</param> /// <param name="resources">Outline resources.</param> /// <param name="dst">Render target.</param> /// <param name="depth">Depth dexture to use.</param> /// <param name="rtDesc">Render texture decsriptor.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="cmd"/> is <see langword="null"/>.</exception> public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst, RenderTargetIdentifier depth, RenderTextureDescriptor rtDesc) { if (cmd is null) { throw new ArgumentNullException(nameof(cmd)); } if (resources is null) { throw new ArgumentNullException(nameof(resources)); } if (rtDesc.width <= 0) { rtDesc.width = -1; } if (rtDesc.height <= 0) { rtDesc.height = -1; } if (rtDesc.dimension == TextureDimension.None || rtDesc.dimension == TextureDimension.Unknown) { rtDesc.dimension = TextureDimension.Tex2D; } rtDesc.shadowSamplingMode = ShadowSamplingMode.None; rtDesc.depthBufferBits = 0; rtDesc.colorFormat = RtFormat; rtDesc.msaaSamples = 1; cmd.GetTemporaryRT(resources.MaskTexId, rtDesc, FilterMode.Bilinear); cmd.GetTemporaryRT(resources.TempTexId, rtDesc, FilterMode.Bilinear); _rtDimention = rtDesc.dimension; _rt = dst; _depth = depth; _commandBuffer = cmd; _resources = resources; }
/// <summary> /// Renders outline around a single object. /// </summary> /// <param name="renderer">A <see cref="Renderer"/> representing an object to be outlined.</param> /// <param name="resources">Outline resources.</param> /// <param name="settings">Outline settings.</param> /// <exception cref="ArgumentNullException">Thrown if any of the arguments is <see langword="null"/>.</exception> public void Render(Renderer renderer, OutlineResources resources, IOutlineSettings settings) { if (renderer == null) { throw new ArgumentNullException("renderers"); } if (resources == null) { throw new ArgumentNullException("resources"); } if (settings == null) { throw new ArgumentNullException("settings"); } Init(resources, settings); RenderObject(renderer, resources.RenderMaterial); RenderHPass(resources, settings); RenderVPassBlend(resources, settings); }
/// <summary> /// Renders outline around a single object. /// </summary> /// <param name="renderers">One or more renderers representing a single object to be outlined.</param> /// <param name="resources">Outline resources.</param> /// <param name="settings">Outline settings.</param> /// <exception cref="ArgumentNullException">Thrown if any of the arguments is <see langword="null"/>.</exception> /// <seealso cref="Render(IList{Renderer}, OutlineResources, IOutlineSettings)"/> /// <seealso cref="Render(Renderer, OutlineResources, IOutlineSettings)"/> public void Render(IEnumerable <Renderer> renderers, OutlineResources resources, IOutlineSettings settings) { if (renderers == null) { throw new ArgumentNullException("renderers"); } if (resources == null) { throw new ArgumentNullException("resources"); } if (settings == null) { throw new ArgumentNullException("settings"); } Init(resources, settings); RenderObject(resources, settings, renderers); RenderHPass(resources, settings); RenderVPassBlend(resources, settings); }
private void Init(OutlineResources resources, IOutlineSettings settings) { _commandBuffer.SetGlobalFloatArray(resources.GaussSamplesId, resources.GetGaussSamples(settings.OutlineWidth)); }
/// <summary> /// Initializes a new instance of the <see cref="OutlineRenderer"/> struct. /// </summary> /// <param name="cmd">A <see cref="CommandBuffer"/> to render the effect to. It should be cleared manually (if needed) before passing to this method.</param> /// <param name="resources">Outline resources.</param> /// <param name="renderingPath">The rendering path of target camera (<see cref="Camera.actualRenderingPath"/>).</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="cmd"/> is <see langword="null"/>.</exception> public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderingPath renderingPath) : this(cmd, resources, BuiltinRenderTextureType.CameraTarget, GetBuiltinDepth(renderingPath), Vector2Int.zero) { }
/// <summary> /// Initializes a new instance of the <see cref="OutlineRenderer"/> struct. /// </summary> /// <param name="cmd">A <see cref="CommandBuffer"/> to render the effect to. It should be cleared manually (if needed) before passing to this method.</param> /// <param name="resources">Outline resources.</param> /// <param name="dst">Render target.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="cmd"/> is <see langword="null"/>.</exception> public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst) : this(cmd, resources, dst, BuiltinRenderTextureType.Depth, Vector2Int.zero) { }
private static void Blit(CommandBuffer cmdBuffer, RenderTargetIdentifier src, OutlineResources resources, int shaderPass, Material mat, MaterialPropertyBlock props) { // Set source texture as _MainTex to match Blit behavior. cmdBuffer.SetGlobalTexture(resources.MainTexId, src); if (SystemInfo.graphicsShaderLevel < 35 || resources.UseFullscreenTriangleMesh) { cmdBuffer.DrawMesh(resources.FullscreenTriangleMesh, Matrix4x4.identity, mat, 0, shaderPass, props); } else { cmdBuffer.DrawProcedural(Matrix4x4.identity, mat, shaderPass, MeshTopology.Triangles, 3, 1, props); } }
/// <summary> /// Initializes a new instance of the <see cref="OutlineRenderer"/> struct. /// </summary> /// <param name="cmd">A <see cref="CommandBuffer"/> to render the effect to. It should be cleared manually (if needed) before passing to this method.</param> /// <param name="resources">Outline resources.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="cmd"/> is <see langword="null"/>.</exception> public OutlineRenderer(CommandBuffer cmd, OutlineResources resources) : this(cmd, resources, BuiltinRenderTextureType.CameraTarget, BuiltinRenderTextureType.Depth, Vector2Int.zero) { }
private void Awake() { OutlineResources.LogSrpNotSupported(this); OutlineResources.LogPpNotSupported(this); }
/// <summary> /// Initializes a new instance of the <see cref="OutlineRenderer"/> struct. /// </summary> /// <param name="cmd">A <see cref="CommandBuffer"/> to render the effect to. It should be cleared manually (if needed) before passing to this method.</param> /// <param name="dst">Render target.</param> /// <param name="renderingPath">The rendering path of target camera (<see cref="Camera.actualRenderingPath"/>).</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="cmd"/> is <see langword="null"/>.</exception> public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst, RenderingPath renderingPath, Vector2Int rtSize) : this(cmd, resources, dst, GetBuiltinDepth(renderingPath), rtSize) { }
public void Init() { _resources = ScriptableObject.CreateInstance <OutlineResources>(); _materialSet = _resources.CreateMaterialSet(); Init(_materialSet); }
private static void Blit(CommandBuffer cmdBuffer, RenderTargetIdentifier src, OutlineResources resources, int shaderPass, Material mat, MaterialPropertyBlock props) { // Set source texture as _MainTex to match Blit behavior. cmdBuffer.SetGlobalTexture(resources.MainTexId, src); // NOTE: SystemInfo.graphicsShaderLevel check is not enough sometimes (esp. on mobiles), so there is SystemInfo.supportsInstancing // check and a flag for forcing DrawMesh. if (SystemInfo.graphicsShaderLevel >= 35 && SystemInfo.supportsInstancing && !resources.UseFullscreenTriangleMesh) { cmdBuffer.DrawProcedural(Matrix4x4.identity, mat, shaderPass, MeshTopology.Triangles, 3, 1, props); } else { cmdBuffer.DrawMesh(resources.FullscreenTriangleMesh, Matrix4x4.identity, mat, 0, shaderPass, props); } }
internal OutlineSettingsInstance(OutlineResources resources) { _resources = resources; }