diff options
Diffstat (limited to 'NvBlast/sdk/extensions/shaders/source/NvBlastExtRadialShaders.cpp')
| -rw-r--r-- | NvBlast/sdk/extensions/shaders/source/NvBlastExtRadialShaders.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/NvBlast/sdk/extensions/shaders/source/NvBlastExtRadialShaders.cpp b/NvBlast/sdk/extensions/shaders/source/NvBlastExtRadialShaders.cpp new file mode 100644 index 0000000..00d1010 --- /dev/null +++ b/NvBlast/sdk/extensions/shaders/source/NvBlastExtRadialShaders.cpp @@ -0,0 +1,205 @@ +/* +* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include "NvBlastExtDamageShaders.h" +#include "NvBlastIndexFns.h" +#include "NvBlastMath.h" +#include "NvBlastGeometry.h" +#include "NvBlastAssert.h" +#include "NvBlast.h" +#include "stdlib.h" // for abs() on linux + +using namespace Nv::Blast; +using namespace Nv::Blast::VecMath; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Profiles +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef float(*ProfileFunction)(float, float, float, float); + +float falloffProfile(float min, float max, float x, float f = 1.0f) +{ + if (x > max) return 0.0f; + if (x < min) return f; + + float y = 1.0f - (x - min) / (max - min); + return y * f; +} + +float cutterProfile(float min, float max, float x, float f = 1.0f) +{ + if (x > max || x < min) return 0.0f; + + return f; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Radial Graph Shader Template +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template <ProfileFunction profile> +void RadialProfileGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) +{ + const uint32_t* graphNodeIndexLinks = actor->graphNodeIndexLinks; + const uint32_t firstGraphNodeIndex = actor->firstGraphNodeIndex; + const uint32_t* adjacencyPartition = actor->adjacencyPartition; + const uint32_t* adjacentNodeIndices = actor->adjacentNodeIndices; + const uint32_t* adjacentBondIndices = actor->adjacentBondIndices; + const NvBlastBond* assetBonds = actor->assetBonds; + const float* familyBondHealths = actor->familyBondHealths; + + const NvBlastExtRadialDamageDesc* damageData = reinterpret_cast<const NvBlastExtRadialDamageDesc*>(params->damageDescBuffer); + const uint32_t damageCount = params->damageDescCount; + + uint32_t outCount = 0; + + uint32_t currentNodeIndex = firstGraphNodeIndex; + while (!Nv::Blast::isInvalidIndex(currentNodeIndex)) + { + for (uint32_t adj = adjacencyPartition[currentNodeIndex]; adj < adjacencyPartition[currentNodeIndex + 1]; adj++) + { + uint32_t adjacentNodeIndex = adjacentNodeIndices[adj]; + if (currentNodeIndex < adjacentNodeIndex) + { + uint32_t bondIndex = adjacentBondIndices[adj]; + + // skip bonds that are already broken or were visited already + // TODO: investigate why testing against health > -1.0f seems slower + // could reuse the island edge bitmap instead + if ((familyBondHealths[bondIndex] > 0.0f)) + { + + const NvBlastBond& bond = assetBonds[bondIndex]; + + float totalBondDamage = 0.0f; + + for (uint32_t damageIndex = 0; damageIndex < damageCount; damageIndex++) + { + const NvBlastExtRadialDamageDesc& damage = damageData[damageIndex]; + + float relativePosition[3]; + sub(damage.position, bond.centroid, relativePosition); + float distance = sqrtf(dot(relativePosition, relativePosition)); + + float dir[3]; + normal(relativePosition, dir); + + totalBondDamage += profile(damage.minRadius, damage.maxRadius, distance, damage.compressive); + } + + if (totalBondDamage > 0.0f) + { + NvBlastBondFractureData& outCommand = commandBuffers->bondFractures[outCount++]; + outCommand.nodeIndex0 = currentNodeIndex; + outCommand.nodeIndex1 = adjacentNodeIndex; + outCommand.health = totalBondDamage; + } + } + } + } + currentNodeIndex = graphNodeIndexLinks[currentNodeIndex]; + } + + commandBuffers->bondFractureCount = outCount; + commandBuffers->chunkFractureCount = 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Radial Single Shader Template +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template <ProfileFunction profile> +void RadialProfileSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) +{ + uint32_t chunkFractureCount = 0; + const uint32_t chunkIndex = actor->chunkIndex; + const NvBlastChunk* assetChunks = actor->assetChunks; + const NvBlastChunk& chunk = assetChunks[chunkIndex]; + + float totalDamage = 0.0f; + for (uint32_t i = 0; i < params->damageDescCount; ++i) + { + const NvBlastExtRadialDamageDesc& damage = reinterpret_cast<const NvBlastExtRadialDamageDesc*>(params->damageDescBuffer)[i]; + + float relativePosition[3]; + sub(damage.position, chunk.centroid, relativePosition); + float distance = sqrtf(dot(relativePosition, relativePosition)); + + totalDamage += profile(damage.minRadius, damage.maxRadius, distance, damage.compressive); + } + + if (totalDamage > 0.0f) + { + NvBlastChunkFractureData& frac = commandBuffers->chunkFractures[chunkFractureCount++]; + frac.chunkIndex = chunkIndex; + frac.health = totalDamage; + } + + commandBuffers->bondFractureCount = 0; + commandBuffers->chunkFractureCount = chunkFractureCount; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Shader Instantiation +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void NvBlastExtFalloffGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileGraphShader<falloffProfile>(commandBuffers, actor, params); +} + +void NvBlastExtFalloffSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileSubgraphShader<falloffProfile>(commandBuffers, actor, params); +} + +void NvBlastExtCutterGraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileGraphShader<cutterProfile>(commandBuffers, actor, params); +} + +void NvBlastExtCutterSubgraphShader(NvBlastFractureBuffers* commandBuffers, const NvBlastSubgraphShaderActor* actor, const NvBlastProgramParams* params) +{ + RadialProfileSubgraphShader<cutterProfile>(commandBuffers, actor, params); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Helper Functions +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool NvBlastExtDamageActorRadialFalloff(NvBlastActor* actor, NvBlastFractureBuffers* buffers, const NvBlastExtRadialDamageDesc* damageDescBuffer, uint32_t damageDescCount, const NvBlastExtMaterial* material, NvBlastLog logFn, NvBlastTimers* timers) +{ + NvBlastDamageProgram program = + { + NvBlastExtFalloffGraphShader, + NvBlastExtFalloffSubgraphShader + }; + + NvBlastProgramParams params = + { + damageDescBuffer, + damageDescCount, + material + }; + + NvBlastActorGenerateFracture(buffers, actor, program, ¶ms, logFn, timers); + if (buffers->bondFractureCount > 0 || buffers->chunkFractureCount > 0) + { + NvBlastActorApplyFracture(nullptr, actor, buffers, logFn, timers); + return true; + } + + return false; +}
\ No newline at end of file |