- Home /
Scissor test/early rejection
Is it possible to reject fragments from a camera's rendering pipeline through either a scissor test, early rejection, or anything else? I need a camera to only render part of what it can see for performance reasons and no matter what I do I just absolutely cannot figure it out.
Answer by MCudlitz · Dec 11, 2016 at 02:13 AM
To those that responded to this topic, and to tothers: Thank you for trying to answer, but unfortunately that scissor script isn't capable of increasing performance like I was looking for- it merely modifies the matrix, the number of fragments being drawn is still the same and unless I wanted to have a dynamically-allocated RT (which is expensive) what I wanted to do would not be possible. To solve this problem, I manually drew a mesh using a command buffer with a material on it that writes to the stencil, then it blits a fullscreen mat that writes 1 to the depth buffer on all but the stenciled area. This fires during BeforeForwardOpaque, which rejects fragments from being rendered that are not visible.
Here is the commandbuffer code:
_stencilBuffer.Clear();
stencilObj.transform.position = targetPortal.transform.position;
stencilObj.transform.rotation = targetPortal.transform.rotation;
stencilObj.transform.Rotate(Vector3.up, 180, Space.Self);
//stencilObj.transform.localScale = transform.lossyScale + new Vector3(0.01f, 0, 0);
stencilObj.transform.localScale = transform.lossyScale + new Vector3(0, 0, 0.01f);
_stencilBuffer.DrawMesh(gameObject.GetComponent<MeshFilter>().mesh, stencilObj.transform.localToWorldMatrix, depthHole);
_stencilBuffer.Blit(BuiltinRenderTextureType.CurrentActive, BuiltinRenderTextureType.CurrentActive, depthMat);
I'm not sure if i got your approach right, but relying on the depth test to reduce the processed fragments won't help much in most cases. Usually the depth test is applied after your fragment shader has run. See this page about the special feature that you would need.
Are you sure you actually tried the script i've linked below? To be honest, i didn't. However it does not just modify the projection matrix. It also sets the camera viewport rect to your specified rectangle. So the camera only draws that portion of the screen and nothing more. Clipping is applied before the rasterization and therefore before your fragment shader.
I'm just wondering: What does your fragment shader do that is so heavy that it becomes a bottleneck?
Thanks for your reply!
The issue that I'm facing is a little unique- I want to be able to scissor out the unneeded renderers, as the camera is rendering a portal effect. Unfortunately, due to this there are some restrictions, with the big one being that any solution has to be applicable to an existing camera matrix. The reason for this is due to the fact that the portals are VR-Enabled, meaning that each eye's matrix is different. Furthermore, the matrix is oblique at the near plane to prevent portals from rendering what is behind them which just makes everything more complicated.
I'll admit, I didn't actually open the script (I thought it was the same one that I've seen posted a hundred times before) but upon opening it, it seems to unfortunately only generate new matrices without being able to modify existing ones which unfortunately doesn't help me. (it may be applicable to a general application as well but I have to admit that my linear algebra isn't that great)
The reason that my test saved render time was apparently due to particle effects, which were effectively culled out. However, it seems like everything else is "culled" (it appears to save a bit of time on the fragment shading) too late, which means that I'm either not hitting that early depth rejection like I thought I was or something else is up.
Unfortunately, this isn't really an easy problem to solve. If I were to modify the camera's view frustum, it would likely result in skewed FOV and portals that don't look right. I wish it were possible to do a simple AABB test on all renderers within the frustum planes, but Unity's geometry is one renderer until Umbra gets its paws on it, so I can't really work with that.
I really wish that Unity was more open about how this stuff works.
I see. Have you tried to integrate those five lines in the projection matrix creation for your cameras? The script actually doesn't create a new absolute matrix but modifies the default projection matrix. The problem is that the script calls "ResetProjection$$anonymous$$atrix" so it gets the default matrix which it modifies. When you set already a custom matrix, that of course would replace your custom matrix. However you can try to perform the same modifications on your custom matrix (without the "ResetProjection$$anonymous$$atrix" of course ^^).
Since your scissor rect most likely can change every frame you would need to recreate the projection matrix every frame. Though that's probably already the case ^^.
Answer by Bunny83 · Nov 27, 2016 at 05:08 PM
Currently Unity's shaderlab syntax doesn't support hardware scissor tests. However you can use this Scissor script which has been posted on this forum thread to modify the projection matrix of your camera.
Other than that you could write a shader where you can pass scissor planes or a scissor rect as parameter. Of course you have to do the clipping yourself inside the fragment shader. One 3d plane can be represented by a single Vector4 (normal vector + distance).
I'm not sure how Unity actually implements it's frustum culling. If it uses the camera's actual projection matrix then the Scissor script would be much more effective as Unity would already filter out objects which bounds are outside the view frustum so they aren't send to the GPU at all.
Thank you for trying to answer, unfortunately it didn't help. See my response for details.
Your answer
Follow this Question
Related Questions
Is there a way to write a Demosaicing fragment shader? 1 Answer
Saving Texture at Run time and Reusing it 0 Answers
Best way to convert particles and sprites in a single sprite at runTime 1 Answer
Reflect Fresnel Mobile VR 0 Answers
How to maintain sharp lines (pixel-like effect) from small textures on 3D assets 2 Answers