Search Unity

Shader rendering in the scene view but not the game view unless all custom shaders are culled (URP)

Discussion in 'Shaders' started by rifintidhamar, Jun 28, 2022.

  1. rifintidhamar

    rifintidhamar

    Joined:
    Jul 29, 2018
    Posts:
    2
    upload_2022-6-28_6-17-35.png

    Issue in action + more detail on the issue:


    As shown above the ember particles are rendering in the scene view (left) but not the game view (right) when the logs (which use a compute shader and graphics shader of their own) are in view. This is true for all but some far away particle(s?). However as soon as the logs are just out of view (and thus culled) the particles start rendering in game view too and the far away particle(s) are removed. In fact, the particles do not seem to render when any other custom shader is in view--besides those far away particle(s). However, it seems like only custom shaders cause this effect. When I used a built in material (ie unlit texture) the particles still render while that material is in view. These particles are calculated using a compute shader and a buffer is shared to a typical unlit shader. Like usual, a c# script sets it all up. I have tried changing the render queue and I have tried changing render type. I can't seem to figure this out. Here is the code for the particles.

    Quick warning: Still pretty new to compute shaders and shaders in general. So please be patient when I inevitably don't understand your solution. I will try my best though.

    c# script:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class phyics : MonoBehaviour
    6. {
    7.     public ComputeShader comp;
    8.     public Material mat;
    9.  
    10.     int fireHandle;
    11.     int groupCount;
    12.     int particleCount = 80;
    13.     int dtID;
    14.  
    15.     struct fireParticle
    16.     {
    17.         public float heat;
    18.         public float lum;
    19.         public float mass;
    20.         public Vector3 pos;
    21.         public Vector3 velocity;
    22.     }
    23.  
    24.     ComputeBuffer fireBuffer;
    25.     ComputeBuffer fireBufferSaved;
    26.     fireParticle[] fireArray;
    27.     int particleSize = (1 + 1 + 1 + 3 + 3) * sizeof(float);
    28.     // Start is called before the first frame update
    29.     void Start()
    30.     {
    31.         fireHandle = comp.FindKernel("emitParticle");
    32.         init();
    33.     }
    34.  
    35.     float weridRand()
    36.     {
    37.         return (Random.value - 0.5f) * 2f * (Random.value - 0.5f) * 2f;
    38.     }
    39.  
    40.     void init()
    41.     {
    42.         dtID = Shader.PropertyToID("dt");
    43.         fireArray = new fireParticle[particleCount];
    44.  
    45.         for (int i = 0; i < particleCount; i++)
    46.         {
    47.             float rand = Random.value * 0.5f + 0.5f;
    48.             fireArray[i].heat = rand;
    49.             fireArray[i].lum = rand;
    50.             fireArray[i].pos = this.transform.position + new Vector3(weridRand(), Random.value * Random.value * 2f, weridRand()) * this.transform.localScale.x;
    51.             fireArray[i].velocity = new Vector3((Random.value - 0.5f), rand, (Random.value - 0.5f)) * this.transform.localScale.x;
    52.         }
    53.  
    54.         fireBuffer = new ComputeBuffer(particleCount, particleSize);
    55.         fireBufferSaved = new ComputeBuffer(particleCount, particleSize);
    56.         fireBuffer.SetData(fireArray);
    57.         fireBufferSaved.SetData(fireArray);
    58.  
    59.         fireHandle = comp.FindKernel("emitParticle");
    60.  
    61.         uint threadGroupSizeX;
    62.         comp.GetKernelThreadGroupSizes(fireHandle, out threadGroupSizeX, out _, out _);
    63.         groupCount = particleCount / (int)threadGroupSizeX;
    64.         comp.SetBuffer(fireHandle, "parti", fireBuffer);
    65.         comp.SetBuffer(fireHandle, "partiSaved", fireBufferSaved);
    66.         mat.SetBuffer("parti", fireBuffer);
    67.     }
    68.  
    69.     void OnRenderObject()
    70.     {
    71.         mat.SetPass(0);
    72.         Graphics.DrawProceduralNow(MeshTopology.Points, 1, particleCount);
    73.     }
    74.  
    75.     // Update is called once per frame
    76.     void Update()
    77.     {
    78.         comp.SetFloat(dtID, Time.deltaTime);
    79.         comp.Dispatch(fireHandle, groupCount, 1, 1);
    80.     }
    81.  
    82.     private void OnDestroy()
    83.     {
    84.         fireBuffer.Release();
    85.         fireBufferSaved.Release();
    86.     }
    87. }
    88.  
    Compute shader:
    Code (CSharp):
    1. // Each #kernel tells which function to compile; you can have many kernels
    2. #pragma kernel logTex
    3. #pragma kernel fireParticle
    4.  
    5.  
    6. RWTexture2D<float4> Result;
    7. float dt;
    8. int texRes;
    9. float2 stretch;
    10. #include "noiseSimplex.cginc"
    11.  
    12. [numthreads(8,8,1)]
    13. void logTex (uint3 id : SV_DispatchThreadID)
    14. {
    15.     float2 pos = float2((((float2)id.xy) / (float)texRes) - 0.5);
    16.     float noise = 1 - abs(snoise(float3(pos * stretch, dt / 20)));
    17.     Result[id.xy] = noise ;
    18. }
    19.  
    Particle Shader:
    Code (CSharp):
    1. Shader "Unlit/fireParticle"
    2. {
    3.     Properties
    4.     {
    5.     }
    6.     SubShader
    7.     {
    8.         Tags {"Queue" = "Transparent - 499" "RenderType" = "Transparent" "LightMode" = "UniversalForward"}
    9.         Blend One OneMinusSrcAlpha
    10.  
    11.         Pass
    12.         {
    13.             CGPROGRAM
    14.             #pragma vertex vert
    15.             #pragma fragment frag
    16.  
    17.             #include "UnityCG.cginc"
    18.  
    19.             struct appdata
    20.             {
    21.                 float4 vertex : POSITION;
    22.             };
    23.            
    24.             struct fireParticle
    25.             {
    26.                 float heat;
    27.                 float lum;
    28.                 float mass;
    29.                 float3 pos;
    30.                 float3 velocity;
    31.             };
    32.  
    33.             StructuredBuffer<fireParticle> parti;
    34.  
    35.             struct v2f
    36.             {
    37.                 float4 pos : SV_POSITION;
    38.                 float4 lum : COLOR;
    39.             };
    40.  
    41.             v2f vert (appdata v, uint id : SV_InstanceID)
    42.             {
    43.                 v2f o;
    44.                 o.pos = UnityObjectToClipPos(float4(parti[id].pos, 1));
    45.                 o.lum = fixed4(parti[id].lum, 0.1, 0, 1);
    46.                 return o;
    47.             }
    48.  
    49.             fixed4 frag(v2f i) : SV_Target
    50.             {
    51.                 fixed4 col = i.lum;
    52.                 return col;
    53.             }
    54.             ENDCG
    55.         }
    56.     }
    57. }
    58.  
     

    Attached Files:

  2. rifintidhamar

    rifintidhamar

    Joined:
    Jul 29, 2018
    Posts:
    2
    1. OH FINALLY. It took two damn days but finally. So I will explain the issue for anyone curiousThe issue was in the particle shader near the bottom. On the line that says "o.pos = UnityObjectToClipPos(float4(parti[id].pos, 1));"The issue here is that the function takes the position from object space all the way to clip space--from object space through world space, view space, and finally into clip space.This is an issue because my particles are already in world space and thus do not need to be converted into world space, and in fact should not be.So the solution was to multiply my position by the view * projection matrix manually. Thus that line turns into " o.pos = mul(UNITY_MATRIX_VP, float4(parti[id].pos,1));"And now it works in both game view and editor view