!B (Vulkan) fixes vulkan validation layer errors. Particle issue was caused because...
[CRYENGINE.git] / Engine / Shaders / HWScripts / CryFX / ModificatorVT.cfi
blob8eb410eab35fe8e55f0ee356803e3b3c99617a7e
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
4 // Note: Unfortunately we couldn't go more atomic with structures as rsx cgc compiler 
5 // doesn't allow empty structures (which we might have on certain conditions with defines not existing)
8 PERLIN_NOISE_MAP
9 WIND_GRID_MAP
11 ////////////////////////////////////////////////////////////////////////////////////////////////////
13 cbuffer CBPerInstance : register(b0)
15 #if %_RT_ENVIRONMENT_CUBEMAP
16         struct
17         {
18                 float3x4        CI_WorldMatrix;
19                 float4          CI_CustomData;   // [x=VegetationBendingVerticalRadius, y=VegetationBendingScale, z=tessellation patch id offset, w=dissolve]
20         } SInstancingData[800];
21 #endif
24 cbuffer CBPerDraw : register(b0)
26  #if !%_RT_ENVIRONMENT_CUBEMAP
27         float3x4  CD_WorldMatrix;
28         float3x4  CD_PrevWorldMatrix;
29         float4    CD_CustomData;       // [x=VegetationBendingVerticalRadius, y=VegetationBendingScale, z=tessellation patch id offset, w=dissolve]
30         float4    CD_CustomData1;      // [xyzw=ShilouetteColor]
31         // TODO: Should be moved after all the data below
32         float4    CD_CustomData2;      // [x=selectionIDs in debug pass, y=AmbientColor, zw=Not used]
33         
34 #if %TEMP_TERRAIN || (%TEMP_VEGETATION && %_RT_BLEND_WITH_TERRAIN_COLOR)
35         float4    CD_BlendTerrainColInfo;
36         float4x4  CD_TerrainLayerInfo;
37 #elif %WRINKLE_BLENDING || %_RT_SKELETON_SSD_LINEAR || %_RT_SKELETON_SSD
38         float4    CD_SkinningInfo;     // Additional offset
39         float4    CD_WrinklesMask0;
40         float4    CD_WrinklesMask1;
41         float4    CD_WrinklesMask2;
42 #endif
43 #endif
46 float4 Get_SPI_BlendWithTerrainColInfo()
48 #if %TEMP_TERRAIN || (%TEMP_VEGETATION && %_RT_BLEND_WITH_TERRAIN_COLOR)
49         #if %_RT_ENVIRONMENT_CUBEMAP
50         return 1;
51         #else
52         return CD_BlendTerrainColInfo;
53         #endif
54 #else
55         return (float4)0;
56 #endif
59 float4x4 Get_SPI_TerrainLayerInfo()
61 #if %TEMP_TERRAIN
62         #if %_RT_ENVIRONMENT_CUBEMAP
63         return float4x4(0);
64         #else
65         return CD_TerrainLayerInfo;
66         #endif
67 #else
68         return float4x4(0);
69 #endif
72 float4 Get_SPI_SkinningInfo()
74 #if !%TEMP_TERRAIN && !%TEMP_VEGETATION && (%_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR)
75         return CD_SkinningInfo;
76 #else
77         return (float4)0;
78 #endif
81 float3x4 Get_SPI_ObjWorldMat(int nIndex)
83  #if %_RT_ENVIRONMENT_CUBEMAP
84         return SInstancingData[nIndex].CI_WorldMatrix;
85  #else
86         return CD_WorldMatrix;
87  #endif
90 float4 DecodeBending(float3 vPos, float bendingRadius,float bendingScale)
92         const half fTime = g_VS_AnimGenParams.z;
93         half2 vPhase = vPos.xy * 0.125h;
95         float fRadiusVert = bendingRadius;
96         float fWaveFreq = 0.4f / (fRadiusVert + 1.f) + 0.2f;
98         float2 vFreq = float2(fWaveFreq, fWaveFreq*1.125);
100         half2 tc = (vPos.xy - g_VS_WindGridOffs.xy) * g_VS_WindGridOffs.zw;
101         half2 vWindVec = GetTexture2DLod(windGridTex, ssMaterialBilinearClamp, float4(tc.xy, 0, 0)).xy;
103         const float fWAVE_PARALLEL = 0.008f;
104         const float fWAVE_TRANSVERSE = 0.002f;
105         float2 vAmp = float2(vWindVec.x * fWAVE_PARALLEL + vWindVec.y * fWAVE_TRANSVERSE, vWindVec.y * fWAVE_PARALLEL - vWindVec.x * fWAVE_TRANSVERSE);
107         half2 vAddBending = sin((fTime * vFreq + vPhase) * 3.1415926) * vAmp;
109         half4 result;   
110         result.xy = vAddBending.xy * 50.f + vWindVec.xy;
111         result.z = length(vWindVec.xy) * 2.f;
112         result.w = length(vAddBending + vWindVec.xy) * 0.3f;
113         result.xyz *= bendingScale;
115         return result;
118 float4 Get_SPI_BendInfo(int nIndex, float3 worldPos)
120 #if %_VT_BEND
121         #if %_RT_ENVIRONMENT_CUBEMAP
122         return DecodeBending(worldPos, SInstancingData[nIndex].CI_CustomData.x,SInstancingData[nIndex].CI_CustomData.y);
123         #else
124         return DecodeBending(worldPos, CD_CustomData.x,CD_CustomData.y); 
125         #endif
126 #else
127         return (float4)0;
128 #endif
131 float4 Get_SPI_RainLayerParams(int nIndex)
133         return g_RainLayerParams;
136 float4 Get_SPI_VertexAO(int nIndex)
138         return g_VertexAO;
141 float Get_MaterialAlphaTest()
143         return CM_DetailTilingAndAlphaRef.z; // alpha ref value is stored in material CB
146 float Get_SPI_Dissolve()
148 #if %_RT_ENVIRONMENT_CUBEMAP
149         // Instancing support
150         // dissolved objects are not instanced, so we always use value from the first object
151         return SInstancingData[0].CI_CustomData.w;
152 #else 
153         return CD_CustomData.w;
154 #endif
157 int Get_PerInstanceTessellationPatchId()
159 #if %_RT_ENVIRONMENT_CUBEMAP
160         // Instancing support
161         return asint(SInstancingData[0].CI_CustomData.z);
162 #else 
163         return asint(CD_CustomData.z);
164 #endif
167 ////////////////////////////////////////////////////////////////////////////////////////////////////
168 // Common vertex attributes
170 #include "ComputeSkinningUtils.cfi"
172 // Note: user should #NOT# use directly any app2vert structures for vertex data modifications and
173 //      use streamPos instead if any modification required
175 // 8 weights skinning. this structure contains the extra 4 weights
176 struct SSkinExtraBlendWeights
178         uint  BlendWeights;     // ubyte[4] -> R8G8B8A8_UNORM
179         uint  BlendIndices[2];  // short[4] -> R16G16B16A16_SINT
182 StructuredBuffer<SSkinExtraBlendWeights> SkinExtraBlendWeights : register(t14); // !%_RT_COMPUTE_SKINNING
183 StructuredBuffer<CSSkinVertexOut>        SkinnedVertices       : register(t14); //  %_RT_COMPUTE_SKINNING
185 // compact structure to store the input assembler skinning stream + the extra 4 influences decoded in case of 8 weights skinning
186 struct SSkinBlendWeightsOut
188         float4 BlendWeights;
189         int4 BlendIndices;
192 struct app2vertCommon
194         IN_P
195         float2 baseTC   : TEXCOORDN;
196         IN_C0
198         // Tangent stream - shadows dont need this, why is it used
199 #if !%TEMP_TERRAIN
200         #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
201         float3 Normal   : NORMAL;
202         #endif
203         IN_TANG_STREAM
204 #else
205         float4 Normal   : NORMAL;
206 #endif
208         // Skinning stream related
209 #if %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
210         IN_SKIN_STREAM
211 #endif
212 #if %_RT_COMPUTE_SKINNING || %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
213         uint VertexID : SV_VertexID;
214 #endif  
215 #if %_RT_VERTEX_VELOCITY
216         IN_VERTEX_VELOCITY_STREAM 
217 #endif
219 #if %_RT_ENVIRONMENT_CUBEMAP
220         uint InstIndex : SV_InstanceID;
221 #endif
224 ////////////////////////////////////////////////////////////////////////////////////////////////////
226 struct app2vertGeneral
227 {  
228         app2vertCommon vertCommon;
231 ////////////////////////////////////////////////////////////////////////////////////////////////////
233 struct app2vertZGeneral
234 {  
235         app2vertCommon vertCommon;
238 ////////////////////////////////////////////////////////////////////////////////////////////////////
240 struct app2vertGBuffer
241 {  
242         app2vertCommon vertCommon;
245 ////////////////////////////////////////////////////////////////////////////////////////////////////
247 struct app2vertSGGeneral
249         app2vertCommon vertCommon;
252 ////////////////////////////////////////////////////////////////////////////////////////////////////
254 struct app2vertMotionBlur
255 {  
256         app2vertCommon vertCommon;
259 ////////////////////////////////////////////////////////////////////////////////////////////////////
261 struct app2vertCustomViews
263         app2vertCommon vertCommon;
266 ////////////////////////////////////////////////////////////////////////////////////////////////////
268 struct app2vertRainPass
270         app2vertCommon vertCommon; 
273 ////////////////////////////////////////////////////////////////////////////////////////////////////
275 struct app2vertEffectLayer
277         app2vertCommon vertCommon;
280 ////////////////////////////////////////////////////////////////////////////////////////////////////
281 // Shared streamPos structure for every vertex program
282 // - user should use this structure for any further vertex data modifications
284 struct streamPos
286         float4 Position;
287         float4 WorldPos;
289         float4 PositionCurr;
290         float4 PositionPrev;
291         float4 WorldPosPrev;
293         float4 Color;
294         float4 baseTC; 
295     
296 #if !%TEMP_TERRAIN
297         float4 Tangent;
298         float4 Binormal;
299         #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
300         float3 Normal;
301         #endif
302 #else
303         float4 Normal;
304 #endif
305         float3x3 ObjToTangentSpace;
306         float4x4 InstMatrix;
308 #if %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
309         SSkinBlendWeightsOut skinBlends[2];
310 #endif
311 #if %_RT_COMPUTE_SKINNING
312         uint VertexID;
313 #endif
314 #if %_RT_VERTEX_VELOCITY
315         float3 VertexVelocity;
316 #endif
318 #if %_RT_ENVIRONMENT_CUBEMAP
319         int nInstance;
320 #endif
323 ////////////////////////////////////////////////////////////////////////////////////////////////////
324 // No unified input struct for pixel shaders: pull the instance-ID explicitly
326 float4 _InstancingParams;
328 void PrepareConstInstancing(in float4 vPos, out int nInstance)
330   // Compute the instance index
331   nInstance = (int)vPos.w * _InstancingParams.w;
334 ////////////////////////////////////////////////////////////////////////////////////////////////////
335 float4 D3DX_R8G8B8A8_UNORM_TO_FLOAT4(uint packedInput)
337         float4 unpackedOutput;
338         unpackedOutput.x = (float)  (packedInput      & 0x000000ff)  / 255.0f;
339         unpackedOutput.y = (float)(((packedInput>> 8) & 0x000000ff)) / 255.0f;
340         unpackedOutput.z = (float)(((packedInput>>16) & 0x000000ff)) / 255.0f;
341         unpackedOutput.w = (float)  (packedInput>>24)                / 255.0f;
342         return unpackedOutput;
345 uint4 D3DX_R16G16B16A16_SINT_TO_UINT4(uint packedInput[2])
347         int4 unpackedOutput;
348         unpackedOutput.x =  (packedInput[0]             & 0x0000ffff);
349         unpackedOutput.y =  (packedInput[0]>>16 & 0x0000ffff);
350         unpackedOutput.z =  (packedInput[1]             & 0x0000ffff);
351         unpackedOutput.w =  (packedInput[1]>>16 & 0x0000ffff);
352         return unpackedOutput;
355 void vtxStreamUnifySkinning( in app2vertCommon IN, inout streamPos OUT )
357 #if %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
358         OUT.skinBlends[0].BlendWeights = IN.BlendWeights; 
359         OUT.skinBlends[0].BlendIndices = IN.BlendIndices;
361         #if !%_RT_COMPUTE_SKINNING
362         if (Get_SPI_SkinningInfo().w)
363         {
364                 SSkinExtraBlendWeights ebw = SkinExtraBlendWeights[IN.VertexID];
365                 OUT.skinBlends[1].BlendWeights = D3DX_R8G8B8A8_UNORM_TO_FLOAT4(ebw.BlendWeights);
366                 OUT.skinBlends[1].BlendIndices = D3DX_R16G16B16A16_SINT_TO_UINT4(ebw.BlendIndices);
367         }
368         #endif
369 #endif
371 #if %_RT_VERTEX_VELOCITY
372         OUT.VertexVelocity = IN.VertexVelocity;
373 #endif
376 ////////////////////////////////////////////////////////////////////////////////////////////////////
378 float4 DecalBinormal = { PB_FromRE[ 0 ], PB_FromRE[ 1 ], PB_FromRE[ 2 ], PB_FromRE[ 3 ] };
379 float4 DecalTangent = { PB_FromRE[ 4 ], PB_FromRE[ 5 ], PB_FromRE[ 6 ], PB_FromRE[ 7 ] };
380 float4 DecalAtten = { PB_FromRE[ 8 ], PB_FromRE[ 9 ], PB_FromRE[ 10 ], PB_FromRE[ 11 ] };
381 float4 DecalNormal = { PB_FromRE[ 12 ], PB_FromRE[ 13 ], PB_FromRE[ 14 ], PB_FromRE[ 15 ] };
383 void vtxStreamUnifyTangents( in app2vertCommon IN, inout streamPos OUT )
385         // Any tangents vertex attributes updates should go through here
387 #if %TEMP_TERRAIN
388         // Output terrain normal
389         OUT.Normal = IN.Normal;
390         OUT.Normal.xyz = EXPAND(OUT.Normal.xyz);
391 #else
393         #if %_RT_COMPUTE_SKINNING
394                 OUT.Tangent  = SkinnedVertices[IN.VertexID].qtangent;
395                 OUT.Binormal = float4(1, 1, 1, 1);
396         #elif %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
397                 OUT.Tangent  = IN.Tangent;
398                 OUT.Binormal = float4(1, 1, 1, 1);
399         #else
400                 OUT.Tangent  = IN.Tangent;
401                 OUT.Binormal = IN.Binormal;
402         #endif
404         // Compute decals tangents  
405         #if %_RT_DECAL_TEXGEN_2D
406                 float3 vNorm = TangNormal(OUT.Tangent, OUT.Binormal);
407                 float3 vBinormalProjToSurface = DecalBinormal.xyz - dot( DecalBinormal.xyz, vNorm ) * vNorm;
408                 float3 vTangentProjToSurface = DecalTangent.xyz - dot( DecalTangent.xyz, vNorm ) * vNorm;
409   
410                 OUT.Binormal = float4( normalize( vBinormalProjToSurface ), 1 );
411                 OUT.Tangent = float4( normalize( vTangentProjToSurface ), -1 );
412         #endif
414         #if %_RT_COMPUTE_SKINNING
415                 OUT.ObjToTangentSpace[0] = SkinnedVertices[IN.VertexID].tangent;
416                 OUT.ObjToTangentSpace[1] = SkinnedVertices[IN.VertexID].bitangent;
417                 OUT.ObjToTangentSpace[2] = normalize(cross(SkinnedVertices[IN.VertexID].tangent, SkinnedVertices[IN.VertexID].bitangent)) * SkinnedVertices[IN.VertexID].qtangent.w;
418         #elif %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
419                 OUT.ObjToTangentSpace = (float3x3)0;
420         #else
421                 // Workaround for invalid tangent space basis (zero-length or parallel)
422                 // TODO: Fix TSB on code side (RC and some breakable glass)
423                 OUT.Tangent.x += 1e-6;
424                 OUT.Binormal.x -= 1e-6;
426                 // Update tangents
427                 OUT.ObjToTangentSpace[0] = OUT.Tangent.xyz;
428                 OUT.ObjToTangentSpace[1] = OUT.Binormal.xyz;
429                 OUT.ObjToTangentSpace[2] = normalize(cross(OUT.Tangent.xyz, OUT.Binormal.xyz)) * OUT.Tangent.w;
430         #endif
432 #endif
436 ////////////////////////////////////////////////////////////////////////////////////////////////////
438 void vtxStreamUnifyCommonInstancing( in app2vertCommon IN, inout streamPos OUT )
440 #if %_RT_ENVIRONMENT_CUBEMAP
441         OUT.nInstance = IN.InstIndex;
442 #endif
445 ////////////////////////////////////////////////////////////////////////////////////////////////////
447 void vtxStreamUnifyCommon( in app2vertCommon IN, inout streamPos OUT )
449 ISOLATE
451 #if %_RT_COMPUTE_SKINNING
452         OUT.VertexID = IN.VertexID;
453         OUT.Position = float4(SkinnedVertices[IN.VertexID].pos, 1.0f); 
454 #else 
455         OUT.Position = float4(IN.Position.xyz, 1.0f); 
456 #endif
458         OUT.baseTC = float4(IN.baseTC, 0, 1);
459         OUT.Color = GetInputColor(IN.Color);
460         
461 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
462         OUT.Normal = IN.Normal;
463 #endif
465         // Must be first to initialize
466         vtxStreamUnifyCommonInstancing( IN, OUT );
467         
468         vtxStreamUnifyTangents( IN, OUT );
469         vtxStreamUnifySkinning( IN, OUT );
473 ////////////////////////////////////////////////////////////////////////////////////////////////////
475 void streamPos_FromGeneral(in app2vertGeneral IN, inout streamPos OUT)
477         vtxStreamUnifyCommon( IN.vertCommon, OUT );
480 ////////////////////////////////////////////////////////////////////////////////////////////////////
482 void streamPos_FromZ(in app2vertZGeneral IN, inout streamPos OUT)
484         vtxStreamUnifyCommon( IN.vertCommon, OUT );
487 ////////////////////////////////////////////////////////////////////////////////////////////////////
489 void streamPos_FromGBuffer(in app2vertGBuffer IN, inout streamPos OUT)
491         vtxStreamUnifyCommon( IN.vertCommon, OUT );
494 ////////////////////////////////////////////////////////////////////////////////////////////////////
496 void streamPos_FromSG(in app2vertSGGeneral IN, inout streamPos OUT)
498         vtxStreamUnifyCommon( IN.vertCommon, OUT );
501 ////////////////////////////////////////////////////////////////////////////////////////////////////
503 void streamPos_FromMotionBlur(in app2vertMotionBlur IN, inout streamPos OUT)
505         vtxStreamUnifyCommon( IN.vertCommon, OUT );
508 ////////////////////////////////////////////////////////////////////////////////////////////////////
510 void streamPos_FromCustomViews(in app2vertCustomViews IN, inout streamPos OUT)
512         vtxStreamUnifyCommon( IN.vertCommon, OUT );
515 ////////////////////////////////////////////////////////////////////////////////////////////////////
517 void streamPos_FromRainPass(in app2vertRainPass IN, inout streamPos OUT)
519         vtxStreamUnifyCommon( IN.vertCommon, OUT );
522 ////////////////////////////////////////////////////////////////////////////////////////////////////
524 void streamPos_FromEffectLayer(in app2vertEffectLayer IN, inout streamPos OUT)
526         vtxStreamUnifyCommon( IN.vertCommon, OUT );
529 ////////////////////////////////////////////////////////////////////////////////////////////////////
530 ////////////////////////////////////////////////////////////////////////////////////////////////////
532 // Vertex modificators
534 ////////////////////////////////////////////////////////////////////////////////////////////////////
535 // Vertex modificator types (%_VT_TYPE):
536 // 1 (VTM_SINWAVE): Sinus wave deformations
537 // 2 (VTM_SINWAVE_VTXCOL): Sinus wave deformations using vertex color for phase/freq/amp control
538 // 3 (VTM_BULGE)  : Bulge wave deformations (depends on texture coordinates)
539 // 4 (VTM_SQUEEZE)  : Sinus squeeze wave deformations
540 // 5 (VTM_PERLIN2D) : Surface 2D perlin-noise deformations
541 // 6 (VTM_PERLIN3D) : Volume 3D perlin-noise deformations
542 // 7 (VTM_FROMCENTER) : Expanding from center
543 // 12 (VTM_FIXED_OFFSET) : Fixed 3D offset along vertex normal
545 // Vertex modificator flags (in order of applying):
546 // %_VT_WIND          : Wind deformations (uses for Cloth and Hair shaders)
547 // %_VT_DEPTH_OFFSET  : Depth offset (uses for decals)
548 // %_VT_DET_BEND      : Detail bending (uses for Vegetations and requires Color stream with specific weight info)
549 // %_VT_BEND          : General bending (engine depend)
551 // %_VT_TYPE_MODIF    : Specified if one or more of vertex modif. flags is existing
552 ////////////////////////////////////////////////////////////////////////////////////////////////////
554 // Vertex modificator types
555 #define VTM_SINWAVE  1
556 #define VTM_SINWAVE_VTXCOL 2
557 #define VTM_BULGE    3
558 #define VTM_SQUEEZE  4
559 #define VTM_PERLIN2D 5
560 #define VTM_PERLIN3D 6
561 #define VTM_FROMCENTER 7
562 #define VTM_BENDING  8
563 #define VTM_FIXED_OFFSET  12
565 ////////////////////////////////////////////////////////////////////////////////////////////////////
567 float4 SmoothCurve( float4 x )
569   return x * x *( 3.0 - 2.0 * x );
570 }  
572 float4 SinCurve( float4 x )
574   return x * ( 1.0 - x * x / 3.0 );
575 }  
576   
577 float4 TriangleWave( float4 x )
578 {                           
579   return abs( frac( x + 0.5 ) * 2.0 - 1.0 );
582 float4 SignedTriangleWave( float4 x )
583 {                           
584   return abs( frac( x + 0.5 ) * 2.0 - 1.0 )*2-1;
587 float4 SmoothTriangleWave( float4 x )
589   return SmoothCurve( TriangleWave( x ) ) ;
592 float4 SmoothSignedTriangleWave( float4 x )
594   return SmoothCurve( TriangleWave( x ) ) *2-1;
597 /////////////////////////////////////////////////////////////////////////////////////////////////////
598 // Vertex modificators bending support
601 // Constants used in leaves procedural animation //////////////////
602 float bendDetailFrequency
604   register = REG_PM_PARAM_INCL_0.x;
605   string UIHelp = "Sets frequency/speed of leaves detail bending";
606   string UIName = "Detail bending frequency";
607   string UIWidget = "slider";
608   float UIMin = 0.0;
609   float UIMax = 10.0;
610   float UIStep = 0.001;
611   string Filter = "Vegetation";
612 > = 1.0;
614 float bendDetailLeafAmplitude
616   register = REG_PM_PARAM_INCL_0.y;
617   string UIHelp = "Sets amplitude of leaves edges bending";
618   string UIName = "Bending edges amplitude";
619   string UIWidget = "slider";
620   float UIMin = 0.0;
621   float UIMax = 1.0;
622   float UIStep = 0.001;
623   string Filter = "Vegetation";
624 > = 0.2;
626 #if !%VEGETATION_EXT_BENDING
627 float bendDetailBranchAmplitude
629   register = REG_PM_PARAM_INCL_0.z;
630   string UIHelp = "Sets amplitude of branches bending";
631   string UIName = "Bending branch amplitude";
632   string UIWidget = "slider";
633   float UIMin = -10.0;
634   float UIMax = 10.0;
635   float UIStep = 0.001;
636   string Filter = "Vegetation";
637 > = -0.5;
638 #endif
640 #if %VEGETATION_EXT_BENDING
641 float bendDetailBranchXYAmplitude
643   register = REG_PM_PARAM_INCL_0.w;
644   string UIHelp = "Sets amplitude of branches bending";
645   string UIName = "Bending branch XY amplitude";
646   string UIWidget = "slider";
647   float UIMin = -100.0;
648   float UIMax = 100.0;
649   float UIStep = 0.001;
650   string Filter = "Vegetation";
651 > = -0.5;
653 float bendDetailBranchXYFreq
655   register = REG_PM_PARAM_INCL_1.x;
656   string UIHelp = "Sets frequency of branches bending";
657   string UIName = "Bending branch XY frequency";
658   string UIWidget = "slider";
659   float UIMin = 0.0;
660   float UIMax = 10.0;
661   float UIStep = 0.001;
662   string Filter = "Vegetation";
663 > = 1.0;
665 float bendDetailBranchZAmplitude
667   register = REG_PM_PARAM_INCL_1.y;
668   string UIHelp = "Sets amplitude of branches bending";
669   string UIName = "Bending branch Z amplitude";
670   string UIWidget = "slider";
671   float UIMin = -100.0;
672   float UIMax = 100.0;
673   float UIStep = 0.001;
674   string Filter = "Vegetation";
675 > = -0.5;
677 float bendDetailBranchZFreq
679   register = REG_PM_PARAM_INCL_1.z;
680   string UIHelp = "Sets frequency of branches bending";
681   string UIName = "Bending branch Z frequency";
682   string UIWidget = "slider";
683   float UIMin = 0.0;
684   float UIMax = 10.0;
685   float UIStep = 0.001;
686   string Filter = "Vegetation";
687 > = 1.0;
689 float bendDetailBranchZOffset
691   register = REG_PM_PARAM_INCL_1.w;
692   string UIHelp = "Sets frequency of branches bending";
693   string UIName = "Bending branch Z phase offset";
694   string UIWidget = "slider";
695   float UIMin = 0.0;
696   float UIMax = 10.;
697   float UIStep = 0.001;
698   string Filter = "Vegetation";
699 > = 0.0;
701 float bendTriangleWaveMultiplier
703         register = REG_PM_PARAM_INCL_2.x;
704         string UIHelp = "How much triangle wave is affecting branch bending.";
705         string UIName = "Bending noise multiplier";
706         string UIWidget = "slider";
707         float UIMin = 0.0;
708         float UIMax = 1.;
709         float UIStep = 0.001;
710         string Filter = "Vegetation";
711 > = 0.0;
714 #endif
716 // vBendParams.x = windir x
717 // vBendParams.y = windir y
718 // vBendParams.z = bending strength
720 // Main vegetation bending animation (applied on entire vegetation)
721 void _MainBending(inout float3 vPos, half3 vBendParams)
723 #if %_VT_TYPE_MODIF || %_VT_TYPE
724         #if %_VT_BEND
725                 // Bend factor
726                 half fBF = vPos.z * vBendParams.z;
727                 fBF *= fBF;
729                 #if %_VT_GRASS
730                         vPos.xy += vBendParams.xy * fBF;
731                 #else
732                         half fLength = length(vPos.xyz);
734                         half3 vNewPos = vPos;
735                         vNewPos.xy += vBendParams.xy * fBF;
737                         vPos = normalize(vNewPos) * fLength;
738                 #endif
739         #endif
740 #endif
743 // vBendDetailParams.x = time
744 // vBendDetailParams.y = detail bend frequency
745 // vBendDetailParams.z = detail bend leaf amplitude
746 // vBendDetailParams.w = bend detail phase
748 // vVertexInfo.x = vertex color R ( edge info )
749 // vVertexInfo.y = vertex color G ( brach phase )
750 // vVertexInfo.z = 1 - vertex color B ( brach bend amount ), would save 1 alu with no inversion, but too late now for changing all assets
751 // vVertexInfo.w = bend detail branch amplitude
752   
753 void _DetailBending(half3 worldPos, inout float3 vPos, float3 vNormal, half3 vVertexInfo, half4 vBendDetailParams)
755 #if %_VT_TYPE_MODIF || %_VT_TYPE
756         #if %_VT_DET_BEND
757                 const half fTime = g_VS_AnimGenParams.z;
759                 half fSpeed = vBendDetailParams.w;
760                 #if %_VT_GRASS
761                         fSpeed *= (vPos.z);
762                 #endif   
764                 half fDetailFreq = vBendDetailParams.x;
765                 half fDetailLeafAmp = vBendDetailParams.y;
766                 half fDetailBranchAmp = vBendDetailParams.z;
768                 half fEdgeAtten = vVertexInfo.x;
769                 half fBranchPhase = vVertexInfo.y;
770                 half fBranchAtten = vVertexInfo.z;
772                 // Phases (object, vertex, branch)
773                 half fObjPhase = ( dot(worldPos.xyz, 2) );
774                 fBranchPhase += fObjPhase;
775                 half fVtxPhase = ( dot(vPos, fBranchPhase) );
777                 // Detail bending for leaves/grass
778                 // x: is used for edges, y is used for branch
779                 half2 vWavesIn = fTime;
780                 vWavesIn += half2(fVtxPhase, fBranchPhase);
782                 half4 vWaves = (frac( vWavesIn.xxyy * half4(1.975, 0.793, 0.375,  0.193) ) * 2.0 - 1.0) * fDetailFreq * fSpeed;
783                 vWaves = TriangleWave( vWaves );
785                 // x: is used for edges, y is used for branches
786                 half2 vWavesSum = ( (vWaves.xz + vWaves.yw)) ;
788                 // Edge and branch bending (xy is used for edges, z for branches)
789                 vPos += vWavesSum.xxy * half3(fEdgeAtten * fDetailLeafAmp * vNormal.xy, fBranchAtten * fDetailBranchAmp);
790         #endif
791 #endif
795 void _ExtBending(half3 worldPos, inout float3 vPos, float3 vNormal, half3 vVertexInfo, half4 vBendDetailParams, half3 BendInfoLocal)
797 #if %_VT_TYPE_MODIF || %_VT_TYPE
798         #if %_VT_DET_BEND
799                 const half fTime = g_VS_AnimGenParams.z;
800         #if %LEAVES || %_VT_GRASS
801                 half fSpeed = vBendDetailParams.w;
802                 #if %_VT_GRASS
803                         fSpeed *= (vPos.z);      
804                 #endif   
805         #endif   
806                 
807                 half2 fwindDir = (BendInfoLocal.x || BendInfoLocal.y) ? normalize(BendInfoLocal.xy) : 0;
808                 half fBranchPhase = vVertexInfo.y;
809                 half fObjPhase = ( dot(worldPos.xyz, 2) );
810                 fBranchPhase += fObjPhase;
811                 
812                 #if %LEAVES || %_VT_GRASS
813                         half fDetailFreq = vBendDetailParams.x;
814                         half fDetailLeafAmp = vBendDetailParams.y;
815                         half noiseMap = GetPerlinNoiseTexLod(perlinNoiseTex, float4((worldPos.xy+(g_VS_AnimGenParams.z)*2)*0.05,0,0)).r * 2 + 0.5 ;
816                         fDetailFreq *= (noiseMap);
817                         half fEdgeAtten = vVertexInfo.x;
818                         half fVtxPhase = ( dot(vPos, fBranchPhase) );
819                 #endif  
820                 
822                 // Detail bending for leaves/grass
823                 // x: is used for edges, y is used for branch
824                 #if %LEAVES || %_VT_GRASS
825                         half2 vWavesIn = fTime;
826                         vWavesIn += half2(fVtxPhase, fBranchPhase);
827                         half4 vWaves = (frac( vWavesIn.xxyy * half4(1.975, 0.793, 0.375,  0.193) ) * 2.0 - 1.0);// * fDetailFreq * fSpeed;
828                         vWaves.xy *= fDetailFreq * fSpeed;
829                         vWaves = TriangleWave( vWaves );
830                         // x: is used for edges, y is used for branches
831                         half2 vWavesSum = ( (vWaves.xz + vWaves.yw)) ;
832                 #else
833                         half vWavesIn = fTime+fBranchPhase;
834                         half2 vWaves = (frac( vWavesIn * half2(0.375,  0.193) ) * 2.0 - 1.0);
835                         vWaves = abs( frac( vWaves + 0.5 ) * 2.0 - 1.0 );
836                         // x: is used for edges, y is used for branches
837                         half2 vWavesSum = half2(0,vWaves.x + vWaves.y);
838                 #endif  
839                 
840                 half2 f = half2(fTime*bendDetailBranchXYFreq+fBranchPhase, fTime*bendDetailBranchZFreq+(fBranchPhase+bendDetailBranchZOffset)) * 3.1415926;
841                 half2 fWave = sin(f) * half2(bendDetailBranchXYAmplitude, bendDetailBranchZAmplitude);
842                 half windStrength = length(BendInfoLocal.xy)*10 ;
843                 // branch bending
844                 half fTriangleWaveStrength = lerp(1.h, vWavesSum.y, bendTriangleWaveMultiplier);
845                 vPos.xyz += half3(fwindDir * fWave.x*windStrength*fTriangleWaveStrength, fWave.y*windStrength*fTriangleWaveStrength)*(vVertexInfo.z);
846         //      vPos.xyz += half3(fwindDir * fWave.x*windStrength, fWave.y*windStrength)*(vVertexInfo.z);
847                 // detail bending
848                 #if %LEAVES || %_VT_GRASS               
849                         vPos += vWavesSum.xxx * half3(fEdgeAtten * fDetailLeafAmp * vNormal.xyz);
850                 #endif  
851         #endif
852 #endif
856 void _VTBending(inout float3 vPos, half3 BendInfoLocal, inout float3 vNormal, half3 vColor, half3 worldPos, half4 vBendDetailParams)
858 #if %_VT_TYPE_MODIF && !%SILHOUETTE_PARALLAX_OCCLUSION_MAPPING
859         half3 vVertexInfo = vColor;
860   
861         #if %VEGETATION_EXT_BENDING
862                 _ExtBending(worldPos, vPos, vNormal.xyz, vVertexInfo, vBendDetailParams, BendInfoLocal);
863         #else
864                 vVertexInfo.z = 1-vVertexInfo.z;
865                 _DetailBending(worldPos, vPos, vNormal.xyz, vVertexInfo, vBendDetailParams);
866                 _MainBending(vPos, BendInfoLocal);
867         #endif
868 #endif
872 ////////////////////////////////////////////////////////////////////////////////////////////////////==================
873 // General procedural wind support
875 #if %WIND_BENDING
877 float AnimFrequency
879   register = REG_PM_PARAM_INCL_1.x;
880   string UIName = "Wind frequency";  
881   
882   string UIWidget = "slider";
883   float UIMin = 0.0;
884   float UIMax = 10.0;
885   float UIStep = 0.001;
886   string Filter = "Cloth, Hair";
887 > = 0.0;
889 float AnimAmplitudeWav0
891   register = REG_PM_PARAM_INCL_1.y;
892   string UIName = "Wind wave0 amp";  
893   
894   string UIWidget = "slider";
895   float UIMin = 0.0;
896   float UIMax = 10.0;
897   float UIStep = 0.001;
898   string Filter = "Cloth, Hair";
899 > = 0.0;
901 float AnimAmplitudeWav2
903   register = REG_PM_PARAM_INCL_1.z;
904   string UIName = "Wind wave2 amp";  
905   
906   string UIWidget = "slider";
907   float UIMin = 0.0;
908   float UIMax = 10.0;
909   float UIStep = 0.001;
910   string Filter = "Cloth, Hair";
911 > = 0.0; 
913 float AnimPhase
915   register = REG_PM_PARAM_INCL_1.w;
916   string UIHelp = "Set cloth animation phase";                     
917   string UIName = "Wind phase";  
918   
919   string UIWidget = "slider";
920   float UIMin = 0.0;
921   float UIMax = 10.0;
922   float UIStep = 0.001;
923   string Filter = "Cloth, Hair";
924 > = 1.0;
926 #endif
929 void pos_wind_General(inout float4 InPos, float3 vNorm, float4 cVtxColors, streamPos IN)
931 #if %_VT_WIND && %WIND_BENDING
932   float fAnimAmplitudeWav1 = (AnimAmplitudeWav0 + AnimAmplitudeWav2)*0.5;
933   float4 vWavesAmp = float4( AnimAmplitudeWav0*0.573, AnimAmplitudeWav0, fAnimAmplitudeWav1, AnimAmplitudeWav2 ) * 0.01;
934   const float4 vWavesPhases = float4(0.5 + 0.3799, 0.5 + 0.575, 0.5 + 0.795, 0.5 + 1.099);
936   float fAnimPhase = dot( InPos.xyz, AnimPhase );//+WindParams.z;
937   float fSpeed = AnimFrequency; //+WindParams.w                
938                                                             
939   float4 vWaves = ( frac( (g_VS_AnimGenParams.z + fAnimPhase) * vWavesPhases ) * 2.0 - 1.0 ) *fSpeed;
940   vWaves = TriangleWave( vWaves );
941   //vWaves = SmoothTriangleWave( vWaves );
942                   
943   float fWaveSum = dot( vWavesAmp.xyzw, vWaves.xyzw ) ;      
944                 
945   InPos.xyz +=  fWaveSum * cVtxColors.w * vNorm.xyz ;                
946   
947   // aprox 18 alu
948 #endif    
951 ////////////////////////////////////////////////////////////////////////////////////////////////////
953 void _VTModify(inout float4 inPos, float3 vNorm, float4x4 InstMatrix, streamPos IN, bool bRelativeToCam, int nType)
955         // CM_DeformWave: .x=time*Freq+Phase; .y=Amp; .z=Level; .w=VertDivider
956         
957         const half fTime = g_VS_AnimGenParams.z;
958         float4 vTC = 0;
959  #if !%TEMP_TERRAIN
960   vTC = IN.baseTC;
961  #endif
963 #ifdef %_VT_TYPE
964   if (nType == VTM_SINWAVE)
965   {
966     float f = (inPos.x + inPos.y + inPos.z) * CM_DeformWave.w;
967     f = (f + CM_DeformWave.x * fTime) * 3.1415926;
968     float fWave = sin(f) * CM_DeformWave.y + CM_DeformWave.z;
969     inPos.xyz += vNorm.xyz * fWave;
970   }
971   else
972   if (nType == VTM_SINWAVE_VTXCOL)
973   {
974         float f = (inPos.x + inPos.y + inPos.z) * CM_DeformWave.w * IN.Color.y;
975     f = (f + (CM_DeformWave.x * fTime) + IN.Color.x) * 3.1415926;
976     float fWave = sin(f) * CM_DeformWave.y + CM_DeformWave.z;
977     inPos.xyz += vNorm.xyz * fWave * IN.Color.z;
978   }
979   else
980   if (nType == VTM_SQUEEZE)
981   {
982     float f = (CM_DeformWave.x * fTime) * 3.1415926;
983     float fWave = sin(f) * CM_DeformWave.y + CM_DeformWave.z;
984     inPos.xyz += vNorm.xyz * fWave;
985   }
986   else
987   if (nType == VTM_BULGE)
988   {
989     float f = (vTC.x + vTC.y + inPos.x + inPos.y + inPos.z) * CM_DeformWave.w;
990     f = (f + CM_DeformWave.x * fTime) * 3.1415926;
991     float fWave = sin(f) * CM_DeformWave.y + CM_DeformWave.z;
992     inPos.xyz += vNorm.xyz * fWave;
993   }
994   else
995   if (nType == VTM_FIXED_OFFSET)
996   {
997     float fOffset = CM_DeformWave.z;
998     inPos.xyz += vNorm.xyz * fOffset;
999   }
1000 #endif
1002 #ifdef %_VT_TYPE_MODIF || %_VT_TYPE
1004 #if %_VT_WIND
1005   pos_wind_General(inPos, vNorm, IN.Color, IN);
1006 #endif  
1008  #if %_VT_DEPTH_OFFSET && !%EYE_SPECULAR_OVERLAY
1009    inPos.xyz += vNorm.xyz * CV_DecalZFightingRemedy.z;
1010  #endif
1012  #if %_VT_DET_BEND && %_VT_BEND // need check for both bend and detail bending, since just detail bending is not anough and the code was still called
1013   nType = VTM_BENDING;
1014  #endif
1016         int nInstance = 0;
1017 #if %_RT_ENVIRONMENT_CUBEMAP
1018         nInstance = IN.nInstance;
1019 #endif
1021   if (nType == VTM_BENDING)
1022   {
1023     half3 worldPos = half3(InstMatrix[0].w, InstMatrix[1].w, InstMatrix[2].w);
1024     if (bRelativeToCam)
1025           worldPos.xyz += g_VS_WorldViewPos.xyz;
1027     half4 vBendingInfo = 0;
1028  #if %_VT_BEND
1029     vBendingInfo  = Get_SPI_BendInfo(nInstance, worldPos.xyz);
1030  #endif
1032  #if %_VT_DET_BEND
1033                 const half3 vColor = IN.Color.xyz;
1034                 #if !%VEGETATION_EXT_BENDING
1035                         const half4 vBendDetailParams = half4( bendDetailFrequency, bendDetailLeafAmplitude, bendDetailBranchAmplitude, vBendingInfo.w);
1036                 #else
1037                         const half4 vBendDetailParams = half4( bendDetailFrequency, bendDetailLeafAmplitude, 0, vBendingInfo.w);
1038                 #endif
1039  #else
1040                 const half3 vColor = 0;
1041     const half4 vBendDetailParams = 0;
1042  #endif
1043     // rotate wind vector to object space
1044         half fScaleCompensation = 1.0h / length(half3(InstMatrix[0].x, InstMatrix[0].y, InstMatrix[0].z));
1045         vBendingInfo.xy = mul(half3(vBendingInfo.xy,0),(const float3x3)InstMatrix) * fScaleCompensation;
1046     _VTBending(inPos.xyz, vBendingInfo.xyz, vNorm.xyz, vColor, worldPos, vBendDetailParams);
1047   }
1048 #endif  
1051 float4 SkinPosition(
1052         int4 indices, float4 weights,
1053         int4 extraIndices, float4 extraWeights,
1054         inout float4 position, inout float3 normal,
1055         bool bPrevFrame = false)
1057 #if %_RT_SKELETON_SSD
1058         ISOLATE 
1059         {
1060                 float4 rotation;
1061                 float4 translation;
1062                 float flip; 
1063                 if (bPrevFrame)
1064                 {
1065                         rotation     = _g_SkinQuat_Prev[indices.x][0] * weights.x;
1066                         translation  = _g_SkinQuat_Prev[indices.x][1] * weights.x;
1067                         rotation    += _g_SkinQuat_Prev[indices.y][0] * weights.y * (flip=dot(rotation, _g_SkinQuat_Prev[indices.y][0])<0?-1:1);
1068                         translation += _g_SkinQuat_Prev[indices.y][1] * weights.y * flip;
1069                         rotation    += _g_SkinQuat_Prev[indices.z][0] * weights.z * (flip=dot(rotation, _g_SkinQuat_Prev[indices.z][0])<0?-1:1);
1070                         translation += _g_SkinQuat_Prev[indices.z][1] * weights.z * flip;
1071                         rotation    += _g_SkinQuat_Prev[indices.w][0] * weights.w * (flip=dot(rotation, _g_SkinQuat_Prev[indices.w][0])<0?-1:1);
1072                         translation += _g_SkinQuat_Prev[indices.w][1] * weights.w * flip;
1073                         
1074                         if (Get_SPI_SkinningInfo().w)
1075                         {
1076                                 rotation    += _g_SkinQuat_Prev[extraIndices.x][0] * extraWeights.x * (flip=dot(rotation, _g_SkinQuat_Prev[extraIndices.x][0])<0?-1:1);;
1077                                 translation += _g_SkinQuat_Prev[extraIndices.x][1] * extraWeights.x * flip;
1078                                 rotation    += _g_SkinQuat_Prev[extraIndices.y][0] * extraWeights.y * (flip=dot(rotation, _g_SkinQuat_Prev[extraIndices.y][0])<0?-1:1);
1079                                 translation += _g_SkinQuat_Prev[extraIndices.y][1] * extraWeights.y * flip;
1080                                 rotation    += _g_SkinQuat_Prev[extraIndices.z][0] * extraWeights.z * (flip=dot(rotation, _g_SkinQuat_Prev[extraIndices.z][0])<0?-1:1);
1081                                 translation += _g_SkinQuat_Prev[extraIndices.z][1] * extraWeights.z * flip;
1082                                 rotation    += _g_SkinQuat_Prev[extraIndices.w][0] * extraWeights.w * (flip=dot(rotation, _g_SkinQuat_Prev[extraIndices.w][0])<0?-1:1);
1083                                 translation += _g_SkinQuat_Prev[extraIndices.w][1] * extraWeights.w * flip;
1084                         }
1085                 }
1086                 else
1087                 {
1088                         rotation     = _g_SkinQuat_Cur[indices.x][0] * weights.x;
1089                         translation  = _g_SkinQuat_Cur[indices.x][1] * weights.x;
1090                         rotation    += _g_SkinQuat_Cur[indices.y][0] * weights.y * (flip=dot(rotation, _g_SkinQuat_Cur[indices.y][0])<0?-1:1);
1091                         translation += _g_SkinQuat_Cur[indices.y][1] * weights.y * flip;
1092                         rotation    += _g_SkinQuat_Cur[indices.z][0] * weights.z * (flip=dot(rotation, _g_SkinQuat_Cur[indices.z][0])<0?-1:1);
1093                         translation += _g_SkinQuat_Cur[indices.z][1] * weights.z * flip;
1094                         rotation    += _g_SkinQuat_Cur[indices.w][0] * weights.w * (flip=dot(rotation, _g_SkinQuat_Cur[indices.w][0])<0?-1:1);
1095                         translation += _g_SkinQuat_Cur[indices.w][1] * weights.w * flip;
1097                         if (Get_SPI_SkinningInfo().w)
1098                         {
1099                                 rotation    += _g_SkinQuat_Cur[extraIndices.x][0] * extraWeights.x * (flip=dot(rotation, _g_SkinQuat_Cur[extraIndices.x][0])<0?-1:1);;
1100                                 translation += _g_SkinQuat_Cur[extraIndices.x][1] * extraWeights.x * flip;
1101                                 rotation    += _g_SkinQuat_Cur[extraIndices.y][0] * extraWeights.y * (flip=dot(rotation, _g_SkinQuat_Cur[extraIndices.y][0])<0?-1:1);
1102                                 translation += _g_SkinQuat_Cur[extraIndices.y][1] * extraWeights.y * flip;
1103                                 rotation    += _g_SkinQuat_Cur[extraIndices.z][0] * extraWeights.z * (flip=dot(rotation, _g_SkinQuat_Cur[extraIndices.z][0])<0?-1:1);
1104                                 translation += _g_SkinQuat_Cur[extraIndices.z][1] * extraWeights.z * flip;
1105                                 rotation    += _g_SkinQuat_Cur[extraIndices.w][0] * extraWeights.w * (flip=dot(rotation, _g_SkinQuat_Cur[extraIndices.w][0])<0?-1:1);
1106                                 translation += _g_SkinQuat_Cur[extraIndices.w][1] * extraWeights.w * flip;
1107                         }
1108                 }
1110                 {
1111                         float length = rsqrt(dot(rotation, rotation));
1112                         rotation *= length;
1113                         translation *= length;
1114                         position.xyz =
1115                                 transform_quat_vec(rotation, position) +
1116                                 (rotation.w*translation - translation.w*rotation + cross(rotation.xyz, translation.xyz)) * 2;
1118 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
1119                         // We use vertex normals for displacement instead of getting normal from tangent space
1120                         // so they have to be skinned separately
1121                         normal = transform_quat_vec(rotation, normal);
1122 #endif
1123                 }
1124         }
1125 #endif
1126 #if %_RT_SKELETON_SSD_LINEAR
1127         ISOLATE 
1128         {
1129                 float3x4 transform = { 
1130                         0,0,0,0, 
1131                         0,0,0,0, 
1132                         0,0,0,0 
1133                 };
1135                 if (bPrevFrame)
1136                 {
1137                         transform += (convert_dq_to_mat( _g_SkinQuat_Prev[indices.x][0], _g_SkinQuat_Prev[indices.x][1] ) * weights.x);
1138                         transform += (convert_dq_to_mat( _g_SkinQuat_Prev[indices.y][0], _g_SkinQuat_Prev[indices.y][1] ) * weights.y);
1139                         transform += (convert_dq_to_mat( _g_SkinQuat_Prev[indices.z][0], _g_SkinQuat_Prev[indices.z][1] ) * weights.z);
1140                         transform += (convert_dq_to_mat( _g_SkinQuat_Prev[indices.w][0], _g_SkinQuat_Prev[indices.w][1] ) * weights.w);
1141                         
1142                         if (Get_SPI_SkinningInfo().w)
1143                         {
1144                                 transform += convert_dq_to_mat( _g_SkinQuat_Prev[extraIndices.x][0], _g_SkinQuat_Prev[extraIndices.x][1] ) * extraWeights.x;
1145                                 transform += convert_dq_to_mat( _g_SkinQuat_Prev[extraIndices.y][0], _g_SkinQuat_Prev[extraIndices.y][1] ) * extraWeights.y;
1146                                 transform += convert_dq_to_mat( _g_SkinQuat_Prev[extraIndices.z][0], _g_SkinQuat_Prev[extraIndices.z][1] ) * extraWeights.z;
1147                                 transform += convert_dq_to_mat( _g_SkinQuat_Prev[extraIndices.w][0], _g_SkinQuat_Prev[extraIndices.w][1] ) * extraWeights.w;
1148                         }
1149                 }
1150                 else
1151                 {
1152                         transform += (convert_dq_to_mat( _g_SkinQuat_Cur[indices.x][0], _g_SkinQuat_Cur[indices.x][1] ) * weights.x);
1153                         transform += (convert_dq_to_mat( _g_SkinQuat_Cur[indices.y][0], _g_SkinQuat_Cur[indices.y][1] ) * weights.y);
1154                         transform += (convert_dq_to_mat( _g_SkinQuat_Cur[indices.z][0], _g_SkinQuat_Cur[indices.z][1] ) * weights.z);
1155                         transform += (convert_dq_to_mat( _g_SkinQuat_Cur[indices.w][0], _g_SkinQuat_Cur[indices.w][1] ) * weights.w);
1157                         if (Get_SPI_SkinningInfo().w)
1158                         {
1159                                 transform += convert_dq_to_mat( _g_SkinQuat_Cur[extraIndices.x][0], _g_SkinQuat_Cur[extraIndices.x][1] ) * extraWeights.x;
1160                                 transform += convert_dq_to_mat( _g_SkinQuat_Cur[extraIndices.y][0], _g_SkinQuat_Cur[extraIndices.y][1] ) * extraWeights.y;
1161                                 transform += convert_dq_to_mat( _g_SkinQuat_Cur[extraIndices.z][0], _g_SkinQuat_Cur[extraIndices.z][1] ) * extraWeights.z;
1162                                 transform += convert_dq_to_mat( _g_SkinQuat_Cur[extraIndices.w][0], _g_SkinQuat_Cur[extraIndices.w][1] ) * extraWeights.w;
1163                         }
1164                 }
1166                 {
1167                         position.xyz = mul(transform,  float4(position.xyz, 1.f)).xyz;
1168 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
1169                         // We use vertex normals for displacement instead of getting normal from tangent space
1170                         // so they have to be skinned separately
1171                         normal = mul(transform,  normal);
1172 #endif
1173                 }
1174         }
1175 #endif
1176   return position;
1179 float4 SkinPositionTangent(
1180         int4 indices, float4 weights,
1181         int4 extraIndices, float4 extraWeights,
1182         inout float4 position, inout float4 tangent,
1183         inout float3x3 tangentFrame, inout float3 normal,
1184         bool bPrevFrame = false)
1186 #if %_RT_SKELETON_SSD
1187         ISOLATE 
1188         {
1189                 float4 rotation;
1190                 float4 translation;
1191                 float flip; 
1192                 if (bPrevFrame)
1193                 {
1194                         rotation     = _g_SkinQuat_Prev[indices.x][0] * weights.x;
1195                         translation  = _g_SkinQuat_Prev[indices.x][1] * weights.x;
1196                         rotation    += _g_SkinQuat_Prev[indices.y][0] * weights.y * (flip=dot(rotation, _g_SkinQuat_Prev[indices.y][0])<0?-1:1);
1197                         translation += _g_SkinQuat_Prev[indices.y][1] * weights.y * flip;
1198                         rotation    += _g_SkinQuat_Prev[indices.z][0] * weights.z * (flip=dot(rotation, _g_SkinQuat_Prev[indices.z][0])<0?-1:1);
1199                         translation += _g_SkinQuat_Prev[indices.z][1] * weights.z * flip;
1200                         rotation    += _g_SkinQuat_Prev[indices.w][0] * weights.w * (flip=dot(rotation, _g_SkinQuat_Prev[indices.w][0])<0?-1:1);
1201                         translation += _g_SkinQuat_Prev[indices.w][1] * weights.w * flip;
1203                         if (Get_SPI_SkinningInfo().w)
1204                         {
1205                                 rotation    += _g_SkinQuat_Prev[extraIndices.x][0] * extraWeights.x * (flip=dot(rotation, _g_SkinQuat_Prev[extraIndices.x][0])<0?-1:1);;
1206                                 translation += _g_SkinQuat_Prev[extraIndices.x][1] * extraWeights.x * flip;
1207                                 rotation    += _g_SkinQuat_Prev[extraIndices.y][0] * extraWeights.y * (flip=dot(rotation, _g_SkinQuat_Prev[extraIndices.y][0])<0?-1:1);
1208                                 translation += _g_SkinQuat_Prev[extraIndices.y][1] * extraWeights.y * flip;
1209                                 rotation    += _g_SkinQuat_Prev[extraIndices.z][0] * extraWeights.z * (flip=dot(rotation, _g_SkinQuat_Prev[extraIndices.z][0])<0?-1:1);
1210                                 translation += _g_SkinQuat_Prev[extraIndices.z][1] * extraWeights.z * flip;
1211                                 rotation    += _g_SkinQuat_Prev[extraIndices.w][0] * extraWeights.w * (flip=dot(rotation, _g_SkinQuat_Prev[extraIndices.w][0])<0?-1:1);
1212                                 translation += _g_SkinQuat_Prev[extraIndices.w][1] * extraWeights.w * flip;             
1213                         }
1214                 }
1215                 else
1216                 {
1217                         rotation     = _g_SkinQuat_Cur[indices.x][0] * weights.x;
1218                         translation  = _g_SkinQuat_Cur[indices.x][1] * weights.x;
1219                         rotation    += _g_SkinQuat_Cur[indices.y][0] * weights.y * (flip=dot(rotation, _g_SkinQuat_Cur[indices.y][0])<0?-1:1);
1220                         translation += _g_SkinQuat_Cur[indices.y][1] * weights.y * flip;
1221                         rotation    += _g_SkinQuat_Cur[indices.z][0] * weights.z * (flip=dot(rotation, _g_SkinQuat_Cur[indices.z][0])<0?-1:1);
1222                         translation += _g_SkinQuat_Cur[indices.z][1] * weights.z * flip;
1223                         rotation    += _g_SkinQuat_Cur[indices.w][0] * weights.w * (flip=dot(rotation, _g_SkinQuat_Cur[indices.w][0])<0?-1:1);
1224                         translation += _g_SkinQuat_Cur[indices.w][1] * weights.w * flip;
1226                         if (Get_SPI_SkinningInfo().w)
1227                         {
1228                                 rotation    += _g_SkinQuat_Cur[extraIndices.x][0] * extraWeights.x * (flip=dot(rotation, _g_SkinQuat_Cur[extraIndices.x][0])<0?-1:1);;
1229                                 translation += _g_SkinQuat_Cur[extraIndices.x][1] * extraWeights.x * flip;
1230                                 rotation    += _g_SkinQuat_Cur[extraIndices.y][0] * extraWeights.y * (flip=dot(rotation, _g_SkinQuat_Cur[extraIndices.y][0])<0?-1:1);
1231                                 translation += _g_SkinQuat_Cur[extraIndices.y][1] * extraWeights.y * flip;
1232                                 rotation    += _g_SkinQuat_Cur[extraIndices.z][0] * extraWeights.z * (flip=dot(rotation, _g_SkinQuat_Cur[extraIndices.z][0])<0?-1:1);
1233                                 translation += _g_SkinQuat_Cur[extraIndices.z][1] * extraWeights.z * flip;
1234                                 rotation    += _g_SkinQuat_Cur[extraIndices.w][0] * extraWeights.w * (flip=dot(rotation, _g_SkinQuat_Cur[extraIndices.w][0])<0?-1:1);
1235                                 translation += _g_SkinQuat_Cur[extraIndices.w][1] * extraWeights.w * flip;              
1236                         }
1237                 }
1239                 {
1240                         float length = rsqrt(dot(rotation, rotation));
1241                         rotation *= length;
1242                         translation *= length;
1243                         position.xyz =
1244                                 transform_quat_vec(rotation, position) +
1245                                 (rotation.w*translation - translation.w*rotation + cross(rotation.xyz, translation.xyz)) * 2;
1247 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
1248                         // We use vertex normals for displacement instead of getting normal from tangent space
1249                         // so they have to be skinned separately
1250                         normal = transform_quat_vec(rotation, normal);
1251 #endif
1252                 }
1254                 float reflection = sign(tangent.w);
1255                 float4 q = transform_quat_quat(rotation, tangent);
1256                 tangentFrame = quat_to_mat(float4(-q.xyz, q.w));
1258                 tangent.w = reflection;
1259                 tangentFrame[2] *= tangent.w;
1260         }
1261 #endif
1262 #if %_RT_SKELETON_SSD_LINEAR
1263         ISOLATE
1264         {
1265                 float3x4 transform = {
1266                         0,0,0,0,
1267                         0,0,0,0,
1268                         0,0,0,0
1269                 };
1271                 if (bPrevFrame)
1272                 {
1273                         transform += convert_dq_to_mat( _g_SkinQuat_Prev[indices.x][0], _g_SkinQuat_Prev[indices.x][1] ) * weights.x;
1274                         transform += convert_dq_to_mat( _g_SkinQuat_Prev[indices.y][0], _g_SkinQuat_Prev[indices.y][1] ) * weights.y;
1275                         transform += convert_dq_to_mat( _g_SkinQuat_Prev[indices.z][0], _g_SkinQuat_Prev[indices.z][1] ) * weights.z;
1276                         transform += convert_dq_to_mat( _g_SkinQuat_Prev[indices.w][0], _g_SkinQuat_Prev[indices.w][1] ) * weights.w;
1278                         if (Get_SPI_SkinningInfo().w)
1279                         {
1280                                 transform += convert_dq_to_mat( _g_SkinQuat_Prev[extraIndices.x][0], _g_SkinQuat_Prev[extraIndices.x][1] ) * extraWeights.x;
1281                                 transform += convert_dq_to_mat( _g_SkinQuat_Prev[extraIndices.y][0], _g_SkinQuat_Prev[extraIndices.y][1] ) * extraWeights.y;
1282                                 transform += convert_dq_to_mat( _g_SkinQuat_Prev[extraIndices.z][0], _g_SkinQuat_Prev[extraIndices.z][1] ) * extraWeights.z;
1283                                 transform += convert_dq_to_mat( _g_SkinQuat_Prev[extraIndices.w][0], _g_SkinQuat_Prev[extraIndices.w][1] ) * extraWeights.w;
1284                         }
1285                 }
1286                 else
1287                 {
1288                         transform += convert_dq_to_mat( _g_SkinQuat_Cur[indices.x][0], _g_SkinQuat_Cur[indices.x][1] ) * weights.x;
1289                         transform += convert_dq_to_mat( _g_SkinQuat_Cur[indices.y][0], _g_SkinQuat_Cur[indices.y][1] ) * weights.y;
1290                         transform += convert_dq_to_mat( _g_SkinQuat_Cur[indices.z][0], _g_SkinQuat_Cur[indices.z][1] ) * weights.z;
1291                         transform += convert_dq_to_mat( _g_SkinQuat_Cur[indices.w][0], _g_SkinQuat_Cur[indices.w][1] ) * weights.w;
1293                         if (Get_SPI_SkinningInfo().w)
1294                         {
1295                                 transform += convert_dq_to_mat( _g_SkinQuat_Cur[extraIndices.x][0], _g_SkinQuat_Cur[extraIndices.x][1] ) * extraWeights.x;
1296                                 transform += convert_dq_to_mat( _g_SkinQuat_Cur[extraIndices.y][0], _g_SkinQuat_Cur[extraIndices.y][1] ) * extraWeights.y;
1297                                 transform += convert_dq_to_mat( _g_SkinQuat_Cur[extraIndices.z][0], _g_SkinQuat_Cur[extraIndices.z][1] ) * extraWeights.z;
1298                                 transform += convert_dq_to_mat( _g_SkinQuat_Cur[extraIndices.w][0], _g_SkinQuat_Cur[extraIndices.w][1] ) * extraWeights.w;
1299                         }
1300                 }
1302                 {
1303                         position.xyz = mul(transform, float4(position.xyz, 1.f)).xyz;
1304 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
1305                         // We use vertex normals for displacement instead of getting normal from tangent space
1306                         // so they have to be skinned separately
1307                         normal = mul((float3x3)transform, normal);
1308 #endif
1309                 }
1311                 float reflection = sign(tangent.w);
1312                 float4 q = transform_quat_quat(mat_to_quat((float3x3)transform), tangent);
1313                 tangentFrame = quat_to_mat(float4(-q.xyz, q.w));
1315                 tangent.w = reflection;
1316                 tangentFrame[2] *= tangent.w;
1317         }
1318 #endif          
1320         return position;
1323 ////////////////////////////////////////////////////////////////////////////////////////////////////
1325 // Vertex shaders for position
1326 float4x4 GetInstanceMatrix(int nInstance=0)
1328   float4x4 Mat = float4x4( float4(1, 0, 0, 0),
1329                            float4(0, 1, 0, 0),
1330                            float4(0, 0, 1, 0),
1331                            float4(0, 0, 0, 1) );
1333 #if !%_RT_OBJ_IDENTITY
1334   float3x4 objWorldMat = Get_SPI_ObjWorldMat(nInstance);
1335   Mat[0] = objWorldMat[0];
1336   Mat[1] = objWorldMat[1];
1337   Mat[2] = objWorldMat[2];
1338 #endif
1340   return Mat;
1343 ////////////////////////////////////////////////////////////////////////////////////////////////////
1345 void Matrix_Inst_General(inout streamPos IN)
1347         // Instancing support
1348         int nInstance = 0;
1349 #if %_RT_ENVIRONMENT_CUBEMAP
1350         nInstance = IN.nInstance;
1351 #endif
1353         IN.InstMatrix = GetInstanceMatrix(nInstance);
1356 ////////////////////////////////////////////////////////////////////////////////////////////////////.
1358 float4 _pos_HPos(float4x4 VPMatrix, float4x4 InstMatrix, float4 InPos)
1360         {
1361   float4 vWorldPos = mul( InstMatrix, InPos );
1362   return mul(VPMatrix, vWorldPos);
1363         }
1366 float4 _pos_Common(float4 InPos)
1368         float4x4 InstMatrix = GetInstanceMatrix();
1369         
1370 #if !%_RT_OBJ_IDENTITY
1371         // Position relative to camera
1372         InstMatrix[0][3] -= g_VS_WorldViewPos.x;
1373         InstMatrix[1][3] -= g_VS_WorldViewPos.y;
1374         InstMatrix[2][3] -= g_VS_WorldViewPos.z;
1375 #endif
1377         return _pos_HPos(g_VS_ViewProjZeroMatr, InstMatrix, InPos);
1380 float4 _pos_WaterLevel(float4x4 VPMatrix, inout float4 InPos, float _Level)
1382   InPos.z = _Level;
1383   return mul(VPMatrix, InPos);
1386 ////////////////////////////////////////////////////////////////////////////////////////////////////
1388 float4 _pos_Modificators(float4x4 VPMatrix, float4x4 InstMatrix, inout streamPos IN, bool bRelativeToCam=true, bool bPrevFrame=false, float fPrevDelta = 0)
1390   int nType = 0;
1391   float4 InPos = IN.Position;
1393 #if %_VT_TYPE
1394   nType = %_VT_TYPE;
1395 #endif
1397 #if %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR || %_RT_COMPUTE_SKINNING
1398         #if !%TEMP_TERRAIN
1399                 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
1400                         float3 vNormal = IN.Normal.xyz;
1401                 #else
1402                         float3 vNormal = 0;
1403                 #endif
1405                 InPos.xyz += Get_SPI_SkinningInfo().xyz;
1406                 
1407                 #if !%_RT_COMPUTE_SKINNING
1408                         if (bPrevFrame == false)
1409                         {
1410                                 SkinPositionTangent(
1411                                         IN.skinBlends[0].BlendIndices, IN.skinBlends[0].BlendWeights, 
1412                                         IN.skinBlends[1].BlendIndices, IN.skinBlends[1].BlendWeights, 
1413                                         InPos, IN.Tangent, IN.ObjToTangentSpace, vNormal);
1414                         }
1415                         else
1416                         {
1417                                 SkinPosition(
1418                                         IN.skinBlends[0].BlendIndices, IN.skinBlends[0].BlendWeights, 
1419                                         IN.skinBlends[1].BlendIndices, IN.skinBlends[1].BlendWeights, 
1420                                         InPos, vNormal, bPrevFrame);
1421                         }
1422                 #endif
1423                 
1424                 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
1425                         IN.Normal.xyz = vNormal;
1426                 #endif
1427         #endif 
1428 #endif
1430 #if %_VT_TYPE || %_VT_TYPE_MODIF
1431 #if %TEMP_VEGETATION 
1432 ISOLATE
1433 #endif
1434         {
1435           float3 vNorm = IN.ObjToTangentSpace[2];
1436    _VTModify(InPos, vNorm, InstMatrix, IN, bRelativeToCam, nType);
1437         }
1438 #endif
1441         if( bPrevFrame == false )
1442         {
1443                 IN.Position.xyz = InPos.xyz;
1444                 IN.WorldPos = mul(IN.InstMatrix, IN.Position);
1445         }
1446         else
1447         {
1448 #if %_RT_VERTEX_VELOCITY
1449                 InPos.xyz += IN.VertexVelocity;
1450 #endif
1451                 InPos.xyz = lerp(IN.PositionCurr.xyz, InPos.xyz, fPrevDelta);
1452                 IN.PositionPrev.xyz = InPos.xyz;
1453                 IN.WorldPosPrev = mul(IN.InstMatrix, IN.PositionPrev);
1454         }
1456   float4 HPosition = _pos_HPos(VPMatrix, InstMatrix, InPos);    
1458 #if %_VT_DEPTH_OFFSET && !%EYE_SPECULAR_OVERLAY
1459   HPosition = HPosition * CV_DecalZFightingRemedy.x + CV_DecalZFightingRemedy.wwyw;  // Eye shader has custom zbias (and still requires _VT_DEPTH_OFFSET for position offset)
1460 #endif  
1462   return HPosition;
1465 // Output view space position (If skinning used, position and tangent space is skinned)
1466 float4 Pos_VS_General(float4x4 VPMatrix, inout streamPos IN, bool bRelativeToCam=true, bool bInstanceMatToWorld=false)
1468 ISOLATE
1470         float4 HPosition;
1472 #if %_RT_OBJ_IDENTITY
1473         VPMatrix = g_VS_ViewProjMatr;
1474 #endif
1476 #if %_RT_NEAREST
1477         bRelativeToCam = false;
1478         VPMatrix = CV_ViewProjNearestMatr;
1479 #endif
1481         // Get instanced matrix
1482         Matrix_Inst_General(IN);
1483         if(bInstanceMatToWorld)
1484         {
1485         #if !%_RT_OBJ_IDENTITY
1486                 IN.InstMatrix[0][3] += g_VS_WorldViewPos.x;
1487                 IN.InstMatrix[1][3] += g_VS_WorldViewPos.y;
1488                 IN.InstMatrix[2][3] += g_VS_WorldViewPos.z;
1489         #endif
1490         }
1491         
1492         if (bRelativeToCam)
1493         {
1494         #if !%_RT_OBJ_IDENTITY 
1495                 IN.InstMatrix[0][3] -= g_VS_WorldViewPos.x;
1496                 IN.InstMatrix[1][3] -= g_VS_WorldViewPos.y;
1497                 IN.InstMatrix[2][3] -= g_VS_WorldViewPos.z;
1498         #endif
1499         }
1502 #if %BILLBOARD
1504         {
1505                 // calculate billboard rotation angle
1506                 float3 vPosWS = mul(IN.InstMatrix, float4(0,0,0,1));
1507                 float2 vDir = normalize(vPosWS.xy);
1508                 float fAngle = atan2(vDir.x, -vDir.y);
1510                 // calculate object rotation angle
1511                 float3 vRotDir;
1512                 vRotDir = IN.InstMatrix[0];
1513                 vRotDir.xy = normalize(vRotDir.xy);
1514                 float fRotAngle = atan2(vRotDir.y, vRotDir.x);
1516                 // rotate position
1517                 float cs = cos(fAngle);
1518                 float sn = sin(fAngle);         
1519                 float2 vXY = IN.Position.xy;
1520                 IN.Position.x = vXY.x * cs - vXY.y * sn;
1521                 IN.Position.y = vXY.x * sn + vXY.y * cs;
1523                 // calculate texture atlas offset from rotation angle
1524                 const int nAtlasDim = 4;
1525                 const int nAtlasMsk = nAtlasDim - 1;
1526                 int nId = floor((-(fAngle + fRotAngle) / PI_X2 + .5) * nAtlasDim * nAtlasDim + .5f);
1527                 nId = nId & (nAtlasDim*nAtlasDim - 1);
1528                 int nX = (nId / nAtlasDim) & nAtlasMsk;
1529                 int nY = (nId & nAtlasMsk);
1531                 // apply texture atlas offset
1532                 IN.baseTC.x = (IN.baseTC.x + nY) / nAtlasDim;
1533                 IN.baseTC.y = (IN.baseTC.y + nX) / nAtlasDim;
1535                 // calculate tangent space
1536                 float3 vNorm = -float3 (normalize(vDir), 0);
1537                 IN.ObjToTangentSpace[2] = -float3(0,0,1);
1538                 IN.ObjToTangentSpace[1] = cross(vNorm, IN.ObjToTangentSpace[2].xyz);
1539                 IN.ObjToTangentSpace[0] = vNorm;
1541                 // remove rotation from matrix (copy values from Z axis)
1542                 IN.InstMatrix[0].xyz = IN.InstMatrix[2].zxy;
1543                 IN.InstMatrix[1].xyz = IN.InstMatrix[2].yzx;
1546 #endif
1548          HPosition = _pos_Modificators(VPMatrix, IN.InstMatrix, IN, bRelativeToCam);
1550         #if %TEMP_TERRAIN
1551                 float4 terrainInfo = Get_SPI_BlendWithTerrainColInfo();
1552                 if (terrainInfo.w<0)
1553                 {
1554                         // Read Z from the texture
1555                         float2 xy = float2(terrainInfo.zz*(IN.WorldPos).yx + terrainInfo.xy);
1556                         IN.Position.z = IN.Position.z * IN.InstMatrix[0][0] + GetTexture2DLod(terrainElevTex, ssMaterialTrilinearClamp, float4(xy, 0, 0)) + terrainInfo.w;
1557                         HPosition = _pos_Modificators(VPMatrix, IN.InstMatrix, IN, bRelativeToCam);
1558                 }
1559         #endif
1561                 return HPosition;
1562         }
1565 float4 Pos_VS_Terrain(float fOffsetZ, float4x4 VPMatrix, inout streamPos IN, bool bSG = false)
1567         float4 InPos = IN.Position;
1568 #if %_RT_OBJ_IDENTITY
1569         if (!bSG)
1570                 InPos.xyz -= g_VS_WorldViewPos.xyz;
1571 #endif
1573 #if %_RT_REVERSE_DEPTH
1574         fOffsetZ = -fOffsetZ;
1575 #endif 
1576         IN.InstMatrix = GetInstanceMatrix();
1578 #if !%_RT_OBJ_IDENTITY
1579         // Position relative to camera
1580         IN.InstMatrix[0][3] -= g_VS_WorldViewPos.x;
1581         IN.InstMatrix[1][3] -= g_VS_WorldViewPos.y;
1582         IN.InstMatrix[2][3] -= g_VS_WorldViewPos.z;
1583 #endif
1585         float4 HPosition = _pos_HPos(VPMatrix, IN.InstMatrix, InPos);
1586         const float fDefaultNearPlaneDist = 0.25;
1587         HPosition.z += fOffsetZ * (g_VS_NearFarClipDist.x / fDefaultNearPlaneDist);
1589         IN.WorldPos = mul(IN.InstMatrix, IN.Position);
1591 #if %TEMP_TERRAIN
1592         float4 terrainInfo = Get_SPI_BlendWithTerrainColInfo();
1593         if (terrainInfo.w<0)
1594         {
1595                 // Read Z from the texture
1596                 float2 xy = float2(terrainInfo.zz*(IN.WorldPos + g_VS_WorldViewPos).yx + terrainInfo.xy);
1597                 InPos.z = InPos.z * IN.InstMatrix[0][0] + GetTexture2DLod(terrainElevTex, ssMaterialTrilinearClamp, float4(xy, 0, 0));
1598                 HPosition = _pos_HPos(VPMatrix, IN.InstMatrix, InPos);
1599                 HPosition.z += fOffsetZ * (g_VS_NearFarClipDist.x / fDefaultNearPlaneDist);
1600         }
1601 #endif
1603   return HPosition;
1605 ////////////////////////////////////////////////////////////////////////////////////////////////////