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)
11 ////////////////////////////////////////////////////////////////////////////////////////////////////
13 cbuffer CBPerInstance : register(b0)
15 #if %_RT_ENVIRONMENT_CUBEMAP
18 float3x4 CI_WorldMatrix;
19 float4 CI_CustomData; // [x=VegetationBendingVerticalRadius, y=VegetationBendingScale, z=tessellation patch id offset, w=dissolve]
20 } SInstancingData[800];
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]
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;
46 float4 Get_SPI_BlendWithTerrainColInfo()
48 #if %TEMP_TERRAIN || (%TEMP_VEGETATION && %_RT_BLEND_WITH_TERRAIN_COLOR)
49 #if %_RT_ENVIRONMENT_CUBEMAP
52 return CD_BlendTerrainColInfo;
59 float4x4 Get_SPI_TerrainLayerInfo()
62 #if %_RT_ENVIRONMENT_CUBEMAP
65 return CD_TerrainLayerInfo;
72 float4 Get_SPI_SkinningInfo()
74 #if !%TEMP_TERRAIN && !%TEMP_VEGETATION && (%_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR)
75 return CD_SkinningInfo;
81 float3x4 Get_SPI_ObjWorldMat(int nIndex)
83 #if %_RT_ENVIRONMENT_CUBEMAP
84 return SInstancingData[nIndex].CI_WorldMatrix;
86 return CD_WorldMatrix;
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;
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;
118 float4 Get_SPI_BendInfo(int nIndex, float3 worldPos)
121 #if %_RT_ENVIRONMENT_CUBEMAP
122 return DecodeBending(worldPos, SInstancingData[nIndex].CI_CustomData.x,SInstancingData[nIndex].CI_CustomData.y);
124 return DecodeBending(worldPos, CD_CustomData.x,CD_CustomData.y);
131 float4 Get_SPI_RainLayerParams(int nIndex)
133 return g_RainLayerParams;
136 float4 Get_SPI_VertexAO(int nIndex)
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;
153 return CD_CustomData.w;
157 int Get_PerInstanceTessellationPatchId()
159 #if %_RT_ENVIRONMENT_CUBEMAP
160 // Instancing support
161 return asint(SInstancingData[0].CI_CustomData.z);
163 return asint(CD_CustomData.z);
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
192 struct app2vertCommon
195 float2 baseTC : TEXCOORDN;
198 // Tangent stream - shadows dont need this, why is it used
200 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
201 float3 Normal : NORMAL;
205 float4 Normal : NORMAL;
208 // Skinning stream related
209 #if %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
212 #if %_RT_COMPUTE_SKINNING || %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
213 uint VertexID : SV_VertexID;
215 #if %_RT_VERTEX_VELOCITY
216 IN_VERTEX_VELOCITY_STREAM
219 #if %_RT_ENVIRONMENT_CUBEMAP
220 uint InstIndex : SV_InstanceID;
224 ////////////////////////////////////////////////////////////////////////////////////////////////////
226 struct app2vertGeneral
228 app2vertCommon vertCommon;
231 ////////////////////////////////////////////////////////////////////////////////////////////////////
233 struct app2vertZGeneral
235 app2vertCommon vertCommon;
238 ////////////////////////////////////////////////////////////////////////////////////////////////////
240 struct app2vertGBuffer
242 app2vertCommon vertCommon;
245 ////////////////////////////////////////////////////////////////////////////////////////////////////
247 struct app2vertSGGeneral
249 app2vertCommon vertCommon;
252 ////////////////////////////////////////////////////////////////////////////////////////////////////
254 struct app2vertMotionBlur
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
299 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
305 float3x3 ObjToTangentSpace;
308 #if %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR
309 SSkinBlendWeightsOut skinBlends[2];
311 #if %_RT_COMPUTE_SKINNING
314 #if %_RT_VERTEX_VELOCITY
315 float3 VertexVelocity;
318 #if %_RT_ENVIRONMENT_CUBEMAP
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])
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)
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);
371 #if %_RT_VERTEX_VELOCITY
372 OUT.VertexVelocity = IN.VertexVelocity;
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
388 // Output terrain normal
389 OUT.Normal = IN.Normal;
390 OUT.Normal.xyz = EXPAND(OUT.Normal.xyz);
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);
400 OUT.Tangent = IN.Tangent;
401 OUT.Binormal = IN.Binormal;
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;
410 OUT.Binormal = float4( normalize( vBinormalProjToSurface ), 1 );
411 OUT.Tangent = float4( normalize( vTangentProjToSurface ), -1 );
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;
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;
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;
436 ////////////////////////////////////////////////////////////////////////////////////////////////////
438 void vtxStreamUnifyCommonInstancing( in app2vertCommon IN, inout streamPos OUT )
440 #if %_RT_ENVIRONMENT_CUBEMAP
441 OUT.nInstance = IN.InstIndex;
445 ////////////////////////////////////////////////////////////////////////////////////////////////////
447 void vtxStreamUnifyCommon( in app2vertCommon IN, inout streamPos OUT )
451 #if %_RT_COMPUTE_SKINNING
452 OUT.VertexID = IN.VertexID;
453 OUT.Position = float4(SkinnedVertices[IN.VertexID].pos, 1.0f);
455 OUT.Position = float4(IN.Position.xyz, 1.0f);
458 OUT.baseTC = float4(IN.baseTC, 0, 1);
459 OUT.Color = GetInputColor(IN.Color);
461 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
462 OUT.Normal = IN.Normal;
465 // Must be first to initialize
466 vtxStreamUnifyCommonInstancing( IN, OUT );
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
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 );
572 float4 SinCurve( float4 x )
574 return x * ( 1.0 - x * x / 3.0 );
577 float4 TriangleWave( float4 x )
579 return abs( frac( x + 0.5 ) * 2.0 - 1.0 );
582 float4 SignedTriangleWave( float4 x )
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";
610 float UIStep = 0.001;
611 string Filter = "Vegetation";
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";
622 float UIStep = 0.001;
623 string Filter = "Vegetation";
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";
635 float UIStep = 0.001;
636 string Filter = "Vegetation";
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;
649 float UIStep = 0.001;
650 string Filter = "Vegetation";
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";
661 float UIStep = 0.001;
662 string Filter = "Vegetation";
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;
673 float UIStep = 0.001;
674 string Filter = "Vegetation";
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";
685 float UIStep = 0.001;
686 string Filter = "Vegetation";
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";
697 float UIStep = 0.001;
698 string Filter = "Vegetation";
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";
709 float UIStep = 0.001;
710 string Filter = "Vegetation";
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
726 half fBF = vPos.z * vBendParams.z;
730 vPos.xy += vBendParams.xy * fBF;
732 half fLength = length(vPos.xyz);
734 half3 vNewPos = vPos;
735 vNewPos.xy += vBendParams.xy * fBF;
737 vPos = normalize(vNewPos) * fLength;
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
753 void _DetailBending(half3 worldPos, inout float3 vPos, float3 vNormal, half3 vVertexInfo, half4 vBendDetailParams)
755 #if %_VT_TYPE_MODIF || %_VT_TYPE
757 const half fTime = g_VS_AnimGenParams.z;
759 half fSpeed = vBendDetailParams.w;
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);
795 void _ExtBending(half3 worldPos, inout float3 vPos, float3 vNormal, half3 vVertexInfo, half4 vBendDetailParams, half3 BendInfoLocal)
797 #if %_VT_TYPE_MODIF || %_VT_TYPE
799 const half fTime = g_VS_AnimGenParams.z;
800 #if %LEAVES || %_VT_GRASS
801 half fSpeed = vBendDetailParams.w;
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;
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) );
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)) ;
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);
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 ;
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);
848 #if %LEAVES || %_VT_GRASS
849 vPos += vWavesSum.xxx * half3(fEdgeAtten * fDetailLeafAmp * vNormal.xyz);
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;
861 #if %VEGETATION_EXT_BENDING
862 _ExtBending(worldPos, vPos, vNormal.xyz, vVertexInfo, vBendDetailParams, BendInfoLocal);
864 vVertexInfo.z = 1-vVertexInfo.z;
865 _DetailBending(worldPos, vPos, vNormal.xyz, vVertexInfo, vBendDetailParams);
866 _MainBending(vPos, BendInfoLocal);
872 ////////////////////////////////////////////////////////////////////////////////////////////////////==================
873 // General procedural wind support
879 register = REG_PM_PARAM_INCL_1.x;
880 string UIName = "Wind frequency";
882 string UIWidget = "slider";
885 float UIStep = 0.001;
886 string Filter = "Cloth, Hair";
889 float AnimAmplitudeWav0
891 register = REG_PM_PARAM_INCL_1.y;
892 string UIName = "Wind wave0 amp";
894 string UIWidget = "slider";
897 float UIStep = 0.001;
898 string Filter = "Cloth, Hair";
901 float AnimAmplitudeWav2
903 register = REG_PM_PARAM_INCL_1.z;
904 string UIName = "Wind wave2 amp";
906 string UIWidget = "slider";
909 float UIStep = 0.001;
910 string Filter = "Cloth, Hair";
915 register = REG_PM_PARAM_INCL_1.w;
916 string UIHelp = "Set cloth animation phase";
917 string UIName = "Wind phase";
919 string UIWidget = "slider";
922 float UIStep = 0.001;
923 string Filter = "Cloth, Hair";
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
939 float4 vWaves = ( frac( (g_VS_AnimGenParams.z + fAnimPhase) * vWavesPhases ) * 2.0 - 1.0 ) *fSpeed;
940 vWaves = TriangleWave( vWaves );
941 //vWaves = SmoothTriangleWave( vWaves );
943 float fWaveSum = dot( vWavesAmp.xyzw, vWaves.xyzw ) ;
945 InPos.xyz += fWaveSum * cVtxColors.w * vNorm.xyz ;
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
957 const half fTime = g_VS_AnimGenParams.z;
964 if (nType == VTM_SINWAVE)
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;
972 if (nType == VTM_SINWAVE_VTXCOL)
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;
980 if (nType == VTM_SQUEEZE)
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;
987 if (nType == VTM_BULGE)
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;
995 if (nType == VTM_FIXED_OFFSET)
997 float fOffset = CM_DeformWave.z;
998 inPos.xyz += vNorm.xyz * fOffset;
1002 #ifdef %_VT_TYPE_MODIF || %_VT_TYPE
1005 pos_wind_General(inPos, vNorm, IN.Color, IN);
1008 #if %_VT_DEPTH_OFFSET && !%EYE_SPECULAR_OVERLAY
1009 inPos.xyz += vNorm.xyz * CV_DecalZFightingRemedy.z;
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;
1017 #if %_RT_ENVIRONMENT_CUBEMAP
1018 nInstance = IN.nInstance;
1021 if (nType == VTM_BENDING)
1023 half3 worldPos = half3(InstMatrix[0].w, InstMatrix[1].w, InstMatrix[2].w);
1025 worldPos.xyz += g_VS_WorldViewPos.xyz;
1027 half4 vBendingInfo = 0;
1029 vBendingInfo = Get_SPI_BendInfo(nInstance, worldPos.xyz);
1033 const half3 vColor = IN.Color.xyz;
1034 #if !%VEGETATION_EXT_BENDING
1035 const half4 vBendDetailParams = half4( bendDetailFrequency, bendDetailLeafAmplitude, bendDetailBranchAmplitude, vBendingInfo.w);
1037 const half4 vBendDetailParams = half4( bendDetailFrequency, bendDetailLeafAmplitude, 0, vBendingInfo.w);
1040 const half3 vColor = 0;
1041 const half4 vBendDetailParams = 0;
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);
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
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;
1074 if (Get_SPI_SkinningInfo().w)
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;
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)
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;
1111 float length = rsqrt(dot(rotation, rotation));
1113 translation *= length;
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);
1126 #if %_RT_SKELETON_SSD_LINEAR
1129 float3x4 transform = {
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);
1142 if (Get_SPI_SkinningInfo().w)
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;
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)
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;
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);
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
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)
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;
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)
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;
1240 float length = rsqrt(dot(rotation, rotation));
1242 translation *= length;
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);
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;
1262 #if %_RT_SKELETON_SSD_LINEAR
1265 float3x4 transform = {
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)
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;
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)
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;
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);
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;
1323 ////////////////////////////////////////////////////////////////////////////////////////////////////
1325 // Vertex shaders for position
1326 float4x4 GetInstanceMatrix(int nInstance=0)
1328 float4x4 Mat = float4x4( float4(1, 0, 0, 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];
1343 ////////////////////////////////////////////////////////////////////////////////////////////////////
1345 void Matrix_Inst_General(inout streamPos IN)
1347 // Instancing support
1349 #if %_RT_ENVIRONMENT_CUBEMAP
1350 nInstance = IN.nInstance;
1353 IN.InstMatrix = GetInstanceMatrix(nInstance);
1356 ////////////////////////////////////////////////////////////////////////////////////////////////////.
1358 float4 _pos_HPos(float4x4 VPMatrix, float4x4 InstMatrix, float4 InPos)
1361 float4 vWorldPos = mul( InstMatrix, InPos );
1362 return mul(VPMatrix, vWorldPos);
1366 float4 _pos_Common(float4 InPos)
1368 float4x4 InstMatrix = GetInstanceMatrix();
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;
1377 return _pos_HPos(g_VS_ViewProjZeroMatr, InstMatrix, InPos);
1380 float4 _pos_WaterLevel(float4x4 VPMatrix, inout float4 InPos, float _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)
1391 float4 InPos = IN.Position;
1397 #if %_RT_SKELETON_SSD || %_RT_SKELETON_SSD_LINEAR || %_RT_COMPUTE_SKINNING
1399 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
1400 float3 vNormal = IN.Normal.xyz;
1405 InPos.xyz += Get_SPI_SkinningInfo().xyz;
1407 #if !%_RT_COMPUTE_SKINNING
1408 if (bPrevFrame == false)
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);
1418 IN.skinBlends[0].BlendIndices, IN.skinBlends[0].BlendWeights,
1419 IN.skinBlends[1].BlendIndices, IN.skinBlends[1].BlendWeights,
1420 InPos, vNormal, bPrevFrame);
1424 #if ENABLE_TESSELLATION && !%_RT_NO_TESSELLATION
1425 IN.Normal.xyz = vNormal;
1430 #if %_VT_TYPE || %_VT_TYPE_MODIF
1431 #if %TEMP_VEGETATION
1435 float3 vNorm = IN.ObjToTangentSpace[2];
1436 _VTModify(InPos, vNorm, InstMatrix, IN, bRelativeToCam, nType);
1441 if( bPrevFrame == false )
1443 IN.Position.xyz = InPos.xyz;
1444 IN.WorldPos = mul(IN.InstMatrix, IN.Position);
1448 #if %_RT_VERTEX_VELOCITY
1449 InPos.xyz += IN.VertexVelocity;
1451 InPos.xyz = lerp(IN.PositionCurr.xyz, InPos.xyz, fPrevDelta);
1452 IN.PositionPrev.xyz = InPos.xyz;
1453 IN.WorldPosPrev = mul(IN.InstMatrix, IN.PositionPrev);
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)
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)
1472 #if %_RT_OBJ_IDENTITY
1473 VPMatrix = g_VS_ViewProjMatr;
1477 bRelativeToCam = false;
1478 VPMatrix = CV_ViewProjNearestMatr;
1481 // Get instanced matrix
1482 Matrix_Inst_General(IN);
1483 if(bInstanceMatToWorld)
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;
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;
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
1512 vRotDir = IN.InstMatrix[0];
1513 vRotDir.xy = normalize(vRotDir.xy);
1514 float fRotAngle = atan2(vRotDir.y, vRotDir.x);
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;
1548 HPosition = _pos_Modificators(VPMatrix, IN.InstMatrix, IN, bRelativeToCam);
1551 float4 terrainInfo = Get_SPI_BlendWithTerrainColInfo();
1552 if (terrainInfo.w<0)
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);
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
1570 InPos.xyz -= g_VS_WorldViewPos.xyz;
1573 #if %_RT_REVERSE_DEPTH
1574 fOffsetZ = -fOffsetZ;
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;
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);
1592 float4 terrainInfo = Get_SPI_BlendWithTerrainColInfo();
1593 if (terrainInfo.w<0)
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);
1605 ////////////////////////////////////////////////////////////////////////////////////////////////////