Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

ProbeVolumeDebugBase.hlsl 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. #ifndef PROBEVOLUMEDEBUG_BASE_HLSL
  2. #define PROBEVOLUMEDEBUG_BASE_HLSL
  3. // TEMPORARY WORKAROUND
  4. // Unfortunately we don't have a cross pipeline way to pass per frame constant.
  5. // One of the reason is that we don't want to force a certain Constant Buffer layout on users (read: SRP writer) for shared data.
  6. // This means that usually SRP Core functions (see SpaceTransforms.hlsl for example) use common names that are NOT declared in the Core package but rather in each pipelines.
  7. // The consequence is that when writing core shaders that need those variables, we currently have to copy their declaration and set them manually from core C# code to the relevant shaders.
  8. // Here is current the subset of variables and functions required by APV debug.
  9. // Copying them here means that these shaders don't support either XR or Camera Relative rendering (at least until those concept become fully cross pipeline)
  10. CBUFFER_START(ShaderVariablesProbeVolumeDebug)
  11. float4x4 unity_MatrixVP; // Sent by builtin
  12. float4x4 unity_MatrixInvV; // Sent by builtin
  13. float4x4 unity_ObjectToWorld; // Sent by builtin
  14. float4x4 unity_MatrixV; // Sent by builtin
  15. float4 _ScreenSize;
  16. float3 _WorldSpaceCameraPos; // Sent by builtin
  17. CBUFFER_END
  18. TEXTURE2D(_ExposureTexture);
  19. #define UNITY_MATRIX_VP unity_MatrixVP
  20. #define UNITY_MATRIX_V unity_MatrixV
  21. #define UNITY_MATRIX_I_V unity_MatrixInvV
  22. #define UNITY_MATRIX_M unity_ObjectToWorld
  23. float3 GetCurrentViewPosition()
  24. {
  25. return UNITY_MATRIX_I_V._14_24_34;
  26. }
  27. float GetCurrentExposureMultiplier()
  28. {
  29. return LOAD_TEXTURE2D(_ExposureTexture, int2(0, 0)).x;
  30. }
  31. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
  32. #include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/DecodeSH.hlsl"
  33. #include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl"
  34. #include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.Debug.cs.hlsl"
  35. uniform int _ShadingMode;
  36. uniform float _ExposureCompensation;
  37. uniform float _ProbeSize;
  38. uniform float4 _Color;
  39. uniform int _SubdivLevel;
  40. uniform float _CullDistance;
  41. uniform int _MaxAllowedSubdiv;
  42. uniform int _MinAllowedSubdiv;
  43. uniform float _ValidityThreshold;
  44. uniform uint _RenderingLayerMask;
  45. uniform float _OffsetSize;
  46. // Sampling Position Debug
  47. uniform bool _DebugProbeVolumeSampling = false;
  48. StructuredBuffer<float4> _positionNormalBuffer;
  49. uniform float4 _DebugArrowColor; // arrow color for position and normal debug
  50. uniform float4 _DebugLocator01Color; // locator color for final sampling position debug
  51. uniform float4 _DebugLocator02Color; // locator color for normal and view bias sampling position debug
  52. uniform float4 _DebugEmptyProbeData; // probe color for missing data
  53. uniform bool _ForceDebugNormalViewBias; // additional locator to debug Normal Bias and View Bias without AntiLeak Reduction Mode
  54. uniform bool _DebugSamplingNoise = false;
  55. uniform sampler2D _NumbersTex;
  56. UNITY_INSTANCING_BUFFER_START(Props)
  57. UNITY_DEFINE_INSTANCED_PROP(float, _Validity)
  58. UNITY_DEFINE_INSTANCED_PROP(float, _RenderingLayer)
  59. UNITY_DEFINE_INSTANCED_PROP(float, _DilationThreshold)
  60. UNITY_DEFINE_INSTANCED_PROP(float, _TouchupedByVolume)
  61. UNITY_DEFINE_INSTANCED_PROP(float4, _IndexInAtlas)
  62. UNITY_DEFINE_INSTANCED_PROP(float4, _Offset)
  63. UNITY_DEFINE_INSTANCED_PROP(float, _RelativeSize)
  64. UNITY_INSTANCING_BUFFER_END(Props)
  65. struct appdata
  66. {
  67. float4 vertex : POSITION;
  68. float3 normal : NORMAL;
  69. float4 color : COLOR0;
  70. float2 texCoord : TEXCOORD0;
  71. UNITY_VERTEX_INPUT_INSTANCE_ID
  72. };
  73. struct v2f
  74. {
  75. float4 vertex : SV_POSITION;
  76. float3 normal : TEXCOORD1;
  77. float4 color : COLOR0;
  78. float2 texCoord : TEXCOORD0;
  79. float2 samplingFactor_ValidityWeight : TEXCOORD2; // stores sampling factor (for Probe Sampling Debug view) and validity weight
  80. float2 centerCoordSS : TEXCOORD3;
  81. UNITY_VERTEX_INPUT_INSTANCE_ID
  82. };
  83. void DoCull(inout v2f o)
  84. {
  85. ZERO_INITIALIZE(v2f, o);
  86. o.samplingFactor_ValidityWeight = float2(0.0f, 1.0f);
  87. }
  88. // snappedProbePosition_WS : worldspace position of main probe (a corner of the 8 probes cube)
  89. // samplingPosition_WS : worldspace sampling position after applying 'NormalBias' and 'ViewBias' and 'ValidityAndNormalBased Leak Reduction'
  90. // normalizedOffset : normalized offset between sampling position and snappedProbePosition
  91. void FindSamplingData(float3 posWS, float3 normalWS, uint renderingLayer, out float3 snappedProbePosition_WS, out float3 samplingPositionNoAntiLeak_WS, out float probeDistance, out float3 normalizedOffset, out float validityWeights[8])
  92. {
  93. float3 cameraPosition_WS = _WorldSpaceCameraPos;
  94. float3 viewDir_WS = normalize(cameraPosition_WS - posWS);
  95. if (_DebugSamplingNoise)
  96. {
  97. float2 posNDC = ComputeNormalizedDeviceCoordinates(posWS, UNITY_MATRIX_VP);
  98. float2 posSS = floor(posNDC.xy * _ScreenSize.xy);
  99. posWS = AddNoiseToSamplingPosition(posWS, posSS, viewDir_WS);
  100. }
  101. posWS -= _APVWorldOffset;
  102. // uvw
  103. APVResources apvRes = FillAPVResources();
  104. float3 uvw;
  105. uint subdiv;
  106. float3 biasedPosWS;
  107. bool valid = TryToGetPoolUVWAndSubdiv(apvRes, posWS, normalWS, viewDir_WS, uvw, subdiv, biasedPosWS);
  108. // Validity mask
  109. float3 texCoord = uvw * _APVPoolDim - .5f;
  110. float3 texFrac = frac(texCoord);
  111. uint validityMask = LoadValidityMask(apvRes, renderingLayer, texCoord);
  112. for (uint i = 0; i < 8; i++)
  113. {
  114. int3 probeCoord = GetSampleOffset(i);
  115. float validityWeight = ((probeCoord.x == 1) ? texFrac.x : 1.0f - texFrac.x) *
  116. ((probeCoord.y == 1) ? texFrac.y : 1.0f - texFrac.y) *
  117. ((probeCoord.z == 1) ? texFrac.z : 1.0f - texFrac.z);
  118. validityWeights[i] = validityWeight * GetValidityWeight(i, validityMask);
  119. }
  120. // Sample position
  121. normalizedOffset = texFrac;
  122. if (_APVLeakReductionMode == APVLEAKREDUCTIONMODE_PERFORMANCE)
  123. {
  124. float3 warped = uvw;
  125. WarpUVWLeakReduction(apvRes, renderingLayer, warped);
  126. normalizedOffset += (warped - uvw) * _APVPoolDim;
  127. }
  128. // stuff
  129. biasedPosWS += _APVWorldOffset;
  130. samplingPositionNoAntiLeak_WS = biasedPosWS;
  131. probeDistance = ProbeDistance(subdiv);
  132. snappedProbePosition_WS = GetSnappedProbePosition(biasedPosWS, subdiv);
  133. }
  134. // Return probe sampling weight
  135. float ComputeSamplingFactor(float3 probePosition_WS, float3 snappedProbePosition_WS, float3 normalizedOffset, float probeDistance)
  136. {
  137. float samplingFactor = -1.0f;
  138. if (distance(snappedProbePosition_WS, probePosition_WS) < 0.0001f)
  139. {
  140. samplingFactor = (1.0f-normalizedOffset.x) * (1.0f-normalizedOffset.y) * (1.0f-normalizedOffset.z);
  141. }
  142. else if (distance(snappedProbePosition_WS, probePosition_WS + float3(-1.0f, 0.0f, 0.0f)*probeDistance) < 0.0001f)
  143. {
  144. samplingFactor = (normalizedOffset.x) * (1.0f-normalizedOffset.y) * (1.0f-normalizedOffset.z);
  145. }
  146. else if (distance(snappedProbePosition_WS, probePosition_WS + float3(-1.0f, -1.0f, 0.0f)*probeDistance) < 0.0001f)
  147. {
  148. samplingFactor = (normalizedOffset.x) * (normalizedOffset.y) * (1.0f-normalizedOffset.z);
  149. }
  150. else if (distance(snappedProbePosition_WS, probePosition_WS + float3(0.0f, -1.0f, 0.0f)*probeDistance) < 0.0001f)
  151. {
  152. samplingFactor = (1.0f-normalizedOffset.x) * (normalizedOffset.y) * (1.0f-normalizedOffset.z);
  153. }
  154. else if (distance(snappedProbePosition_WS, probePosition_WS + float3(-1.0f, 0.0f, -1.0f)*probeDistance) < 0.0001f)
  155. {
  156. samplingFactor = (normalizedOffset.x) * (1.0f-normalizedOffset.y) * (normalizedOffset.z);
  157. }
  158. else if (distance(snappedProbePosition_WS, probePosition_WS + float3(0.0f, 0.0f, -1.0f)*probeDistance) < 0.0001f)
  159. {
  160. samplingFactor = (1.0f-normalizedOffset.x) * (1.0f-normalizedOffset.y) * (normalizedOffset.z);
  161. }
  162. else if (distance(snappedProbePosition_WS, probePosition_WS + float3(-1.0f, -1.0f, -1.0f)*probeDistance) < 0.0001f)
  163. {
  164. samplingFactor = (normalizedOffset.x) * (normalizedOffset.y) * (normalizedOffset.z);
  165. }
  166. else if (distance(snappedProbePosition_WS, probePosition_WS + float3(0.0f, -1.0f, -1.0f)*probeDistance) < 0.0001f)
  167. {
  168. samplingFactor = (1.0f-normalizedOffset.x) * (normalizedOffset.y) * (normalizedOffset.z);
  169. }
  170. return samplingFactor;
  171. }
  172. // Sample a texture with numbers at the right place depending on a number input
  173. half4 SampleCharacter(int input, float2 texCoord) // Samples _NumbersTex to get given character
  174. {
  175. // texture is divided in 16 parts and contains following characters : '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' (+ empty space)
  176. float2 uv = float2((texCoord.x + input) / 16.0f, texCoord.y);
  177. half4 color = tex2D(_NumbersTex, uv);
  178. return color;
  179. }
  180. // Writes a floating number with two decimals using a texture with numbers.
  181. // Use to debug probe sampling weights with text
  182. half4 WriteFractNumber(float input, float2 texCoord)
  183. {
  184. // using 4 characters
  185. float i = 4.0f;
  186. // 0.00X
  187. int n3_value = floor(frac(input * 100.0f) * 10.0f);
  188. int n2_add = 0;
  189. if (n3_value >= 5) {n2_add = 1;}
  190. // 0.0X
  191. int n2_value = floor(frac(input * 10.0f) * 10.0f);
  192. n2_value += n2_add;
  193. int n1_add = 0;
  194. if (n2_value >= 10) {n2_value -= 10; n1_add = 1;}
  195. // 0.X
  196. int n1_value = floor(frac(input) * 10.0f);
  197. n1_value += n1_add;
  198. int n0_add = 0;
  199. if (n1_value >= 10) {n1_value -= 10; n0_add = 1;}
  200. // X
  201. int n0_value = floor(input);
  202. n0_value += n0_add;
  203. float2 n0_uv = float2(clamp(texCoord.x*i - 0.0f, 0.0f, 1.0f), texCoord.y);
  204. float2 dot_uv = float2(clamp(texCoord.x*i - 1.0f, 0.0f, 1.0f), texCoord.y);
  205. float2 n1_uv = float2(clamp(texCoord.x*i - 2.0f, 0.0f, 1.0f), texCoord.y);
  206. float2 n2_uv = float2(clamp(texCoord.x*i - 3.0f, 0.0f, 1.0f), texCoord.y);
  207. half4 outVal = 0;
  208. if (texCoord.x <= 0.25)
  209. outVal = SampleCharacter(n0_value, n0_uv);
  210. else if (texCoord.x <= 0.50)
  211. outVal = SampleCharacter(10, dot_uv);
  212. else if (texCoord.x <= 0.75)
  213. outVal = SampleCharacter(n1_value, n1_uv);
  214. else
  215. outVal = SampleCharacter(n2_value, n2_uv);
  216. return outVal;
  217. }
  218. // Finer culling, degenerate the vertices of the debug element if it lies over the max distance.
  219. // Coarser culling has already happened on CPU.
  220. bool ShouldCull(inout v2f o)
  221. {
  222. float4 position = float4(UNITY_MATRIX_M._m03_m13_m23, 1);
  223. int brickSize = UNITY_ACCESS_INSTANCED_PROP(Props, _IndexInAtlas).w;
  224. bool shouldCull = false;
  225. if (distance(position.xyz, GetCurrentViewPosition()) > _CullDistance || brickSize > _MaxAllowedSubdiv || brickSize < _MinAllowedSubdiv)
  226. {
  227. DoCull(o);
  228. shouldCull = true;
  229. }
  230. return shouldCull;
  231. }
  232. float3 EvalL1(float3 L0, float3 L1_R, float3 L1_G, float3 L1_B, float3 N)
  233. {
  234. float3 outLighting = 0;
  235. L1_R = DecodeSH(L0.r, L1_R);
  236. L1_G = DecodeSH(L0.g, L1_G);
  237. L1_B = DecodeSH(L0.b, L1_B);
  238. outLighting += SHEvalLinearL1(N, L1_R, L1_G, L1_B);
  239. return outLighting;
  240. }
  241. float3 EvalL2(inout float3 L0, float4 L2_R, float4 L2_G, float4 L2_B, float4 L2_C, float3 N)
  242. {
  243. DecodeSH_L2(L0, L2_R, L2_G, L2_B, L2_C);
  244. return SHEvalLinearL2(N, L2_R, L2_G, L2_B, L2_C);
  245. }
  246. float3 CalculateDiffuseLighting(v2f i)
  247. {
  248. APVResources apvRes = FillAPVResources();
  249. int3 texLoc = UNITY_ACCESS_INSTANCED_PROP(Props, _IndexInAtlas).xyz;
  250. float3 normal = normalize(i.normal);
  251. float3 skyShadingDirection = normal;
  252. if (_ShadingMode == DEBUGPROBESHADINGMODE_PROBE_OCCLUSION)
  253. {
  254. float4 shadowmask = apvRes.ProbeOcclusion[texLoc];
  255. return float4(shadowmask.rgb * 0.5 + (shadowmask.a * 0.5), 1);
  256. }
  257. else if (_ShadingMode == DEBUGPROBESHADINGMODE_SKY_DIRECTION)
  258. {
  259. if (_APVSkyDirectionWeight > 0)
  260. {
  261. float value = 1.0f / GetCurrentExposureMultiplier();
  262. uint index = apvRes.SkyShadingDirectionIndices[texLoc].r * 255;
  263. if (index != 255)
  264. skyShadingDirection = apvRes.SkyPrecomputedDirections[index].rgb;
  265. else
  266. return float3(value, 0.0f, 0.0f);
  267. if (dot(normal, skyShadingDirection) > 0.95)
  268. return float3(0.0f, value, 0.0f);
  269. return float3(0.0f, 0.0f, 0.0f);
  270. }
  271. else
  272. {
  273. return _DebugEmptyProbeData.xyz / GetCurrentExposureMultiplier();
  274. }
  275. }
  276. else
  277. {
  278. float3 skyOcclusion = _DebugEmptyProbeData.xyz;
  279. if (_APVSkyOcclusionWeight > 0)
  280. {
  281. // L0 L1
  282. float4 temp = float4(kSHBasis0, kSHBasis1 * normal.x, kSHBasis1 * normal.y, kSHBasis1 * normal.z);
  283. skyOcclusion = dot(temp, apvRes.SkyOcclusionL0L1[texLoc].rgba);
  284. }
  285. if (_ShadingMode == DEBUGPROBESHADINGMODE_SKY_OCCLUSION_SH)
  286. {
  287. return skyOcclusion / GetCurrentExposureMultiplier();
  288. }
  289. else
  290. {
  291. float4 L0_L1Rx = apvRes.L0_L1Rx[texLoc].rgba;
  292. float3 L0 = L0_L1Rx.xyz;
  293. if (_ShadingMode == DEBUGPROBESHADINGMODE_SHL0)
  294. return L0;
  295. float L1Rx = L0_L1Rx.w;
  296. float4 L1G_L1Ry = apvRes.L1G_L1Ry[texLoc].rgba;
  297. float4 L1B_L1Rz = apvRes.L1B_L1Rz[texLoc].rgba;
  298. float3 bakeDiffuseLighting = EvalL1(L0, float3(L1Rx, L1G_L1Ry.w, L1B_L1Rz.w), L1G_L1Ry.xyz, L1B_L1Rz.xyz, normal);
  299. bakeDiffuseLighting += L0;
  300. if (_ShadingMode == DEBUGPROBESHADINGMODE_SHL0L1)
  301. return bakeDiffuseLighting;
  302. #ifdef PROBE_VOLUMES_L2
  303. float4 L2_R = apvRes.L2_0[texLoc].rgba;
  304. float4 L2_G = apvRes.L2_1[texLoc].rgba;
  305. float4 L2_B = apvRes.L2_2[texLoc].rgba;
  306. float4 L2_C = apvRes.L2_3[texLoc].rgba;
  307. bakeDiffuseLighting += EvalL2(L0, L2_R, L2_G, L2_B, L2_C, normal);
  308. #endif
  309. if (_APVSkyOcclusionWeight > 0)
  310. bakeDiffuseLighting += skyOcclusion * EvaluateAmbientProbe(skyShadingDirection);
  311. return bakeDiffuseLighting;
  312. }
  313. }
  314. }
  315. CBUFFER_START(TouchupVolumeBounds)
  316. float4 _TouchupVolumeBounds[16 * 3]; // A BBox is 3 float4
  317. uint _AdjustmentVolumeCount;
  318. CBUFFER_END
  319. bool IsInSelection(float3 position)
  320. {
  321. for (uint i = 0; i < _AdjustmentVolumeCount; i++)
  322. {
  323. float3 center = _TouchupVolumeBounds[i * 3 + 0].xyz;
  324. bool isSphere = _TouchupVolumeBounds[i * 3 + 0].w >= FLT_MAX;
  325. if (isSphere)
  326. {
  327. float radius = _TouchupVolumeBounds[i * 3 + 1].x;
  328. if (dot(position - center, position - center) < radius * radius)
  329. return true;
  330. }
  331. else
  332. {
  333. float3 X = _TouchupVolumeBounds[i * 3 + 1].xyz;
  334. float3 Y = _TouchupVolumeBounds[i * 3 + 2].xyz;
  335. float3 Z = float3(_TouchupVolumeBounds[i * 3 + 0].w,
  336. _TouchupVolumeBounds[i * 3 + 1].w,
  337. _TouchupVolumeBounds[i * 3 + 2].w);
  338. if (abs(dot(position - center, normalize(X))) < length(X) &&
  339. abs(dot(position - center, normalize(Y))) < length(Y) &&
  340. abs(dot(position - center, normalize(Z))) < length(Z))
  341. return true;
  342. }
  343. }
  344. return false;
  345. }
  346. #endif //PROBEVOLUMEDEBUG_BASE_HLSL