Search Unity

Feedback Scriptable Culling in SRP Should be Much Easier to Work With

Discussion in 'General Graphics' started by equalsequals, Jun 25, 2021.

  1. equalsequals

    equalsequals

    Joined:
    Sep 27, 2010
    Posts:
    154
    I have been working on a subset of features for our custom SRP which has been heavily reliant on getting "special" CullingResults, and I have found a number of really frustrating pain points.

    First, it seems that no matter what, a Camera Component needs to be involved at some point during the Culling process. If I simply create a ScriptableCullingParameters without involving a Camera by way of TryGetCullingParameters, Unity will hard crash when I perform a Cull. I believe I have tracked this down to the CameraProperties in ScriptableCullingParameters not being able to be defined correctly without first getting it directly from a Camera. This feels very broken since I can query a Cull through the ScriptableRenderContext at any time outside of the scope of any Camera. I would assume that I should just be able to query based on a set of View & Projection Matrices (read: culling matrix) and the CullingOptions flag.

    Secondly, it appears that simply setting the cullingMatrix does NOT update the culling planes, and instead I must do the following, which I found in this thread:

    Code (CSharp):
    1. Plane[] planes = GeometryUtility.CalculateFrustumPlanes (cp.cullingMatrix);
    2.             for (int i = 0; i < 6; i++)
    3.                 cp.SetCullingPlane (i, planes[i]);
    Why? If these planes are clearly derivative of the cullingMatrix, setting this should do this for me!

    Another gripe I have is that the CullingResults are completely black box. I cannot even query the results for how many Renderers passed the Cull, let alone do anything with it other than pass it along to a couple of APIs to Draw. It would be great if I could have some native buffer access here to do something on.

    With the whole "screws on the top" methodology of SRP, the way this part of the pipeline is so closed off is very counterintuitive and makes for a lot of really bad hacky workarounds that I shouldn't have to be fighting with.

    Please fix this.
     
  2. equalsequals

    equalsequals

    Joined:
    Sep 27, 2010
    Posts:
    154
    I found this issue while trying to debug another issue with culling. Apparently isOrthographic is not set in ScriptableCullingParameters, even if the Camera which it was pulled from is?



    Seems like a bug?
     
    alexmalyutindev and apkdev like this.
  3. equalsequals

    equalsequals

    Joined:
    Sep 27, 2010
    Posts:
    154
    Upon further investigation, it seems like ScriptableCullingParameters.isOrthographic is completely irrelevant.

    Man, I love a good red herring.
     
    sabojako and apkdev like this.
  4. equalsequals

    equalsequals

    Joined:
    Sep 27, 2010
    Posts:
    154
    Bumping this thread because I have some additional input.

    A feature of Culling that I feel is lacking is the ability to use something like BatchRendererGroup.OnPerformCulling but for an arbitrary group of Renderers.

    Ideally, I would like to add any Renderers to a data structure, perhaps something like https://docs.unity3d.com/ScriptReference/CullingGroup.html where I receive a callback and can process them myself. These Renderers would then be flagged to be ignored by the core culling system because they will be handled by the delegate. This would allow me to process subsets of a given Scene's Renderers how I want for an effect without using workaround like multiple cameras.
     
    apkdev likes this.
  5. dirtypwnography2

    dirtypwnography2

    Joined:
    Sep 20, 2021
    Posts:
    14
    was this ever solved? I am having a similar problem. I need to ability to manually pick and choose which game Objects render in which camera that way player A can not see what player B has zoned for building at their city. And I know about layers, but there simply is not enough layers for every player in the game. As a result I need a way to customize what gets rendered in which camera and to what player
     
  6. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    184
    I'd also like to see this kind of functionality implemented. You should just be able to create a ScriptableCullingParameters struct with matrices, a view position, etc. There's no reason why it should need to have a camera involved. Feels like this would be a very simple thing to support, you could probably even do it with the current code with reflection, but that is never a nice work flow.

    I know there is some kind of "ScriptableCulling" system coming soon, as it's mentioned several times in HDRP code, which may fix the issue, but it seems like a weird oversight either way which makes a lot of SRP stuff feel like a hack.
     
    Bovine likes this.
  7. guoxx_

    guoxx_

    Joined:
    Mar 16, 2021
    Posts:
    55
    I completely agree with you. Another drawback of coupling the Camera and ScriptableCullingParameters is that the Camera is a MonoBehaviour, it must be instantiated in a scene that's quite awful. We definitely don't want the rendering code to change the scene assets.
     
    Arycama likes this.
  8. Fewes

    Fewes

    Joined:
    Jul 1, 2014
    Posts:
    259
    I'm going to second (third, fourth, fifth?) this. Digging more into the SRP API it is very disheartening to see functions that require passing cameras or lights as parameters with no alternatives. It really sucks when you have to bloat your render pipeline with hidden dummy cameras and the like just to be able to call certain functions.
     
    Saniell and Arycama like this.
  9. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    184
    Yeah it's quite a strange API. I just added custom reflection probes (Because the builtin reflection probes have hardcoded behaviour you can't change, HDRP has a ton of code to work around this while still using the builtin probes), and I have implemented deferred probes which store the albedo/normal/depth instead, and can then be re-lit with a simple deferred lighting pass.

    However this requires manually creating a camera per probe, both for culling objects and also for culling lights. I want to do all my light culling on the GPU and not rely on the CPU for anything, but there is no simple way to get all the active lights in the scene. (There is one method that returns an array, but that would allocate every frame, and it's undocumented) I really don't like the idea of having to add a custom AdditionalLightData component to every light, which is what HDRP does. I'm questioning why I'm even using the builtin light components at this stage, they have a lot of weird hardcoded behaviour (Eg you can't use the builtin area light type, as it is only intended for baking and will cause a lot of errors when you try to build as the code is editor only, and won't work with shadow casting)

    The API definitely needs an overhaul to allow for it to be more decoupled from builtin Camera, Light, Reflection Probe, and even renderer components. You can't implement any kind of GPU driven rendering that nicely hooks into the built in components. Which also makes techniques such as global distance fields very tricky.
     
  10. JJRivers

    JJRivers

    Joined:
    Oct 16, 2018
    Posts:
    137
    Year late for your needs likely, but if you ever make a sequel.. The solution is to Render from code to begin with, the stock rendering components really are not that flexible or useful if your needs include any of the following:

    • Need tens of thousands+ objects in the scene
    • Custom rendering behaviour such as you describe here
    • Rendering data manipulations in runtime without huge memory and performance spikes
     
  11. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    195
    When you say "render from code to begin with" what are you suggesting? DrawMesh calls? This appears to break batching. Do you mean build your own god meshes and render those?