Created Lightning Gun effect (Uses LineRenderer, very slow) Created GPU Lightning renderer (very fast, still needs integration)
139 lines
4.1 KiB
Text
139 lines
4.1 KiB
Text
#pragma kernel AddNode
|
||
#pragma kernel CreateWidth
|
||
|
||
#define NUM_THREAD_X 32
|
||
|
||
#include "GPUTrailVariablesCS.compute"
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// AddNode
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
StructuredBuffer<InputData> _InputBuffer;
|
||
RWStructuredBuffer<Trail> _TrailBufferW;
|
||
RWStructuredBuffer<Node> _NodeBufferW;
|
||
|
||
[numthreads(NUM_THREAD_X,1,1)]
|
||
void AddNode (uint3 id : SV_DispatchThreadID)
|
||
{
|
||
uint trailIdx = id.x;
|
||
if ( trailIdx < _TrailNum )
|
||
{
|
||
Trail trail = _TrailBufferW[trailIdx];
|
||
uint totalInputNum = trail.totalInputNum;
|
||
bool isFirst = (totalInputNum==0);
|
||
|
||
InputData inputData = _InputBuffer[trailIdx];
|
||
if ( isFirst || (_MinNodeDistance <= distance(inputData.pos, _NodeBufferW[calcNodeIdx(trailIdx, totalInputNum-1)].pos)))
|
||
{
|
||
Node node;
|
||
node.pos = inputData.pos;
|
||
node.time = _Time;
|
||
node.color = inputData.color;
|
||
uint nodeIdx = calcNodeIdx(trailIdx, totalInputNum);
|
||
_NodeBufferW[nodeIdx] = node;
|
||
|
||
trail.startTime = isFirst ? _Time : trail.startTime;
|
||
trail.totalInputNum++;
|
||
|
||
_TrailBufferW[trailIdx] = trail;
|
||
}
|
||
}
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// CreateWidth
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
StructuredBuffer<Trail> _TrailBuffer;
|
||
StructuredBuffer<Node> _NodeBuffer;
|
||
RWStructuredBuffer<Vertex> _VertexBuffer;
|
||
|
||
|
||
uint calcPrevIdxInTrail(uint idx)
|
||
{
|
||
return (idx + _NodeNumPerTrail-1) % _NodeNumPerTrail;
|
||
}
|
||
uint calcNextIdxInTrail(uint idx)
|
||
{
|
||
return (idx + 1) % _NodeNumPerTrail;
|
||
}
|
||
|
||
uint calcNodeIdxFromInTrail(uint trailIdx, uint idxInTrail)
|
||
{
|
||
return trailIdx * _NodeNumPerTrail + idxInTrail;
|
||
}
|
||
|
||
Node getNode(uint trailIdx, uint idxInTrail, uint totalInputNum)
|
||
{
|
||
idxInTrail = min(idxInTrail, totalInputNum-1); // 未使用ノードのIdxが指定されたら最新のノードを返す
|
||
return _NodeBuffer[calcNodeIdxFromInTrail(trailIdx, idxInTrail)];
|
||
}
|
||
|
||
float3 calcNodeDir(uint trailIdx, uint nodeIdxInTrail, uint totalInputNum)
|
||
{
|
||
float3 dirPrev = float3(0,0,0);
|
||
float3 dirNext = float3(0,0,0);
|
||
|
||
float3 pos = getNode(trailIdx, nodeIdxInTrail, totalInputNum).pos;
|
||
|
||
uint prevIdxInTrail = calcPrevIdxInTrail(nodeIdxInTrail);
|
||
uint inputIdxInTrail = calcPrevIdxInTrail(totalInputNum);
|
||
|
||
bool prevEnable = (prevIdxInTrail != inputIdxInTrail) && (prevIdxInTrail < totalInputNum);
|
||
if ( prevEnable )
|
||
{
|
||
dirPrev = normalize(pos - getNode(trailIdx, prevIdxInTrail, totalInputNum).pos);
|
||
}
|
||
|
||
bool nextEnable = nodeIdxInTrail!= inputIdxInTrail;
|
||
if ( nextEnable )
|
||
{
|
||
uint nextIdxInTrail = calcNextIdxInTrail(nodeIdxInTrail);
|
||
dirNext = normalize(getNode(trailIdx, nextIdxInTrail, totalInputNum).pos - pos);
|
||
}
|
||
|
||
return normalize(dirPrev + dirNext);
|
||
}
|
||
|
||
[numthreads(NUM_THREAD_X,1,1)]
|
||
void CreateWidth (uint3 id : SV_DispatchThreadID)
|
||
{
|
||
uint nodeIdx = id.x;
|
||
uint trailIdx = nodeIdx / _NodeNumPerTrail;
|
||
if ( trailIdx < _TrailNum )
|
||
{
|
||
Trail trail = _TrailBuffer[trailIdx];
|
||
uint totalInputNum = trail.totalInputNum;
|
||
uint nodeIdxInTrail = nodeIdx % _NodeNumPerTrail;
|
||
|
||
Vertex v0 = GetDefaultVertex();
|
||
Vertex v1 = GetDefaultVertex();
|
||
{
|
||
Node node = getNode(trailIdx, nodeIdxInTrail, totalInputNum);
|
||
|
||
float life = min(_Life, _Time - trail.startTime);
|
||
float rate = life <= 0 ? 1 : max(0, 1 - ((_Time - node.time) / life));
|
||
|
||
float3 pos = node.pos;
|
||
float3 dir = calcNodeDir(trailIdx, nodeIdxInTrail, totalInputNum);
|
||
|
||
float3 toCameraDir = calcToCameraDir(pos);
|
||
float3 right = normalize(cross(dir, toCameraDir)) * lerp(_EndWidth, _StartWidth, rate) * 0.5f;
|
||
|
||
v0.pos = pos - right;
|
||
v0.uv = float2(rate, 0);
|
||
v0.color = node.color;
|
||
|
||
v1.pos = pos + right;
|
||
v1.uv = float2(rate, 1);
|
||
v1.color = node.color;
|
||
}
|
||
|
||
uint startIdxInTrail = (totalInputNum <= _NodeNumPerTrail) ? 0 : calcNextIdxInTrail(totalInputNum-1);
|
||
uint nodeIdxFromStartInTrail = ((nodeIdxInTrail + _NodeNumPerTrail) - startIdxInTrail) % _NodeNumPerTrail;
|
||
uint drawIdx = calcNodeIdxFromInTrail(trailIdx, nodeIdxFromStartInTrail);
|
||
|
||
uint vIdx = drawIdx * 2;
|
||
_VertexBuffer[vIdx] = v0;
|
||
_VertexBuffer[vIdx+1] = v1;
|
||
}
|
||
}
|