Skip to content

Commit

Permalink
Initial commit with SDF rendering + mutate + physics.
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelbigos committed Feb 17, 2021
0 parents commit 836023d
Show file tree
Hide file tree
Showing 182 changed files with 29,755 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.vs*
Build/
Library/
Logs/
obj/
UserSettings/
WebGL/
Temp/
LocalPackages/
*.csproj
*.sln
8 changes: 8 additions & 0 deletions Assets/Compute.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

129 changes: 129 additions & 0 deletions Assets/Compute/BoidPhysics.compute
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#pragma kernel Step

struct Boid
{
float3 position;
float3 velocity;
float radius;
};

float3 _planetCentre;
float _timeStep;
float _gravity;

Texture3D<float> _sdfTex;
SamplerState sampler_sdfTex;
float _sdfRadius;
float _sdfDistMod;

int _numBoids;
RWStructuredBuffer<Boid> _boidBufferIn;
RWStructuredBuffer<Boid> _boidBufferOut;

float sdf(float3 uv)
{
uv /= (_sdfRadius * 2.0);
uv += float3(0.5, 0.5, 0.5);
float sdf = _sdfTex.SampleLevel(sampler_sdfTex, uv, 0);
sdf = (sdf * 2.0) - 1.0;
sdf *= (_sdfRadius * 2.0);
sdf *= _sdfDistMod;
return sdf;
}

float3 projectUonV(float3 u, float3 v)
{
float3 r;
r = v * (dot(u, v) / dot(v, v));
return r;
}

float3 calcNormal(float3 p)
{
float h = 0.001;
float2 k = float2(1, -1);
return normalize(k.xyy * sdf(p + k.xyy * h) +
k.yyx * sdf(p + k.yyx * h) +
k.yxy * sdf(p + k.yxy * h) +
k.xxx * sdf(p + k.xxx * h));
}

[numthreads(1,1,1)]
void Step (uint3 id : SV_DispatchThreadID)
{
Boid boid = _boidBufferIn[id.x];

// collide with other boids
for (uint i = 0; i < (uint)_numBoids; i++)
{
if (i == id.x)
continue;

float3 p0 = boid.position;
float3 p1 = _boidBufferIn[i].position;
float3 v0 = boid.velocity;
float3 v1 = _boidBufferIn[i].velocity;
float r0 = boid.radius;
float r1 = _boidBufferIn[i].radius;

float dist = distance(p0, p1);
float r = r0 + r1;
float diff = dist - r;
if (diff <= 0.0) // hit
{
float3 mov = diff * 0.5 * normalize(p1 - p0);
boid.position += mov;
p0 = boid.position;

float3 nv0 = v0;
nv0 += projectUonV(v1, p1 - p0);
nv0 -= projectUonV(v0, p0 - p1);
boid.velocity = nv0 * 1.0;
}
}

float dist = sdf(boid.position.xyz) - boid.radius;

// collide with planet
{
float3 toSurface = -calcNormal(boid.position);

float3 p0 = boid.position;
float3 p1 = boid.position + toSurface * (dist + boid.radius);
float3 v0 = boid.velocity;
float3 v1 = 0.0;
float r0 = boid.radius;
float r1 = 0.0;

float dist = distance(p0, p1);
float r = r0 + r1;
float diff = dist - r;
if (diff <= 0.0) // hit
{
float3 mov = diff * 0.5 * normalize(p1 - p0);
boid.position += mov;
p0 = boid.position;

float3 nv0 = v0;
nv0 += projectUonV(v1, p1 - p0);
nv0 -= projectUonV(v0, p0 - p1);
boid.velocity = nv0 * 1.0;
}

/*float3 toSurface = -calcNormal(boid.position);
float onPlanet = 1.0 - step(0.0, dist + 0.0001);
float speed = length(boid.velocity) * 0.4;
float normComponent = dot(boid.velocity, toSurface.xyz);
boid.velocity += (normComponent * -toSurface) * onPlanet;
boid.velocity += -toSurface * speed * onPlanet;*/
}

// gravity
float3 toPlanet = normalize(_planetCentre - boid.position);
float3 gravity = toPlanet * _gravity;
boid.velocity += gravity * _timeStep;

boid.position = boid.position + boid.velocity * _timeStep;

_boidBufferOut[id.x] = boid;
}
9 changes: 9 additions & 0 deletions Assets/Compute/BoidPhysics.compute.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions Assets/Compute/SDFGen.compute
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma kernel SDFGen

RWTexture3D<float> _sdfTex;
uint _sdfTexSizeX;
uint _sdfTexSizeY;
uint _sdfTexSizeZ;
float _sdfRadius;
float _sdfDistMod;
float _sphereRadius;

float sdSphere(float3 pos, float radius)
{
return length(pos) - radius;
}

[numthreads(8,8,8)]
void SDFGen(uint3 id : SV_DispatchThreadID)
{
float3 uv = float3(float(id.x), float(id.y), float(id.z)) + float3(0.5f, 0.5f, 0.5f);
uv /= float3(float(_sdfTexSizeX), float(_sdfTexSizeY), float(_sdfTexSizeZ));

float3 centre;
centre.x = 0.5f;
centre.y = 0.5f;
centre.z = 0.5f;
float sphereRadius = _sphereRadius / (_sdfRadius * 2.0f);
float dist = sdSphere(uv - centre, sphereRadius);

dist = clamp(dist / _sdfDistMod, -1.0f, 1.0f);
dist = dist * 0.5f + 0.5f;
_sdfTex[id.xyz] = dist;
}
9 changes: 9 additions & 0 deletions Assets/Compute/SDFGen.compute.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

163 changes: 163 additions & 0 deletions Assets/Compute/SDFGenMutate.compute
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#pragma kernel SDFMutate

Texture3D<float> _sdfTexIn;
SamplerState sampler_sdfTexIn;
RWTexture3D<float> _sdfTexOut;
uint _sdfTexSizeX;
uint _sdfTexSizeY;
uint _sdfTexSizeZ;
float _sdfRadius;
float _sdfDistMod;

bool _mouseSubtract;
bool _mouseAdd;
float4 _mouseOrigin;
float4 _mouseDir;

float raySphereIntersect(float3 r0, float3 rd, float3 s0, float sr)
{
// - r0: ray origin
// - rd: normalized ray direction
// - s0: sphere center
// - sr: sphere radius
// - Returns distance from r0 to first intersecion with sphere,
// or -1.0 if no intersection.
float a = dot(rd, rd);
float3 s0_r0 = r0 - s0;
float b = 2.0 * dot(rd, s0_r0);
float c = dot(s0_r0, s0_r0) - (sr * sr);
if (b * b - 4.0 * a * c < 0.0)
{
return -1.0;
}
return (-b - sqrt((b * b) - 4.0 * a * c)) / (2.0 * a);
}

float sdf(float3 uv)
{
uv /= (_sdfRadius * 2.0);
uv += float3(0.5, 0.5, 0.5);
float sdf = _sdfTexIn.SampleLevel(sampler_sdfTexIn, uv, 0);
sdf = (sdf * 2.0) - 1.0;
sdf *= (_sdfRadius * 2.0);
sdf *= _sdfDistMod;
return sdf;
}

bool outOfBounds(float3 pos)
{
if (length(pos) < _sdfRadius)
{
return false;
}
return true;
}

float rayMarch(float3 origin, float3 dir, float k, out float res, out float3 hitPos)
{
res = 1.0;
float t = 0.0001;
[loop]
for (int i = 0; i < 256; i++)
{
float3 current = origin + dir * t;
if (outOfBounds(current))
{
return 0.0;
}
float dist = sdf(current);
if (dist <= 0.0)
{
hitPos = current;
res = 0.0;
return 1.0;
}
dist = max(dist, 0.0001);
res = min(res, k * dist / t);
t += dist;
}
return 0.0;
}

float sdSphere(float3 pos, float radius)
{
return length(pos) - radius;
}

float opSubtraction(float d1, float d2)
{
return max(d1, -d2);
}
float opSmoothSubtraction(float d1, float d2, float k)
{
float h = clamp(0.5 - 0.5 * (d2 + d1) / k, 0.0, 1.0);
return lerp(d2, -d1, h) + k * h * (1.0 - h);
}

float opUnion(float d1, float d2)
{
return min(d1, d2);
}
float opSmoothUnion(float d1, float d2, float k)
{
float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
return lerp(d2, d1, h) - k * h * (1.0 - h);
}

[numthreads(8,8,8)]
void SDFMutate(uint3 id : SV_DispatchThreadID)
{
float3 uv = float3(float(id.x), float(id.y), float(id.z)) + float3(0.5f, 0.5f, 0.5f);
uv /= float3(float(_sdfTexSizeX), float(_sdfTexSizeY), float(_sdfTexSizeZ));

float3 centre;
centre.x = 0.5f;
centre.y = 0.5f;
centre.z = 0.5f;
float3 worldUV = (uv - centre) * (_sdfRadius * 2.0);
float dist = sdf(worldUV);

//sdf = opSmoothSubtraction(sdSphere(worldUV - float3(0.0, 1.0, 0.0), 0.3), sdf, 0.15);
//sdf = opSmoothUnion(sdSphere(worldUV - float3(0.0, 0.75, 0.0), 0.5), sdf, 0.05);
//sdf = opSmoothUnion(sdSphere(worldUV - float3(0.9, 0.0, 0.0), 0.3), sdf, 0.1);
//sdf = opSmoothUnion(sdSphere(worldUV - float3(-0.9, 0.0, 0.0), 0.3), sdf, 0.1);
//sdf = opSmoothUnion(sdSphere(worldUV - float3(0.0, 0.0, 0.9), 0.3), sdf, 0.1);
//sdf = opSmoothUnion(sdSphere(worldUV - float3(0.0, 0.0, -0.9), 0.3), sdf, 0.1);
//sdf = opSmoothSubtraction(sdSphere(worldUV - float3(0.0, -1.0, 0.0), 0.5), sdf, 0.15);

if (_mouseAdd)
{
float toSdf = raySphereIntersect(_mouseOrigin.xyz, _mouseDir.xyz, float3(0.0, 0.0, 0.0), 1.0);
float3 ro = _mouseOrigin.xyz + _mouseDir.xyz * toSdf;
float3 rd = _mouseDir.xyz;
float res;
float3 hitPos;
float hit = rayMarch(ro, _mouseDir.xyz, 1.0, res, hitPos);
if (hit > 0.0)
{
float addRadius = 0.05;
float3 pos = ro;
dist = opSmoothUnion(sdSphere(worldUV - pos, addRadius), dist, 0.05);
}
}

if (_mouseSubtract)
{
float toSdf = raySphereIntersect(_mouseOrigin.xyz, _mouseDir.xyz, float3(0.0, 0.0, 0.0), 1.0);
float3 ro = _mouseOrigin.xyz + _mouseDir.xyz * toSdf;
float3 rd = _mouseDir.xyz;
float res;
float3 hitPos;
float hit = rayMarch(ro, _mouseDir.xyz, 1.0, res, hitPos);
if (hit > 0.0)
{
float subtractRadius = 0.05;
float3 pos = ro;
dist = opSmoothSubtraction(sdSphere(worldUV - pos, subtractRadius), dist, 0.05);
}
}

dist /= (_sdfRadius * 2.0f);
dist /= _sdfDistMod;
_sdfTexOut[id.xyz] = dist * 0.5 + 0.5;
}
9 changes: 9 additions & 0 deletions Assets/Compute/SDFGenMutate.compute.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Assets/Editor.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 836023d

Please sign in to comment.