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.

169 lines
6.8 KiB
Plaintext

3 years ago
//---------------------------------------------------------------------------------------
// Shader code related to simulating hair strands in compute.
//-------------------------------------------------------------------------------------
//
// 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.
//
#pragma kernel InitializeSignedDistanceField
#pragma kernel ConstructSignedDistanceField
#pragma kernel FinalizeSignedDistanceField
#pragma kernel CollideWithVerletNodesKernel
#pragma multi_compile __ USE_FORWARD_COLLISION
#include "VerletSimulationInclude.hlsl"
#include "Thread.hlsl"
// One thread for each cell.
THREAD_SIZE_LARGE
void InitializeSignedDistanceField(uint GIndex : SV_GroupIndex,
uint3 GId : SV_GroupID,
uint3 DTid : SV_DispatchThreadID)
{
int numSdfCells = g_NumCellsX * g_NumCellsY * g_NumCellsZ;
int sdfCellIndex = GId.x * THREAD_SIZE_LARGE_VAL + GIndex;
if (sdfCellIndex >= numSdfCells) return;
g_SignedDistanceField[sdfCellIndex] = FloatFlip3(INITIAL_DISTANCE);
}
int3 GetLocalCellPositionFromIndex(uint localCellIndex, int3 cellsPerDimensionLocal)
{
uint cellsPerLine = (uint)cellsPerDimensionLocal.x;
uint cellsPerPlane = (uint)(cellsPerDimensionLocal.x * cellsPerDimensionLocal.y);
uint numPlanesZ = localCellIndex / cellsPerPlane;
uint remainder = localCellIndex % cellsPerPlane;
uint numLinesY = remainder / cellsPerLine;
uint numCellsX = remainder % cellsPerLine;
return int3((int)numCellsX, (int)numLinesY, (int)numPlanesZ);
}
static const uint out_struc_stride = 32;
uniform int numTriangles;
uniform float4x4 rootMatrix;
// One thread per each triangle
THREAD_SIZE_LARGE
void ConstructSignedDistanceField(uint GIndex : SV_GroupIndex,
uint3 GId : SV_GroupID,
uint3 DTid : SV_DispatchThreadID)
{
int triangleIndex = GId.x * THREAD_SIZE_LARGE_VAL + GIndex;
if (triangleIndex >= numTriangles)
return;
int indexFormatMultiplier = 4;
uint index0 = g_TrimeshVertexIndices.Load((triangleIndex * 3 + 0) * indexFormatMultiplier);
uint index1 = g_TrimeshVertexIndices.Load((triangleIndex * 3 + 1) * indexFormatMultiplier);
uint index2 = g_TrimeshVertexIndices.Load((triangleIndex * 3 + 2) * indexFormatMultiplier);
float3 tri0 = mul(rootMatrix, float4(collMeshVertexPositions[index0].sourceVertex, 1)).xyz;
float3 tri1 = mul(rootMatrix, float4(collMeshVertexPositions[index1].sourceVertex, 1)).xyz;
float3 tri2 = mul(rootMatrix, float4(collMeshVertexPositions[index2].sourceVertex, 1)).xyz;
float3 aabbMin = min(tri0, min(tri1, tri2)) - float3(MARGIN, MARGIN, MARGIN);
float3 aabbMax = max(tri0, max(tri1, tri2)) + float3(MARGIN, MARGIN, MARGIN);
int3 gridMin = GetSdfCoordinates(aabbMin) - GRID_MARGIN;
int3 gridMax = GetSdfCoordinates(aabbMax) + GRID_MARGIN;
gridMin.x = max(0, min(gridMin.x, g_NumCellsX - 1));
gridMin.y = max(0, min(gridMin.y, g_NumCellsY - 1));
gridMin.z = max(0, min(gridMin.z, g_NumCellsZ - 1));
gridMax.x = max(0, min(gridMax.x, g_NumCellsX - 1));
gridMax.y = max(0, min(gridMax.y, g_NumCellsY - 1));
gridMax.z = max(0, min(gridMax.z, g_NumCellsZ - 1));
for (int z = gridMin.z; z <= gridMax.z; ++z)
for (int y = gridMin.y; y <= gridMax.y; ++y)
for (int x = gridMin.x; x <= gridMax.x; ++x)
{
int3 gridCellCoordinate = int3(x, y, z);
int gridCellIndex = GetSdfCellIndex(gridCellCoordinate);
float3 cellPosition = GetSdfCellPosition(gridCellCoordinate);
float distance = SignedDistancePointToTriangle(cellPosition, tri0, tri1, tri2);
//distance -= MARGIN;
uint distanceAsUint = FloatFlip3(distance);
InterlockedMin(g_SignedDistanceField[gridCellIndex], distanceAsUint);
}
}
// One thread per each cell.
THREAD_SIZE_LARGE
void FinalizeSignedDistanceField(uint GIndex : SV_GroupIndex,
uint3 GId : SV_GroupID,
uint3 DTid : SV_DispatchThreadID)
{
int numSdfCells = g_NumCellsX * g_NumCellsY * g_NumCellsZ;
int sdfCellIndex = GId.x * THREAD_SIZE_LARGE_VAL + GIndex;
if (sdfCellIndex >= numSdfCells) return;
uint distance = g_SignedDistanceField[sdfCellIndex];
g_SignedDistanceField[sdfCellIndex] = IFloatFlip3(distance);
}
uint nodesCount;
#pragma warning( disable : 4714 )
#pragma warning( disable : 4000 )
THREAD_SIZE_LARGE
void CollideWithVerletNodesKernel(uint3 id : SV_DispatchThreadID)
{
int nodeIndex = id.x;
if (nodeIndex >= (int)nodesCount) return;
VerletNode currentNode = verletNodes[nodeIndex];
float3 hairVertex = currentNode.position;
if (isFixed(currentNode)) return;
int didSDFCollide = 0;
#if defined(USE_FORWARD_COLLISION)
CollideHairVerticesWithSdf_forward(didSDFCollide, hairVertex, 0);//Out hairVertex
#else
collideWithSDF(didSDFCollide, hairVertex, 0);//Out hairVertex
#endif
const float3 collisionDiff = currentNode.position - hairVertex;
if (didSDFCollide == 1)
{
const uint furMeshLeftIndex = nodeIndex * 2 * furMeshBufferStride;
const uint furMeshRightIndex = (nodeIndex * 2 + 1) * furMeshBufferStride;
const float3 meshVertexPositionLeft = loadSourceVertex(furMeshLeftIndex);
const float3 meshVertexPositionRight = loadSourceVertex(furMeshRightIndex);
writeVector3(furMeshLeftIndex, 0, meshVertexPositionLeft + collisionDiff);
writeVector3(furMeshRightIndex, 0, meshVertexPositionRight + collisionDiff);
currentNode.position = hairVertex;
verletNodes[nodeIndex] = currentNode;
}
}