説明なし
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

VirtualTexturing.hlsl 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #include "GraniteShaderLibBase.hlsl"
  2. #define VtAddressMode_Wrap 0
  3. #define VtAddressMode_Clamp 1
  4. #define VtAddressMode_Udim 2
  5. #define VtFilter_Anisotropic 0
  6. #define VtLevel_Automatic 0
  7. #define VtLevel_Lod 1
  8. #define VtLevel_Bias 2
  9. #define VtLevel_Derivatives 3
  10. #define VtUvSpace_Regular 0
  11. #define VtUvSpace_PreTransformed 1
  12. #define VtSampleQuality_Low 0
  13. #define VtSampleQuality_High 1
  14. struct VtInputParameters
  15. {
  16. float2 uv;
  17. float lodOrOffset;
  18. float2 dx;
  19. float2 dy;
  20. int addressMode;
  21. int filterMode;
  22. int levelMode;
  23. int uvMode;
  24. int sampleQuality;
  25. int enableGlobalMipBias;
  26. };
  27. int VirtualTexturingLookup(
  28. in GraniteConstantBuffers grCB,
  29. in GraniteTranslationTexture translationTable,
  30. in VtInputParameters input,
  31. out GraniteLookupData graniteLookupData,
  32. out float4 resolveResult
  33. )
  34. {
  35. GraniteStreamingTextureConstantBuffer grSTCB = grCB.streamingTextureBuffer;
  36. GraniteTilesetConstantBuffer tsCB = grCB.tilesetBuffer;
  37. float2 texCoord = input.uv;
  38. float2 dx;
  39. float2 dy;
  40. float mipLevel; //interger
  41. if (input.levelMode == VtLevel_Automatic)
  42. {
  43. dx = ddx(texCoord);
  44. dy = ddy(texCoord);
  45. }
  46. else if (input.levelMode == VtLevel_Bias)
  47. {
  48. // We can't simply add the bias after the mip-calculation since the derivatives
  49. // are also used when sampling the cache so make sure we apply bias by scaling derivatives
  50. if ( input.sampleQuality == VtSampleQuality_High )
  51. {
  52. float offsetPow2 = pow(2.0f, input.lodOrOffset);
  53. dx = ddx(texCoord) * offsetPow2;
  54. dy = ddy(texCoord) * offsetPow2;
  55. }
  56. // In low quality we don't care about cache derivatives and will add the bias later
  57. else
  58. {
  59. dx = ddx(texCoord);
  60. dy = ddy(texCoord);
  61. }
  62. }
  63. else if (input.levelMode == VtLevel_Derivatives)
  64. {
  65. dx = input.dx;
  66. dy = input.dy;
  67. }
  68. else /*input.levelMode == VtLevel_Lod*/
  69. {
  70. //gra_TrilinearOffset ensures we do round-nearest for no-trilinear and
  71. //round-floor for trilinear.
  72. float clampedLevel = clamp(input.lodOrOffset + gra_TrilinearOffset, 0.0f, gra_NumLevels);
  73. mipLevel = floor(clampedLevel);
  74. dx = float2(frac(clampedLevel), 0.0f); // trilinear blend ratio
  75. dy = float2(0.0f,0.0f);
  76. }
  77. // Transform the derivatives to atlas space if needed
  78. if (input.uvMode == VtUvSpace_Regular && input.levelMode != VtLevel_Lod)
  79. {
  80. dx = gra_Transform.zw * dx;
  81. dy = gra_Transform.zw * dy;
  82. }
  83. if (input.levelMode != VtLevel_Lod)
  84. {
  85. #ifdef VT_GLOBAL_MIP_BIAS_MULTIPLIER
  86. if (input.enableGlobalMipBias)
  87. {
  88. dx *= VT_GLOBAL_MIP_BIAS_MULTIPLIER;
  89. dy *= VT_GLOBAL_MIP_BIAS_MULTIPLIER;
  90. }
  91. #endif
  92. mipLevel = GranitePrivate_CalcMiplevelAnisotropic(grCB.tilesetBuffer, grCB.streamingTextureBuffer, dx, dy);
  93. // Simply add it here derivatives are wrong from this point onwards but not used anymore
  94. if ( input.sampleQuality == VtSampleQuality_Low && input.levelMode == VtLevel_Bias)
  95. {
  96. mipLevel += input.lodOrOffset;
  97. // GranitePrivate_CalcMiplevelAnisotropic will already clamp between 0 gra_NumLevels
  98. // But we need to do it again here. The alternative is modifying dx,dy before passing to
  99. // GranitePrivate_CalcMiplevelAnisotropic adding a pow2 + 4 fmuls so probably
  100. // the exra clamp is more appropriate here.
  101. mipLevel = clamp(mipLevel, 0.0f, gra_NumLevels);
  102. }
  103. mipLevel = floor(mipLevel + 0.5f); //round nearest
  104. }
  105. // Apply clamp/wrap mode if needed and transform into atlas space
  106. // If the user passes in pre-transformed texture coords clamping and wrapping should be handled by the user
  107. if (input.uvMode == VtUvSpace_Regular)
  108. {
  109. if (input.addressMode == VtAddressMode_Wrap)
  110. {
  111. texCoord = frac(input.uv);
  112. }
  113. else if (input.addressMode == VtAddressMode_Clamp)
  114. {
  115. float2 epsilon2 = float2(gra_AssetWidthRcp, gra_AssetHeightRcp);
  116. texCoord = clamp(input.uv, epsilon2, float2(1,1) - epsilon2);
  117. }
  118. else if (input.addressMode == VtAddressMode_Udim)
  119. {
  120. // not modified (i.e outside of the 0-1 range, atlas transform below will take care of it)
  121. texCoord = input.uv;
  122. }
  123. texCoord = Granite_Transform(gra_StreamingTextureCB, texCoord);
  124. }
  125. // calculate resolver data
  126. float2 level0NumTiles = float2(gra_Level0NumTilesX, gra_Level0NumTilesX*gra_NumTilesYScale);
  127. float2 virtualTilesUv = floor(texCoord * level0NumTiles * pow(0.5, mipLevel));
  128. resolveResult = GranitePrivate_MakeResolveOutput(tsCB, virtualTilesUv, mipLevel);
  129. float4 translationTableData;
  130. if (input.levelMode != VtLevel_Lod)
  131. {
  132. // Look up the physical page indexes and the number of pages on the mipmap
  133. // level of the page in the translation texture
  134. // Note: this is equal for both anisotropic and linear sampling
  135. // We could use a sample bias here for 'auto' mip level detection
  136. #if (GRA_LOAD_INSTR==0)
  137. translationTableData = GranitePrivate_SampleLevel_Translation(translationTable, texCoord, mipLevel);
  138. #else
  139. translationTableData = GranitePrivate_Load(translationTable, gra_Int3(virtualTilesUv, mipLevel));
  140. #endif
  141. }
  142. else
  143. {
  144. // Look up the physical page indexes and the number of pages on the mipmap
  145. // level of the page in the translation texture
  146. // Note: this is equal for both anisotropic and linear sampling
  147. // We could use a sample bias here for 'auto' mip level detection
  148. #if (GRA_LOAD_INSTR==0)
  149. translationTableData = GranitePrivate_SampleLevel_Translation(translationTable, texCoord, mipLevel);
  150. #else
  151. translationTableData = GranitePrivate_Load(translationTable, gra_Int3(virtualTilesUv, mipLevel));
  152. #endif
  153. }
  154. graniteLookupData.translationTableData = translationTableData;
  155. graniteLookupData.textureCoordinates = texCoord;
  156. graniteLookupData.dX = dx;
  157. graniteLookupData.dY = dy;
  158. return 1;
  159. }
  160. int VirtualTexturingSample(
  161. in GraniteTilesetConstantBuffer tsCB,
  162. in GraniteLookupData graniteLookupData,
  163. in GraniteCacheTexture cacheTexture,
  164. in int layer,
  165. in int levelMode,
  166. in int quality,
  167. out float4 result)
  168. {
  169. // Convert from pixels to [0-1] and look up in the physical page texture
  170. float2 deltaScale;
  171. float3 cacheCoord = GranitePrivate_TranslateCoord(tsCB, graniteLookupData.textureCoordinates, graniteLookupData.translationTableData, layer, deltaScale);
  172. if ( levelMode != VtLevel_Lod )
  173. {
  174. if ( quality == VtSampleQuality_Low )
  175. {
  176. // This leads to small artefacts at tile borders but is generally not noticable unless the texture
  177. // is greatly magnified
  178. result = GranitePrivate_SampleArray(cacheTexture, cacheCoord);
  179. }
  180. else /* quality == VtSampleQuality_High */
  181. {
  182. deltaScale *= gra_LodBiasPow2;
  183. // Calculate the delta scale this works by first converting the [0-1] texcoord deltas to
  184. // pixel deltas on the current mip level, then dividing by the cache size to convert to [0-1] cache deltas
  185. float2 sampDeltaX = graniteLookupData.dX*deltaScale;
  186. float2 sampDeltaY = graniteLookupData.dY*deltaScale;
  187. result = GranitePrivate_SampleGradArray(cacheTexture, cacheCoord, sampDeltaX, sampDeltaY);
  188. }
  189. }
  190. else
  191. {
  192. result = GranitePrivate_SampleLevelArray(cacheTexture, cacheCoord, graniteLookupData.dX.x);
  193. }
  194. return 1;
  195. }