Skip to content

Commit

Permalink
Added reconstruction compute shader.
Browse files Browse the repository at this point in the history
  • Loading branch information
keijiro committed May 29, 2017
1 parent e7aec7a commit b5f7a8c
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 33 deletions.
37 changes: 31 additions & 6 deletions Assets/Swarm/CrawlerSwarm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public sealed class CrawlerSwarm : MonoBehaviour

ComputeBuffer _drawArgsBuffer;
ComputeBuffer _positionBuffer;
ComputeBuffer _tangentBuffer;
ComputeBuffer _normalBuffer;
MaterialPropertyBlock _props;
int _frameCount;

Expand Down Expand Up @@ -57,13 +59,18 @@ void Start()
(uint)InstanceCount, 0, 0, 0
});

// Initialize the position buffer.
// Allocate compute buffers.
_positionBuffer = new ComputeBuffer(HistoryLength * InstanceCount, 16);
_tangentBuffer = new ComputeBuffer(HistoryLength * InstanceCount, 16);
_normalBuffer = new ComputeBuffer(HistoryLength * InstanceCount, 16);

// 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.Dispatch(kernel, ThreadGroupCount, 1, 1);

Expand All @@ -72,10 +79,18 @@ void Start()
_compute.SetBuffer(kernel, "PositionBuffer", _positionBuffer);
_compute.SetTexture(kernel, "DFVolume", _volume.texture);

// Initialize the reconstruction kernel.
kernel = _compute.FindKernel("CrawlerReconstruct");
_compute.SetBuffer(kernel, "PositionBufferRO", _positionBuffer);
_compute.SetBuffer(kernel, "TangentBuffer", _tangentBuffer);
_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);

// This property block is used only for avoiding an instancing bug.
_props = new MaterialPropertyBlock();
Expand All @@ -86,25 +101,33 @@ void OnDestroy()
{
_drawArgsBuffer.Release();
_positionBuffer.Release();
_tangentBuffer.Release();
_normalBuffer.Release();
}

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

// Update the position buffer.
var kernel = _compute.FindKernel("CrawlerUpdate");
// Parameters for the compute kernels.
_compute.SetInt("IndexOffset0", offset0);
_compute.SetInt("IndexOffset1", offset1);
_compute.SetInt("IndexOffset2", offset2);
_compute.SetFloat("Time", Time.time);

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

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

// Draw the meshes with instancing.
_material.SetInt("_IndexOffset", _frameCount % HistoryLength);
_material.SetInt("_IndexOffset", _frameCount + 3);
_material.SetVector("_GradientA", _gradient.coeffsA);
_material.SetVector("_GradientB", _gradient.coeffsB);
_material.SetVector("_GradientC", _gradient.coeffsC2);
Expand All @@ -117,6 +140,8 @@ void Update()
new Bounds(Vector3.zero, Vector3.one * 10000),
_drawArgsBuffer, 0, _props
);

_frameCount++;
}

#endregion
Expand Down
48 changes: 44 additions & 4 deletions Assets/Swarm/Shader/Crawler.compute
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@

#pragma kernel CrawlerInit
#pragma kernel CrawlerUpdate
#pragma kernel CrawlerReconstruct

#include "UnityCG.cginc"
#include "SimplexNoise3D.cginc"

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

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

Texture3D<float4> DFVolume;
SamplerState samplerDFVolume;

Expand All @@ -16,6 +22,7 @@ CBUFFER_START(Params)
uint HistoryLength;
uint IndexOffset0;
uint IndexOffset1;
uint IndexOffset2;
float Time;
CBUFFER_END

Expand Down Expand Up @@ -56,16 +63,21 @@ void CrawlerInit(uint id : SV_DispatchThreadID)
d = min(d, d2);
}

// Fill the position buffer.
// Fill the position/tangent/normal buffer.
for (uint i = 0; i < HistoryLength; i++)
PositionBuffer[id + i * InstanceCount] = p;
{
uint offs = id + i * InstanceCount;
PositionBuffer[offs] = p;
TangentBuffer[offs] = float4(0, 0, 1, 0);
NormalBuffer[offs] = float4(1, 0, 0, 0);
}
}

[numthreads(64, 1, 1)]
void CrawlerUpdate(uint id : SV_DispatchThreadID)
{
// Retrieve the previous position.
float3 p = PositionBuffer[IndexOffset0 + id].xyz;
float3 p = PositionBuffer[IndexOffset1 + id].xyz;

// Distance field (gradient.x, y, z, distance).
float4 df = SampleVolume(p) * 6;
Expand All @@ -81,5 +93,33 @@ void CrawlerUpdate(uint id : SV_DispatchThreadID)
p += cross(sn1.xyz, sn2.xyz) * 0.005;

// Update the buffer.
PositionBuffer[IndexOffset1 + id].xyz = p;
PositionBuffer[IndexOffset2 + id].xyz = p;
}

[numthreads(64, 1, 1)]
void CrawlerReconstruct(uint id : SV_DispatchThreadID)
{
// Retrieve the history.
float3 p0 = PositionBufferRO[IndexOffset0 + id].xyz; // Two frames ago
float3 p1 = PositionBufferRO[IndexOffset1 + id].xyz; // Previous frame
float3 p2 = PositionBufferRO[IndexOffset2 + id].xyz; // Current frame

float3 t0 = TangentBuffer[IndexOffset0 + id].xyz; // Two frames ago
float3 n0 = NormalBuffer[IndexOffset0 + id].xyz;
float3 b0 = cross(t0, n0);

// Tangent vectors.
float3 t1 = normalize(p2 - p0);
float3 t2 = normalize(p2 - p1);

// Compute normal vectors based on b0.
float3 n1 = normalize(cross(b0, t1));
float3 b1 = cross(t1, n1);
float3 n2 = normalize(cross(b1, t2));

// Store the results.
TangentBuffer[IndexOffset1 + id] = float4(t1, 0);
TangentBuffer[IndexOffset2 + id] = float4(t2, 0);
NormalBuffer[IndexOffset1 + id] = float4(n1, 0);
NormalBuffer[IndexOffset2 + id] = float4(n2, 0);
}
42 changes: 19 additions & 23 deletions Assets/Swarm/Shader/Tube.shader
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED

StructuredBuffer<float4> _PositionBuffer;
StructuredBuffer<float4> _TangentBuffer;
StructuredBuffer<float4> _NormalBuffer;
uint _InstanceCount;
uint _HistoryLength;
uint _IndexOffset;
Expand All @@ -53,34 +55,28 @@

const float radius = 0.01;

float phi = v.vertex.x;
float seg = v.vertex.z;
float phi = v.vertex.x; // Angle in slice
float seg = v.vertex.z; // Segment index
uint iseg = (uint)seg;

uint id = unity_InstanceID;
uint idx = clamp(seg, 1, _HistoryLength - 2);
uint idx0 = (idx - 1 + _IndexOffset + _HistoryLength) % _HistoryLength;
uint idx1 = (idx + _IndexOffset) % _HistoryLength;
uint idx2 = (idx + 1 + _IndexOffset) % _HistoryLength;
uint idx3 = (idx + 2 + _IndexOffset) % _HistoryLength;

float3 p0 = _PositionBuffer[id + idx0 * _InstanceCount].xyz;
float3 p1 = _PositionBuffer[id + idx1 * _InstanceCount].xyz;
float3 p2 = _PositionBuffer[id + idx2 * _InstanceCount].xyz;
float3 p3 = _PositionBuffer[id + idx3 * _InstanceCount].xyz;
// Parameter along the curve (used for coloring).
float param = seg / _HistoryLength;
param += (float)unity_InstanceID / _InstanceCount;

float3 vt0 = normalize(p2 - p0);
float3 vt1 = normalize(p3 - p1);
float3 vn = normalize(vt1 - vt0);
float3 vb = cross(vt1, vn);
vn = cross(vb, vt1);
// Index of the current slice in the buffers.
uint idx = unity_InstanceID;
idx += _InstanceCount * ((iseg + _IndexOffset) % _HistoryLength);

float2 xy = float2(cos(phi), sin(phi));
float3 p = _PositionBuffer[idx].xyz; // Position
float3 t = _TangentBuffer[idx].xyz; // Curve-TNB: Tangent
float3 n = _NormalBuffer[idx].xyz; // Curve-TNB: Normal
float3 b = cross(t, n); // Curve-TNB: Binormal

float param = seg / _HistoryLength;
param += (float)unity_InstanceID / _InstanceCount;
float3 normal = n * cos(phi) + b * sin(phi); // Surface normal

v.vertex.xyz = p1 + (vn * xy.x + vb * xy.y) * radius;
v.normal.xyz = vn * xy.x + vb * xy.y;
// Feedback the results.
v.vertex = float4(p + normal * radius, 1);
v.normal = normal;
v.color = param;

#endif
Expand Down

0 comments on commit b5f7a8c

Please sign in to comment.