ray-tracing-simple-lighting.azsl 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // AZSL version of the example raytracing shader found here:
  2. // https://github.com/microsoft/DirectX-Graphics-Samples/blob/master/Samples/Desktop/D3D12Raytracing/src/D3D12RaytracingSimpleLighting/Raytracing.hlsl
  3. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  4. List of intrinsic declarations used in this shader:
  5. struct RayDesc
  6. {
  7. float3 Origin;
  8. float TMin;
  9. float3 Direction;
  10. float TMax;
  11. };
  12. uint3 DispatchRaysIndex();
  13. uint3 DispatchRaysDimensions();
  14. Template<payload_t>
  15. void TraceRay(RaytracingAccelerationStructure AccelerationStructure,
  16. uint RayFlags,
  17. uint InstanceInclusionMask,
  18. uint RayContributionToHitGroupIndex,
  19. uint MultiplierForGeometryContributionToHitGroupIndex,
  20. uint MissShaderIndex,
  21. RayDesc Ray,
  22. inout payload_t Payload);
  23. struct BuiltInTriangleIntersectionAttributes
  24. {
  25. float2 barycentrics;
  26. };
  27. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  28. // [Atom-2078] TODO support using namespace
  29. // It's probably enough just to reemit this and don't make sense of it - for now
  30. // using namespace DirectX;
  31. struct SceneConstantBuffer
  32. {
  33. float4x4 projectionToWorld;
  34. float4 cameraPosition;
  35. float4 lightPosition;
  36. float4 lightAmbientColor;
  37. float4 lightDiffuseColor;
  38. };
  39. struct CubeConstantBuffer
  40. {
  41. float4 albedo;
  42. };
  43. struct Vertex
  44. {
  45. float3 position;
  46. float3 normal;
  47. };
  48. ShaderResourceGroupSemantic RaySemantic
  49. {
  50. FrequencyId = 0u;
  51. };
  52. ShaderResourceGroup RaySRG : RaySemantic
  53. {
  54. RaytracingAccelerationStructure Scene; // : register(t0, space0);
  55. RWTexture2D<float4> RenderTarget; // : register(u0);
  56. ByteAddressBuffer Indices; // : register(t1, space0);
  57. StructuredBuffer<Vertex> Vertices; // : register(t2, space0);
  58. ConstantBuffer<SceneConstantBuffer> g_sceneCB; // : register(b0);
  59. ConstantBuffer<CubeConstantBuffer> g_cubeCB; // : register(b1);
  60. };
  61. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. // Load three 16 bit indices from a byte addressed buffer.
  63. uint3 Load3x16BitIndices(uint offsetBytes)
  64. {
  65. uint3 indices_;
  66. // ByteAdressBuffer loads must be aligned at a 4 byte boundary.
  67. // Since we need to read three 16 bit indices: { 0, 1, 2 }
  68. // aligned at a 4 byte boundary as: { 0 1 } { 2 0 } { 1 2 } { 0 1 } ...
  69. // we will load 8 bytes (~ 4 indices { a b | c d }) to handle two possible index triplet layouts,
  70. // based on first index's offsetBytes being aligned at the 4 byte boundary or not:
  71. // Aligned: { 0 1 | 2 - }
  72. // Not aligned: { - 0 | 1 2 }
  73. const uint dwordAlignedOffset = offsetBytes & ~3;
  74. const uint2 four16BitIndices = RaySRG::Indices.Load2(dwordAlignedOffset);
  75. // Aligned: { 0 1 | 2 - } => retrieve first three 16bit indices
  76. if (dwordAlignedOffset == offsetBytes)
  77. {
  78. indices_.x = four16BitIndices.x & 0xffff;
  79. indices_.y = (four16BitIndices.x >> 16) & 0xffff;
  80. indices_.z = four16BitIndices.y & 0xffff;
  81. }
  82. else // Not aligned: { - 0 | 1 2 } => retrieve last three 16bit indices
  83. {
  84. indices_.x = (four16BitIndices.x >> 16) & 0xffff;
  85. indices_.y = four16BitIndices.y & 0xffff;
  86. indices_.z = (four16BitIndices.y >> 16) & 0xffff;
  87. }
  88. return indices_;
  89. }
  90. // [Atom-942] TODO support typedef
  91. // typedef BuiltInTriangleIntersectionAttributes MyAttributes;
  92. struct RayPayload
  93. {
  94. float4 color;
  95. };
  96. // Retrieve hit world position.
  97. float3 HitWorldPosition()
  98. {
  99. return WorldRayOrigin() + RayTCurrent() * WorldRayDirection();
  100. }
  101. // Retrieve attribute at a hit position interpolated from vertex attributes using the hit's barycentrics.
  102. float3 HitAttribute(float3 vertexAttribute[3], BuiltInTriangleIntersectionAttributes attr)
  103. {
  104. return vertexAttribute[0] +
  105. attr.barycentrics.x * (vertexAttribute[1] - vertexAttribute[0]) +
  106. attr.barycentrics.y * (vertexAttribute[2] - vertexAttribute[0]);
  107. }
  108. // Generate a ray in world space for a camera pixel corresponding to an index from the dispatched 2D grid.
  109. // TODO support inline ? (are raytraced shaders not always inlined??)
  110. // inline
  111. void GenerateCameraRay(uint2 index, out float3 origin, out float3 direction)
  112. {
  113. float2 xy = index + 0.5f; // center in the middle of the pixel.
  114. float2 screenPos = xy / DispatchRaysDimensions().xy * 2.0 - 1.0;
  115. // Invert Y for DirectX-style coordinates.
  116. screenPos.y = -screenPos.y;
  117. // Unproject the pixel coordinate into a ray.
  118. float4 world = mul(float4(screenPos, 0, 1), RaySRG::g_sceneCB.projectionToWorld);
  119. world.xyz /= world.w;
  120. origin = RaySRG::g_sceneCB.cameraPosition.xyz;
  121. direction = normalize(world.xyz - origin);
  122. }
  123. // Diffuse lighting calculation.
  124. float4 CalculateDiffuseLighting(float3 hitPosition, float3 normal)
  125. {
  126. float3 pixelToLight = normalize(RaySRG::g_sceneCB.lightPosition.xyz - hitPosition);
  127. // Diffuse contribution.
  128. float fNDotL = max(0.0f, dot(pixelToLight, normal));
  129. return RaySRG::g_cubeCB.albedo * RaySRG::g_sceneCB.lightDiffuseColor * fNDotL;
  130. }
  131. [shader("raygeneration")]
  132. void MyRaygenShader()
  133. {
  134. float3 rayDir;
  135. float3 origin;
  136. // Generate a ray for a camera pixel corresponding to an index from the dispatched 2D grid.
  137. GenerateCameraRay(DispatchRaysIndex().xy, origin, rayDir);
  138. // Trace the ray.
  139. // Set the ray's extents.
  140. RayDesc ray;
  141. ray.Origin = origin;
  142. ray.Direction = rayDir;
  143. // Set TMin to a non-zero small value to avoid aliasing issues due to floating - point errors.
  144. // TMin should be kept small to prevent missing geometry at close contact areas.
  145. ray.TMin = 0.001;
  146. ray.TMax = 10000.0;
  147. RayPayload payload_ = { float4(0, 0, 0, 0) };
  148. TraceRay(RaySRG::Scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, ~0, 0, 1, 0, ray, payload_);
  149. // Write the raytraced color to the output texture.
  150. RaySRG::RenderTarget[DispatchRaysIndex().xy] = payload_.color;
  151. }
  152. [shader("closesthit")]
  153. void MyClosestHitShader(inout RayPayload a_payload, in BuiltInTriangleIntersectionAttributes attr)
  154. {
  155. float3 hitPosition = HitWorldPosition();
  156. // Get the base index of the triangle's first 16 bit index.
  157. uint indexSizeInBytes = 2;
  158. uint indicesPerTriangle = 3;
  159. uint triangleIndexStride = indicesPerTriangle * indexSizeInBytes;
  160. uint baseIndex = PrimitiveIndex() * triangleIndexStride;
  161. // Load up 3 16 bit indices for the triangle.
  162. const uint3 indices_ = Load3x16BitIndices(baseIndex);
  163. // Retrieve corresponding vertex normals for the triangle vertices.
  164. float3 vertexNormals[3] = {
  165. RaySRG::Vertices[indices_[0]].normal,
  166. RaySRG::Vertices[indices_[1]].normal,
  167. RaySRG::Vertices[indices_[2]].normal
  168. };
  169. // Compute the triangle's normal.
  170. // This is redundant and done for illustration purposes
  171. // as all the per-vertex normals are the same and match triangle's normal in this sample.
  172. float3 triangleNormal = HitAttribute(vertexNormals, attr);
  173. float4 diffuseColor = CalculateDiffuseLighting(hitPosition, triangleNormal);
  174. float4 color = RaySRG::g_sceneCB.lightAmbientColor + diffuseColor;
  175. a_payload.color = color;
  176. }
  177. [shader("miss")]
  178. void MyMissShader(inout RayPayload a_payload)
  179. {
  180. float4 background = float4(0.0f, 0.2f, 0.4f, 1.0f);
  181. a_payload.color = background;
  182. }