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 :
Plane[] planes = GeometryUtility.CalculateFrustumPlanes (cp.cullingMatrix);
for (int i = 0; i < 6; i++)
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.
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?
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 Unity - Scripting API: CullingGroup 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.
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
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.
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.
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.
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.
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
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?
Bumping because I’m getting stuck with the exact same sets of issues!
Needed a way to render a bunch of Renderers with split triangles in a custom shader.
I render everything in a special CommandBuffer without using any camera. I need to cull all the Renderer who’s AABB is smaller than a certain size. I need to cull everything outside an AABB.
Either I do the culling myself, and render everything in a CommandBuffer, but I loose batching
OR
I duplicate every single renderer, put them all on a separate layer, but I don’t have any way to do per-object culling. I have 4 cascade in my system, so I can’t simply toggle on and off my duplicated renderers, and I’m wasting a layer.
Should I do the batching myself? If only the culling was a bit more scriptable.