Skip to content

Commit

Permalink
Small improvements and refactorings.
Browse files Browse the repository at this point in the history
  • Loading branch information
keijiro committed May 31, 2017
1 parent 6f75b51 commit f8e337d
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 95 deletions.
2 changes: 1 addition & 1 deletion Assets/DFVolume/VolumeData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void Initialize(VolumeSampler sampler)
_texture.name = "Distance Field Texture";
_texture.filterMode = FilterMode.Bilinear;
_texture.wrapMode = TextureWrapMode.Clamp;
_texture.SetPixels(sampler.GenerateBitmap2());
_texture.SetPixels(sampler.GenerateBitmap());
_texture.Apply();
}

Expand Down
2 changes: 1 addition & 1 deletion Assets/DFVolume/VolumeSampler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void OnDrawGizmos()
Gizmos.DrawWireCube(Vector3.zero, Vector3.one * _extent * 2);
}

public Color[] GenerateBitmap2()
public Color[] GenerateBitmap()
{
// Generate a distance field.
var df = new float[_resolution * _resolution * _resolution];
Expand Down
89 changes: 48 additions & 41 deletions Assets/Swarm/CrawlerSwarm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ public int instanceCount {

#endregion

#region Renderer settings
#region Render settings

[SerializeField] TubeTemplate _template;

public TubeTemplate template {
get { return _template; }
}

[SerializeField, Range(0, 0.1f)] float _radius = 0.01f;
[SerializeField] float _radius = 0.005f;

public float radius {
get { return _radius; }
Expand All @@ -52,7 +52,7 @@ public CosineGradient gradient {

#region Dynamics settings

[SerializeField] float _speed = 0.5f;
[SerializeField] float _speed = 0.75f;

public float speed {
get { return _speed; }
Expand All @@ -65,20 +65,20 @@ public VolumeData volume {
get { return _volume; }
}

[SerializeField] float _constraint = 6;

public float constraint {
get { return _constraint; }
set { _constraint = value; }
}

[SerializeField] float _noiseFrequency = 2;
[SerializeField] float _noiseFrequency = 4;

public float noiseFrequency {
get { return _noiseFrequency; }
set { _noiseFrequency = value; }
}

[SerializeField] float _noiseSpread = 0.5f;

public float noiseSpread {
get { return _noiseSpread; }
set { _noiseSpread = value; }
}

[SerializeField] float _noiseMotion = 0.1f;

public float noiseMotion {
Expand Down Expand Up @@ -116,6 +116,11 @@ public float noiseMotion {

#region MonoBehaviour functions

void OnValidate()
{
_instanceCount = Mathf.Max(kThreadCount, _instanceCount);
}

void Start()
{
// Initialize the indirect draw args buffer.
Expand All @@ -135,12 +140,12 @@ void Start()

// Initialize the position buffer.
var kernel = _compute.FindKernel("CrawlerInit");
_compute.SetInt("InstanceCount", InstanceCount);
_compute.SetInt("HistoryLength", HistoryLength);
_compute.SetBuffer(kernel, "PositionBuffer", _positionBuffer);
_compute.SetBuffer(kernel, "TangentBuffer", _tangentBuffer);
_compute.SetBuffer(kernel, "NormalBuffer", _normalBuffer);
_compute.SetTexture(kernel, "DFVolume", _volume.texture);
_compute.SetInt("InstanceCount", InstanceCount);
_compute.SetInt("HistoryLength", HistoryLength);
_compute.Dispatch(kernel, ThreadGroupCount, 1, 1);

// Initialize the update kernel.
Expand All @@ -155,11 +160,11 @@ void Start()
_compute.SetBuffer(kernel, "NormalBuffer", _normalBuffer);

// Initialize the mateiral.
_material.SetInt("_InstanceCount", InstanceCount);
_material.SetInt("_HistoryLength", HistoryLength);
_material.SetBuffer("_PositionBuffer", _positionBuffer);
_material.SetBuffer("_TangentBuffer", _tangentBuffer);
_material.SetBuffer("_NormalBuffer", _normalBuffer);
_material.SetInt("_InstanceCount", InstanceCount);
_material.SetInt("_HistoryLength", HistoryLength);

// This property block is used only for avoiding an instancing bug.
_props = new MaterialPropertyBlock();
Expand All @@ -176,31 +181,33 @@ void OnDestroy()

void Update()
{
var time = Time.time;
var delta = Mathf.Min(Time.deltaTime, 1.0f / 15);

// Index offset on the position buffer.
var offset0 = InstanceCount * ( _frameCount % HistoryLength);
var offset1 = InstanceCount * ((_frameCount + 1) % HistoryLength);
var offset2 = InstanceCount * ((_frameCount + 2) % HistoryLength);

// Parameters for the compute kernels.
_compute.SetInt("IndexOffset0", offset0);
_compute.SetInt("IndexOffset1", offset1);
_compute.SetInt("IndexOffset2", offset2);
_compute.SetFloat("Time", time);
_compute.SetFloat("Speed", _speed * delta);
_compute.SetFloat("Constraint", _constraint);
_compute.SetFloat("NoiseFrequency", _noiseFrequency);
_compute.SetFloat("NoiseOffset", time * _noiseMotion);

// Update the position buffer.
var kernel = _compute.FindKernel("CrawlerUpdate");
_compute.Dispatch(kernel, ThreadGroupCount, 1, 1);

// Reconstruct tangent/normal vectors.
kernel = _compute.FindKernel("CrawlerReconstruct");
_compute.Dispatch(kernel, ThreadGroupCount, 1, 1);
var delta = Mathf.Min(Time.deltaTime, 1.0f / 30);

if (delta > 0)
{
// Index offset on the position buffer.
var offset0 = InstanceCount * ( _frameCount % HistoryLength);
var offset1 = InstanceCount * ((_frameCount + 1) % HistoryLength);
var offset2 = InstanceCount * ((_frameCount + 2) % HistoryLength);

// Update the parameters for the compute kernels.
_compute.SetInt("IndexOffset0", offset0);
_compute.SetInt("IndexOffset1", offset1);
_compute.SetInt("IndexOffset2", offset2);
_compute.SetFloat("Speed", _speed * delta);
_compute.SetFloat("NoiseFrequency", _noiseFrequency);
_compute.SetFloat("NoiseSpread", _noiseSpread / InstanceCount);
_compute.SetFloat("NoiseOffset", Time.time * _noiseMotion);
_compute.SetFloat("Time", Time.time);

// Update the position buffer.
var kernel = _compute.FindKernel("CrawlerUpdate");
_compute.Dispatch(kernel, ThreadGroupCount, 1, 1);

// Reconstruct tangent/normal vectors.
kernel = _compute.FindKernel("CrawlerReconstruct");
_compute.Dispatch(kernel, ThreadGroupCount, 1, 1);
}

// Draw the meshes with instancing.
_material.SetInt("_IndexOffset", _frameCount + 3);
Expand All @@ -214,7 +221,7 @@ void Update()

Graphics.DrawMeshInstancedIndirect(
_template.mesh, 0, _material,
new Bounds(Vector3.zero, Vector3.one * 10000),
new Bounds(Vector3.zero, Vector3.one * 1.5f),
_drawArgsBuffer, 0, _props
);

Expand Down
6 changes: 3 additions & 3 deletions Assets/Swarm/CrawlerSwarm.cs.meta

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

10 changes: 5 additions & 5 deletions Assets/Swarm/Editor/CrawlerSwarmEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ public class CrawlerSwarmEditor : Editor
SerializedProperty _material;
SerializedProperty _gradient;

SerializedProperty _speed;
SerializedProperty _volume;
SerializedProperty _constraint;
SerializedProperty _speed;
SerializedProperty _noiseFrequency;
SerializedProperty _noiseSpread;
SerializedProperty _noiseMotion;

void OnEnable()
Expand All @@ -32,10 +32,10 @@ void OnEnable()
_material = serializedObject.FindProperty("_material");
_gradient = serializedObject.FindProperty("_gradient");

_speed = serializedObject.FindProperty("_speed");
_volume = serializedObject.FindProperty("_volume");
_constraint = serializedObject.FindProperty("_constraint");
_speed = serializedObject.FindProperty("_speed");
_noiseFrequency = serializedObject.FindProperty("_noiseFrequency");
_noiseSpread = serializedObject.FindProperty("_noiseSpread");
_noiseMotion = serializedObject.FindProperty("_noiseMotion");
}

Expand All @@ -56,8 +56,8 @@ public override void OnInspectorGUI()

EditorGUILayout.PropertyField(_speed);
EditorGUILayout.PropertyField(_volume);
EditorGUILayout.PropertyField(_constraint);
EditorGUILayout.PropertyField(_noiseFrequency);
EditorGUILayout.PropertyField(_noiseSpread);
EditorGUILayout.PropertyField(_noiseMotion);

serializedObject.ApplyModifiedProperties();
Expand Down
16 changes: 16 additions & 0 deletions Assets/Swarm/Editor/Default Gradient.asset
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 54276434dda9c694e85abaf98cdd981d, type: 3}
m_Name: Default Gradient
m_EditorClassIdentifier:
_redCoeffs: {x: 0.5, y: 0.5, z: 1, w: 0}
_greenCoeffs: {x: 0.5, y: 0.5, z: 1, w: 0.333}
_blueCoeffs: {x: 0.5, y: 0.5, z: 1, w: 0.665}
9 changes: 9 additions & 0 deletions Assets/Swarm/Editor/Default Gradient.asset.meta

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

67 changes: 31 additions & 36 deletions Assets/Swarm/Shader/Crawler.compute
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
#include "SimplexNoise3D.cginc"

RWStructuredBuffer<float4> PositionBuffer;
StructuredBuffer<float4> PositionBufferRO;

RWStructuredBuffer<float4> TangentBuffer;
RWStructuredBuffer<float4> NormalBuffer;

StructuredBuffer<float4> PositionBufferRO;

// Distance field volume (gradient.xyz, distance)
Texture3D<float4> DFVolume;
SamplerState samplerDFVolume;

Expand All @@ -23,55 +24,48 @@ CBUFFER_START(Params)
uint IndexOffset0;
uint IndexOffset1;
uint IndexOffset2;
float Time;
float Speed;
float Constraint;
float NoiseFrequency;
float NoiseSpread;
float NoiseOffset;
float Time;
CBUFFER_END

float UVRandom(float u, float v)
float Random(float u, float v)
{
float f = dot(float2(12.9898, 78.233), float2(u, v));
return frac(43758.5453 * sin(f));
}

// Nearly uniformly distributed random vector in the unit sphere.
float3 RandomPoint(float id)
{
float u = Random(id * 0.01334, 0.3728) * UNITY_PI * 2;
float z = Random(0.8372, id * 0.01197) * 2 - 1;
float l = Random(4.438, id * 0.01938 - 4.378);
return float3(float2(cos(u), sin(u)) * sqrt(1 - z * z), z) * sqrt(l);
}

float4 SampleVolume(float3 p)
{
return DFVolume.SampleLevel(samplerDFVolume, p * 0.5 + 0.5, 0);
return DFVolume.SampleLevel(samplerDFVolume, p + 0.5, 0);
}

[numthreads(64, 1, 1)]
void CrawlerInit(uint id : SV_DispatchThreadID)
{
// Get a random point.
float x = UVRandom(id * 0.01334, 0.3728);
float y = UVRandom(0.8372, id * 0.01197);
float z = UVRandom(4.438, id * 0.01938 - 4.378);
float4 p = float4(x, y, z, 0) * 0.5 - 0.25;
float d = SampleVolume(p);

// Swizzle and compre, choose one with closer distance.
{
float4 p2 = p.yzxw;
float d2 = SampleVolume(p2);
p = d2 < d ? p2 : p;
d = min(d, d2);
}

// Swizzle again.
{
float4 p2 = p.zxyw;
float d2 = SampleVolume(p2);
p = d2 < d ? p2 : p;
d = min(d, d2);
}
// Pick two random points and use closer one.
float3 p1 = RandomPoint(id + 0.0) / 3;
float3 p2 = RandomPoint(id + 0.5) / 3;
float d1 = SampleVolume(p1).w;
float d2 = SampleVolume(p2).w;
float3 p = d1 < d2 ? p1 : p2;

// Fill the position/tangent/normal buffer.
for (uint i = 0; i < HistoryLength; i++)
{
uint offs = id + i * InstanceCount;
PositionBuffer[offs] = p;
PositionBuffer[offs] = float4(p, 0);
TangentBuffer[offs] = float4(0, 0, 1, 0);
NormalBuffer[offs] = float4(1, 0, 0, 0);
}
Expand All @@ -83,17 +77,18 @@ void CrawlerUpdate(uint id : SV_DispatchThreadID)
// Retrieve the previous position.
float3 p = PositionBuffer[IndexOffset1 + id].xyz;

// Distance field (gradient.x, y, z, distance).
float4 df = SampleVolume(p) * Constraint;
// Sample the point in the distance field.
float4 df = SampleVolume(p);

// Two independent noise fields (not completely independent though).
float4 sn1 = snoise(10.33 + p.xyz * NoiseFrequency + NoiseOffset);
float4 sn2 = snoise(32.38 - p.yzx * NoiseFrequency + NoiseOffset);
// Two independent noise fields.
float3 offs = float3(0, NoiseOffset, id * NoiseSpread);
float4 sn1 = snoise(98.4898 + p * NoiseFrequency + offs);
float4 sn2 = snoise( 1.2278 - p * NoiseFrequency + offs);

// Apply the boundary condition to the first noise field.
// Apply the boundary condition (distance field) to the first noise field.
sn1.xyz = -sn1.xyz * df.w + df.xyz * sn1.w;

// Apply the divergence free noise field to the position.
// Construct the divergence-free noise field and apply it to the point.
p += cross(sn1.xyz, sn2.xyz) * Speed;

// Update the buffer.
Expand Down
Loading

0 comments on commit f8e337d

Please sign in to comment.