forked from samuelbigos/signed_distance_fields_in_unity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit with SDF rendering + mutate + physics.
- Loading branch information
0 parents
commit 836023d
Showing
182 changed files
with
29,755 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.