Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Filter on LayerMask - Renderpass / Scriptable Render pass / render feature

Discussion in 'Universal Render Pipeline' started by Dark_Seth, Sep 21, 2022.

  1. Dark_Seth

    Dark_Seth

    Joined:
    May 28, 2014
    Posts:
    130
    Hi Guys

    Looking at this video . I want to leave my game in Full res but only pixelate one layer.


    Cause of all the jitter in Pixel perfect cam I am not using it but using Scriptable Render pass.

    So I manged to get this working following some other guides and trying to understand it all.

    It Work!! But full screen only. Which I wanted but I want to mix the styles.
    I Added a LayerMask in PixelizeFeature.cs ( ScriptableRendererFeature ) and pass it to PixelizePass.cs ( ScriptableRenderPass)

    But I have no Idea how to apply this Layermask to it. Here is the Code and the Shader. Would love if someone cane help me on this.

    PixelizePass.cs
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.Rendering;
    4. using UnityEngine.Rendering.Universal;
    5.  
    6. public class PixelizePass : ScriptableRenderPass
    7. {
    8.     private PixelizeFeature.CustomPassSettings settings;
    9.  
    10.     private RenderTargetIdentifier colorBuffer, pixelBuffer;
    11.     private int pixelBufferID = Shader.PropertyToID("_PixelBuffer");
    12.  
    13.     //private RenderTargetIdentifier pointBuffer;
    14.     //private int pointBufferID = Shader.PropertyToID("_PointBuffer");
    15.  
    16.     private Material material;
    17.     private int pixelScreenHeight, pixelScreenWidth;
    18.  
    19.     public PixelizePass(PixelizeFeature.CustomPassSettings settings)
    20.     {
    21.         this.settings = settings;
    22.         this.renderPassEvent = settings.renderPassEvent;
    23.         if (material == null) material = CoreUtils.CreateEngineMaterial("Hidden/Pixelize");
    24.     }
    25.  
    26.     public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    27.     {
    28.         colorBuffer = renderingData.cameraData.renderer.cameraColorTarget;
    29.         RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
    30.  
    31.         //cmd.GetTemporaryRT(pointBufferID, descriptor.width, descriptor.height, 0, FilterMode.Point);
    32.         //pointBuffer = new RenderTargetIdentifier(pointBufferID);
    33.  
    34.         pixelScreenHeight = settings.screenHeight;
    35.         pixelScreenWidth = (int)(pixelScreenHeight * renderingData.cameraData.camera.aspect + 0.5f);
    36.  
    37.         material.SetVector("_BlockCount", new Vector2(pixelScreenWidth, pixelScreenHeight));
    38.         material.SetVector("_BlockSize", new Vector2(1.0f / pixelScreenWidth, 1.0f / pixelScreenHeight));
    39.         material.SetVector("_HalfBlockSize", new Vector2(0.5f / pixelScreenWidth, 0.5f / pixelScreenHeight));
    40.  
    41.         descriptor.height = pixelScreenHeight;
    42.         descriptor.width = pixelScreenWidth;
    43.  
    44.         cmd.GetTemporaryRT(pixelBufferID, descriptor, FilterMode.Point);
    45.         pixelBuffer = new RenderTargetIdentifier(pixelBufferID);
    46.     }
    47.  
    48.     public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    49.     {
    50.         CommandBuffer cmd = CommandBufferPool.Get();
    51.         using (new ProfilingScope(cmd, new ProfilingSampler("Pixelize Pass")))
    52.         {
    53.             // No-shader variant
    54.             //Blit(cmd, colorBuffer, pointBuffer);
    55.             //Blit(cmd, pointBuffer, pixelBuffer);
    56.             //Blit(cmd, pixelBuffer, colorBuffer);
    57.  
    58.             Blit(cmd, colorBuffer, pixelBuffer, material);
    59.             Blit(cmd, pixelBuffer, colorBuffer);
    60.         }
    61.  
    62.         context.ExecuteCommandBuffer(cmd);
    63.         CommandBufferPool.Release(cmd);
    64.     }
    65.  
    66.     public override void OnCameraCleanup(CommandBuffer cmd)
    67.     {
    68.         if (cmd == null) throw new System.ArgumentNullException("cmd");
    69.         cmd.ReleaseTemporaryRT(pixelBufferID);
    70.         //cmd.ReleaseTemporaryRT(pointBufferID);
    71.     }
    72.  
    73. }
    74.  
    PixelizeFeature.cs
    Code (CSharp):
    1.  
    2.  
    3. using UnityEngine;
    4. using UnityEngine.Rendering;
    5. using UnityEngine.Rendering.Universal;
    6.  
    7. public class PixelizeFeature : ScriptableRendererFeature
    8. {
    9.     [System.Serializable]
    10.     public class CustomPassSettings
    11.     {
    12.         public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
    13.         public int screenHeight = 144;
    14.         public LayerMask LayerMask;
    15.     }
    16.    
    17.        
    18.      
    19.  
    20.  
    21.     [SerializeField] private CustomPassSettings settings;
    22.    
    23.     private PixelizePass customPass;
    24.  
    25.     public override void Create()
    26.     {
    27.        
    28.         customPass = new PixelizePass(settings);
    29.     }
    30.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    31.     {
    32.  
    33. #if UNITY_EDITOR
    34.         if (renderingData.cameraData.isSceneViewCamera) return;
    35. #endif
    36.         renderer.EnqueuePass(customPass);
    37.     }
    38. }
    39.  
    40.  
    41.  
     

    Attached Files:

  2. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    949
    Is this what you are going to achieve?
    gif2.gif
    I have applied a mask feature - the same I am using in the CrossSection asset for selective outline effect.
    The sphere stays on a separate layer with the mask feature applied, and the pixelize shader uses input from the mask texture.

    The gif image illustrates the animation of the pixelScreenHeight parameter in the pixelize effect.
     
    Last edited: Sep 26, 2022
    NathanNie, agubudaa and Dark_Seth like this.
  3. Dark_Seth

    Dark_Seth

    Joined:
    May 28, 2014
    Posts:
    130
    Wow. That is what I want. But I haven' found a way to get it working yet.
     
  4. QuigsBigSpecGames

    QuigsBigSpecGames

    Joined:
    Apr 20, 2019
    Posts:
    37
    Is there any movement on this? I'm also looking for a way to filter objects in a render pass.
     
  5. AurochChris

    AurochChris

    Joined:
    Jan 7, 2014
    Posts:
    24
    To filter objects in a RenderPass, you use the ScriptableRenderContext to call the DrawRenderers command with CullResults, DrawSettings, and FilterSettings parameters inside Execute().

    Code (CSharp):
    1. FilterSettings filteringSettings = new FilteringSettings(RenderQueueRange.all, passSettings.LayerMask.value);
    2.  
    3. DrawingSettings drawingSettings = CreateDrawingSettings(passSettings.shaderTags, ref renderingData, passSettings.SortingCriteria);
    4. drawingSettings.overrideMaterial = passSettings.MaskMaterial;
    5. drawingSettings.overrideMaterialPassIndex = 0;
    6.  
    7. context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings);
    Note that you can define your DrawSettings and FilterSettings anywhere, so doesn't need to be done inside Execute.

    As @tomekkie2 showed, because pixelization is as a post-process effect, you'll want to do this in two RenderPasses.

    In the first pass, you filter your objects to those Layers/RenderLayers you want and draw them to a new render texture using an RTHandle. You're simply creating a greyscale mask here, so the shader will be relatively simple. You then set this mask texture as a global texture using the cmd.SetGlobalTexture() method.

    In the second pass, you Blit the screen with a shader that takes your global MaskTexture as an input.

    Be careful when using Global variables in shaders: your global texture needs to be declared with the same name as defined by cmd.SetGlobalTexture() inside the relevant shader pass; but don't declare it in the Shader's Properties block. If you do, the compiler will assume you're looking for Material property and not a Global property of the same name, and your Mask Texture won't be set on your shader.
     
    lilacsky824 and Dark_Seth like this.
  6. Dark_Seth

    Dark_Seth

    Joined:
    May 28, 2014
    Posts:
    130

    Thanks for the info. I still have to learn a lot here. This is just something I understand what to do but don't know how to
    . I just can't seem to get it working. One day I will try again to do this. I just can't. Not giving up! Just stuck
     
  7. QuigsBigSpecGames

    QuigsBigSpecGames

    Joined:
    Apr 20, 2019
    Posts:
    37
    Thanks from me as well. I will give this a go.
     
  8. AurochChris

    AurochChris

    Joined:
    Jan 7, 2014
    Posts:
    24
    Honestly, we had very much the same experience. Our team consists of two technical artists, and the Render Feature we implemented was thoroughly explained by Ben Golus, but the URP API caused huge headaches which were only solved with two weeks of trial and error. That also included sleuthing old docs and making some educated guesses and assumptions about how URP worked in the current version.

    All that to say is I feel your pain. If you do want to ask any more questions, I'm happy to help when I can. (Though my knowledge is pretty much limited to making one multi-pass RenderFeature work.)
     
    noio likes this.
  9. Dark_Seth

    Dark_Seth

    Joined:
    May 28, 2014
    Posts:
    130
    Thanks a lot!. Will do. Skipping this step for now to continue on my progress with some other objectives. I am doing is solo at this stage.

    when I return to this section. I would love to be in contact.
     
  10. Renegade_Wolf

    Renegade_Wolf

    Joined:
    Jan 17, 2022
    Posts:
    35
    So, I'm trying to understand this, and maybe this will help others in the future.

    Currently, I have this code in my render pass
    Code (CSharp):
    1.  
    2.     RenderTargetIdentifier source;
    3.     RenderTargetHandle destination;
    4.  
    5. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    6.     {
    7.         source = renderingData.cameraData.renderer.cameraColorTarget;
    8.         cmd.GetTemporaryRT(destination.id, renderingData.cameraData.cameraTargetDescriptor);
    9.     }
    10.  
    11.     // Here you can implement the rendering logic.
    12.     // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
    13.     // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
    14.     // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
    15.  
    16.     public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    17.     {
    18.         CommandBuffer cmd = CommandBufferPool.Get();
    19.  
    20.         cmd.Blit(source, destination.Identifier(), settings.material, 0);
    21.         cmd.Blit(destination.Identifier(), source);
    22.  
    23.         context.ExecuteCommandBuffer(cmd);
    24.         CommandBufferPool.Release(cmd);
    25.     }
    26.  
    27.     // Cleanup any allocated resources that were created during the execution of this render pass.
    28.  
    29.     public override void OnCameraCleanup(CommandBuffer cmd)
    30.     {
    31.         cmd.ReleaseTemporaryRT(destination.id);
    32.     }
    Pretty simple, it just blits a given material onto all the objects seen in the renderer color camera target, and back to the same camera. That much, I think I understand.
    However, it's currently all happening in pass 0. Do I need to do something like "if (pass == 0)" outside of these commands, in order to apply the drawing settings in the first pass, put the above in an else block and change the render pass there in the Blit to 1? Or would it be sufficient to put all of this code in execute, just change that render pass in the Blit to a 1, and add
    Code (CSharp):
    1.         //filter by layer
    2.         drawingSettings = CreateDrawingSettings(settings.shaderTags, ref renderingData, settings.SortingCriteria);
    3.         drawingSettings.overrideMaterial = settings.material;
    4.         drawingSettings.overrideMaterialPassIndex = 0;
    5.         context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings);
    into Execute above my code?

    As I understand it, I would instead need to pass the drawingSettings.overrideMaterial into the Blit(), right?

    If I understand that much correctly, I believe I am just stuck on the shader and the sorting criteria.
    You said "You're simply creating a greyscale mask here, so the shader will be relatively simple. You then set this mask texture as a global texture using the cmd.SetGlobalTexture() method." So that means I have to create a new shader to pass into the DrawingSettings as the shaderTags? I don't understand what this shader is meant to do. No shader is "simple" to me, I'm afraid =/ What is the purpose of setting the global texture? Clearly it has something to do with the shader, so that's a complete mystery to me.
    As for the sorting criteria, I don't want to apply any additional sorting beyond what the cameras are already handling. Is that None sorting? RendererPriority sorting? RenderQueue sorting? All of them make some sense.

    Finally, you say "In the first pass, you filter your objects to those Layers/RenderLayers you want and draw them to a new render texture using an RTHandle." I don't see an RTHandle being used anywhere in your code. Is that associated with the shaderTags somehow?

    Sorry for the extremely noob questions, shaders and postprocessing are still mostly a mystery to me and it's very difficult to debug attempts when I don't really even understand what it is I'm trying to do to accomplish my goal. I think the sorting would be fairly simple to figure out, but the shader is really stopping my progress.
     
  11. Renegade_Wolf

    Renegade_Wolf

    Joined:
    Jan 17, 2022
    Posts:
    35
    Hmm still stuck on this, this is where I've got to in Execute(). I know I'm missing something but not sure what...
    Code (CSharp):
    1.         // Filter objects by layer mask
    2.         drawingSettings = CreateDrawingSettings(settings.shaderTags, ref renderingData, settings.sortingCriteria);
    3.         drawingSettings.overrideMaterial = settings.material;
    4.         drawingSettings.overrideMaterialPassIndex = 0;
    5.         context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings);
    6.         context.Submit();
    7.  
    8.         var culledSource = renderingData.cameraData.renderer.cameraColorTarget;
    9.  
    10.         // Blit filtered objects to temporary render target
    11.         var cmd = CommandBufferPool.Get();
    12.         cmd.Blit(culledSource, destination.Identifier(), settings.material);
    13.  
    14.         // Overlay filtered objects onto original image
    15.         cmd.SetGlobalTexture("_MainTex", destination.Identifier());
    16.         cmd.Blit(destination.Identifier(), source);
    17.  
    18.         context.ExecuteCommandBuffer(cmd);
    19.  
    20.         CommandBufferPool.Release(cmd);
     
    Propagant likes this.
  12. Propagant

    Propagant

    Joined:
    Nov 18, 2013
    Posts:
    32
    Yeah, I'm struggling to wrap this up as well... Ended up with pretty similar code, however what I need is to filter certain objects with layer mask and blit that into the material. This is for custom fog which needs to have a filtered objects. Any thoughts how to properly filter objects, make a blit of them and push the texture into shader? I mean documentation for renderer features in URP is pretty NON-EXISTING
     
  13. Renegade_Wolf

    Renegade_Wolf

    Joined:
    Jan 17, 2022
    Posts:
    35
    My research has told me documentation has been forthcoming for... I think like 3 years now. I think we're trying to accomplish the same goal? I have a shader/material that does postprocessing, but it does it on all layers and I need to only blit the modifications to a specific layer as identified by a layer mask.
    This is the sort of thing that would be really easy with a specific example. Tonight I plan on trying to look at the RenderObject postprocessing code, if I can, because I know it has a layermask option.
     
    trombonaut likes this.
  14. Propagant

    Propagant

    Joined:
    Nov 18, 2013
    Posts:
    32
    RenderObject doesn't blit a currently rendered frame into texture. I need to 1. render certain objects with specific layer mask 2. blit that rendered image into shader 3. blit that modified shader to the output image. Doesn't really sound that difficult.
     
  15. Renegade_Wolf

    Renegade_Wolf

    Joined:
    Jan 17, 2022
    Posts:
    35
    That sounds like the same goal to me. Get objects with a layer mask, apply the shader/mat only to those objects, and render those objects with the shader applied to the final image.
    I've been looking into various approaches - the problem is, I have no idea how to (easily) see what is happening when I try different things, because all I have is the output to the screen and I don't have enough knowledge about postprocessing in Unity to come up with a bunch of alternative methods.

    My results have been, so far:
    1. the shader/material applies to my whole scene (what I had when I started)
    2. my whole screen is black
    3. the whole screen is black but the shader appears (but what it appears on is not in the layer mask)

    So, basically, no progress on this since I started.
     
  16. Propagant

    Propagant

    Joined:
    Nov 18, 2013
    Posts:
    32
    I've come up with a pretty nice solution (Put a lot of resources together) and it works for me! The only thing that is still problematic is transparency (as always, lol). My approach for custom fog in post-processing is as follows:

    1. Render a black and white image with filtered objects using a LayerMask.
    2. Blit the rendered black and white image into a render texture and use that render texture in a custom fog shader.
    3. The fog shader does not actually work with the scene color, but with black and white masks. So, I can use that to filter objects regarding the black/white pixel (black means *0, one means *1).
    4. I use a transition from clear black to fog color, which is determined by the depth buffer. The depth buffer is then multiplied by the mask value received from custom blit. If the value is zero, the object won't be highlighted or will ignore the fog.
    5. The most important thing to figure out is, "How do I blend this image with the scene color?" I have to apply a blending option, such as "Blend One One" (default additional) or "Blend SrcAlpha OneMinusSrcAlpha" (traditional transparency). I guess that was the trickiest part.
    6. In the final stage, I use that material to blit to the actual scene color.
    Here is my RendererFeature. I hope that helps...

    Code (CSharp):
    1. public sealed class CustomMaskRendererFeature : ScriptableRendererFeature
    2.     {
    3.         private class MaskRendererPass : ScriptableRenderPass
    4.         {
    5.             private readonly string profName;
    6.  
    7.             private readonly Material fogMaterial;
    8.             private readonly Material maskMaterial;
    9.  
    10.             private FilteringSettings filteringSettings;
    11.  
    12.             private readonly RenderTargetHandle texHandle = RenderTargetHandle.CameraTarget;
    13.             private readonly List<ShaderTagId> shaderTags = new List<ShaderTagId>
    14.             {
    15.                 new ShaderTagId("SRPDefaultUnlit"),
    16.                 new ShaderTagId("UniversalForward"),
    17.                 new ShaderTagId("UniversalForwardOnly"),
    18.                 new ShaderTagId("LightweightForward")
    19.             };
    20.  
    21.             public MaskRendererPass(string profName, Material fogMat, LayerMask layerMask)
    22.             {
    23.                 this.profName = profName;
    24.                 fogMaterial = fogMat;
    25.                 texHandle.Init("_TempFogTex");
    26.                 filteringSettings = new FilteringSettings(RenderQueueRange.all, layerMask);
    27.                 if(maskMaterial == null)
    28.                     maskMaterial = new Material(Shader.Find("Hidden/BlackMask")); // This is basically a shader that outputs just a black color, nothing else
    29.             }
    30.  
    31.             /// <summary>
    32.             /// Setup before executing for each camera
    33.             /// </summary>
    34.             public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    35.             {
    36.                 RenderTextureDescriptor cameraTextureDesc = renderingData.cameraData.cameraTargetDescriptor;
    37.                 cameraTextureDesc.depthBufferBits = 0;
    38.  
    39.                 cmd.GetTemporaryRT(texHandle.id, cameraTextureDesc, FilterMode.Bilinear);
    40.                 ConfigureTarget(texHandle.Identifier());
    41.             }
    42.  
    43.             /// <summary>
    44.             /// Execute every frame for each camera
    45.             /// </summary>
    46.             public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    47.             {
    48.                 if (fogMaterial == null)
    49.                     return;
    50.  
    51.                 CommandBuffer cmd = CommandBufferPool.Get(profName);
    52.  
    53.                 using (new ProfilingScope(cmd,
    54.                 new ProfilingSampler(profName)))
    55.                 {
    56. // Render plain image
    57.                     context.ExecuteCommandBuffer(cmd);
    58.                     cmd.Clear();
    59. // Fill the skybox
    60.                     context.DrawSkybox(renderingData.cameraData.camera);
    61.                     DrawingSettings drawSettings = CreateDrawingSettings(shaderTags, ref renderingData, SortingCriteria.CommonOpaque);
    62. // Override the current objects material with the mask material
    63.                     drawSettings.overrideMaterial = maskMaterial;
    64. // Draw the filtered objects (will appear black)
    65.                     context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings);
    66. // Push to command buffer
    67.                     context.Submit();
    68. // Blit the fog shader to the current final frame
    69.                     Blit(cmd, texHandle.Identifier(), renderingData.cameraData.renderer.cameraColorTarget, fogMaterial);
    70.                 }
    71.  
    72.                 context.ExecuteCommandBuffer(cmd);
    73.                 CommandBufferPool.Release(cmd);
    74.             }
    75.  
    76.             /// <summary>
    77.             /// Cleanup after finishing for each camera
    78.             /// </summary>
    79.             public override void OnCameraCleanup(CommandBuffer cmd)
    80.             {
    81.                 cmd.ReleaseTemporaryRT(texHandle.id);
    82.             }
    83.         }
    84.  
    85.         [Serializable]
    86.         public sealed class Settings
    87.         {
    88.             public Material fogMaterial;
    89.             public LayerMask exludeLayers;
    90.             public RenderPassEvent renderEvent = RenderPassEvent.AfterRenderingTransparents;
    91.         }
    92.  
    93.         public Settings settings = new Settings();
    94.  
    95.         private MaskRendererPass renderPass;
    96.  
    97.         /// <summary>
    98.         /// Once the feature is created
    99.         /// </summary>
    100.         public override void Create()
    101.         {
    102.             renderPass = new MaskRendererPass(name, settings.fogMaterial, settings.exludeLayers);
    103.             renderPass.renderPassEvent = settings.renderEvent;
    104.         }
    105.  
    106.         /// <summary>
    107.         /// Updated every frame
    108.         /// </summary>
    109.         public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    110.         {
    111.             renderer.EnqueuePass(renderPass);
    112.         }
    113.     }
     
    Last edited: Apr 18, 2023
  17. Propagant

    Propagant

    Joined:
    Nov 18, 2013
    Posts:
    32
    And this is my simple fog shader in post processing, just to clear your image...

    Code (CSharp):
    1. real4 frag(Varyings i) : SV_Target
    2.             {
    3. // Screen space pos
    4.                 real2 pos = i.vertex.xy / _ScreenParams.xy;
    5.  
    6. // This is the mask called _MainTex (dunno why Unity needs this specific name) pushed from the renderer feature
    7. // This mask holds b/w pixels of the filtered objects. I'm also multiplying this with some value to see the pixels more bright in some cases...
    8.                 real4 mask = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, pos) * _FogMulti;
    9.  
    10.                 real dp = SampleSceneDepth(pos);
    11.                 real depth = smoothstep(_FogStart, _FogStart + _FogEnd, saturate(dp * _FogDist));
    12.  
    13. // Shader feature for overriding skybox
    14. #ifdef _OVRDSKYBOX
    15.                 if (depth <= 0.0) _BaseColor;
    16. #else
    17.                 if (depth <= 0.0) discard;
    18. #endif
    19.  
    20. // Middle gardient feature
    21. #ifdef _MIDGRAD
    22.                 if (depth >= 1.0) return 0.;
    23.                 real dgrad = 1.0 - depth;
    24. #else
    25.                 real dgrad = 1.0;
    26.                 depth = 1.0 - depth;
    27. #endif
    28.                 return lerp(0., _BaseColor, ((dgrad * depth) * _FogIntens * mask.r));
    29.             }
    At the very top, below the SubShader or above the Pass keywords I have a blending mode Blend One One which basically blends the black and white pixels. But Blend SrcAlpha OneMinusSrcAlpha works better...
     
  18. Renegade_Wolf

    Renegade_Wolf

    Joined:
    Jan 17, 2022
    Posts:
    35
    How performant is that? I'm no expert but it seems like a lot of additional draw calls (2 + the blit?) every frame that you have fog, for every camera?
     
  19. Propagant

    Propagant

    Joined:
    Nov 18, 2013
    Posts:
    32
    Yeah, first rendering the skybox and mesh, then fog and the final blit = 3 batches.