Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma kernel Main
- struct Sample
- {
- float4 vertex;
- };
- struct Vertex
- {
- float3 Position;
- float3 Normal;
- float2 TexCoord;
- };
- StructuredBuffer<Sample> _Source;
- StructuredBuffer<float2> _Segments;
- RWStructuredBuffer<Vertex> _VertexBuffer;
- RWStructuredBuffer<uint> _IndexBuffer;
- RWStructuredBuffer<float4> _Debug;
- uint _NumSamples;
- uint _NumSegments;
- float _Thickness;
- float _Strain;
- float4 _UVScale;
- #define QUATERNION_IDENTITY float4(0.0f, 0.0f, 0.0f, 1.0f);
- #define PI 3.14159265359f
- float4 QuaternionMultiply(float4 q1, float4 q2)
- {
- return float4(
- q2.xyz * q1.w + q1.xyz * q2.w + cross(q1.xyz, q2.xyz),
- q1.w * q2.w - dot(q1.xyz, q2.xyz)
- );
- }
- float3 QuaternionRotateVector(float3 v, float4 r)
- {
- float4 r_c = r * float4(-1.0f, -1.0f, -1.0f, 1.0f);
- return QuaternionMultiply(r, QuaternionMultiply(float4(v, 0.0f), r_c)).xyz;
- }
- float4 QuaternionRotateAngleAxis(float angle, float3 axis)
- {
- float sn = sin(angle * 0.5f);
- float cs = cos(angle * 0.5f);
- return float4(axis * sn, cs);
- }
- float4 QuaternionFromTo(float3 from, float3 to)
- {
- float4 q;
- float d = dot(from, to);
- if (d < -0.995f)
- {
- float3 right = float3(1.0f, 0.0f, 0.0f);
- float3 up = float3(0.0f, 1.0f, 0.0f);
- float3 tmp = cross(up, from);
- if (length(tmp) < 0.0001f)
- {
- tmp = cross(right, from);
- }
- tmp = normalize(tmp);
- q = QuaternionRotateAngleAxis(PI, tmp);
- }
- else if (d > 0.995f)
- {
- q = QUATERNION_IDENTITY;
- }
- else
- {
- q.xyz = cross(from, to);
- q.w = 1.0f + d;
- q = normalize(q);
- }
- return q;
- }
- groupshared float3 _Origin[32];
- groupshared float3 _Tangent[32];
- groupshared float3 _Normal[32];
- groupshared float3 _Binormal[32];
- groupshared float _VCoord[32];
- [numthreads(32,16,1)]
- void Main(uint3 id : SV_DispatchThreadID, uint3 gid : SV_GroupThreadID)
- {
- // Process only the valid samples
- if (id.x < _NumSamples)
- {
- if (id.y == 0)
- {
- // Default basis
- float3 origin = float3(0.0f, 0.0f, 0.0f);
- float3 tangent = float3(0.0f, 0.0f, 1.0f);
- float3 normal = float3(0.0f, 1.0f, 0.0f);
- float3 binormal = float3(-1.0f, 0.0f, 0.0f);
- // Build frame basis for sample
- int next = min(id.x + 1, _NumSamples - 1);
- int prev = max(int(id.x) - 1, 0);
- float3 nextVertex = (_Source[next].vertex.xyz - _Source[id.x].vertex.xyz);
- float3 prevVertex = (_Source[id.x].vertex.xyz - _Source[prev].vertex.xyz);
- float3 newTangent = normalize(nextVertex + prevVertex);
- // Compute rotated basis and store in groupshared memory
- float4 rotation = QuaternionFromTo(tangent, newTangent);
- _Normal[gid.x] = QuaternionRotateVector(normal, rotation);
- _Binormal[gid.x] = QuaternionRotateVector(binormal, rotation);
- _Tangent[gid.x] = newTangent;
- _Origin[gid.x] = _Source[id.x].vertex.xyz;
- _VCoord[gid.x] = _UVScale.w + _UVScale.y * (_Source[id.x].vertex.w / _Strain);
- //_Debug[id.x] = float4(rotation.x, rotation.y, rotation.z, rotation.w);
- _Debug[id.x] = float4(_VCoord[gid.x], 0.0f, 0.0f, 0.0f);
- }
- }
- GroupMemoryBarrierWithGroupSync();
- uint VerticesPerSection = _NumSegments + 1;
- if (id.x < _NumSamples && id.y < VerticesPerSection)
- {
- float3 norm = (_Segments[gid.y].x * _Normal[gid.x] + _Segments[gid.y].y * _Binormal[gid.x]) * _Thickness;
- _VertexBuffer[id.x * VerticesPerSection + id.y].Position = _Origin[gid.x] + norm;
- _VertexBuffer[id.x * VerticesPerSection + id.y].Normal = norm;
- _VertexBuffer[id.x * VerticesPerSection + id.y].TexCoord = float2(float(gid.y) / float(_NumSegments) * _UVScale.x, _VCoord[gid.x]);
- }
- if (id.x < _NumSamples - 1 && id.y < _NumSegments)
- {
- _IndexBuffer[(id.x * _NumSegments + id.y) * 6 + 0] = id.x * VerticesPerSection + id.y;
- _IndexBuffer[(id.x * _NumSegments + id.y) * 6 + 1] = id.x * VerticesPerSection + id.y + 1;
- _IndexBuffer[(id.x * _NumSegments + id.y) * 6 + 2] = (id.x + 1) * VerticesPerSection + id.y;
- _IndexBuffer[(id.x * _NumSegments + id.y) * 6 + 3] = id.x * VerticesPerSection + id.y + 1;
- _IndexBuffer[(id.x * _NumSegments + id.y) * 6 + 4] = (id.x + 1) * VerticesPerSection + id.y + 1;
- _IndexBuffer[(id.x * _NumSegments + id.y) * 6 + 5] = (id.x + 1) * VerticesPerSection + id.y;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement