HairRenderingFillPPLL.azsl 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Modifications Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. //---------------------------------------------------------------------------------------
  9. // Shader code related to per-pixel linked lists.
  10. //-------------------------------------------------------------------------------------
  11. //
  12. // Copyright (c) 2019 Advanced Micro Devices, Inc. All rights reserved.
  13. //
  14. // Permission is hereby granted, free of charge, to any person obtaining a copy
  15. // of this software and associated documentation files (the "Software"), to deal
  16. // in the Software without restriction, including without limitation the rights
  17. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  18. // copies of the Software, and to permit persons to whom the Software is
  19. // furnished to do so, subject to the following conditions:
  20. //
  21. // The above copyright notice and this permission notice shall be included in
  22. // all copies or substantial portions of the Software.
  23. //
  24. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  27. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  28. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  29. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  30. // THE SOFTWARE.
  31. //
  32. //==============================================================================
  33. #include <Atom/Features/SrgSemantics.azsli>
  34. #include <HairRenderingSrgs.azsli>
  35. //!------------------------------ SRG Structure --------------------------------
  36. //! Per pass SRG the holds the dynamic shared read-write buffer shared
  37. //! across all dispatches and draw calls and used for all the dynamic buffers
  38. //! that can change between passes due to the application of skinning, simulation
  39. //! and physics affect and is then read by the rendering shaders.
  40. ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback
  41. {
  42. //! This shared buffer needs to match the SharedBuffer structure
  43. //! shared between all draw calls / dispatches for the hair skinning
  44. StructuredBuffer<int> m_skinnedHairSharedBuffer;
  45. //! Per Pixel Linked List data used by the render raster pass to generate per pixel
  46. //! hair OIT data and shade it in the full screen resolve pass.
  47. //! Originally used space3 for raster pass linked lists and space0 for the resolve pass.
  48. RWTexture2D<uint> m_fragmentListHead;
  49. RWStructuredBuffer<PPLL_STRUCT> m_linkedListNodes;
  50. RWBuffer<uint> m_linkedListCounter;
  51. }
  52. //------------------------------------------------------------------------------
  53. // Originally marked for the TressFX raster pass at space3
  54. #define RWFragmentListHead PassSrg::m_fragmentListHead
  55. #define LinkedListUAV PassSrg::m_linkedListNodes
  56. #define LinkedListCounter PassSrg::m_linkedListCounter
  57. //------------------------------------------------------------------------------
  58. //!=============================================================================
  59. //!
  60. //! Per Instance Space 1 - Dynamic Buffers for Hair Skinning and Simulation
  61. //!
  62. //! ----------------------------------------------------------------------------
  63. struct StrandLevelData
  64. {
  65. float4 skinningQuat;
  66. float4 vspQuat;
  67. float4 vspTranslation;
  68. };
  69. //!------------------------------ SRG Structure --------------------------------
  70. //! Per instance/draw SRG representing dynamic read-write set of buffers
  71. //! that are unique per instance and are shared and changed between passes due
  72. //! to the application of skinning, simulation and physics affect.
  73. //! It is then also read by the rendering shaders.
  74. //! This Srg is NOT shared by the passes since it requires having barriers between
  75. //! both passes and draw calls, instead, all buffers are allocated from a single
  76. //! shared buffer (through BufferViews) and that buffer is then shared between
  77. //! the passes via the PerPass Srg frequency.
  78. ShaderResourceGroup HairDynamicDataSrg : SRG_PerObject // space 1 - per instance / object
  79. {
  80. Buffer<float4> m_hairVertexPositions;
  81. Buffer<float4> m_hairVertexTangents;
  82. //! Per hair object offset to the start location of each buffer within
  83. //! 'm_skinnedHairSharedBuffer'. The offset is in bytes!
  84. uint m_positionBufferOffset;
  85. uint m_tangentBufferOffset;
  86. };
  87. //------------------------------------------------------------------------------
  88. // Allow for the code to run with minimal changes - skinning / simulation compute passes
  89. // Usage of per-instance buffer
  90. #define g_GuideHairVertexPositions HairDynamicDataSrg::m_hairVertexPositions
  91. #define g_GuideHairVertexTangents HairDynamicDataSrg::m_hairVertexTangents
  92. //==============================================================================
  93. #include <HairStrands.azsli> // VS resides here
  94. //==============================================================================
  95. // Allocate a new fragment location in fragment color, depth, and link buffers
  96. int AllocateFragment(int2 vScreenAddress)
  97. {
  98. uint newAddress;
  99. InterlockedAdd(LinkedListCounter[0], 1, newAddress);
  100. if (newAddress < 0 || newAddress >= NodePoolSize)
  101. newAddress = FRAGMENT_LIST_NULL;
  102. return newAddress;
  103. }
  104. // Insert a new fragment at the head of the list. The old list head becomes the
  105. // the second fragment in the list and so on. Return the address of the *old* head.
  106. int MakeFragmentLink(int2 vScreenAddress, int nNewHeadAddress)
  107. {
  108. int nOldHeadAddress;
  109. InterlockedExchange(RWFragmentListHead[vScreenAddress], nNewHeadAddress, nOldHeadAddress);
  110. return nOldHeadAddress;
  111. }
  112. // Write fragment attributes to list location.
  113. void WriteFragmentAttributes(int nAddress, int nPreviousLink, float4 vData, float3 vColor3, float fDepth)
  114. {
  115. PPLL_STRUCT element;
  116. element.data = PackFloat4IntoUint(vData);
  117. element.color = PackFloat3ByteIntoUint(vColor3, RenderParamsIndex);
  118. element.depth = asuint(saturate(fDepth));
  119. element.uNext = nPreviousLink;
  120. LinkedListUAV[nAddress] = element;
  121. }
  122. // Use the following structure for debug purposes for outputting test results to RT
  123. // You can use depth, color or both when outputing and testing the calculation.
  124. struct PSOutput
  125. {
  126. float4 m_color : SV_Target0;
  127. float m_depth : SV_Depth;
  128. };
  129. //////////////////////////////////////////////////////////////
  130. // PPLL Fill PS
  131. // First pass of PPLL implementation
  132. // Builds up the linked list of hair fragments
  133. [earlydepthstencil]
  134. void PPLLFillPS(PS_INPUT_HAIR input)
  135. {
  136. // Strand Color read in is either the BaseMatColor, or BaseMatColor modulated with a color read
  137. // from texture in the vertex shader for base color along with modulation by the tip color
  138. float4 strandColor = float4(input.StrandColor.rgb, MatBaseColor.a);
  139. // If we are supporting strand UV texturing, further blend in the texture color/alpha
  140. // Do this while computing NDC and coverage to hide latency from texture lookup
  141. if (EnableStrandUV)
  142. {
  143. // Grab the uv in case we need it
  144. float2 uv = float2(input.Tangent.w, input.StrandColor.w);
  145. // Apply StrandUVTiling
  146. float2 strandUV = float2(uv.x, (uv.y * StrandUVTilingFactor) - floor(uv.y * StrandUVTilingFactor));
  147. strandColor.rgb *= StrandAlbedoTexture.Sample(LinearWrapSampler, strandUV).rgb;
  148. }
  149. //////////////////////////////////////////////////////////////////////
  150. // [To Do] Hair: anti aliasing via coverage requires work and is disabled for now
  151. // float3 vNDC = ScreenPosToNDC(PassSrg::m_linearDepth, input.Position.xy, input.Position.z);
  152. // uint2 dimensions;
  153. // PassSrg::m_linearDepth.GetDimensions(dimensions.x, dimensions.y);
  154. // float coverage = ComputeCoverage(input.p0p1.xy, input.p0p1.zw, vNDC.xy, float2(dimensions.x, dimensions.y));
  155. float coverage = 1.0;
  156. /////////////////////////////////////////////////////////////////////
  157. // Update the alpha to have proper value (accounting for coverage, base alpha, and strand alpha)
  158. float alpha = coverage * strandColor.w;
  159. // Early out
  160. if (alpha < 1.f / 255.f)
  161. {
  162. discard;
  163. }
  164. // Get the screen address
  165. int2 vScreenAddress = int2(input.Position.xy);
  166. // Allocate a new fragment
  167. int nNewFragmentAddress = AllocateFragment(vScreenAddress);
  168. int nOldFragmentAddress = MakeFragmentLink(vScreenAddress, nNewFragmentAddress);
  169. WriteFragmentAttributes(nNewFragmentAddress, nOldFragmentAddress,
  170. float4(input.Tangent.xyz * 0.5 + float3(0.5, 0.5, 0.5), alpha),
  171. strandColor.xyz,
  172. input.Position.z
  173. );
  174. }