Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 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
1
Question by vexe · Jul 24, 2015 at 01:08 AM · shadercullingfragment

Simple cut shader: determine if fragment is inside another sphere?

I'm going over the cg series here.

In the first entry under the second chapter they throw this exercise to the reader:

f you are familiar with scripting in Unity, you could try this idea: write a script for an object that takes a reference to another sphere object and assigns (using renderer.sharedMaterial.SetMatrix()) the inverse model matrix (renderer.worldToLocalMatrix) of that sphere object to a float4x4 uniform parameter of the shader. In the shader, compute the position of the fragment in world coordinates and apply the inverse model matrix of the other sphere object to the fragment position. Now you have the position of the fragment in the local coordinate system of the other sphere object; here, it is easy to test whether the fragment is inside the sphere or not because in this coordinate system all Unity spheres are centered around the origin with radius 0.5. Discard the fragment if it is inside the other sphere object. The resulting script and shader can cut away points from the surface of any object with the help of a cutting sphere that can be manipulated interactively in the editor like any other sphere.

This is what I did:

 using UnityEngine;

 [ExecuteInEditMode]
 public class CullMe : MonoBehaviour
 {
     public Transform culler;
 
     void Update()
     {
         if (!culler)
             return;
 
         var renderer = GetComponent<Renderer>();
         if (!renderer)
             return;
 
         var material = renderer.sharedMaterial;
         material.SetMatrix("_CullerSpace", culler.worldToLocalMatrix);
     }
 }

This is the shader I have:

 Shader "CGShader5"
 {
     SubShader
     {
         Pass
         {
             /*Cull Off*/
 
             CGPROGRAM
 
             #pragma vertex vert
             #pragma fragment frag
 
             uniform float4x4 _CullerSpace;
 
             struct vout
             {
                 float4 pos : SV_POSITION;
                 float4 worldpos : TEXCOORD0;
                 float4 localpos : TEXCOORD1;
                 float4 cullerpos : TEXCOORD2;
             };
 
             vout vert(float4 vertex : POSITION)
             {
                 vout _out;
                 _out.pos = mul(UNITY_MATRIX_MVP, vertex);
                 _out.localpos = vertex;
                 _out.worldpos = mul(_Object2World, vertex);
                 _out.cullerpos = mul(_CullerSpace, _out.worldpos);
                 return _out;
             }
 
             float4 frag(vout _in) : COLOR
             {
                 /*return float4(_in.cullerpos.x, _in.cullerpos.y, 0, 1);*/
 
                 if (_in.cullerpos.x > -0.5 && _in.cullerpos.x < 0.5 &&
                     _in.cullerpos.y > -0.5 && _in.cullerpos.y < 0.5 &&
                     _in.cullerpos.z > -0.5 && _in.cullerpos.z < 0.5)
                     discard;
 
                 return float4(0, 1, 0, 1);
             }
 
             ENDCG
         }
     }
 }

To use this:

  1. Create two spheres

  2. Give one of them a custom material with "CGShader5" as the material's shader.

  3. Attach CullMe.cs to the previous sphere, and assign the other sphere as 'culler'

  4. Move the two spheres close to each other

You should see something like this:

alt text

What I expect however is:

alt text

That is, I want to discard the fragments in the left sphere that are intersecting/inside of the right sphere, only those fragments!

The check in the frag function is actually doing what it should, but it's incorrect. See those non-intersecting frags that are discarded? well according to this check they should be discarded cause their 'x' local to the other sphere is less than 0.5 (contained within the radius of the other sphere)

I believe it can be solved just with this inverse model matrix without introducing any other uniform variables (like the position of the other sphere) but I'm just not seeing it...

What am I missing?

Any help is appreciated!

whatiexpect.png (78.2 kB)
whatyouget.png (93.1 kB)
Comment
Add comment · Show 3
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 · Jul 24, 2015 at 07:27 AM 0
Share

btw: I know your expected image is quickly drawn but what you would expect to see is the same as Unity already shows you with the mesh grid which is cut off at the seam where the spheres intersect.

When your culling sphere is visible you won't see any difference to a normal shader since the intersecting part is actually hidden due to z buffering. However if you disable the culling sphere's renderer or use a transparent material for it you should see the cut-out part.

avatar image vexe · Jul 24, 2015 at 07:34 AM 0
Share

I do realize that. But when I include the 'length' part it's not actually cutting anything :(

alt text

doh.png (71.3 kB)
avatar image MagicFighter96 · May 16, 2016 at 03:34 PM 0
Share

Hi I have a Problem, which bases on your Problem. I want multiple Spears not be inside each other. If I am using your shader and C# Code I would need a $$anonymous$$ind of Array of possitions, which will be checked in a loop inside the shader. Is this possible? (Full quesion here: http://answers.unity3d.com/questions/1185084/unity-overlapping-transparent-spheres.html#comment-1186541) Thank you for your time dude, even until now great work ;-)

2 Replies

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

Answer by Bunny83 · Jul 24, 2015 at 07:11 AM

You did not test the length of the vector but it's enclosing bounding box ^^. You have to handle the length like you would in Unity. There is a "length" function available in cg, so you don't need to square, add and square-root it manually.

 if (length(_in.cullerpos.xyz) < 0.5)
     discard;

edit
A square-root isn't really a problem when calculated on the GPU, but you can get rid of it like this (just don't forget to test against the squared radius):

 if (dot(_in.cullerpos.xyz,_in.cullerpos.xyz) < 0.25)
     discard;

edit
As said in the comment below another problem was that we worked with float4 values. So "length" as well as "dot" will calculate x² + y² + z² + w². Since w is 1.0 the caluclated length doesn't match the 3d length. The solution is to convert it to a float3 value and discarding w before calculating the length. I changed the examples above

Comment
Add comment · Show 8 · 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 · Jul 24, 2015 at 07:15 AM 0
Share

So the equation your position has to fullfill is this:

 (x² + y² + z² < 0.5²)

or

 (x² + y² + z² < 0.25)

or

 (sqrt(a.x² + a.y² + a.z²) < 0.5) // which is the same as: length(a) < 0.5
avatar image vexe · Jul 24, 2015 at 07:23 AM 0
Share

I did try length I should have mentioned it, it's not doing anything :(

             if (length(_in.cullerpos) < 0.5)
                 discard;

or

             if (length(_in.cullerpos) < 0.5 &&
                 _in.cullerpos.x > -0.5 && _in.cullerpos.x < 0.5 &&
                 _in.cullerpos.y > -0.5 && _in.cullerpos.y < 0.5 &&
                 _in.cullerpos.z > -0.5 && _in.cullerpos.z < 0.5)
                 discard;

not discarding the fragment, I can tell because I if I change the value I'm comparing against the legnth nothing happens.

I try to visualize the length:

             return float4(length(_in.cullerpos), 0, 0, 1);

it's always bright red even if I move the sphere closer :(

avatar image Bunny83 · Jul 24, 2015 at 08:05 AM 1
Share

:D i found the problem ^^. The problem is that we work with float4 values with a w component of 1 (since it's a position, not a direction). However that means that "length" does include the w component as well but we want the 3D euclidean length, not the 4D. So using this will work:

 if (length(_in.cullerpos.xyz) < 0.5)
     discard;
 // or
 if (dot(_in.cullerpos.xyz, _in.cullerpos.xyz) < 0.25)
     discard;

edit
I first thought there has to be something wrong with the matrix so the position is way off. But i remembered your first picture. That was the prove that the position comes out right. So the problem has to be in checking the length ^^.

avatar image vexe · Jul 24, 2015 at 08:08 AM 0
Share

GENIUS!! Sankeh Bannnehh!! :D

avatar image vexe · Jul 24, 2015 at 09:22 AM 0
Share

@Bunny83 in case you were wondering, I'm going after similar stuff as in here http://www.valvesoftware.com/publications/2010/gdc2010_vlachos_l4d2wounds.pdf - here's what I have so far:

alt text

Not perfect but getting there! :D

(Code)

gore.png (113.3 kB)
Show more comments
avatar image
0

Answer by AMAT_Sooraj · Aug 29, 2018 at 01:40 PM

I did go through it. I'm actually just starting out with shader programming and I'm unable to grasp the use of that snippet without seeing the full shader code. I need to make this shader support Standard lighting model including all the channels as well(Even in the areas that are filled up after the fragments were discarded). If you could you please post the full shader code, it would be really helpful.

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 ewoudwerf · Feb 04, 2019 at 11:58 AM 0
Share

Hey @A$$anonymous$$AT_Sooraj, a bit late to the thread, but I'm also interested in the full shader or at least I want to fill the fragments that were discarded. Did you find a solution yet?

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

26 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Culling part of a sprite in Sprite Manager 2 1 Answer

Getting a pixel's screen-space coordinate in a fragment shader 1 Answer

Shaders: Turn culling on/off by keyword 0 Answers

Distance from pixel to camera in shader 0 Answers

shader material showing over every object. 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