You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/AtomTressFX/Assets/Shaders/HairComputeSrgs.azsli

217 lines
9.0 KiB
Plaintext

/*
* Modifications 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) AND MIT
*
*/
//-----------------------------------------------------------------------------------------------------------
//
// Copyright (c) 2019 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//------------------------------------------------------------------------------
// File: HairComputeSrgs.azsli
//
// Declarations of SRGs used by the hair shaders.
//------------------------------------------------------------------------------
#pragma once
#include <Atom/Features/SrgSemantics.azsli>
// Whether bones are specified by dual quaternion.
// This option is not currently functional.
#define TRESSFX_DQ 0
//! notice - the following constants need to match what appears in AMD_TressFX.h
#define AMD_TRESSFX_MAX_HAIR_GROUP_RENDER 16
#define AMD_TRESSFX_MAX_NUM_BONES 512
#define CM_TO_METERS 1.0
#define METERS_TO_CM 1.0
//#define CM_TO_METERS 0.01
//#define METERS_TO_CM 100.0
// The following macro is not being used yet due to limitation of the C preprocessor
// mcpp that creates a shader compilation fault not being able to extend the macro.
#define BYTE_OFFSET(index,baseOffset) ((baseOffset >> 2) + (index << 2))
//!------------------------------ SRG Structure --------------------------------
//! Per pass SRG the holds the dynamic read-write buffer shared across all
//! dispatches and draw calls and used as the memory pool for all the dynamic
//! buffer that can change between passes due to the application of skinning,
//! simulation and physics affect and read by the rendering shaders.
ShaderResourceGroup PassSrg : SRG_PerPass
{
RWStructuredBuffer<int> m_skinnedHairSharedBuffer;
}
//!=============================================================================
//!
//! Per Instance Space 1 - Dynamic Buffers for Hair Skinning and Simulation
//!
//! ----------------------------------------------------------------------------
struct StrandLevelData
{
float4 skinningQuat;
float4 vspQuat;
float4 vspTranslation;
};
//!------------------------------ SRG Structure --------------------------------
//! Per instance/draw SRG representing dynamic read-write set of buffers
//! that are unique per instance and are shared and changed between passes due
//! to the application of skinning, simulation and physics affect.
//! It is then also read by the rendering shaders.
//! This Srg is NOT shared by the passes since it requires having barriers between
//! both passes and draw calls, instead, all buffers are allocated from a single
//! shared buffer (through BufferViews) and that buffer is then shared between
//! the passes via the PerPass Srg frequency.
ShaderResourceGroup HairDynamicDataSrg : SRG_PerObject // space 1 - per instance / object
{
RWBuffer<float4> m_hairVertexPositions;
RWBuffer<float4> m_hairVertexPositionsPrev;
RWBuffer<float4> m_hairVertexPositionsPrevPrev;
RWBuffer<float4> m_hairVertexTangents;
RWStructuredBuffer<StrandLevelData> m_strandLevelData;
//! Per hair object offset to the start location of each buffer within
//! 'm_skinnedHairSharedBuffer'. The offset is in bytes!
uint m_positionBufferOffset;
uint m_positionPrevBufferOffset;
uint m_positionPrevPrevBufferOffset;
uint m_tangentBufferOffset;
uint m_strandLevelDataOffset;
};
//------------------------------------------------------------------------------
// Allow for the code to run with minimal changes - skinning / simulation compute passes
// Usage of per-instance buffer
#define g_HairVertexPositions HairDynamicDataSrg::m_hairVertexPositions
#define g_HairVertexPositionsPrev HairDynamicDataSrg::m_hairVertexPositionsPrev
#define g_HairVertexPositionsPrevPrev HairDynamicDataSrg::m_hairVertexPositionsPrevPrev
#define g_HairVertexTangents HairDynamicDataSrg::m_hairVertexTangents
#define g_StrandLevelData HairDynamicDataSrg::m_strandLevelData
//------------------------------------------------------------------------------
float3 GetSharedVector3(int offset)
{
return float3(
asfloat(PassSrg::m_skinnedHairSharedBuffer[offset]),
asfloat(PassSrg::m_skinnedHairSharedBuffer[offset + 1]),
asfloat(PassSrg::m_skinnedHairSharedBuffer[offset + 2])
);// *CM_TO_METERS; // convert to meters when using
}
void SetSharedVector3(int offset, float3 pos)
{
// pos.xyz *= METERS_TO_CM; // convert to cm when storing
PassSrg::m_skinnedHairSharedBuffer[offset] = asint(pos.x);
PassSrg::m_skinnedHairSharedBuffer[offset+1] = asint(pos.y);
PassSrg::m_skinnedHairSharedBuffer[offset+2] = asint(pos.z);
}
float4 GetSharedVector4(int offset)
{
return float4(
float3(
asfloat(PassSrg::m_skinnedHairSharedBuffer[offset]),
asfloat(PassSrg::m_skinnedHairSharedBuffer[offset + 1]),
asfloat(PassSrg::m_skinnedHairSharedBuffer[offset + 2])
),// * CM_TO_METERS, // convert to meters when using
asfloat(PassSrg::m_skinnedHairSharedBuffer[offset + 3])
);
}
void SetSharedVector4(int offset, float4 pos)
{
// pos.xyz *= METERS_TO_CM; // convert to cm when storing
PassSrg::m_skinnedHairSharedBuffer[offset] = asint(pos.x);
PassSrg::m_skinnedHairSharedBuffer[offset+1] = asint(pos.y);
PassSrg::m_skinnedHairSharedBuffer[offset+2] = asint(pos.z);
PassSrg::m_skinnedHairSharedBuffer[offset+3] = asint(pos.w);
}
//------------------------------------------------------------------------------
//! Getter/setter of position / tangent in the global shared buffer based on the
//! per-instance offset of the instance positions buffer within the global shared buffer
void SetSharedPosition3(int vertexIndex, float3 position)
{
int vertexOffset = (HairDynamicDataSrg::m_positionBufferOffset >> 2) + (vertexIndex << 2);
SetSharedVector3(vertexOffset, position);
}
void SetSharedPosition(int vertexIndex, float4 position)
{
int vertexOffset = (HairDynamicDataSrg::m_positionBufferOffset >> 2) + (vertexIndex << 2);
SetSharedVector4(vertexOffset, position);
}
float4 GetSharedPosition(int vertexIndex)
{
int vertexOffset = (HairDynamicDataSrg::m_positionBufferOffset >> 2) + (vertexIndex << 2);
return GetSharedVector4(vertexOffset);
}
void SetSharedPrevPosition(int vertexIndex, float4 position)
{
int vertexOffset = (HairDynamicDataSrg::m_positionPrevBufferOffset >> 2) + (vertexIndex << 2);
SetSharedVector4(vertexOffset, position);
}
float4 GetSharedPrevPosition(int vertexIndex)
{
int vertexOffset = (HairDynamicDataSrg::m_positionPrevBufferOffset >> 2) + (vertexIndex << 2);
return GetSharedVector4(vertexOffset);
}
void SetSharedPrevPrevPosition(int vertexIndex, float4 position)
{
int vertexOffset = (HairDynamicDataSrg::m_positionPrevPrevBufferOffset >> 2) + (vertexIndex << 2);
SetSharedVector4(vertexOffset, position);
}
float4 GetSharedPrevPrevPosition(int vertexIndex)
{
int vertexOffset = (HairDynamicDataSrg::m_positionPrevPrevBufferOffset >> 2) + (vertexIndex << 2);
return GetSharedVector4(vertexOffset);
}
void SetSharedTangent(int tangentIndex, float3 currentTangent)
{
int tangentOffset = (HairDynamicDataSrg::m_tangentBufferOffset >> 2) + (tangentIndex << 2);
PassSrg::m_skinnedHairSharedBuffer[tangentOffset] = asint(currentTangent.x);
PassSrg::m_skinnedHairSharedBuffer[tangentOffset+1] = asint(currentTangent.y);
PassSrg::m_skinnedHairSharedBuffer[tangentOffset+2] = asint(currentTangent.z);
}
float3 GetSharedTangent(int tangentIndex)
{
int tangentOffset = (HairDynamicDataSrg::m_tangentBufferOffset >> 2) + (tangentIndex << 2);
return float3(
asfloat(PassSrg::m_skinnedHairSharedBuffer[tangentOffset]),
asfloat(PassSrg::m_skinnedHairSharedBuffer[tangentOffset + 1]),
asfloat(PassSrg::m_skinnedHairSharedBuffer[tangentOffset + 2])
);
}