Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Cull Pixels Inside Overlapping Primitive

Discussion in 'Shader Graph' started by adamgffrd, Mar 5, 2022.

  1. adamgffrd


    Sep 26, 2018
    Re-posting this here as I originally posted in HDRP forum and have 0 responses as of yet.

    Hello Unity Community,

    Using HDRP 2021.2.0b15.3666

    Is it possible to cull pixels that fall inside of another overlapping primitive. So you have Sphere A with culling Shader on it along with a Cullme script, then Sphere B touches/overlaps a portion of Sphere A. All pixels from Sphere A, that fall inside Sphere B, then get culled off of Sphere A. Sphere B is transparent.

    I am very determined to continue working inside HDRP and really could use a nudge in the right direction with this. I am trying to recreate the L4D effect of culling a mesh and then showing another mesh hidden underneath (insides).

    I got this half working with a CGPROGRAM shader file copied from another user (sorry I don't recall the source). Tried adding that to a Custom Node (String and File) in Shader Graph and hitting a wall. Do I need to sign up for Unity HDRP Shader Classes or is this something someone here can help me with? Is that even a thing? If I wanted to pay someone to make this as an HDRP LIT shader that can be culled, where would I post for that?

    Attached is a zip file of a short video showing the CGPROGRAM shader in action, in this HDRP project.

    Any help is appreciated. :)

    Code (CSharp):
    1.      Shader "CGShader5"
    2.          {
    3.              SubShader
    4.              {
    5.                  Pass
    6.                  {
    7.                      /*Cull Off*/
    9.                      CGPROGRAM
    11.                      #pragma vertex vert
    12.                      #pragma fragment frag
    14.                      uniform float4x4 _CullerSpace;
    16.                      struct vout
    17.                      {
    18.                          float4 pos : SV_POSITION;
    19.                          float4 worldpos : TEXCOORD0;
    20.                          float4 localpos : TEXCOORD1;
    21.                          float4 cullerpos : TEXCOORD2;
    22.                      };
    24.                      vout vert(float4 vertex : POSITION)
    25.                      {
    26.                          vout _out;
    27.                          _out.pos = UnityObjectToClipPos(vertex);
    28.                          //_out.pos = mul(Unity_Matrix_VP, Unity_ObjectToWorld), (vertex);
    29.                          _out.localpos = vertex;
    30.                          _out.worldpos = mul(unity_ObjectToWorld, vertex);
    31.                          _out.cullerpos = mul(_CullerSpace, _out.worldpos);
    32.                          return _out;
    33.                      }
    35.                      float4 frag(vout _in) : COLOR
    36.                      {
    37.                          /*return float4(_in.cullerpos.x, _in.cullerpos.y, 0, 1);*/
    39.                          if (_in.cullerpos.x > -0.5 && _in.cullerpos.x < 0.5 &&
    40.                              _in.cullerpos.y > -0.5 && _in.cullerpos.y < 0.5 &&
    41.                              _in.cullerpos.z > -0.5 && _in.cullerpos.z < 0.5)
    42.                              discard;
    44.                          return float4(0, 1, 0, 1);
    45.                      }
    47.                      ENDCG
    48.                  }
    49.              }
    50.          }

    Code (CSharp):
    1.  using UnityEngine;
    2. [ExecuteInEditMode]
    3. public class CullMe : MonoBehaviour
    4. {
    5.      public Transform culler;
    6.      void Update()
    7.      {
    8.          if (!culler)
    9.              return;
    10.          var renderer = GetComponent<Renderer>();
    11.          if (!renderer)
    12.              return;
    13.          var material = renderer.sharedMaterial;
    14.          material.SetMatrix("_CullerSpace", culler.worldToLocalMatrix);

    From the time I posted this, I have been experimenting with different approaches. One that has gotten me the closest results is from here:


    The problem is that I can only get it working on a plane right now. I want to get it working on a sphere so that ONLY INTERSECTING PIXELS get culled, not the entire model. When I swapped in a sphere for the plane, it wasn't actually doing it based off the intersection but rather the planes position and normal vector.

    My thoughts at this point are that I need to figure out the equivalent for the CGSHADER which does exactly what I want. However, I am running into a roadblock with figuring out how to replicate the logic inside Shadergraph. I was thinking that I need to be using a Custom Node in shadergraph and feed in the Intersecting TEXCOORD's ...... somehow. Isn't there a way to just reference this File in the Custom Node and have it work that way?

    Does anyone know of any working examples I can look at or if there is a tutorial you know of that can help me along in this pursuit? Anything? I am all for putting in the leg work, I just need a little guidance please. The end goal is to instantiate a transparent mesh onto another mesh, and then cull the intersecting pixels.
    Last edited: Mar 5, 2022
  2. adamgffrd


    Sep 26, 2018
    Taking a Jettely course which specifically goes over how to create/configure the Custom Node and create the HLSL file from scratch to input the values/functions. Hoping to have a rough draft done by tomorrow afternoon and will post the final result then. :)
  3. adamgffrd


    Sep 26, 2018
    I am convinced that this just isn't possible. I have tried messing around with replicating the CGSHADER5 functions in ShaderGraph. The closest I have come is to cut the entire mesh at once, not one section of the mesh based on where another object intersects. Another version takes the POSITION node and then try's to subtract it from the UV node but that shows the seams and I didn't get the Intersection part to work. Spent three day's off researching and trying to replicate this effect.

    I had already created another effect that uses Forward Rendering and partially achieves the effect I want. The problem is that it creates a new mesh on-top of the existing mesh and just adds more to the scene, rather than have a shader just cull the pixels away. Also I need to figure out how to wrap the top mask to the mesh so it can compensate for non flat surfaces. And how to merge it with existing scars when they overlap eachother.

    From here I think I will just table it and when I have more time off I will try to merge the CGSHADER5 code directly into an HDRP shader or maybe URP instead. Looks like the URP code is easier to work with. Maybe I will try creating a new project in URP and copy pasta that code into the URP shader and mess around with that.

    Attached Files: