您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
485 行
21 KiB
485 行
21 KiB
//-------------------------------------------------------------------------------------
|
|
// Fill SurfaceData/Builtin data function
|
|
//-------------------------------------------------------------------------------------
|
|
#include "../MaterialUtilities.hlsl"
|
|
#include "../SampleLayer.hlsl"
|
|
|
|
void GetBuiltinData(FragInputs input, SurfaceData surfaceData, float alpha, float depthOffset, out BuiltinData builtinData)
|
|
{
|
|
// Builtin Data
|
|
builtinData.opacity = alpha;
|
|
|
|
// TODO: Sample lightmap/lightprobe/volume proxy
|
|
// This should also handle projective lightmap
|
|
// Note that data input above can be use to sample into lightmap (like normal)
|
|
builtinData.bakeDiffuseLighting = SampleBakedGI(input.positionWS, surfaceData.normalWS, input.texCoord1, input.texCoord2);
|
|
|
|
// Emissive Intensity is only use here, but is part of BuiltinData to enforce UI parameters as we want the users to fill one color and one intensity
|
|
builtinData.emissiveIntensity = _EmissiveIntensity; // We still store intensity here so we can reuse it with debug code
|
|
|
|
// If we chose an emissive color, we have a dedicated texture for it and don't use MaskMap
|
|
#ifdef _EMISSIVE_COLOR
|
|
#ifdef _EMISSIVE_COLOR_MAP
|
|
builtinData.emissiveColor = SAMPLE_TEXTURE2D(_EmissiveColorMap, sampler_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor * builtinData.emissiveIntensity;
|
|
#else
|
|
builtinData.emissiveColor = _EmissiveColor * builtinData.emissiveIntensity;
|
|
#endif
|
|
// If we have a MaskMap, use emissive slot as a mask on baseColor
|
|
#elif defined(_MASKMAP) && !defined(LAYERED_LIT_SHADER) // With layered lit we have no emissive mask option
|
|
builtinData.emissiveColor = surfaceData.baseColor * (SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).b * builtinData.emissiveIntensity).xxx;
|
|
#else
|
|
builtinData.emissiveColor = float3(0.0, 0.0, 0.0);
|
|
#endif
|
|
|
|
builtinData.velocity = float2(0.0, 0.0);
|
|
|
|
#ifdef _DISTORTION_ON
|
|
float3 distortion = SAMPLE_TEXTURE2D(_DistortionVectorMap, sampler_DistortionVectorMap, input.texCoord0).rgb;
|
|
builtinData.distortion = distortion.rg;
|
|
builtinData.distortionBlur = distortion.b;
|
|
#else
|
|
builtinData.distortion = float2(0.0, 0.0);
|
|
builtinData.distortionBlur = 0.0;
|
|
#endif
|
|
|
|
builtinData.depthOffset = depthOffset;
|
|
}
|
|
|
|
struct LayerTexCoord
|
|
{
|
|
#ifndef LAYERED_LIT_SHADER
|
|
LayerUV base;
|
|
LayerUV details;
|
|
#else
|
|
// Regular texcoord
|
|
LayerUV base0;
|
|
LayerUV base1;
|
|
LayerUV base2;
|
|
LayerUV base3;
|
|
|
|
LayerUV details0;
|
|
LayerUV details1;
|
|
LayerUV details2;
|
|
LayerUV details3;
|
|
#endif
|
|
|
|
// triplanar weight
|
|
float3 weights;
|
|
};
|
|
|
|
#ifndef LAYERED_LIT_SHADER
|
|
|
|
// include LitDataInternal to define GetSurfaceData
|
|
#define LAYER_INDEX 0
|
|
#define ADD_IDX(Name) Name
|
|
#define ADD_ZERO_IDX(Name) Name
|
|
#include "LitDataInternal.hlsl"
|
|
|
|
void GetLayerTexCoord(float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3,
|
|
float3 positionWS, float3 normalWS, out LayerTexCoord layerTexCoord)
|
|
{
|
|
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
|
|
|
|
#ifdef _MAPPING_TRIPLANAR
|
|
// one weight for each direction XYZ - Use vertex normal for triplanar
|
|
layerTexCoord.weights = ComputeTriplanarWeights(normalWS);
|
|
#endif
|
|
|
|
// Be sure that the compiler is aware that we don't touch UV1 to UV3 for base layer in case of non layer shader
|
|
// so it can remove code
|
|
_UVMappingMask.yzw = float3(0.0, 0.0, 0.0);
|
|
bool isTriplanar = false;
|
|
#ifdef _MAPPING_TRIPLANAR
|
|
isTriplanar = true;
|
|
#endif
|
|
ComputeLayerTexCoord( texCoord0, texCoord1, texCoord2, texCoord3,
|
|
positionWS, normalWS, isTriplanar, layerTexCoord);
|
|
}
|
|
|
|
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
|
|
{
|
|
#if defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT)
|
|
|
|
// ref: https://www.gamedev.net/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
|
|
float3 viewDirTS = TransformWorldToTangent(V, input.tangentToWorld);
|
|
// Change the number of samples per ray depending on the viewing angle for the surface.
|
|
// Oblique angles require smaller step sizes to achieve more accurate precision for computing displacement.
|
|
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
|
|
|
|
ParallaxOcclusionMappingLayer(layerTexCoord, numSteps, viewDirTS);
|
|
|
|
// TODO: We are supposed to modify lightmaps coordinate (fetch in GetBuiltin), but this isn't the same uv mapping, so can't apply the offset here...
|
|
// Let's assume it will be "fine" as indirect diffuse is often low frequency
|
|
#endif
|
|
}
|
|
|
|
// Calculate displacement for per vertex displacement mapping
|
|
float ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
|
|
{
|
|
return SampleHeightmapLod(layerTexCoord, lod);
|
|
}
|
|
|
|
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
|
|
{
|
|
LayerTexCoord layerTexCoord;
|
|
GetLayerTexCoord(input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
|
|
input.positionWS, input.tangentToWorld[2].xyz, layerTexCoord);
|
|
|
|
|
|
ApplyPerPixelDisplacement(input, V, layerTexCoord);
|
|
float depthOffset = 0.0;
|
|
|
|
#ifdef _DEPTHOFFSET_ON
|
|
ApplyDepthOffsetPositionInput(V, depthOffset, posInput);
|
|
#endif
|
|
|
|
// We perform the conversion to world of the normalTS outside of the GetSurfaceData
|
|
// so it allow us to correctly deal with detail normal map and optimize the code for the layered shaders
|
|
float3 normalTS;
|
|
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData, normalTS);
|
|
GetNormalAndTangentWS(input, V, normalTS, surfaceData.normalWS, surfaceData.tangentWS);
|
|
// Done one time for all layered - cumulate with spec occ alpha for now
|
|
surfaceData.specularOcclusion *= GetHorizonOcclusion(V, surfaceData.normalWS, input.tangentToWorld[2].xyz, _HorizonFade);
|
|
|
|
// Caution: surfaceData must be fully initialize before calling GetBuiltinData
|
|
GetBuiltinData(input, surfaceData, alpha, depthOffset, builtinData);
|
|
}
|
|
|
|
#else
|
|
|
|
#define ADD_ZERO_IDX(Name) Name##0
|
|
|
|
// include LitDataInternal multiple time to define the variation of GetSurfaceData for each layer
|
|
#define LAYER_INDEX 0
|
|
#define ADD_IDX(Name) Name##0
|
|
#include "LitDataInternal.hlsl"
|
|
#undef LAYER_INDEX
|
|
#undef ADD_IDX
|
|
|
|
#define LAYER_INDEX 1
|
|
#define ADD_IDX(Name) Name##1
|
|
#include "LitDataInternal.hlsl"
|
|
#undef LAYER_INDEX
|
|
#undef ADD_IDX
|
|
|
|
#define LAYER_INDEX 2
|
|
#define ADD_IDX(Name) Name##2
|
|
#include "LitDataInternal.hlsl"
|
|
#undef LAYER_INDEX
|
|
#undef ADD_IDX
|
|
|
|
#define LAYER_INDEX 3
|
|
#define ADD_IDX(Name) Name##3
|
|
#include "LitDataInternal.hlsl"
|
|
#undef LAYER_INDEX
|
|
#undef ADD_IDX
|
|
|
|
void ComputeMaskWeights(float4 inputMasks, out float outWeights[_MAX_LAYER])
|
|
{
|
|
float masks[_MAX_LAYER];
|
|
#if defined(_DENSITY_MODE)
|
|
masks[0] = inputMasks.a;
|
|
#else
|
|
masks[0] = 1.0;
|
|
#endif
|
|
masks[1] = inputMasks.r;
|
|
masks[2] = inputMasks.g;
|
|
masks[3] = inputMasks.b;
|
|
|
|
// calculate weight of each layers
|
|
// Algorithm is like this:
|
|
// Top layer have priority on others layers
|
|
// If a top layer doesn't use the full weight, the remaining can be use by the following layer.
|
|
float weightsSum = 0.0;
|
|
|
|
[unroll]
|
|
for (int i = _LAYER_COUNT - 1; i >= 0; --i)
|
|
{
|
|
outWeights[i] = min(masks[i], (1.0 - weightsSum));
|
|
weightsSum = saturate(weightsSum + masks[i]);
|
|
}
|
|
}
|
|
|
|
float3 BlendLayeredVector3(float3 x0, float3 x1, float3 x2, float3 x3, float weight[4])
|
|
{
|
|
float3 result = float3(0.0, 0.0, 0.0);
|
|
|
|
result = x0 * weight[0] + x1 * weight[1];
|
|
#if _LAYER_COUNT >= 3
|
|
result += (x2 * weight[2]);
|
|
#endif
|
|
#if _LAYER_COUNT >= 4
|
|
result += x3 * weight[3];
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
float BlendLayeredScalar(float x0, float x1, float x2, float x3, float weight[4])
|
|
{
|
|
float result = 0.0;
|
|
|
|
result = x0 * weight[0] + x1 * weight[1];
|
|
#if _LAYER_COUNT >= 3
|
|
result += x2 * weight[2];
|
|
#endif
|
|
#if _LAYER_COUNT >= 4
|
|
result += x3 * weight[3];
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
#define SURFACEDATA_BLEND_VECTOR3(surfaceData, name, mask) BlendLayeredVector3(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
|
|
#define SURFACEDATA_BLEND_SCALAR(surfaceData, name, mask) BlendLayeredScalar(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
|
|
#define PROP_BLEND_SCALAR(name, mask) BlendLayeredScalar(name##0, name##1, name##2, name##3, mask);
|
|
|
|
void GetLayerTexCoord(float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3,
|
|
float3 positionWS, float3 normalWS, out LayerTexCoord layerTexCoord)
|
|
{
|
|
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
|
|
|
|
#if defined(_LAYER_MAPPING_TRIPLANAR_0) || defined(_LAYER_MAPPING_TRIPLANAR_1) || defined(_LAYER_MAPPING_TRIPLANAR_2) || defined(_LAYER_MAPPING_TRIPLANAR_3)
|
|
// one weight for each direction XYZ - Use vertex normal for triplanar
|
|
layerTexCoord.weights = ComputeTriplanarWeights(normalWS);
|
|
#endif
|
|
|
|
bool isTriplanar = false;
|
|
#ifdef _LAYER_MAPPING_TRIPLANAR_0
|
|
isTriplanar = true;
|
|
#endif
|
|
ComputeLayerTexCoord0( texCoord0, texCoord1, texCoord2, texCoord3,
|
|
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling0);
|
|
|
|
isTriplanar = false;
|
|
#ifdef _LAYER_MAPPING_TRIPLANAR_1
|
|
isTriplanar = true;
|
|
#endif
|
|
ComputeLayerTexCoord1( texCoord0, texCoord1, texCoord2, texCoord3,
|
|
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling1);
|
|
|
|
isTriplanar = false;
|
|
#ifdef _LAYER_MAPPING_TRIPLANAR_2
|
|
isTriplanar = true;
|
|
#endif
|
|
ComputeLayerTexCoord2( texCoord0, texCoord1, texCoord2, texCoord3,
|
|
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling2);
|
|
|
|
isTriplanar = false;
|
|
#ifdef _LAYER_MAPPING_TRIPLANAR_3
|
|
isTriplanar = true;
|
|
#endif
|
|
ComputeLayerTexCoord3( texCoord0, texCoord1, texCoord2, texCoord3,
|
|
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling3);
|
|
}
|
|
|
|
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
|
|
{
|
|
#if defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT)
|
|
float3 viewDirTS = TransformWorldToTangent(V, input.tangentToWorld);
|
|
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
|
|
|
|
ParallaxOcclusionMappingLayer0(layerTexCoord, numSteps, viewDirTS);
|
|
ParallaxOcclusionMappingLayer1(layerTexCoord, numSteps, viewDirTS);
|
|
ParallaxOcclusionMappingLayer2(layerTexCoord, numSteps, viewDirTS);
|
|
ParallaxOcclusionMappingLayer3(layerTexCoord, numSteps, viewDirTS);
|
|
#endif
|
|
}
|
|
|
|
float3 ComputeMainNormalInfluence(FragInputs input, float3 normalTS0, float3 normalTS1, float3 normalTS2, float3 normalTS3, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])
|
|
{
|
|
// Get our regular normal from regular layering
|
|
float3 normalTS = BlendLayeredVector3(normalTS0, normalTS1, normalTS2, normalTS3, weights);
|
|
|
|
// THen get Main Layer Normal influence factor. Main layer is 0 because it can't be influence. In this case the final lerp return normalTS.
|
|
float influenceFactor = BlendLayeredScalar(0.0, _InheritBaseNormal1, _InheritBaseNormal2, _InheritBaseNormal3, weights);
|
|
// We will add smoothly the contribution of the normal map by using lower mips with help of bias sampling. InfluenceFactor must be [0..numMips] // Caution it cause banding...
|
|
// Note: that we don't take details map into account here.
|
|
float maxMipBias = log2(max(_NormalMap0_TexelSize.z, _NormalMap0_TexelSize.w)); // don't do + 1 as it is for bias, not lod
|
|
float3 mainNormalTS = GetNormalTS0(input, layerTexCoord, float3(0.0, 0.0, 1.0), 0.0, true, maxMipBias * (1.0 - influenceFactor));
|
|
|
|
// Add on our regular normal a bit of Main Layer normal base on influence factor. Note that this affect only the "visible" normal.
|
|
return lerp(normalTS, BlendNormalRNM(normalTS, mainNormalTS), influenceFactor);
|
|
}
|
|
|
|
float3 ComputeMainBaseColorInfluence(float3 baseColor0, float3 baseColor1, float3 baseColor2, float3 baseColor3, float compoMask, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])
|
|
{
|
|
float3 baseColor = BlendLayeredVector3(baseColor0, baseColor1, baseColor2, baseColor3, weights);
|
|
|
|
float influenceFactor = BlendLayeredScalar(0.0, _InheritBaseColor1, _InheritBaseColor2, _InheritBaseColor3, weights);
|
|
float influenceThreshold = BlendLayeredScalar(1.0, _InheritBaseColorThreshold1, _InheritBaseColorThreshold2, _InheritBaseColorThreshold3, weights);
|
|
|
|
influenceFactor = influenceFactor * (1.0 - saturate(compoMask / influenceThreshold));
|
|
|
|
// We want to calculate the mean color of the texture. For this we will sample a low mipmap
|
|
float textureBias = 15.0; // Use maximum bias
|
|
float3 baseMeanColor0 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap0, sampler_BaseColorMap0, layerTexCoord.base0, textureBias).rgb *_BaseColor0.rgb;
|
|
float3 baseMeanColor1 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap1, sampler_BaseColorMap0, layerTexCoord.base1, textureBias).rgb *_BaseColor1.rgb;
|
|
float3 baseMeanColor2 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap2, sampler_BaseColorMap0, layerTexCoord.base2, textureBias).rgb *_BaseColor2.rgb;
|
|
float3 baseMeanColor3 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap3, sampler_BaseColorMap0, layerTexCoord.base3, textureBias).rgb *_BaseColor3.rgb;
|
|
|
|
float3 meanColor = BlendLayeredVector3(baseMeanColor0, baseMeanColor1, baseMeanColor2, baseMeanColor3, weights);
|
|
|
|
// If we inherit from base layer, we will add a bit of it
|
|
// We add variance of current visible level and the base color 0 or mean (to retrieve initial color) depends on influence
|
|
// (baseColor - meanColor) + lerp(meanColor, baseColor0, inheritBaseColor) simplify to
|
|
return saturate(influenceFactor * (baseColor0 - meanColor) + baseColor);
|
|
}
|
|
|
|
// Caution: Blend mask are Layer 1 R - Layer 2 G - Layer 3 B - Main Layer A
|
|
float4 GetBlendMask(LayerTexCoord layerTexCoord, float4 vertexColor, bool useLodSampling = false, float lod = 0)
|
|
{
|
|
// Caution:
|
|
// Blend mask are Main Layer A - Layer 1 R - Layer 2 G - Layer 3 B
|
|
// Value for Mani layer is not use for blending itself but for alternate weighting like density.
|
|
// Settings this specific Main layer blend mask in alpha allow to be transparent in case we don't use it and 1 is provide by default.
|
|
float4 blendMasks = useLodSampling ? SAMPLE_LAYER_TEXTURE2D_LOD(_LayerMaskMap, sampler_LayerMaskMap, layerTexCoord.base0, lod) : SAMPLE_LAYER_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, layerTexCoord.base0);
|
|
|
|
#if defined(_LAYER_MASK_VERTEX_COLOR_MUL)
|
|
blendMasks *= vertexColor;
|
|
#elif defined(_LAYER_MASK_VERTEX_COLOR_ADD)
|
|
blendMasks = saturate(blendMasks + vertexColor * 2.0 - 1.0);
|
|
#endif
|
|
|
|
return blendMasks;
|
|
}
|
|
|
|
// Calculate displacement for per vertex displacement mapping
|
|
float ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
|
|
{
|
|
float4 blendMasks = GetBlendMask(layerTexCoord, vertexColor, true, lod);
|
|
|
|
float weights[_MAX_LAYER];
|
|
ComputeMaskWeights(blendMasks, weights);
|
|
|
|
float height0 = SampleHeightmapLod0(layerTexCoord, lod, _HeightCenterOffset0, _HeightFactor0);
|
|
float height1 = SampleHeightmapLod1(layerTexCoord, lod, _HeightCenterOffset1, _HeightFactor1);
|
|
float height2 = SampleHeightmapLod2(layerTexCoord, lod, _HeightCenterOffset2, _HeightFactor2);
|
|
float height3 = SampleHeightmapLod3(layerTexCoord, lod, _HeightCenterOffset3, _HeightFactor3);
|
|
float heightResult = BlendLayeredScalar(height0, height1, height2, height3, weights);
|
|
|
|
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
|
|
// Think that inheritbasedheight will be 0 if height0 is fully visible in weights. So there is no double contribution of height0
|
|
float inheritBaseHeight = BlendLayeredScalar(0.0, _InheritBaseHeight1, _InheritBaseHeight2, _InheritBaseHeight3, weights);
|
|
return heightResult + height0 * inheritBaseHeight;
|
|
#endif
|
|
|
|
return heightResult;
|
|
}
|
|
|
|
float3 ApplyHeightBasedBlend(float3 inputMask, float3 inputHeight, float3 blendUsingHeight)
|
|
{
|
|
return saturate(lerp(inputMask * inputHeight * blendUsingHeight * 100, 1, inputMask * inputMask)); // 100 arbitrary scale to limit blendUsingHeight values.
|
|
}
|
|
|
|
// Calculate weights to apply to each layer
|
|
// Caution: This function must not be use for per vertex of per pixel displacement, there is a dedicated function for them.
|
|
// this function handle triplanar
|
|
void ComputeLayerWeights(FragInputs input, LayerTexCoord layerTexCoord, float4 inputAlphaMask, out float outWeights[_MAX_LAYER])
|
|
{
|
|
float4 blendMasks = GetBlendMask(layerTexCoord, input.color);
|
|
|
|
#if defined(_DENSITY_MODE)
|
|
// Note: blendMasks.argb because a is main layer
|
|
float4 minOpaParam = float4(_MinimumOpacity0, _MinimumOpacity1, _MinimumOpacity2, _MinimumOpacity3);
|
|
float4 remapedOpacity = lerp(minOpaParam, float4(1.0, 1.0, 1.0, 1.0), inputAlphaMask); // Remap opacity mask from [0..1] to [minOpa..1]
|
|
float4 opacityAsDensity = saturate((inputAlphaMask - (float4(1.0, 1.0, 1.0, 1.0) - blendMasks.argb)) * 20.0);
|
|
|
|
float4 useOpacityAsDensityParam = float4(_OpacityAsDensity0, _OpacityAsDensity1, _OpacityAsDensity2, _OpacityAsDensity3);
|
|
blendMasks.argb = lerp(blendMasks.argb * remapedOpacity, opacityAsDensity, useOpacityAsDensityParam);
|
|
#endif
|
|
|
|
#if defined(_HEIGHT_BASED_BLEND)
|
|
float height0 = SampleHeightmap0(layerTexCoord, _HeightCenterOffset0, _HeightFactor0);
|
|
float height1 = SampleHeightmap1(layerTexCoord, _HeightCenterOffset1, _HeightFactor1);
|
|
float height2 = SampleHeightmap2(layerTexCoord, _HeightCenterOffset2, _HeightFactor2);
|
|
float height3 = SampleHeightmap3(layerTexCoord, _HeightCenterOffset3, _HeightFactor3);
|
|
float4 heights = float4(height0, height1, height2, height3);
|
|
|
|
// HACK, use height0 to avoid compiler error for unused sampler
|
|
// To remove once we have POM
|
|
heights.y += (heights.x * 0.0001);
|
|
|
|
// don't apply on main layer
|
|
blendMasks.rgb = ApplyHeightBasedBlend(blendMasks.rgb, heights.yzw, float3(_BlendUsingHeight1, _BlendUsingHeight2, _BlendUsingHeight3));
|
|
#endif
|
|
|
|
ComputeMaskWeights(blendMasks, outWeights);
|
|
}
|
|
|
|
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
|
|
{
|
|
LayerTexCoord layerTexCoord;
|
|
GetLayerTexCoord(input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
|
|
input.positionWS, input.tangentToWorld[2].xyz, layerTexCoord);
|
|
|
|
ApplyPerPixelDisplacement(input, V, layerTexCoord);
|
|
|
|
float depthOffset = 0.0;
|
|
#ifdef _DEPTHOFFSET_ON
|
|
ApplyDepthOffsetPositionInput(V, depthOffset, posInput);
|
|
#endif
|
|
|
|
SurfaceData surfaceData0, surfaceData1, surfaceData2, surfaceData3;
|
|
float3 normalTS0, normalTS1, normalTS2, normalTS3;
|
|
float alpha0 = GetSurfaceData0(input, layerTexCoord, surfaceData0, normalTS0);
|
|
float alpha1 = GetSurfaceData1(input, layerTexCoord, surfaceData1, normalTS1);
|
|
float alpha2 = GetSurfaceData2(input, layerTexCoord, surfaceData2, normalTS2);
|
|
float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3, normalTS3);
|
|
|
|
// For layering we kill pixel based on maximun alpha
|
|
#ifdef _ALPHATEST_ON
|
|
#if _LAYER_COUNT == 2
|
|
clip(max(alpha0, alpha1) - _AlphaCutoff);
|
|
#endif
|
|
#if _LAYER_COUNT == 3
|
|
clip(max3(alpha0, alpha1, alpha2) - _AlphaCutoff);
|
|
#endif
|
|
#if _LAYER_COUNT == 4
|
|
clip(max(alpha3, max3(alpha0, alpha1, alpha2)) - _AlphaCutoff);
|
|
#endif
|
|
#endif
|
|
|
|
float weights[_MAX_LAYER];
|
|
ComputeLayerWeights(input, layerTexCoord, float4(alpha0, alpha1, alpha2, alpha3), weights);
|
|
|
|
// For layered shader, alpha of base color is used as either an opacity mask, a composition mask for inheritance parameters or a density mask.
|
|
float alpha = PROP_BLEND_SCALAR(alpha, weights);
|
|
|
|
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
|
|
surfaceData.baseColor = ComputeMainBaseColorInfluence(surfaceData0.baseColor, surfaceData1.baseColor, surfaceData2.baseColor, surfaceData3.baseColor, alpha, layerTexCoord, weights);
|
|
float3 normalTS = ComputeMainNormalInfluence(input, normalTS0, normalTS1, normalTS2, normalTS3, layerTexCoord, weights);
|
|
#else
|
|
surfaceData.baseColor = SURFACEDATA_BLEND_VECTOR3(surfaceData, baseColor, weights);
|
|
float3 normalTS = BlendLayeredVector3(normalTS0, normalTS1, normalTS2, normalTS3, weights);
|
|
#endif
|
|
|
|
surfaceData.perceptualSmoothness = SURFACEDATA_BLEND_SCALAR(surfaceData, perceptualSmoothness, weights);
|
|
surfaceData.ambientOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, ambientOcclusion, weights);
|
|
surfaceData.metallic = SURFACEDATA_BLEND_SCALAR(surfaceData, metallic, weights);
|
|
|
|
// Init other unused parameter
|
|
surfaceData.tangentWS = normalize(input.tangentToWorld[0].xyz);
|
|
surfaceData.materialId = 0;
|
|
surfaceData.anisotropy = 0;
|
|
surfaceData.specular = 0.04;
|
|
surfaceData.subsurfaceRadius = 1.0;
|
|
surfaceData.thickness = 0.0;
|
|
surfaceData.subsurfaceProfile = 0;
|
|
surfaceData.coatNormalWS = float3(1.0, 0.0, 0.0);
|
|
surfaceData.coatPerceptualSmoothness = 1.0;
|
|
surfaceData.specularColor = float3(0.0, 0.0, 0.0);
|
|
|
|
GetNormalAndTangentWS(input, V, normalTS, surfaceData.normalWS, surfaceData.tangentWS);
|
|
// Done one time for all layered - cumulate with spec occ alpha for now
|
|
surfaceData.specularOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, specularOcclusion, weights);
|
|
surfaceData.specularOcclusion *= GetHorizonOcclusion(V, surfaceData.normalWS, input.tangentToWorld[2].xyz, _HorizonFade);
|
|
|
|
GetBuiltinData(input, surfaceData, alpha, depthOffset, builtinData);
|
|
}
|
|
|
|
#endif // #ifndef LAYERED_LIT_SHADER
|
|
|
|
#ifdef TESSELLATION_ON
|
|
#include "LitTessellation.hlsl" // Must be after GetLayerTexCoord() declaration
|
|
#endif
|