home *** CD-ROM | disk | FTP | other *** search
- #ifndef QSSHADER_QSSkin_H
- #define QSSHADER_QSSkin_H
- /*
- * shader definition for skin
- */
- #include "DX12Defines.fxh"
- #include "QSConstant.fxh"
- #include "FunctionLib.fxh"
- #include "QSLighting.fxh"
- #include "QSShadow.fxh"
- #include "QSSkinning.fxh"
- #include "QSVertexCalc.fxh"
- #include "QSScreenSpaceDepth.fxh"
- #include "QSPhysicalLighting.fxh"
- #include "QSShaderAtmosphere.fxh"
- #include "PostFx.fxh"
- #include "DepthUtil.fxh"
- #include "QSMaterialDetail.fxh"
- #include "QSMaterialCommon.fxh"
- #include "QSShaderIndirectLighting.fxh"
- #include "QSMaterialScreenDoor.fxh"
-
- float SkinGlossFactor; // Not gloss now, for adjusting the saturation of spec. map.
-
- float4 SpecularColor; //xyz -- spec, w -- gloss
- float3 SkinColor;
-
- //textures
- sampler2D NormalSampler;
- sampler2D SpecularMap;
-
- sampler2D DiffuseMaskMap0;
- sampler2D DiffuseMaskMap1;
- sampler2D DiffuseMaskMap2;
-
-
- float4 DiffuseMaskUvScaleBias0; //xy bias, zw scale
- float4 DiffuseMaskUvScaleBias1;
- float4 DiffuseMaskUvScaleBias2;
-
- float3 DiffuseMaskColor0;
- float3 DiffuseMaskColor1;
- float3 DiffuseMaskColor2;
- #if NORMAL_DETAIL
- sampler2D NormalDetailMap;
- float DetailMapIntensity;
- #endif
- #if NORMAL_WRINKLE
- sampler2D NormalWrinkleMap;
- float WrinkleMapIntensity;
- #endif
- #if NORMAL_EXPRESSION
- sampler2D NormalExpressionMap;
- sampler2D NormalExpressionMapSrc;
- float4 NormalExpressionMapIntensity;//x for expression intensity , y for blend weight of two expressions
- //z for src normal intensity , w for current normal intentsity
- float4 NormalExpressionSizeBias;//xy for offset , z for scale , w for slotIndex
- float4 NormalExpressionSizeBiasSrc;
- float NormalExpressionIntensityScale;
- static const float4 cNormalExpressionOffsetBias[5] =
- {
- {1.0f,1.0f,0.0f,0.0f},
- {0.5f,0.5f,0.0f,0.0f},
- {0.5f,0.5f,0.5f,0.0f},
- {0.5f,0.5f,0.0f,0.5f},
- {0.5f,0.5f,0.5f,0.5f}
- };
- #endif
- //float4 NormalMaskUvScaleBias;
-
- float4 BaseDiffuseColor;
- #include "PostFxColor.fxh"
-
- float3 CustomSatAndLum(float3 color, float3 colorAdjuster )
- {
- float3 result;
-
- result = RgbToHsl(color);
- result.g *= colorAdjuster.r;
- result.b *= colorAdjuster.g;
- return HslToRgb(result);
-
- }
-
- float3 CustomColor(float3 color, float3 colorAdjuster )
- {
- float3 result;
-
- result = RgbToHsl(color);
-
- if( colorAdjuster.r != 0.0f )
- {
- result.r = colorAdjuster.r;
- }
- result.g *= colorAdjuster.g;
- result.b *= colorAdjuster.b;
- return HslToRgb(result);
-
- }
-
- float3 CustomSaturation( float3 rgb, float satFactor )
- {
- float3 hsl;
- hsl = RgbToHsl(rgb);
- hsl.b *= satFactor;
- return HslToRgb(hsl);
- }
-
- //-------------------------------------------------------------------------
- //lighting ps and vs
- //-------------------------------------------------------------------------
- #if LIGHTING
- VsOut SkinLightingVS(VsIn param)
- {
- VsOut result;
-
- //variable
- float3 pos, normal, tangent, binormal;
-
- //collect variable data
- #if VERTEX_COMPRESSION
- //pos
- pos = param.pos.xyz * param.pos.w;
-
- #if QTANGENTS
- float4 qtangents = DecompressCharToFloat(param.qtangents);
- DecodeQTangents(qtangents, normal, tangent, binormal);
- #else
- //normal
- #if HAS_NORMAL
- normal = DecompressCharToFloat(param.normal);
- #else
- normal = 0.0f;
- #endif
-
- #if NORMALMAP
- float4 tempTangent = DecompressCharToFloat( param.tangent );
- tangent = tempTangent.xyz;
- binormal = DecompressCharToFloat( param.binormal );
- #if !HAS_NORMAL
- normal =cross(tangent.xyz, binormal.xyz);
- normal = normalize( normal );
- if( tempTangent.w == -1.0f )
- {
- normal *= -1.0f;
- }
- #endif
- #endif
- #endif // QTANGENTS
- #else
- pos = param.pos.xyz;
- normal = param.normal.xyz;
- #if NORMALMAP
- tangent = param.tangent.xyz;
- binormal = param.binormal.xyz;
- #endif//NORMALMAP
- #endif
-
- result.pos = 0;
-
- #if WRITE_VELOCITY
- result.curPos = 0;
- result.prePos = 0;
- #if SKINNING
- VertexTransformCalc(pos, param.blendWeight, param.blendIndices, result.pos, result.curPos, result.prePos, normal, tangent, binormal);
- #else
- VertexTransformCalc(pos, result.pos, result.curPos, result.prePos, normal, tangent, binormal);
- #endif
-
- #else //WRITE_VELOCITY
- #if SKINNING
- VertexTransformCalc(pos, param.blendWeight, param.blendIndices, result.pos, normal, tangent, binormal);
- #else
- VertexTransformCalc(pos, result.pos, normal, tangent, binormal);
- #endif
-
- #endif //WRITE_VELOCITY
-
- result.normal = normal;
-
- #if NORMALMAP
- result.binormal = binormal;
- result.tangent = tangent;
- #endif
-
- //other property setup-------------------------------------------------
- #if SECOND_UV
- result.uv0 = float4(param.uv0, param.uv1);
- #else
- result.uv0 = param.uv0;
- #endif
-
- #if FORWARD_LIGHTING
- result.projPos = result.pos;
- #endif
-
- return result;
- }
- #define alphaThreshold 0.05f
- #define LipsAlphaThreshold 0.4f
- #include "QSDeferredLighting.fxh"
- PsOut SkinLightingPS(VsOut param, float4 vPos:VPOS)
- {
- PsOut result;
-
- float2 uv, offsetUV, tattooUV;
- float2 detailUv;
- float tattooMask;
- #if SECOND_UV
- detailUv = param.uv0.zw;
- #else
- detailUv = param.uv0.xy;
- #endif
-
- uv = param.uv0.xy;
- ScreenDoor(uv);
-
- float4 diffuseColor = tex2D(BaseSampler, MipMapLinear, uv);
-
- #if EYEBROW
- offsetUV = GetOffsetUV(uv, EyebrowSizeBias);
- if( false == IsUVOutOfRange( offsetUV ) )
- {
- float4 eyebrowColor = tex2D(EyeBrowMap, MipMapLinear, offsetUV);
- diffuseColor.rgb = lerp(diffuseColor.rgb, eyebrowColor.rgb, eyebrowColor.a);
- }
- #endif
-
- #if BEARD
- offsetUV = GetOffsetUV(uv, BeardSizeBias);
- if( false == IsUVOutOfRange( offsetUV ) )
- {
- float4 beardColor = tex2D(BeardMap, MipMapLinear, offsetUV);
-
- if( beardColor.a > 0.0f )
- {
- diffuseColor.rgb = lerp(diffuseColor.rgb, beardColor.rgb, beardColor.a);
- }
- }
- #endif
-
- #if TATTOO
- tattooUV = GetOffsetUV(uv, TattooSizeBias);
- if( false == IsUVOutOfRange( tattooUV ) )
- {
- float4 tattooColor = tex2D(TattooMap, MipMapLinear, tattooUV);
-
- if( tattooColor.a > 0.0f )
- {
- diffuseColor.rgb = lerp(diffuseColor.rgb, diffuseColor.rgb*tattooColor.rgb*2, tattooColor.a);
- tattooMask = tattooColor.a;
- }
- }
- #endif
-
- #if EYESHADOW
- offsetUV = GetOffsetUV(uv, EyeShadowSizeBias);
- if( false == IsUVOutOfRange( offsetUV ) )
- {
- float4 eyeShadowColor = tex2D(EyeShadowMap, MipMapLinear, offsetUV);
- if( eyeShadowColor.a > 0.0f )
- {
- eyeShadowColor.rgb = CustomSatAndLum(eyeShadowColor.rgb, EyeShadowColor);
- diffuseColor.rgb = lerp(diffuseColor.rgb, diffuseColor.rgb*eyeShadowColor.rgb*2, eyeShadowColor.a);
- }
- }
- #endif
-
- #if EYELINER
- offsetUV = GetOffsetUV(uv, EyelinerSizeBias );
- if( false == IsUVOutOfRange( offsetUV ) )
- {
- float4 eyelinerColor = tex2D(EyelinerMap, MipMapLinear, offsetUV);
- if( eyelinerColor.a > 0.0f )
- {
- diffuseColor.rgb = lerp(diffuseColor.rgb, diffuseColor.rgb*eyelinerColor.rgb*2, eyelinerColor.a);
- }
- }
- #endif
-
-
- diffuseColor.rgb = CustomColor(diffuseColor.rgb, SkinColor);
-
- //alpha test
- #if ALPHATEST
- AlphaTest(diffuseColor.a);
- #endif
-
- float3 specColor = tex2D(SpecularMap, MipMapLinear, uv).xyz;
-
- specColor = CustomSaturation(specColor, SkinGlossFactor);
-
- float gloss;
-
- #if NORMALMAP
- float3 normalTexSpace;
- ReadNormalGloss(NormalSampler, uv, normalTexSpace, gloss);
- ComposeDetail(detailUv, normalTexSpace, diffuseColor.xyz, specColor, gloss);
-
- #if NORMAL_DETAIL
- float detailGloss;
- float3 normalDetail = 0;
- ReadNormalGloss(NormalDetailMap, uv, normalDetail, detailGloss);
- //normalDetail = normalDetail*2.0f-1.0f;
- normalTexSpace.xy += normalDetail.xy*DetailMapIntensity;
-
- //normalTexSpace.xy = float2(1.0,0.0);
- #endif
-
- #if NORMAL_WRINKLE
- float wrinkleGloss;
- float3 normalWrink = 0;
- ReadNormalGloss(NormalWrinkleMap , uv , normalWrink , wrinkleGloss);
- normalTexSpace.xy += normalWrink.xy *WrinkleMapIntensity;
- #endif
-
- #if NORMAL_EXPRESSION
- float expressionGloss;
- float3 normalExpression = 0;
- float3 normalExpressionSrc = 0;
- float2 normalExpressionUVOffset = uv * NormalExpressionSizeBias.z + NormalExpressionSizeBias.xy;
- float4 normalExpressionPackUVParam = cNormalExpressionOffsetBias[NormalExpressionSizeBias.w];
- float2 normalExpressionUVOffsetSrc = uv * NormalExpressionSizeBiasSrc.z + NormalExpressionSizeBiasSrc.xy;
- float4 normalExpressionPackUVParamSrc = cNormalExpressionOffsetBias[NormalExpressionSizeBiasSrc.w];
-
- float uvOutRangeWeight = getUVInRangeWeight(normalExpressionUVOffset);
- ReadNormalGloss(NormalExpressionMap,normalExpressionUVOffset * normalExpressionPackUVParam.xy + normalExpressionPackUVParam.zw,normalExpression,expressionGloss);
- normalExpression *= uvOutRangeWeight;
-
- uvOutRangeWeight = getUVInRangeWeight(normalExpressionUVOffsetSrc);
- ReadNormalGloss(NormalExpressionMapSrc,normalExpressionUVOffsetSrc * normalExpressionPackUVParamSrc.xy + normalExpressionPackUVParamSrc.zw,normalExpressionSrc,expressionGloss);
- normalExpressionSrc *= uvOutRangeWeight;
-
- normalExpression = lerp(normalExpressionSrc * NormalExpressionMapIntensity.z,normalExpression * NormalExpressionMapIntensity.w ,NormalExpressionMapIntensity.y);
- normalTexSpace.xy += normalExpression.xy * NormalExpressionMapIntensity.x * NormalExpressionIntensityScale;
-
-
- #endif
-
- normalTexSpace = normalize(normalTexSpace);
-
- #if LIPS
- offsetUV = GetOffsetUV(uv, LipsSizeBias);
- if( false == IsUVOutOfRange( offsetUV ) )
- {
- float lipMask = tex2D(LipsMap, MipMapLinear, offsetUV).a;
- if( lipMask > LipsAlphaThreshold )
- {
- gloss *= LipGlossFactor;
- }
-
- }
- #endif
-
- #if TATTOO && TATTOO_NORM
- if( false == IsUVOutOfRange( tattooUV ) )
- {
- if(tattooMask > alphaThreshold )
- {
- ReadNormalGloss(TattooNormalMap, tattooUV, normalTexSpace, gloss);
- }
- }
- #endif
-
- float3 normalWorldSpace = mul(normalTexSpace, float3x3(param.tangent, param.binormal, param.normal));
-
- normalWorldSpace = normalize(normalWorldSpace);
- #else//NORMALMAP
- float3 normalWorldSpace = normalize(param.normal);
- gloss = SpecularColor.w;
-
- ComposeDetail(detailUv, diffuseColor.xyz, specColor, gloss);
- #endif//NORMALMAP
-
- //pack gbuffer
- #if FORWARD_LIGHTING
- //direct lighting
- float2 screenUv = (vPos.xy+0.5f)*BufferResolution.zw;
-
- float3 finalLighting,diffuseLighting, specLighting, adjustDiffuse;
- float4 projPos = param.projPos /param.projPos.w;
- float3 toCamera = GetPartialWorldPosFromScreenPos(projPos);
- float3 viewDir = normalize(toCamera);
- diffuseColor.rgb = pow(diffuseColor.rgb,2.2);
- specColor.rgb = pow(specColor.rgb,2.2);
-
-
- float xBias;
- float2 smUv;
- float4 shadow = CascadedShadowMap(float4(screenUv.xy,projPos.z,1), xBias, smUv);
-
- float ndl, ndh;
- QSDirectLighting(
- //output
- finalLighting, diffuseLighting, specLighting, adjustDiffuse, ndl, ndh,
- //light property
- SunLightDir, SunColor.xyz,
- //material property
- normalWorldSpace, viewDir.xyz, diffuseColor.xyz, gloss, specColor.xyz, SunColor.w, shadow);
-
- #if ENHANCE_INDIRECT_LIGHTING
- float3 sndLightResult, sndDiffuseLighting, sndSpecLighting, sndAdjustDiffuse;
- float sndNdl, sndNdh;
- QSDirectLighting(
- //output
- sndLightResult, sndDiffuseLighting, sndSpecLighting, sndAdjustDiffuse, sndNdl, sndNdh,
- //light property
- SecondDirLightDir.xyz, SecondDirLightColor.xyz,
- //material property
- normalWorldSpace, viewDir.xyz, diffuseColor, gloss, specColor*SecondDirLightDir.w, 1.0f, 1.0f);
-
- finalLighting += sndLightResult;
- #endif
-
- float3 envDiffuse;
-
- QSAmbientLighting(
- envDiffuse,
- SkyLightColor.xyz, GroundLightColor.xyz,
- normalWorldSpace, adjustDiffuse, SpecularIndirectLightingEnhance);
-
- finalLighting += envDiffuse;
-
- #if ENHANCE_INDIRECT_LIGHTING
- {
- float envGloss = gloss*gloss*2.0f;
- float3 envMapColor = SampleEnvMapLightColor(viewDir.xyz, normalWorldSpace, envGloss);
- float3 envMapPhyLighting = PhyLightingImageBasedSpecular(normalWorldSpace, viewDir, envGloss, specColor, EnvMapProbePos.w, envMapColor);
-
- finalLighting += envMapPhyLighting;
- }
- #endif
-
- result.color0 = float4(finalLighting.xyz,TransFactor);
-
- #if FOG
- ApplyFogWithZFade(result.color0, toCamera, screenUv);
- #endif
-
- #else //FORWARD_LIGHTING
-
- PackGBufferNormalFit(result.color0, result.color1, result.color2, diffuseColor, normalWorldSpace, specColor, gloss);
-
- #if WRITE_VELOCITY
- // SKin should always be movable, so, no static case.
- float2 velocity = ((param.curPos.xy/param.curPos.w) - (param.prePos.xy/param.prePos.w));
- result.velocity = float4(EncodeVelocityToTexture(velocity), 0, 1); // w=1 means need full Subsurface scattering effect.
- #endif
-
- #endif //FORWARD_LIGHTING
- return result;
- }
- #endif//LIGHTING
-
- //-------------------------------------------------------------------------
- //depth(shadow) ps and vs
- //-------------------------------------------------------------------------
- #if DEPTH
- VsOut SkinDepthVS(VsIn param)
- {
- VsOut result;
-
- float3 pos;
- #if VERTEX_COMPRESSION
- pos = param.pos.xyz*param.pos.w;
- #else
- pos = param.pos.xyz;
- #endif
-
- #if SKINNING
- VertexTransformCalc(pos, param.blendWeight, param.blendIndices, result.pos);
- #else
- VertexTransformCalc(pos, result.pos);
- #endif
-
- #if ALPHATEST
- result.uv0 = param.uv0;
- #endif//ALPHATEST
-
- #if DEPTH_COLOR
- result.homoDepth = float2(result.pos.z,result.pos.w);
- #endif
-
- return result;
- }
-
- PsOut SkinDepthPS(VsOut param)
- {
- PsOut result;
- result.color0 = 0.0f;
-
- #if DEPTH_COLOR
- DepthEncodeToColor(param.homoDepth.x/param.homoDepth.y, result.color0);
- #endif
-
- #if ALPHATEST
- AlphaTest(tex2D(BaseSampler, MipMapLinear, param.uv0).a);
- #endif
-
- return result;
- }
- #endif//DEPTH
-
- #endif // QSSHADER_QSSkin_H
-