I tried to simulate the smoke emission process with compute shader. After calculating the density of particles with NS equation, I used ray marching to display the animation for each frame. However, the animation seems strange as below.
![alt text][1]
[1]: /storage/temp/199430-ani.png
So you can find obvious square-shaped particles on the left part while the right part looks smooth as real smoke.
I'm not sure what caused the difference and I'd appreciate any insight on it.
My HLSL code for ray marching is below:
[numthreads(8,8,1)]
void Main (uint3 id : SV_DispatchThreadID)
{
// Get the dimensions of the RenderTexture
uint width, height;
Result.GetDimensions(width, height);
// Transform pixel to [-1,1] range
float2 uv = float2((id.xy + float2(0.5f, 0.5f)) / float2(width, height) * 2.0f - 1.0f);
// Get a ray for the UVs
Ray ray = CreateCameraRay(uv);
AABB aabb;
aabb.min = float3(-0.5, -0.5, -0.5);
aabb.max = float3(0.5, 0.5, 0.5);
if (!intersection(aabb, ray)) {
Result[id.xy] = float4(0, 0, 0, 1);
return;
}
float tnear;
float tfar;
intersect(ray, aabb, tnear, tfar);
tnear = max(0.0, tnear);
float3 start = ray.origin + ray.direction * tnear;
float3 end = ray.origin + ray.direction * tfar;
float step_size = 0.01;
float3 ds = normalize(end - start) * step_size;
float curdensity = 0;
float transmittance = 1;
float3 lightenergy = 0;
float3 p = start;
float3 LightVector = normalize(float3(0, 0, -1)) * step_size;
for (int iter = 0; iter < ITERATIONS; iter++)
{
float _initialDensity = SampleLinear(p) * _density;
if (_initialDensity > 0.001)
{
float3 lpos = p;
float shadowdist = 0;
for (int s = 0; s < 50; s++)
{
lpos += LightVector;
float lsample = SampleLinear(lpos);
shadowdist += lsample;
}
//Accumulate to get the current Density
curdensity = saturate(_initialDensity);
float shadowterm = exp(-shadowdist * _shadowAmount);
lightenergy += shadowterm * curdensity * transmittance;
//Renew Transmittance
transmittance *= 1 - curdensity;
}
p += ds;
if (abs(p.x) > 0.5 || abs(p.y) > 0.5 || abs(p.z) > 0.5)
break;
}
Result[id.xy] = float4(lightenergy, transmittance);
cnt++;
}
↧