You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
5.3 KiB
192 lines
5.3 KiB
#pragma kernel CSMain
|
|
|
|
#include "UnityCG.cginc"
|
|
#include "../../ParticleWorks/Shader/Inc/Defines.cginc"
|
|
#include "../../ParticleWorks/Shader/Inc/Math.cginc"
|
|
#include "../../ParticleWorks/Shader/Noise/noise3Dgrad.cginc"
|
|
#include "../../ParticleWorks/Shader/ParticleUniforms.cginc"
|
|
|
|
CBUFFER_START(Variables)
|
|
float timeStep;
|
|
float timeValue;
|
|
float bufferCount;
|
|
float3 coeffsA;
|
|
float3 coeffsB;
|
|
float3 coeffsC;
|
|
float3 coeffsD;
|
|
float4 FluidGridDim;
|
|
float4 FluidGridRoot;
|
|
float4 FluidGridSize;
|
|
CBUFFER_END
|
|
|
|
RWStructuredBuffer<Particle> ssbo;
|
|
RWStructuredBuffer<ParticleUniforms> uniform_buffer;
|
|
StructuredBuffer<int> home_count_buffer;
|
|
StructuredBuffer<float4> home_position_buffer;
|
|
StructuredBuffer<float4> home_velocity_buffer;
|
|
StructuredBuffer<float3> fluid_velocity_buffer;
|
|
|
|
float rand(float2 co)
|
|
{
|
|
return frac(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453);
|
|
}
|
|
|
|
float rand(float a, float b)
|
|
{
|
|
return rand(float2(a, b));
|
|
}
|
|
|
|
[numthreads(WORK_GROUP_SIZE, 1, 1)]
|
|
void CSMain(uint3 id : SV_DispatchThreadID)
|
|
{
|
|
int home_count = home_count_buffer[0];
|
|
uint idx = id.x;
|
|
Particle p = ssbo[idx];
|
|
float4 home_position = (home_count > 0) ? home_position_buffer[p.seed * home_count] : float4(0, 0, 0, 1);
|
|
float4 home_velocity = (home_count > 0) ? home_velocity_buffer[p.seed * home_count] : float4(0, 0, 0, 1);
|
|
ParticleUniforms uni = uniform_buffer[0];
|
|
|
|
float3 acc = float3(0, 0, 0);
|
|
float3 F = float3(0, 0, 0);
|
|
|
|
if (home_count > 0)
|
|
{
|
|
float duration = uni.lifeDuration * (1.0f + p.seed * uni.lifeVariation);
|
|
float current_life = p.life * duration + timeStep;
|
|
//bool is_reset = false;
|
|
//if (current_life > duration)
|
|
//{
|
|
// current_life -= duration;
|
|
// is_reset = true;
|
|
//}
|
|
//if (is_reset || p.life < 0.0f)
|
|
if (current_life > duration && uni.lifeDuration > 0.1f)
|
|
{
|
|
current_life -= duration;
|
|
//if (isEmit == 0 && current_life > 0.0) current_life -= duration;
|
|
p.position = home_position.xyz;
|
|
p.color.rgb = float3(1, 1, 1);
|
|
//p.velocity = home_velocity.xyz * 20.0f * pow(length(home_velocity.xyz), 2.0f);
|
|
p.velocity = home_velocity.xyz * 100.0f * uni.homeStrength;
|
|
//p.velocity = forceDirection * 3.0f;
|
|
}
|
|
p.life = current_life / duration;
|
|
}
|
|
|
|
// noise
|
|
{
|
|
//float n_seed = p.seed * 0.12f;
|
|
//float time_seed = timeValue * noiseTimeScale;
|
|
float3 np = p.position * uni.noiseFrequency;
|
|
float3 n1, n2;
|
|
snoise(np, n1);
|
|
snoise(np + float3(uni.noiseSeed, p.seed * 0.12f, timeValue * uni.noiseTimeScale), n2);
|
|
F = cross(n1, n2);
|
|
acc += F * uni.noiseStrength;
|
|
}
|
|
|
|
// convergence
|
|
{
|
|
F = -p.position;
|
|
acc += F * uni.convergence;
|
|
}
|
|
|
|
// home as tangential
|
|
/*
|
|
{
|
|
F = cross(p.position, float3(0, 1, 0));
|
|
float d = clamp(abs(p.position.y), 1, 100);
|
|
F = normalize(F) * 10.0f / pow(d, 2 * 2);
|
|
acc += F * uni.homeStrength;
|
|
}
|
|
*/
|
|
// force
|
|
{
|
|
F = float3(0, 0, 0);
|
|
if (length(uni.forceDirection) > 0.1f)
|
|
F = normalize(uni.forceDirection) * 10.0f;
|
|
acc += F * uni.forceStrength;
|
|
}
|
|
|
|
// impulse
|
|
{
|
|
//F = uni.impulsePosition - p.position;
|
|
//float mag = F.x*F.x + F.y*F.y + F.z*F.z;
|
|
//float rad2 = uni.impulseRadius * uni.impulseRadius;
|
|
//acc += F * exp(-mag / rad2) * uni.impulseStrength;
|
|
}
|
|
|
|
// fluid
|
|
{
|
|
float3 dim = ((p.position - FluidGridRoot) / FluidGridSize) * FluidGridDim;
|
|
dim = clamp(dim, float3(0, 0, 0), FluidGridDim - 1);
|
|
int idx = (int)dim.x + (int)dim.y * FluidGridDim.x + (int)dim.z * FluidGridDim.x * FluidGridDim.y;
|
|
float3 F = fluid_velocity_buffer[idx].xyz * 5.0f;
|
|
acc += F * uni.impulseStrength;
|
|
}
|
|
|
|
|
|
acc *= uni.movement;
|
|
p.velocity += acc * timeStep;
|
|
p.position += p.velocity * timeStep;
|
|
|
|
//float damping = lerp(0.965f, 0.985f, p.seed) * velocityDamping;
|
|
p.velocity *= lerp(0.965f, 0.985f, p.seed) * uni.velocityDamping;
|
|
|
|
// calculate rotate quat
|
|
{
|
|
float vel = length(p.velocity);
|
|
float a = (1 + p.seed) * vel * 0.05f;
|
|
float4 q = quat_from_axis_angle(normalize(p.velocity + float3(0, FLT_EPSILON, 0)), a);
|
|
q = quat_mult(p.quat, q);
|
|
q = normalize(q);
|
|
p.quat = lerp(p.quat, q, saturate(vel - 0.01f));
|
|
}
|
|
|
|
// calculate model matrix
|
|
{
|
|
//float life = saturate(p.life);
|
|
//float th = 0.05f;
|
|
//size = (life < th) ? (life / th) : ((1.0 - life) / (1.0 - th));
|
|
//size = lerp(1, sin(size * UNITY_HALF_PI), any(uni.lifeDuration));
|
|
float size = sin(saturate(p.life / 0.1f) * UNITY_HALF_PI);
|
|
size = lerp(1, size, any(uni.lifeDuration));
|
|
|
|
size *= uni.geomSize * lerp(0.5, 1.0, rand(p.seed, 5.4687));
|
|
if (idx > (uint)(uni.numRate * bufferCount) || (p.life < 0.0f && uni.lifeDuration > 0.1f))
|
|
{
|
|
size = 0.0f;
|
|
}
|
|
|
|
float4x4 mat = make_translation_matrix(p.position);
|
|
//mat = mul(mat, quat_to_rotation_matrix(p.quat));
|
|
mat = mul(mat, quat_to_rotation_matrix(float4(0, p.quat.y, 0, 1)));
|
|
mat = mul(mat, make_scaling_matrix(size));
|
|
p.model_matrix = mat;
|
|
}
|
|
|
|
// ground collision
|
|
{
|
|
float3 pos = mul(p.model_matrix, float4(p.position, 1.0f)).xyz;
|
|
pos = p.position;
|
|
if (pos.y < 0.0f)
|
|
{
|
|
p.velocity.y = abs(p.velocity.y) * 0.8f;
|
|
p.position.y = 0.0f;
|
|
}
|
|
}
|
|
|
|
// cosine gradient
|
|
{
|
|
float t = (uni.lifeDuration > 0.1f) ? clamp(p.life, 0.0f, 1.0f) : rand(p.seed, 1.2487);
|
|
half3 rgb = cosine_gradient(coeffsA, coeffsB, coeffsC, coeffsD, t);
|
|
#if !defined(UNITY_COLORSPACE_GAMMA)
|
|
rgb = GammaToLinearSpace(rgb);
|
|
#endif
|
|
p.color.rgb = rgb;
|
|
}
|
|
|
|
p.color.a = cos(saturate(p.life) * UNITY_HALF_PI);
|
|
|
|
ssbo[id.x] = p;
|
|
}
|
|
|