*Issue in action + more detail on the issue*: https://youtu.be/O912PTdmFdc
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 fire particles but some far away particle(s?)**. However as soon as the logs are just out of view (and thus culled) the particles starts properly rendering in game view and the far away particle(s) are removed. In fact, the particles do not seem to render when any other unlit shader is in view--besides those far away particle(s). However, it seems like **only unlit shaders cause this effect**. 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:-------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class phyics : MonoBehaviour
{
public ComputeShader comp;
public Material mat;
int fireHandle;
int groupCount;
int particleCount = 80;
int dtID;
struct fireParticle
{
public float heat;
public float lum;
public float mass;
public Vector3 pos;
public Vector3 velocity;
}
ComputeBuffer fireBuffer;
ComputeBuffer fireBufferSaved;
fireParticle[] fireArray;
int particleSize = (9) * sizeof(float);
// Start is called before the first frame update
void Start()
{
fireHandle = comp.FindKernel("emitParticle");
init();
}
float weridRand()
{
return (Random.value - 0.5f) * 2f * (Random.value - 0.5f) * 2f;
}
void init()
{
dtID = Shader.PropertyToID("dt");
fireArray = new fireParticle[particleCount];
for (int i = 0; i < particleCount; i++)
{
float rand = Random.value * 0.5f + 0.5f;
fireArray[i].heat = rand;
fireArray[i].lum = rand;
fireArray[i].pos = this.transform.position + new Vector3(weridRand(), Random.value * Random.value * 2f, weridRand()) * this.transform.localScale.x;
fireArray[i].velocity = new Vector3((Random.value - 0.5f), rand, (Random.value - 0.5f)) * this.transform.localScale.x;
}
fireBuffer = new ComputeBuffer(particleCount, particleSize);
fireBufferSaved = new ComputeBuffer(particleCount, particleSize);
fireBuffer.SetData(fireArray);
fireBufferSaved.SetData(fireArray);
fireHandle = comp.FindKernel("emitParticle");
uint threadGroupSizeX;
comp.GetKernelThreadGroupSizes(fireHandle, out threadGroupSizeX, out _, out _);
groupCount = particleCount / (int)threadGroupSizeX;
comp.SetBuffer(fireHandle, "parti", fireBuffer);
comp.SetBuffer(fireHandle, "partiSaved", fireBufferSaved);
mat.SetBuffer("parti", fireBuffer);
}
void OnRenderObject()
{
mat.SetPass(0);
Graphics.DrawProceduralNow(MeshTopology.Points, 1, particleCount);
}
// Update is called once per frame
void Update()
{
comp.SetFloat(dtID, Time.deltaTime);
comp.Dispatch(fireHandle, groupCount, 1, 1);
}
private void OnDestroy()
{
if (fireBuffer != null)
{
fireBuffer.Release();
fireBufferSaved.Release();
}
}
}
Compute shader:----------------------------------------
// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel emitParticle
struct fireParticle
{
float heat;
float lum;
float mass;
float3 pos;
float3 velocity;
};
RWStructuredBuffer parti;
StructuredBuffer partiSaved;
float dt;
void respawn(uint id)
{
parti[id].pos = partiSaved[id].pos;/
parti[id].heat = partiSaved[id].heat;
parti[id].lum = partiSaved[id].lum;
}
[numthreads(8, 1, 1)]
void emitParticle(uint3 id : SV_DispatchThreadID)
{
parti[id.x].heat -= dt / 2;
parti[id.x].lum -= dt / 10;
parti[id.x].pos += parti[id.x].velocity * dt;
if (parti[id.x].heat < 0.1)
respawn(id.x);
}
Particle shader:----------------------------------------------
Shader "Custom/fireParticle"
{
Properties
{
}
SubShader
{
Tags {"Queue" = "Geometry" "RenderType" = "LoadCunt"}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct fireParticle
{
float heat;
float lum;
float mass;
float3 pos;
float3 velocity;
};
StructuredBuffer parti;
struct v2f
{
float4 pos : SV_POSITION;
float4 lum : COLOR;
};
v2f vert (appdata v, uint id : SV_InstanceID)
{
v2f o;
o.pos = UnityObjectToClipPos(float4(parti[id].pos, 1));
o.lum = fixed4(parti[id].lum, 0.1, 0, 1);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = i.lum;
return col;
}
ENDCG
}
}
}
↧