home *** CD-ROM | disk | FTP | other *** search
- #ifndef QSClothWind_h__
- #define QSClothWind_h__
-
- #include "QSVertexProcessUtils.h"
-
- #if CLOTH_WIND
- #include "QSGameTime.h"
- sampler2D ClothWrinkleSampler;
- sampler2D ClothWrinkleNormalSampler;
- float4 ClothWindParam;
- float4 ClothWindMotion;
-
- #define time GameTime.x
- #define speed ClothWindParam.x // 0.02
- #define tiling ClothWindParam.y // 0.4
- #define offsetAmp ClothWindParam.z
- #define normalAmp ClothWindParam.w
- #define windDir ClothWindMotion.xyz
-
- #define xDir float3(1, 0, 0)
- #define yDir float3(0, 1, 0)
- #define zDir float3(0, 0, 1)
-
- float4 GetRotateQuat(float3 from, float3 to)
- {
- const float3 hv = normalize(from + to);
- return float4(cross(from, hv), dot(from, hv));
- }
-
- float3 Rotate(float4 rot, float3 pos)
- {
- float qs = rot.w;
- float3 qv = rot.xyz;
-
- return (qs * qs - dot(qv, qv)) * pos + 2 * qs * cross(qv, pos) + 2 * dot(qv, pos) * qv;
- }
-
- bool AffectByWind(float wrinkleBlend)
- {
- return abs(wrinkleBlend) > 0.001;
- }
-
- void GetSmoothNormalAndWrinkleBlend(VsIn param, float2 boneUv, out float3 smoothNormal, out float wrinkleBlend)
- {
- #if VERTEX_COMPRESSION
- float3 vertexColor = DecompressColorbToFloat(param.vertexColor).xyz;
- #else
- float3 vertexColor = param.vertexColor;
- #endif
-
- wrinkleBlend = vertexColor.z;
-
- const float2 normxy = vertexColor.xy * 2 - 1;
- const float normz = sqrt(1 - saturate(dot(normxy, normxy)));
- smoothNormal = normalize(float3(normxy, normz));
-
- #if SKINNING
- VertexTransformCalc_SkinningDir(smoothNormal, param.blendWeight, param.blendIndices, boneUv, smoothNormal);
- #endif
- }
-
- float3 GetSamplePos(float3 pos)
- {
- return pos * tiling + fmod(time * speed * normalize(windDir), 100);
- }
-
- float SampleOffsetInVs(sampler2D s, float2 uv)
- {
- return tex2Dlod(s, float4(uv, 0, 0)).x * offsetAmp;
- }
-
- float3 SampleNormal(sampler2D s, float2 uv)
- {
- float4 color = tex2D(s, uv);
- float2 normalxy = BiDecompress(color.rg) * normalAmp;
- float normalz = sqrt(1.0f - saturate(dot(normalxy, normalxy)));
- return float3(normalxy, normalz);
- }
-
- void ClothWindPosition(inout float3 pos, float wrinkleBlend, float3 smoothNormalWS, float3 samplePos)
- {
- if (!AffectByWind(wrinkleBlend))
- {
- return;
- }
-
- const float2 sampleXz = samplePos.xz;
- const float2 sampleYz = samplePos.yz;
-
- const float xzRatio = abs(dot(smoothNormalWS, yDir));
- const float yzRatio = abs(dot(smoothNormalWS, xDir));
-
- const float wrinkleOffsetXz = SampleOffsetInVs(ClothWrinkleSampler, sampleXz) * xzRatio;
- const float wrinkleOffsetYz = SampleOffsetInVs(ClothWrinkleSampler, sampleYz) * yzRatio;
-
- pos += (wrinkleOffsetXz + wrinkleOffsetYz) * wrinkleBlend *smoothNormalWS;
- }
-
- void ClothWindNormal(inout float3 normal, inout float3 binormal, inout float3 tangent, float3 smoothNormal, float wrinkleBlend, float3 samplePos)
- {
- if (!AffectByWind(wrinkleBlend))
- {
- return;
- }
-
- const float2 sampleXz = samplePos.xz;
- const float2 sampleYz = samplePos.yz;
-
- const float3 smoothNormalXy = normalize(float3(smoothNormal.xy, 0));
-
- const float xzDot = dot(smoothNormalXy, yDir);
- const float yzDot = dot(smoothNormalXy, xDir);
-
- const float xzRatio = abs(xzDot);
- const float yzRatio = abs(yzDot);
-
- const float xzRev = (xzDot > 0) ? 1 : -1;
- const float yzRev = (yzDot > 0) ? 1 : -1;
-
- const float3 wrinkleNormalXzTS = SampleNormal(ClothWrinkleNormalSampler, sampleXz);
- const float3 wrinkleNormalYzTS = SampleNormal(ClothWrinkleNormalSampler, sampleYz);
-
- const float3x3 xzTBN = float3x3(xDir, -zDir, yDir * xzRev); // normal along y axis
- const float3 wrinkleNormalXzMS = mul(wrinkleNormalXzTS, xzTBN);
-
- const float3x3 yzTBN = float3x3(yDir, -zDir, xDir * yzRev); // normal along x axis
- const float3 wrinkleNormalYzMS = mul(wrinkleNormalYzTS, yzTBN);
-
- float3 wrinkleNormalMS = normalize(wrinkleNormalXzMS * xzRatio + wrinkleNormalYzMS * yzRatio);
- wrinkleNormalMS = normalize(lerp(smoothNormalXy, wrinkleNormalMS, wrinkleBlend));
-
- const float4 rot = GetRotateQuat(
- mul(smoothNormalXy, (float3x3)worldMatrix),
- mul(wrinkleNormalMS, (float3x3)worldMatrix));
-
- normal = Rotate(rot, normal);
- binormal = Rotate(rot, binormal);
- tangent = Rotate(rot, tangent);
- }
-
- #if LIGHTING || ELECTRONIZE
- void ClothWindVs(inout float3 pos, out float4 smoothNormal, out float4 wrinkleParam, VsIn param, float2 boneUv)
- {
- float3 smoothNorm;
- float wrinkleBlend;
- GetSmoothNormalAndWrinkleBlend(param, boneUv, smoothNorm, wrinkleBlend);
-
- const float3 wrinkleSamplePos = GetSamplePos(param.pos);
- ClothWindPosition(pos, wrinkleBlend, smoothNorm, wrinkleSamplePos);
-
- smoothNormal = float4(smoothNorm, 1);
- wrinkleParam = float4(wrinkleSamplePos, wrinkleBlend);
- }
- #endif
-
- #if DEPTH
- void ClothWindVs(inout float3 pos, VsIn param, float2 boneUv)
- {
- float3 smoothNormal;
- float wrinkleBlend;
- GetSmoothNormalAndWrinkleBlend(param, boneUv, smoothNormal, wrinkleBlend);
-
- const float3 wrinkleSamplePos = GetSamplePos(param.pos);
- ClothWindPosition(pos, wrinkleBlend, smoothNormal, wrinkleSamplePos);
- }
- #endif
-
- #if LIGHTING
- void ClothWindPs(inout VsOut param)
- {
- // cloth wind lighting ps
- const float3 wrinkleSamplePos = param.wrinkleParam.xyz;
- const float wrinkleBlend = param.wrinkleParam.w;
- const float3 smoothNormal = normalize(param.smoothNormal.xyz);
- ClothWindNormal(param.normal, param.binormal, param.tangent, smoothNormal, wrinkleBlend, wrinkleSamplePos);
- }
- #endif
-
- #endif // CLOTH_WIND
-
- #endif // QSClothWind_h__