RtMaterialFetch.hlsl 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Shaders/Include/MiscRendererTypes.h>
  7. #include <AnKi/Shaders/Include/GpuSceneTypes.h>
  8. #include <AnKi/Shaders/Common.hlsl>
  9. #include <AnKi/Shaders/LightFunctions.hlsl>
  10. #include <AnKi/Shaders/Sky.hlsl>
  11. struct [raypayload] RtMaterialFetchRayPayload
  12. {
  13. // Use FP32 on D3D because FP16 crashes at least on nVidia
  14. #if ANKI_GR_BACKEND_VULKAN
  15. # define PAYLOAD_SCALAR F16
  16. #else
  17. # define PAYLOAD_SCALAR F32
  18. #endif
  19. vector<PAYLOAD_SCALAR, 3> m_diffuseColor : write(closesthit, miss): read(caller);
  20. vector<PAYLOAD_SCALAR, 3> m_worldNormal : write(closesthit, miss): read(caller);
  21. vector<PAYLOAD_SCALAR, 3> m_emission : write(closesthit, miss): read(caller);
  22. PAYLOAD_SCALAR m_textureLod : write(caller): read(closesthit);
  23. F32 m_rayT : write(closesthit, miss): read(caller);
  24. #undef PAYLOAD_SCALAR
  25. };
  26. // Have a common resouce interface for all shaders. It should be compatible between all ray shaders in DX and VK
  27. #if ANKI_RAY_GEN_SHADER || defined(INCLUDE_ALL)
  28. # define SPACE space2
  29. ConstantBuffer<GlobalRendererConstants> g_globalRendererConstants : register(b0, SPACE);
  30. // SRVs
  31. RaytracingAccelerationStructure g_tlas : register(t0, SPACE);
  32. Texture2D<Vec4> g_envMap : register(t1, SPACE);
  33. Texture2D<Vec4> g_shadowAtlasTex : register(t2, SPACE);
  34. # if !defined(CLIPMAP_VOLUME)
  35. StructuredBuffer<GpuSceneGlobalIlluminationProbe> g_giProbes : register(t3, SPACE);
  36. Texture2D<Vec4> g_depthTex : register(t4, SPACE);
  37. Texture2D<Vec4> g_gbufferRt1 : register(t5, SPACE);
  38. Texture2D<Vec4> g_gbufferRt2 : register(t6, SPACE);
  39. StructuredBuffer<PixelFailedSsr> g_pixelsFailedSsr : register(t7, SPACE);
  40. # endif
  41. // Output of GpuVisibilityLocalLights:
  42. StructuredBuffer<GpuSceneLight> g_lights : register(t8, SPACE);
  43. StructuredBuffer<U32> g_lightIndexCountsPerCell : register(t9, SPACE);
  44. StructuredBuffer<U32> g_lightIndexOffsetsPerCell : register(t10, SPACE);
  45. StructuredBuffer<U32> g_lightIndexList : register(t11, SPACE);
  46. // UAVs
  47. # if defined(CLIPMAP_VOLUME)
  48. RWTexture2D<Vec4> g_lightResultTex : register(u0, SPACE);
  49. RWTexture2D<Vec4> g_dummyUav : register(u1, SPACE);
  50. # else
  51. RWTexture2D<Vec4> g_colorAndPdfTex : register(u0, SPACE);
  52. RWTexture2D<Vec4> g_hitPosAndDepthTex : register(u1, SPACE);
  53. # endif
  54. // Samplers
  55. SamplerState g_linearAnyClampSampler : register(s0, SPACE);
  56. SamplerComparisonState g_shadowSampler : register(s1, SPACE);
  57. SamplerState g_linearAnyRepeatSampler : register(s2, SPACE);
  58. template<typename T>
  59. struct GBufferLight
  60. {
  61. vector<T, 3> m_diffuse;
  62. vector<T, 3> m_worldNormal;
  63. vector<T, 3> m_emission;
  64. };
  65. template<typename T>
  66. Bool materialRayTrace(Vec3 rayOrigin, Vec3 rayDir, F32 tMin, F32 tMax, T textureLod, out GBufferLight<T> gbuffer, out F32 rayT, out Bool backfacing,
  67. U32 traceFlags = RAY_FLAG_FORCE_OPAQUE)
  68. {
  69. RtMaterialFetchRayPayload payload;
  70. payload.m_textureLod = textureLod;
  71. const U32 sbtRecordOffset = 0u;
  72. const U32 sbtRecordStride = 0u;
  73. const U32 missIndex = 0u;
  74. const U32 cullMask = 0xFFu;
  75. RayDesc ray;
  76. ray.Origin = rayOrigin;
  77. ray.TMin = tMin;
  78. ray.Direction = rayDir;
  79. ray.TMax = tMax;
  80. TraceRay(g_tlas, traceFlags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, ray, payload);
  81. rayT = payload.m_rayT;
  82. const Bool hasHitSky = rayT == kMaxF32;
  83. backfacing = rayT < 0.0;
  84. rayT = abs(rayT);
  85. if(hasHitSky)
  86. {
  87. gbuffer = (GBufferLight<T>)0;
  88. gbuffer.m_emission = sampleSkyCheap<T>(g_globalRendererConstants.m_sky, rayDir, g_linearAnyClampSampler);
  89. }
  90. else
  91. {
  92. gbuffer.m_diffuse = payload.m_diffuseColor;
  93. gbuffer.m_worldNormal = payload.m_worldNormal;
  94. gbuffer.m_emission = payload.m_emission;
  95. }
  96. return !hasHitSky;
  97. }
  98. template<typename T>
  99. Bool materialRayTraceInlineRt(Vec3 rayOrigin, Vec3 rayDir, F32 tMin, F32 tMax, T textureLod, out GBufferLight<T> gbuffer, out F32 rayT,
  100. out Bool backfacing)
  101. {
  102. gbuffer = (GBufferLight<T>)0;
  103. Bool hit = false;
  104. rayT = -1.0;
  105. backfacing = false;
  106. # if ANKI_GR_BACKEND_VULKAN
  107. RayQuery<RAY_FLAG_FORCE_OPAQUE> q;
  108. const U32 cullMask = 0xFFu;
  109. RayDesc ray;
  110. ray.Origin = rayOrigin;
  111. ray.TMin = tMin;
  112. ray.Direction = rayDir;
  113. ray.TMax = tMax;
  114. q.TraceRayInline(g_tlas, RAY_FLAG_FORCE_OPAQUE, cullMask, ray);
  115. while(q.Proceed())
  116. {
  117. }
  118. hit = q.CommittedStatus() == COMMITTED_TRIANGLE_HIT;
  119. if(!hit)
  120. {
  121. backfacing = false;
  122. gbuffer.m_emission = sampleSkyCheap<T>(g_globalRendererConstants.m_sky, rayDir, g_linearAnyClampSampler);
  123. rayT = -1.0;
  124. }
  125. else
  126. {
  127. backfacing = q.CommittedTriangleFrontFace();
  128. // Read the diff color from the AS instance
  129. UVec3 diffColoru = q.CommittedInstanceID();
  130. diffColoru >>= UVec3(16, 8, 0);
  131. diffColoru &= 0xFF;
  132. gbuffer.m_diffuse = Vec3(diffColoru) / 255.0;
  133. // Compute the normal
  134. const Vec3 positions[3] = spvRayQueryGetIntersectionTriangleVertexPositionsKHR(q, SpvRayQueryCommittedIntersectionKHR);
  135. const Vec3 vertNormal = normalize(cross(positions[1] - positions[0], positions[2] - positions[1]));
  136. gbuffer.m_worldNormal = normalize(mul(q.CommittedObjectToWorld3x4(), Vec4(vertNormal, 0.0)));
  137. rayT = q.CommittedRayT();
  138. }
  139. # endif
  140. return hit;
  141. }
  142. Bool rayVisibility(Vec3 rayOrigin, Vec3 rayDir, F32 tMax, U32 traceFlags)
  143. {
  144. RayQuery<RAY_FLAG_NONE> q;
  145. const U32 cullMask = 0xFFu;
  146. RayDesc ray;
  147. ray.Origin = rayOrigin;
  148. ray.TMin = 0.01;
  149. ray.Direction = rayDir;
  150. ray.TMax = tMax;
  151. q.TraceRayInline(g_tlas, traceFlags, cullMask, ray);
  152. while(q.Proceed())
  153. {
  154. }
  155. const Bool hit = q.CommittedStatus() == COMMITTED_TRIANGLE_HIT;
  156. return hit;
  157. }
  158. template<typename T>
  159. vector<T, 3> directLighting(GBufferLight<T> gbuffer, Vec3 hitPos, Bool isSky, Bool tryShadowmapFirst, F32 shadowTMax, Bool doLocalLightShadow,
  160. U32 traceFlags = RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH)
  161. {
  162. vector<T, 3> color = gbuffer.m_emission;
  163. if(isSky)
  164. {
  165. return color;
  166. }
  167. // Sun
  168. const DirectionalLight dirLight = g_globalRendererConstants.m_directionalLight;
  169. if(dirLight.m_active)
  170. {
  171. const vector<T, 3> l = -dirLight.m_direction;
  172. const T lambert = dot(l, gbuffer.m_worldNormal);
  173. if(lambert > T(0))
  174. {
  175. F32 shadow = 1.0;
  176. if(dirLight.m_shadowCascadeCount)
  177. {
  178. // Trace shadow
  179. Vec4 vv4 = mul(g_globalRendererConstants.m_matrices.m_viewProjection, Vec4(hitPos, 1.0));
  180. vv4.xy /= vv4.w;
  181. const Bool bInsideFrustum = all(vv4.xy > -1.0) && all(vv4.xy < 1.0) && vv4.w > 0.0;
  182. if(bInsideFrustum && tryShadowmapFirst)
  183. {
  184. const F32 negativeZViewSpace = -mul(g_globalRendererConstants.m_matrices.m_view, Vec4(hitPos, 1.0)).z;
  185. const U32 shadowCascadeCount = dirLight.m_shadowCascadeCount;
  186. const U32 cascadeIdx = computeShadowCascadeIndex(negativeZViewSpace, dirLight.m_shadowCascadeDistances, shadowCascadeCount);
  187. shadow = computeShadowFactorDirLight<F32>(dirLight, cascadeIdx, hitPos, g_shadowAtlasTex, g_shadowSampler);
  188. }
  189. else
  190. {
  191. shadow = rayVisibility(hitPos, -dirLight.m_direction, shadowTMax, traceFlags) ? 0.0 : 1.0;
  192. }
  193. }
  194. // Simple light shading
  195. const vector<T, 3> diffC = diffuseLobe(gbuffer.m_diffuse);
  196. color += diffC * dirLight.m_diffuseColor * lambert * shadow;
  197. }
  198. }
  199. // Local lights
  200. const LocalLightsGridConstants lightGrid = g_globalRendererConstants.m_localLightsGrid;
  201. if(all(hitPos < lightGrid.m_volumeMax) && all(hitPos > lightGrid.m_volumeMin))
  202. {
  203. const UVec3 cellId = (hitPos - lightGrid.m_volumeMin) / lightGrid.m_cellSize;
  204. const U32 cellIdx = cellId.z * lightGrid.m_cellCounts.x * lightGrid.m_cellCounts.y + cellId.y * lightGrid.m_cellCounts.x + cellId.x;
  205. // Compute an attenuation factor that will fade out the resulting color at the edges of the grid
  206. Vec3 a = (hitPos - lightGrid.m_volumeMin) / (lightGrid.m_volumeMax - lightGrid.m_volumeMin);
  207. a = abs(a * 2.0 - 1.0);
  208. a = 1.0 - a;
  209. const F32 gridEdgesAttenuation = sqrt(a.x * a.y * a.z);
  210. const U32 lightCount = SBUFF(g_lightIndexCountsPerCell, cellIdx);
  211. const U32 listOffset = SBUFF(g_lightIndexOffsetsPerCell, cellIdx);
  212. for(U32 i = 0; i < lightCount; ++i)
  213. {
  214. const U32 lightIdx = SBUFF(g_lightIndexList, listOffset + i);
  215. const GpuSceneLight light = SBUFF(g_lights, lightIdx);
  216. const Vec3 frag2Light = light.m_position - hitPos;
  217. const Vec3 nFrag2Light = normalize(frag2Light);
  218. const T lambert = max(T(0), dot(nFrag2Light, gbuffer.m_worldNormal));
  219. F32 attenuation = computeAttenuationFactor(light.m_radius, frag2Light);
  220. if(light.m_isSpotLight)
  221. {
  222. attenuation *= computeSpotFactor(nFrag2Light, light.m_outerCos, light.m_innerCos, light.m_direction);
  223. }
  224. if(attenuation > kEpsilonF32 && lambert > kEpsilonF32 && doLocalLightShadow)
  225. {
  226. const F32 shadowFactor = rayVisibility(hitPos, nFrag2Light, length(frag2Light) - 0.1, traceFlags) ? 0.0 : 1.0;
  227. attenuation *= shadowFactor;
  228. }
  229. const vector<T, 3> diffC = diffuseLobe(gbuffer.m_diffuse);
  230. color += diffC * light.m_diffuseColor * lambert * attenuation * gridEdgesAttenuation;
  231. // color += Vec3(0.5, 0, 0);
  232. }
  233. }
  234. return color;
  235. }
  236. #endif // ANKI_RAY_GEN_SHADER