/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include ShaderResourceGroup PassSrg : SRG_PerPass { StructuredBuffer m_sourceVertexData; RWStructuredBuffer m_targetVertexData; StructuredBuffer m_instanceOffsetData; float m_frameTime; uint m_vertexCountPerInstance; uint m_targetVertexStridePerInstance; } class ContinuousSineRng { uint m_seed; float m_timeshift; void Initialize(float3 position, uint instanceIndex, float timeshift) { m_seed = 0; m_seed ^= asuint(position.x); Xorshift(m_seed); m_seed ^= asuint(position.y); Xorshift(m_seed); m_seed ^= asuint(position.z); Xorshift(m_seed); m_seed ^= instanceIndex; Xorshift(m_seed); m_timeshift = timeshift; } float GetRandomNormalizedFloat() { // Duration in seconds after which the animation repeats float animationDuration = (Xorshift(m_seed) % 60 + 120) / 60.f; // The float values passed to the sin-function should not be too large, otherwise the result is not continuous uint seedSmall = m_seed % 1024; float timeshiftSmall = (m_timeshift % animationDuration) / animationDuration * TWO_PI; return sin(seedSmall + timeshiftSmall) * 0.5f + 0.5f; } float3 GetRandomUnitSphereDirection() { float z = GetRandomNormalizedFloat() * 2.f - 1.f; float phi = GetRandomNormalizedFloat() * TWO_PI; float rxy = sqrt(1.f - z * z); float x = rxy * cos(phi); float y = rxy * sin(phi); return normalize(float3(x, y, z)); } }; [numthreads(64, 1, 1)] void AnimateVertices(uint3 dispatchId : SV_DispatchThreadID) { uint instanceIndex = dispatchId.x / PassSrg::m_vertexCountPerInstance; uint inputIndex = dispatchId.x % PassSrg::m_vertexCountPerInstance; uint outputIndex = instanceIndex * PassSrg::m_targetVertexStridePerInstance + inputIndex; ContinuousSineRng rng; rng.Initialize(PassSrg::m_sourceVertexData[inputIndex], instanceIndex, PassSrg::m_frameTime); // Animated the vertices by displacing each vertex in a random direction by a random amount float3 animationMoveDirection = rng.GetRandomUnitSphereDirection(); float animationMoveAmount = rng.GetRandomNormalizedFloat() * 0.02f; // Need to move vertices per instance in the compute shader since CLAS does not have a separate transform float3 vertexBaseLocation = PassSrg::m_instanceOffsetData[instanceIndex] + PassSrg::m_sourceVertexData[inputIndex]; PassSrg::m_targetVertexData[outputIndex] = vertexBaseLocation + animationMoveDirection * animationMoveAmount; }