Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
5
Question by GlitchEnzo2 · Dec 02, 2010 at 10:46 PM · gpudisplacementvertexshaderisvisiblefrustrumculling

Disable Frustum Culling?

Is there a way to disable frustum culling on specific objects? Or perhaps disable it entirely?

I'm displacing the vertices in my mesh in a vertex shader. They are displaced to the extent that the original mesh (on the CPU side) is out of the view frustum, whereas the displaced vertices (on the GPU side) ARE in the view frustum. This causes the mesh to suddenly stop rendering and disappear, which is obviously not the desired behavior.

I tried solving this by overriding the OnBecameInvisible() method and forcing the renderer to be enabled, but that did nothing. (I had thought that the frustum culling disabled the renderer, but that is not the case.)

I wish the isVisible field on the renderer was able to be set. I feel that would solve this issue. Any other ideas?

Update: I thought about forcing the bounds on the renderer to be the same size as the maximum displacement, but the bounds property is read-only too.

I then tried having a second camera in the scene that is static and moved back enough to always have the displaced mesh in view, but that didn't work either. Apparently each camera does it's own frustum culling, which makes sense.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

10 Replies

· Add your reply
  • Sort: 
avatar image
5
Best Answer

Answer by Lemon · Apr 14, 2011 at 04:32 AM

I have also had issues with the frustum culling taking place too early / incorrectly. When using the exact same code, the frustum would cull early if the Initialization of the GameObject took place in my Update() call rather than Start(). Very strange. I changed the bounds size to be extremely large and less culling occurred, but it was still bad. When I moved the bounds center to the center of the frustum, it worked every time. To move the frustum I placed the following code at the end of my Update() - after the mesh modification:

Transform camTransform = Camera.main.transform;
float distToCenter = (Camera.main.farClipPlane - Camera.main.nearClipPlane) / 2.0f;
Vector3 center = camTransform.position + camTransform.forward * distToCenter;
float extremeBound = 500.0f;
MeshFilter meshFilter = frontRenderer.GetComponent<MeshFilter>();
meshFilter.sharedMesh.bounds = new Bounds (center, new Vector3.one * extremeBound);

Obviously if you need the bounds for anything else you'll run into problems and will want to make a backup before you force the change.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
16

Answer by H-Alex · Sep 12, 2017 at 08:57 AM

@GlitchEnzo2

I'm pretty sure the best solution here is to use the cullingMatrix (the matrix used for culling only) which should normally be equal to projection * worldToCameraMatrix.

I'm exactly in your case changing vert position in a shader and I wrote this script :

 public class DisableFrustrumCulling : MonoBehaviour
 {
     private Camera cam;
 
     void Start()
     {
         cam = this.GetComponent<Camera>();
     }
 
     void OnPreCull()
     {
         cam.cullingMatrix = Matrix4x4.Ortho(-99999, 99999, -99999, 99999, 0.001f, 99999) * 
                             Matrix4x4.Translate(Vector3.forward * -99999 / 2f) * 
                             cam.worldToCameraMatrix;
     }
 
     void OnDisable()
     {
         cam.ResetCullingMatrix();
     }
 }

What is does is create a cullingMatrix equivalent to the culling matrix that would be built by Unity with a camera moved back from your actual point of view and a gigantic orthogonal frustrum (you could use a perspective projection, it's equivalent as soon as all objects are in the frustrum).

When you want to enable frustrum culling again, you disable the script.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Sep 12, 2017 at 11:01 AM 0
Share

The culling$$anonymous$$atrix has been introduced around Unity 5.4. He asked the question in Dec 2010 around that time we had Unity version 2.6

avatar image H-Alex Bunny83 · Sep 12, 2017 at 11:05 AM 2
Share

I do hope that if he's still working on his software he did upgrade Unity. If he's not maybe this will help someone with the same problem with recent version of Unity. This is the main post when doing a google search on the subject, so I'm sure it's worth keeping this up to date.

avatar image Zyblade Bunny83 · Nov 07, 2020 at 03:58 PM 1
Share

Well, this answer hub is for everyone and it just helped me to solve a very annoying unity behaviour.

avatar image HeshamAkmal · Apr 16, 2020 at 11:54 AM 0
Share

Best solution for completely disabling culling without dropping a script on each GameObject in the whole game.

For projects using SRP, OnPreCull is deprecated but there's a slightly similar event. Here is what worked for me:

 using UnityEngine;
 using UnityEngine.Rendering;
 
 public class DisableCamCull : $$anonymous$$onoBehaviour
 {
     private void Start()
     {
         RenderPipeline$$anonymous$$anager.beginCameraRendering += RenderPipeline$$anonymous$$anager_beginCameraRendering;
     }
 
     private void RenderPipeline$$anonymous$$anager_beginCameraRendering(ScriptableRenderContext context, Camera camera)
     {
         Camera.main.culling$$anonymous$$atrix = $$anonymous$$atrix4x4.Ortho(-99999, 99999, -99999, 99999, 0.001f, 99999) *
                             $$anonymous$$atrix4x4.Translate(Vector3.forward * -99999 / 2f) *
                             Camera.main.worldToCamera$$anonymous$$atrix;
     }
 }
 
 
avatar image AshwinMods · Jun 25, 2020 at 12:33 PM 0
Share

Just got to know we can use Separate matrix for culling, which doesn't have to be equal to projection. It's awesome, Thanks a lot mate.

avatar image Zyblade · Nov 07, 2020 at 03:59 PM 0
Share

Thanks for posting that! Helped me quite a lot for a current problem =)

avatar image
8

Answer by EeroH · Dec 25, 2012 at 05:16 PM

After fighting with a similar issue (displacement in the vertex shader), I found a possible solution to change the bounds: Replace your model's MeshRenderer with SkinnedMeshRenderer, which is actually ment to be used with animated meshes that have larger bounds than the mesh itself.

One way to get a SkinnedMeshRenderer component automatically generated for your mesh, is to create one (useless) bone/armature parented to your mesh in your 3d modelling software. Then in Unity, import the rig for the model as well (you don't need to import animations, at least not in Unity 4). When you have the model in the project hierarchy, you can even disable the animator component and the armature/bone gameobject (everything animation-related excess except for SkinnedMeshRenderer itself. Deleting those seems to cause problems, though). There may be an other way to create a proper SkinnedMeshRenderer, but I don't know yet if it's possible just by scripting.

Now, the trick is that SkinnedMeshRenderer has a localBounds member that can be changed. This is because an animated model may move/change inside its boundaries. Supposing that you know the maximum bounds (or maximum displacement as you mentioned) for your model, you can initialize the renderer with proper bounds once (in OnEnable(), for example):

 // Get the SkinnedMeshRenderer component
 skinnedMeshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
 
 // Create and set your new bounds
 Bounds newBounds = new Bounds(myMaxBoundsCenter, myMaxBoundsSize);
 skinnedMeshRenderer.localBounds = newBounds;
 

As a result, the rendering will use these bounds for frustum culling, and you don't have to worry about the bounds after initializing them once. A nice thing about SkinnedMeshRenderer is also that it shows the actual AABB bounding box in the editor, so it's easy to see if the runtime-set boundaries are correct.

This solution took a while to come up with, but at least so far it has worked like a charm.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image mbbmbbmm · Oct 10, 2016 at 12:59 PM 0
Share

Very comfortable solution! It's also possible to just add a Skinned $$anonymous$$esh Renderer component to the object in Unity (don't forget to remove the original $$anonymous$$esh Filter and $$anonymous$$esh Renderer components) and then assign the mesh to the corresponding field. Only thing to keep in $$anonymous$$d is that meshes must be named in a recognizable way to be able to reassign them in the editor. And also Skinned $$anonymous$$esh Renderers won't be batched as far as I know.

avatar image
6

Answer by allenwp · Dec 20, 2013 at 02:25 PM

Lemon, your answer looks pretty close, but doesn't work out of the box for me. I just made a blog post answering this question:

http://allenwp.com/blog/2013/12/19/disabling-frustum-culling-on-a-game-object-in-unity/

 // boundsTarget is the center of the camera's frustum, in world coordinates:
 Vector3 camPosition = camera.transform.position;
 Vector3 normCamForward = Vector3.Normalize(camera.transform.forward);
 float boundsDistance = (camera.farClipPlane - camera.nearClipPlane) / 2 + camera.nearClipPlane;
 Vector3 boundsTarget = camPosition + (normCamForward * boundsDistance);
 
 // The game object's transform will be applied to the mesh's bounds for frustum culling checking.
 // We need to "undo" this transform by making the boundsTarget relative to the game object's transform:
 Vector3 realtiveBoundsTarget = this.transform.InverseTransformPoint(boundsTarget);
 
 // Set the bounds of the mesh to be a 1x1x1 cube (actually doesn't matter what the size is)
 Mesh mesh = GetComponent<MeshFilter>().mesh;
 mesh.bounds = new Bounds(realtiveBoundsTarget, Vector3.one);
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image xuancoolcat2 · Oct 21, 2015 at 05:36 AM 2
Share

Thanks. Ins$$anonymous$$d, I used the solution of the comment in the link. Just enlarge the bounds of mesh. Simplest and works enough to me now.

 float boundwidth = 500.0f;
 model$$anonymous$$esh.bounds = new UnityEngine.Bounds(new Vector3(0,0,0), new Vector3(1,1,1) * boundwidth);



avatar image zero4444 xuancoolcat2 · Sep 04, 2019 at 11:10 PM 0
Share

This still works. Only 2 lines of code.

avatar image
5

Answer by soulburner · Mar 01, 2017 at 03:47 PM

Spent 2 days trying to solve this problem.

And I found the solution!!! The key is:

 camera.cullingMatrix

My final solution is:

 public void OnPreCull()
     {
         _camera.ResetCullingMatrix();
         Matrix4x4 m = _camera.cullingMatrix;
         m.SetRow(0, m.GetRow(0)*0.5f);
         m.SetRow(1, m.GetRow(1)*0.5f);
         _camera.cullingMatrix = m;
     }

Don't ask me why I'm multiplying two rows by 0.5f. I don't know how that matrix works, so I had to experiment :)

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Piyush_Mishra · Apr 17, 2021 at 12:39 PM 0
Share

Worked like a charm. Thanks.

  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Modify water displacement 0 Answers

iPhone Performance Question relating to CPU-WAITS-GPU 1 Answer

Porting DXSDK GPU Bitonic Sort to Unity 3 Answers

for a 2d background, sprite or a quad with shader, would be best? 0 Answers

GPU Memory : Impact of Grayscale Textures 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges