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
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;
|
||
|
|
}
|
||
|
|
}
|