Ingen beskrivning
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TextureStack.hlsl 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. #ifndef TEXTURESTACK_include
  2. #define TEXTURESTACK_include
  3. #define GRA_HLSL_5 1
  4. #define GRA_ROW_MAJOR 1
  5. #define GRA_TEXTURE_ARRAY_SUPPORT 1
  6. #define GRA_PACK_RESOLVE_OUTPUT 0
  7. #if SHADER_API_PSSL
  8. #define GRA_NO_UNORM 1
  9. #endif
  10. #include "VirtualTexturing.hlsl"
  11. #include "Packing.hlsl"
  12. /*
  13. Warning: the following guide is subject to change due to VT's experimental status.
  14. For more information, visit https://docs.unity3d.com/ScriptReference/UnityEngine.VirtualTexturingModule.html.
  15. This header adds the following pseudo definitions. Actual types etc may vary depending
  16. on vt- being on or off.
  17. struct StackInfo { opaque struct ... }
  18. struct VTProperty { opaque struct ... }
  19. struct VTPropertyWithTextureType { VTProperty + int layerTextureType[4] }
  20. StackInfo PrepareVT(VTProperty vtProperty, VtInputParameters vtParams)
  21. float4 SampleVTLayerWithTextureType(VTPropertyWithTextureType vtPropWithTexType, VtInputParameters vtParams, StackInfo info, [immediate] int layerIndex)
  22. ("int layerIndex" cannot be a variable or expression, must be an immediate constant)
  23. To use this in your materials add the following to various locations in the shader:
  24. In shaderlab "Properties" section add:
  25. [TextureStack.MyFancyStack] DiffuseTexture ("DiffuseTexture", 2D) = "white" {}
  26. [TextureStack.MyFancyStack] NormalTexture ("NormalTexture", 2D) = "white" {}
  27. This will declare a texture stack with two textures.
  28. Then add the following to the PerMaterial constant buffer:
  29. CBUFFER_START(UnityPerMaterial)
  30. ...
  31. DECLARE_STACK_CB(MyFancyStack)
  32. ...
  33. CBUFFER_END
  34. Then in your shader root add the following:
  35. ...
  36. DECLARE_STACK(MyFancyStack, DiffuseTexture)
  37. or
  38. DECLARE_STACK2(MyFancyStack, DiffuseTexture, NormalTexture)
  39. or
  40. DECLARE_STACK3(MyFancyStack, TextureSlot1, TextureSlot2, TextureSlot2)
  41. etc...
  42. NOTE: The Stack shaderlab property and DECLARE_STACKn define need to match i.e. the same name and same texture slots.
  43. Then in the pixel shader function (likely somewhere at the beginning) do:
  44. VTPropertyWithTextureType vtPropWithTexType = AddTextureType(BuildVTProperties_MyFancyStack(), TEXTURETYPE_DEFAULT, TEXTURETYPE_DEFAULT, ...);
  45. // or: TEXTURETYPE_NORMALTANGENTSPACE / TEXTURETYPE_NORMALOBJECTSPACE, match with each texture slot's actual texture type.
  46. VtInputParameters vtParams;
  47. vtParams.uv = uv;
  48. vtParams.lodOrOffset = 0.0f;
  49. ...
  50. StackInfo info = PrepareVT(vtPropWithTexType.vtProperty, vtParams);
  51. Then later on when you want to sample the actual texture do a call(s):
  52. // LayerIndex must be an immediate constant, do not use a variable or expression.
  53. float4 color1 = SampleVTLayerWithTextureType(vtPropWithTexType, vtParams, info, 0);
  54. float4 color2 = SampleVTLayerWithTextureType(vtPropWithTexType, vtParams, info, 1);
  55. ...
  56. The above steps can be repeated for multiple stacks. But be sure that when using the SampleVTLayerWithTextureType you always
  57. pass in the VtInputParameters + the result of the AddTextureType and PrepareVT for the correct stack the texture belongs to.
  58. Also, for tiles to be automatically loaded, you need to write to the VT Feedback texture
  59. (SV_Target1) by yourself in the "ForwardOnly" pass. For example:
  60. #if defined(UNITY_VIRTUAL_TEXTURING) && defined(SHADER_API_PSSL)
  61. // Prevent loss of precision on some Sony platforms.
  62. #pragma PSSL_target_output_format(target 1 FMT_32_ABGR)
  63. #endif
  64. void Frag(PackedVaryingsToPS packedInput, out float4 outColor : SV_Target0
  65. #ifdef UNITY_VIRTUAL_TEXTURING
  66. , out float4 outVTFeedback : SV_Target1
  67. #endif
  68. , ...)
  69. {
  70. ... (PrepareVT and SampleVTLayerWithTextureType called at some point)
  71. #ifdef UNITY_VIRTUAL_TEXTURING
  72. float4 resolveOutput = GetResolveOutput(info);
  73. float4 vtPackedFeedback = GetPackedVTFeedback(resolveOutput);
  74. outVTFeedback = PackVTFeedbackWithAlpha(vtPackedFeedback, screenSpacePos.xy, color1.a);
  75. // Include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
  76. // for "PackVTFeedbackWithAlpha".
  77. #endif
  78. ...
  79. }
  80. If multiple stacks are present on the same pixel, alternate between resolve outputs in the following manner
  81. and pass the result to "GetPackedVTFeedback", etc... to ensure that all relevant tiles get loaded properly:
  82. ...
  83. float4 resolveOutput = GetResolveOutput(info);
  84. float4 resolveOutput2 = GetResolveOutput(info2);
  85. float4 resolveOutputs[2] = { resolveOutput, resolveOutput2 };
  86. uint pixelColumn = screenSpacePos.x;
  87. float4 actualResolveOutput = resolveOutputs[(pixelColumn + _FrameCount) % 2];
  88. float4 vtPackedFeedback = GetPackedVTFeedback(actualResolveOutput);
  89. outVTFeedback = PackVTFeedbackWithAlpha(vtPackedFeedback, ...
  90. ...
  91. */
  92. #if defined(UNITY_VIRTUAL_TEXTURING) && !defined(FORCE_VIRTUAL_TEXTURING_OFF)
  93. struct StackInfo
  94. {
  95. GraniteLookupData lookupData;
  96. GraniteLODLookupData lookupDataLod;
  97. float4 resolveOutput;
  98. };
  99. struct VTProperty
  100. {
  101. GraniteConstantBuffers grCB;
  102. GraniteTranslationTexture translationTable;
  103. GraniteCacheTexture cacheLayer[4];
  104. int layerCount;
  105. int layerIndex[4];
  106. };
  107. #ifdef TEXTURESTACK_CLAMP
  108. #define GR_LOOKUP Granite_Lookup_Clamp_Linear
  109. #define GR_LOOKUP_LOD Granite_Lookup_Clamp
  110. #else
  111. #define GR_LOOKUP Granite_Lookup_Anisotropic
  112. #define GR_LOOKUP_LOD Granite_Lookup
  113. #endif
  114. // This can be used by certain resolver implementations to override screen space derivatives
  115. #ifndef RESOLVE_SCALE_OVERRIDE
  116. #define RESOLVE_SCALE_OVERRIDE float2(1,1)
  117. #endif
  118. #ifndef VT_CACHE_SAMPLER
  119. #define VT_CACHE_SAMPLER sampler_clamp_trilinear_aniso4
  120. SAMPLER(VT_CACHE_SAMPLER);
  121. #endif
  122. StructuredBuffer<GraniteTilesetConstantBuffer> _VTTilesetBuffer;
  123. #define DECLARE_STACK_CB(stackName) \
  124. float4 stackName##_atlasparams[2]
  125. #define DECLARE_STACK_BASE(stackName) \
  126. TEXTURE2D(stackName##_transtab);\
  127. SAMPLER(sampler##stackName##_transtab);\
  128. \
  129. GraniteTilesetConstantBuffer GetConstantBuffer_##stackName() \
  130. { \
  131. int idx = (int)stackName##_atlasparams[1].w; \
  132. GraniteTilesetConstantBuffer graniteParamBlock; \
  133. graniteParamBlock = _VTTilesetBuffer[idx]; \
  134. \
  135. graniteParamBlock.data[0][2][0] *= RESOLVE_SCALE_OVERRIDE.x; \
  136. graniteParamBlock.data[0][3][0] *= RESOLVE_SCALE_OVERRIDE.y; \
  137. \
  138. return graniteParamBlock; \
  139. } \
  140. StackInfo PrepareVT_##stackName(VtInputParameters par)\
  141. {\
  142. GraniteStreamingTextureConstantBuffer textureParamBlock;\
  143. textureParamBlock.data[0] = stackName##_atlasparams[0];\
  144. textureParamBlock.data[1] = stackName##_atlasparams[1];\
  145. \
  146. GraniteTilesetConstantBuffer graniteParamBlock = GetConstantBuffer_##stackName(); \
  147. \
  148. GraniteConstantBuffers grCB;\
  149. grCB.tilesetBuffer = graniteParamBlock;\
  150. grCB.streamingTextureBuffer = textureParamBlock;\
  151. \
  152. GraniteTranslationTexture translationTable;\
  153. translationTable.Texture = stackName##_transtab;\
  154. translationTable.Sampler = sampler##stackName##_transtab;\
  155. \
  156. StackInfo info;\
  157. VirtualTexturingLookup(grCB, translationTable, par, info.lookupData, info.resolveOutput);\
  158. return info;\
  159. }
  160. // TODO: we could replace all uses of GetConstantBuffer_*() with this one:
  161. GraniteTilesetConstantBuffer GetConstantBuffer(GraniteStreamingTextureConstantBuffer textureParamBlock)
  162. {
  163. int idx = (int)textureParamBlock.data[1].w;
  164. GraniteTilesetConstantBuffer graniteParamBlock;
  165. graniteParamBlock = _VTTilesetBuffer[idx];
  166. graniteParamBlock.data[0][2][0] *= RESOLVE_SCALE_OVERRIDE.x;
  167. graniteParamBlock.data[0][3][0] *= RESOLVE_SCALE_OVERRIDE.y;
  168. return graniteParamBlock;
  169. }
  170. #define jj2(a, b) a##b
  171. #define jj(a, b) jj2(a, b)
  172. #define DECLARE_STACK_LAYER(stackName, layerSamplerName, layerIndex) \
  173. TEXTURE2D_ARRAY(stackName##_c##layerIndex);
  174. #define DECLARE_BUILD_PROPERTIES(stackName, layers, layer0Index, layer1Index, layer2Index, layer3Index)\
  175. VTProperty BuildVTProperties_##stackName()\
  176. {\
  177. VTProperty vtProperty; \
  178. \
  179. GraniteStreamingTextureConstantBuffer textureParamBlock; \
  180. textureParamBlock.data[0] = stackName##_atlasparams[0]; \
  181. textureParamBlock.data[1] = stackName##_atlasparams[1]; \
  182. \
  183. vtProperty.grCB.tilesetBuffer = GetConstantBuffer(textureParamBlock); \
  184. vtProperty.grCB.streamingTextureBuffer = textureParamBlock; \
  185. \
  186. vtProperty.translationTable.Texture = stackName##_transtab; \
  187. vtProperty.translationTable.Sampler = sampler##stackName##_transtab; \
  188. \
  189. vtProperty.layerCount = layers; \
  190. vtProperty.layerIndex[0] = layer0Index; \
  191. vtProperty.layerIndex[1] = layer1Index; \
  192. vtProperty.layerIndex[2] = layer2Index; \
  193. vtProperty.layerIndex[3] = layer3Index; \
  194. \
  195. vtProperty.cacheLayer[0].TextureArray = stackName##_c##layer0Index; \
  196. ASSIGN_SAMPLER(vtProperty.cacheLayer[0].Sampler, VT_CACHE_SAMPLER);\
  197. vtProperty.cacheLayer[1].TextureArray = stackName##_c##layer1Index; \
  198. ASSIGN_SAMPLER(vtProperty.cacheLayer[1].Sampler, VT_CACHE_SAMPLER);\
  199. vtProperty.cacheLayer[2].TextureArray = stackName##_c##layer2Index; \
  200. ASSIGN_SAMPLER(vtProperty.cacheLayer[2].Sampler, VT_CACHE_SAMPLER);\
  201. vtProperty.cacheLayer[3].TextureArray = stackName##_c##layer3Index; \
  202. ASSIGN_SAMPLER(vtProperty.cacheLayer[3].Sampler, VT_CACHE_SAMPLER);\
  203. \
  204. return vtProperty; \
  205. }
  206. #define DECLARE_STACK(stackName, layer0SamplerName)\
  207. DECLARE_STACK_BASE(stackName)\
  208. DECLARE_STACK_LAYER(stackName, layer0SamplerName, 0)\
  209. DECLARE_BUILD_PROPERTIES(stackName, 1, 0, 0, 0, 0)
  210. #define DECLARE_STACK2(stackName, layer0SamplerName, layer1SamplerName)\
  211. DECLARE_STACK_BASE(stackName)\
  212. DECLARE_STACK_LAYER(stackName, layer0SamplerName, 0)\
  213. DECLARE_STACK_LAYER(stackName, layer1SamplerName, 1)\
  214. DECLARE_BUILD_PROPERTIES(stackName, 2, 0, 1, 1, 1)
  215. #define DECLARE_STACK3(stackName, layer0SamplerName, layer1SamplerName, layer2SamplerName)\
  216. DECLARE_STACK_BASE(stackName)\
  217. DECLARE_STACK_LAYER(stackName, layer0SamplerName, 0)\
  218. DECLARE_STACK_LAYER(stackName, layer1SamplerName, 1)\
  219. DECLARE_STACK_LAYER(stackName, layer2SamplerName, 2)\
  220. DECLARE_BUILD_PROPERTIES(stackName, 3, 0, 1, 2, 2)
  221. #define DECLARE_STACK4(stackName, layer0SamplerName, layer1SamplerName, layer2SamplerName, layer3SamplerName)\
  222. DECLARE_STACK_BASE(stackName)\
  223. DECLARE_STACK_LAYER(stackName, layer0SamplerName, 0)\
  224. DECLARE_STACK_LAYER(stackName, layer1SamplerName, 1)\
  225. DECLARE_STACK_LAYER(stackName, layer2SamplerName, 2)\
  226. DECLARE_STACK_LAYER(stackName, layer3SamplerName, 3)\
  227. DECLARE_BUILD_PROPERTIES(stackName, 4, 0, 1, 2, 3)
  228. #define PrepareStack(inputParams, stackName) PrepareVT_##stackName(inputParams)
  229. #define SampleStack(info, lodMode, quality, textureName) SampleVT_##textureName(info, lodMode, quality)
  230. #define GetResolveOutput(info) info.resolveOutput
  231. #define PackResolveOutput(output) Granite_PackTileId(output)
  232. StackInfo PrepareVT(VTProperty vtProperty, VtInputParameters vtParams)
  233. {
  234. StackInfo info;
  235. VirtualTexturingLookup(vtProperty.grCB, vtProperty.translationTable, vtParams, info.lookupData, info.resolveOutput);
  236. return info;
  237. }
  238. // NOTE: layerIndex here can only be an immediate constant (i.e. 0,1,2, or 3) -- it CANNOT be a variable or expression
  239. // this is because we use macro concatentation on it when VT is disabled
  240. float4 SampleVTLayer(VTProperty vtProperty, VtInputParameters vtParams, StackInfo info, int layerIndex)
  241. {
  242. float4 result;
  243. VirtualTexturingSample(vtProperty.grCB.tilesetBuffer, info.lookupData, vtProperty.cacheLayer[layerIndex], vtProperty.layerIndex[layerIndex], vtParams.levelMode, vtParams.sampleQuality, result);
  244. return result;
  245. }
  246. float4 GetPackedVTFeedback(float4 feedback)
  247. {
  248. return Granite_PackTileId(feedback);
  249. }
  250. #define VIRTUAL_TEXTURING_SHADER_ENABLED
  251. #else
  252. // Virtual Texturing Disabled -- fallback to regular texture sampling
  253. #define DECLARE_BUILD_PROPERTIES(stackName, layers, layer0, layer1, layer2, layer3)\
  254. VTProperty BuildVTProperties_##stackName()\
  255. {\
  256. VTProperty vtProperty; \
  257. \
  258. vtProperty.layerCount = layers; \
  259. vtProperty.Layer0 = layer0; \
  260. vtProperty.Layer1 = layer1; \
  261. vtProperty.Layer2 = layer2; \
  262. vtProperty.Layer3 = layer3; \
  263. \
  264. ASSIGN_SAMPLER(vtProperty.samplerLayer0, sampler##layer0); \
  265. ASSIGN_SAMPLER(vtProperty.samplerLayer1, sampler##layer1); \
  266. ASSIGN_SAMPLER(vtProperty.samplerLayer2, sampler##layer2); \
  267. ASSIGN_SAMPLER(vtProperty.samplerLayer3, sampler##layer3); \
  268. \
  269. return vtProperty; \
  270. }
  271. // Stacks amount to nothing when VT is off
  272. #define DECLARE_STACK(stackName, layer0) \
  273. DECLARE_BUILD_PROPERTIES(stackName, 1, layer0, layer0, layer0, layer0)
  274. #define DECLARE_STACK2(stackName, layer0, layer1) \
  275. DECLARE_BUILD_PROPERTIES(stackName, 2, layer0, layer1, layer1, layer1)
  276. #define DECLARE_STACK3(stackName, layer0, layer1, layer2) \
  277. DECLARE_BUILD_PROPERTIES(stackName, 3, layer0, layer1, layer2, layer2)
  278. #define DECLARE_STACK4(stackName, layer0, layer1, layer2, layer3) \
  279. DECLARE_BUILD_PROPERTIES(stackName, 4, layer0, layer1, layer2, layer3)
  280. #define DECLARE_STACK_CB(stackName)
  281. // Info is just the uv's
  282. // We could do a straight #define StackInfo float2 but this makes it a bit more type safe
  283. // and allows us to do things like function overloads,...
  284. struct StackInfo
  285. {
  286. VtInputParameters vt;
  287. };
  288. struct VTProperty
  289. {
  290. int layerCount;
  291. TEXTURE2D(Layer0);
  292. TEXTURE2D(Layer1);
  293. TEXTURE2D(Layer2);
  294. TEXTURE2D(Layer3);
  295. SAMPLER(samplerLayer0);
  296. SAMPLER(samplerLayer1);
  297. SAMPLER(samplerLayer2);
  298. SAMPLER(samplerLayer3);
  299. };
  300. StackInfo MakeStackInfo(VtInputParameters vt)
  301. {
  302. StackInfo result;
  303. result.vt = vt;
  304. return result;
  305. }
  306. // Prepare just passes the texture coord around
  307. #define PrepareStack(inputParams, stackName) MakeStackInfo(inputParams)
  308. // Sample just samples the texture
  309. #define SampleStack(info, vtLevelMode, quality, texture) \
  310. SampleVTFallbackToTexture(info, vtLevelMode, TEXTURE2D_ARGS(texture, sampler##texture))
  311. float4 SampleVTFallbackToTexture(StackInfo info, int vtLevelMode, TEXTURE2D_PARAM(layerTexture, layerSampler))
  312. {
  313. if (info.vt.enableGlobalMipBias)
  314. {
  315. if (vtLevelMode == VtLevel_Automatic)
  316. return SAMPLE_TEXTURE2D(layerTexture, layerSampler, info.vt.uv);
  317. else if (vtLevelMode == VtLevel_Lod)
  318. return SAMPLE_TEXTURE2D_LOD(layerTexture, layerSampler, info.vt.uv, info.vt.lodOrOffset);
  319. else if (vtLevelMode == VtLevel_Bias)
  320. return SAMPLE_TEXTURE2D_BIAS(layerTexture, layerSampler, info.vt.uv, info.vt.lodOrOffset);
  321. else // vtLevelMode == VtLevel_Derivatives
  322. return SAMPLE_TEXTURE2D_GRAD(layerTexture, layerSampler, info.vt.uv, info.vt.dx, info.vt.dy);
  323. }
  324. else
  325. {
  326. if (vtLevelMode == VtLevel_Automatic)
  327. return PLATFORM_SAMPLE_TEXTURE2D(layerTexture, layerSampler, info.vt.uv);
  328. else if (vtLevelMode == VtLevel_Lod)
  329. return PLATFORM_SAMPLE_TEXTURE2D_LOD(layerTexture, layerSampler, info.vt.uv, info.vt.lodOrOffset);
  330. else if (vtLevelMode == VtLevel_Bias)
  331. return PLATFORM_SAMPLE_TEXTURE2D_BIAS(layerTexture, layerSampler, info.vt.uv, info.vt.lodOrOffset);
  332. else // vtLevelMode == VtLevel_Derivatives
  333. return PLATFORM_SAMPLE_TEXTURE2D_GRAD(layerTexture, layerSampler, info.vt.uv, info.vt.dx, info.vt.dy);
  334. }
  335. }
  336. StackInfo PrepareVT(VTProperty vtProperty, VtInputParameters vtParams)
  337. {
  338. StackInfo result;
  339. result.vt = vtParams;
  340. return result;
  341. }
  342. // NOTE: layerIndex here can only be an immediate constant (i.e. 0,1,2, or 3) -- it CANNOT be a variable or expression
  343. // this is because we use macro concatentation on it when VT is disabled
  344. #define SampleVTLayer(vtProperty, vtParams, info, layerIndex) \
  345. SampleVTFallbackToTexture(info, vtParams.levelMode, TEXTURE2D_ARGS(vtProperty.Layer##layerIndex, vtProperty.samplerLayer##layerIndex))
  346. // Resolve does nothing
  347. #define GetResolveOutput(info) float4(1,1,1,1)
  348. #define PackResolveOutput(output) output
  349. #define GetPackedVTFeedback(feedback) feedback
  350. #endif
  351. // Shared code between VT enabled and VT disabled, adding TextureType handling
  352. // these texture types should be kept in sync with LayerTextureType in C# code
  353. #define TEXTURETYPE_DEFAULT 0 // LayerTextureType.Default
  354. #define TEXTURETYPE_NORMALTANGENTSPACE 1 // LayerTextureType.NormalTangentSpace
  355. #define TEXTURETYPE_NORMALOBJECTSPACE 2 // LayerTextureType.NormalObjectSpace
  356. struct VTPropertyWithTextureType
  357. {
  358. VTProperty vtProperty;
  359. int layerTextureType[4];
  360. };
  361. VTPropertyWithTextureType AddTextureType(VTProperty vtProperty, int layer0TextureType, int layer1TextureType = TEXTURETYPE_DEFAULT, int layer2TextureType = TEXTURETYPE_DEFAULT, int layer3TextureType = TEXTURETYPE_DEFAULT)
  362. {
  363. VTPropertyWithTextureType result;
  364. result.vtProperty = vtProperty;
  365. result.layerTextureType[0] = layer0TextureType;
  366. result.layerTextureType[1] = layer1TextureType;
  367. result.layerTextureType[2] = layer2TextureType;
  368. result.layerTextureType[3] = layer3TextureType;
  369. return result;
  370. }
  371. float4 ApplyTextureType(float4 value, int textureType)
  372. {
  373. // NOTE: when textureType is a compile-time constant, the branches compile out
  374. if (textureType == TEXTURETYPE_NORMALTANGENTSPACE)
  375. {
  376. value.rgb = UnpackNormalmapRGorAG(value);
  377. }
  378. else if (textureType == TEXTURETYPE_NORMALOBJECTSPACE)
  379. {
  380. value.rgb = UnpackNormalRGB(value);
  381. }
  382. return value;
  383. }
  384. // if we _could_ express it as a function, the function signature would be:
  385. // float4 SampleVTLayerWithTextureType(VTPropertyWithTextureType vtPropWithTexType, VtInputParameters vtParams, StackInfo info, [immediate] int layerIndex)
  386. // NOTE: layerIndex here can only be an immediate constant (i.e. 0,1,2, or 3) -- it CANNOT be a variable or expression
  387. // this is because we use macro concatentation on it when VT is disabled
  388. #define SampleVTLayerWithTextureType(vtPropWithTexType, vtParams, info, layerIndex) \
  389. ApplyTextureType(SampleVTLayer(vtPropWithTexType.vtProperty, vtParams, info, layerIndex), vtPropWithTexType.layerTextureType[layerIndex])
  390. #endif //TEXTURESTACK_include