您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

593 行
23 KiB

//-------------------------------------------------------------------------------------
// Fill SurfaceData/Builtin data function
//-------------------------------------------------------------------------------------
// In unity we can have a mix of fully baked lightmap (static lightmap) + enlighten realtime lightmap (dynamic lightmap)
// for each case we can have directional lightmap or not.
// Else we have lightprobe for dynamic/moving entity. Either SH9 per object lightprobe or SH4 per pixel per object volume probe
float3 SampleBakedGI(float3 positionWS, float3 normalWS, float2 uvStaticLightmap, float2 uvDynamicLightmap)
{
// If there is no lightmap, it assume lightprobe
#if !defined(LIGHTMAP_ON) && !defined(DYNAMICLIGHTMAP_ON)
// TODO: Confirm with Ionut but it seems that UNITY_LIGHT_PROBE_PROXY_VOLUME is always define for high end and
// unity_ProbeVolumeParams always bind.
if (unity_ProbeVolumeParams.x == 0.0)
{
// TODO: pass a tab of coefficient instead!
float4 SHCoefficients[7];
SHCoefficients[0] = unity_SHAr;
SHCoefficients[1] = unity_SHAg;
SHCoefficients[2] = unity_SHAb;
SHCoefficients[3] = unity_SHBr;
SHCoefficients[4] = unity_SHBg;
SHCoefficients[5] = unity_SHBb;
SHCoefficients[6] = unity_SHC;
return SampleSH9(SHCoefficients, normalWS);
}
else
{
// TODO: Move all this to C++!
float4x4 identity = 0;
identity._m00_m11_m22_m33 = 1.0;
float4x4 WorldToTexture = (unity_ProbeVolumeParams.y == 1.0f) ? unity_ProbeVolumeWorldToObject : identity;
float4x4 translation = identity;
translation._m30_m31_m32 = -unity_ProbeVolumeMin.xyz;
float4x4 scale = 0;
scale._m00_m11_m22_m33 = float4(unity_ProbeVolumeSizeInv.xyz, 1.0);
WorldToTexture = mul(mul(scale, translation), WorldToTexture);
return SampleProbeVolumeSH4(TEXTURE3D_PARAM(unity_ProbeVolumeSH, samplerunity_ProbeVolumeSH), positionWS, normalWS, WorldToTexture, unity_ProbeVolumeParams.z);
}
#else
float3 bakeDiffuseLighting = float3(0.0, 0.0, 0.0);
#ifdef LIGHTMAP_ON
#ifdef DIRLIGHTMAP_COMBINED
bakeDiffuseLighting += SampleDirectionalLightmap(TEXTURE2D_PARAM(unity_Lightmap, samplerunity_Lightmap),
TEXTURE2D_PARAM(unity_LightmapInd, samplerunity_Lightmap),
uvStaticLightmap, unity_LightmapST, normalWS);
#else
bakeDiffuseLighting += SampleSingleLightmap(TEXTURE2D_PARAM(unity_Lightmap, samplerunity_Lightmap), uvStaticLightmap, unity_LightmapST);
#endif
#endif
#ifdef DYNAMICLIGHTMAP_ON
#ifdef DIRLIGHTMAP_COMBINED
bakeDiffuseLighting += SampleDirectionalLightmap(TEXTURE2D_PARAM(unity_DynamicLightmap, samplerunity_DynamicLightmap),
TEXTURE2D_PARAM(unity_DynamicDirectionality, samplerunity_DynamicLightmap),
uvDynamicLightmap, unity_DynamicLightmapST, normalWS);
#else
bakeDiffuseLighting += SampleSingleLightmap(TEXTURE2D_PARAM(unity_DynamicLightmap, samplerunity_DynamicLightmap), uvDynamicLightmap, unity_DynamicLightmapST);
#endif
#endif
return bakeDiffuseLighting;
#endif
}
float2 CalculateVelocity(float4 positionCS, float4 previousPositionCS)
{
// This test on define is required to remove warning of divide by 0 when initializing empty struct
// TODO: Add forward opaque MRT case...
#if (SHADERPASS == SHADERPASS_VELOCITY) || (SHADERPASS == SHADERPASS_GBUFFER && SHADEROPTIONS_VELOCITY_IN_GBUFFER)
// Encode velocity
positionCS.xy = positionCS.xy / positionCS.w;
previousPositionCS.xy = previousPositionCS.xy / previousPositionCS.w;
return (positionCS.xy - previousPositionCS.xy) * _ForceNoMotion;
#else
return float2(0.0, 0.0);
#endif
}
float3 LerpWhiteTo(float3 b, float t)
{
float oneMinusT = 1.0 - t;
return float3(oneMinusT, oneMinusT, oneMinusT) + b * t;
}
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) ((tex.xy) * name##_ST.xy + name##_ST.zw)
#if !defined(LAYERED_LIT_SHADER)
void GetSurfaceAndBuiltinData(FragInput input, out SurfaceData surfaceData, out BuiltinData builtinData)
{
#ifdef _HEIGHTMAP
// TODO: in case of shader graph, a node like parallax must be nullify if use to generate code for Meta pass
#ifndef _HEIGHTMAP_AS_DISPLACEMENT
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS); // This should be remove by the compiler as we usually cal it before.
float height = SAMPLE_TEXTURE2D(_HeightMap, sampler_HeightMap, input.texCoord0).r * _HeightScale + _HeightBias;
// Transform view vector in tangent space
float3 viewDirTS = TransformWorldToTangent(V, input.tangentToWorld);
float2 offset = ParallaxOffset(viewDirTS, height);
input.texCoord0 += offset;
input.texCoord1 += offset;
#endif
#endif
#ifdef _DETAIL_MAP
float2 texCoordDetail = TRANSFORM_TEX(_UVDetail ? input.texCoord1 : input.texCoord0, _DetailMap);
float detailMask = SAMPLE_TEXTURE2D(_DetailMask, sampler_DetailMask, input.texCoord0).b;
float4 detail = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail);
float detailAlbedo = detail.r;
float detailSmoothness = detail.b;
#ifdef _DETAIL_MAP_WITH_NORMAL
float3 detailNormalTS = UnpackNormalAG(detail, _DetailNormalScale);
//float detailAO = 0.0;
#else
// TODO: Use heightmap as a derivative with Morten Mikklesen approach
// Or reconstruct
float U = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail + float2(0.005, 0)).a;
float V = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail + float2(0, 0.005)).a;
float dHdU = U - detail.a; //create bump map U offset
float dHdV = V - detail.a; //create bump map V offset
//float3 detailNormal = 1 - float3(dHdU, dHdV, 0.05); //create the tangent space normal
float3 detailNormalTS = float3(0.0, 0.0, 1.0);
//float3 detailNormal = UnpackNormalAG(unifiedDetail.r).a;
//float detailAO = detail.b;
#endif
#endif
surfaceData.baseColor = SAMPLE_TEXTURE2D(_BaseColorMap, sampler_BaseColorMap, input.texCoord0).rgb * _BaseColor.rgb;
#ifdef _DETAIL_MAP
surfaceData.baseColor *= LerpWhiteTo(2.0 * saturate(detailAlbedo * _DetailAlbedoScale), detailMask);
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
float alpha = _BaseColor.a;
#else
float alpha = SAMPLE_TEXTURE2D(_BaseColorMap, sampler_BaseColorMap, input.texCoord0).a * _BaseColor.a;
#endif
#ifdef _ALPHATEST_ON
clip(alpha - _AlphaCutoff);
#endif
#ifdef _SPECULAROCCLUSIONMAP
// TODO: Do something. For now just take alpha channel
surfaceData.specularOcclusion = SAMPLE_TEXTURE2D(_SpecularOcclusionMap, sampler_SpecularOcclusionMap, input.texCoord0).a;
#else
// Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087
//surfaceData.specularOcclusion = saturate(1.0 + horizonFade * dot(r, input.tangentToWorld[2].xyz);
// smooth it
//surfaceData.specularOcclusion *= surfaceData.specularOcclusion;
surfaceData.specularOcclusion = 1.0;
#endif
// TODO: think about using BC5
float3 vertexNormalWS = input.tangentToWorld[2].xyz;
#ifdef _NORMALMAP
#ifdef _NORMALMAP_TANGENT_SPACE
float3 normalTS = UnpackNormalAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0));
#ifdef _DETAIL_MAP
normalTS = lerp(normalTS, blendNormal(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#else // Object space
float3 normalOS = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0).rgb;
surfaceData.normalWS = TransformObjectToWorldDir(normalOS);
#ifdef _DETAIL_MAP
float3 detailNormalWS = TransformTangentToWorld(detailNormalTS, input.tangentToWorld);
surfaceData.normalWS = lerp(surfaceData.normalWS, blendNormal(surfaceData.normalWS, detailNormalWS), detailMask);
#endif
#endif
#else
surfaceData.normalWS = vertexNormalWS;
#endif
#if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR)
#ifdef _DOUBLESIDED_LIGHTING_FLIP
float3 oppositeNormalWS = -surfaceData.normalWS;
#else
// Mirror the normal with the plane define by vertex normal
float3 oppositeNormalWS = reflect(surfaceData.normalWS, vertexNormalWS);
#endif
// TODO : Test if GetOdddNegativeScale() is necessary here in case of normal map, as GetOdddNegativeScale is take into account in CreateTangentToWorld();
surfaceData.normalWS = input.isFrontFace ?
(GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS) :
(-GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS);
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
surfaceData.perceptualSmoothness = SAMPLE_TEXTURE2D(_BaseColorMap, sampler_BaseColorMap, input.texCoord0).a;
#elif defined(_MASKMAP)
surfaceData.perceptualSmoothness = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).a;
#else
surfaceData.perceptualSmoothness = 1.0;
#endif
surfaceData.perceptualSmoothness *= _Smoothness;
#ifdef _DETAIL_MAP
surfaceData.perceptualSmoothness *= LerpWhiteTo(2.0 * saturate(detailSmoothness * _DetailSmoothnessScale), detailMask);
#endif
surfaceData.materialId = 0;
// MaskMap is Metallic, Ambient Occlusion, (Optional) - emissive Mask, Optional - Smoothness (in alpha)
#ifdef _MASKMAP
surfaceData.metallic = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).r;
surfaceData.ambientOcclusion = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).g;
#else
surfaceData.metallic = 1.0;
surfaceData.ambientOcclusion = 1.0;
#endif
surfaceData.metallic *= _Metallic;
// TODO: think about using BC5
#ifdef _TANGENTMAP
#ifdef _NORMALMAP_TANGENT_SPACE // Normal and tangent use same space
float3 tangentTS = UnpackNormalAG(SAMPLE_TEXTURE2D(_TangentMap, sampler_TangentMap, input.texCoord0));
surfaceData.tangentWS = TransformTangentToWorld(tangentTS, input.tangentToWorld);
#else // Object space (TODO: We need to apply the world rotation here! - Require to pass world transform)
surfaceData.tangentWS = SAMPLE_TEXTURE2D(_TangentMap, sampler_TangentMap, input.texCoord0).rgb;
#endif
#else
surfaceData.tangentWS = input.tangentToWorld[0].xyz;
#endif
// TODO: Is there anything todo regarding flip normal but for the tangent ?
#ifdef _ANISOTROPYMAP
surfaceData.anisotropy = SAMPLE_TEXTURE2D(_AnisotropyMap, sampler_AnisotropyMap, input.texCoord0).g;
#else
surfaceData.anisotropy = 1.0;
#endif
surfaceData.anisotropy *= _Anisotropy;
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);
// 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
#elif defined(_MASKMAP) // If we have a MaskMap, use emissive slot as a mask on baseColor
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 = CalculateVelocity(input.positionCS, input.previousPositionCS);
builtinData.distortion = float2(0.0, 0.0);
builtinData.distortionBlur = 0.0;
}
#else
float3 BlendLayeredColor(float3 rgb0, float3 rgb1, float3 rgb2, float3 rgb3, float weight[4])
{
float3 result = float3(0.0, 0.0, 0.0);
result = rgb0 * weight[0] + rgb1 * weight[1];
#if _LAYER_COUNT >= 3
result += (rgb2 * weight[2]);
#endif
#if _LAYER_COUNT >= 4
result += rgb3 * weight[3];
#endif
return result;
}
float3 BlendLayeredNormal(float3 normal0, float3 normal1, float3 normal2, float3 normal3, float weight[4])
{
float3 result = float3(0.0, 0.0, 0.0);
// TODO : real normal map blending function
result = normal0 * weight[0] + normal1 * weight[1];
#if _LAYER_COUNT >= 3
result += normal2 * weight[2];
#endif
#if _LAYER_COUNT >= 4
result += normal3 * 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;
}
void ComputeMaskWeights(float3 inputMasks, out float outWeights[_MAX_LAYER])
{
float masks[_MAX_LAYER];
masks[0] = 1.0f; // Layer 0 is always full
masks[1] = inputMasks.r;
masks[2] = inputMasks.g;
masks[3] = inputMasks.b;
// calculate weight of each layers
float left = 1.0f;
[unroll]
for (int i = _LAYER_COUNT - 1; i > 0; --i)
{
outWeights[i] = masks[i] * left;
left -= outWeights[i];
}
outWeights[0] = left;
}
float2 ComputePlanarXZCoord(float3 worldPos, float layerSize)
{
return frac(worldPos.xz / layerSize);
}
void ComputeLayerCoordinates(out LayerCoordinates outCoord, FragInput input)
{
#if defined(_LAYER_MAPPING_UV1_0)
outCoord.texcoord[0] = input.texCoord1;
outCoord.isTriplanar[0] = false;
#elif defined(_LAYER_MAPPING_PLANAR_0)
outCoord.texcoord[0] = ComputePlanarXZCoord(input.positionWS, _LayerSize0);
outCoord.isTriplanar[0] = false;
#elif defined(_LAYER_MAPPING_TRIPLANAR_0)
outCoord.texcoord[0] = input.texCoord0;
outCoord.isTriplanar[0] = true;
#else
outCoord.texcoord[0] = input.texCoord0;
outCoord.isTriplanar[0] = false;
#endif
#if defined(_LAYER_MAPPING_UV1_1)
outCoord.texcoord[1] = input.texCoord1;
outCoord.isTriplanar[1] = false;
#elif defined(_LAYER_MAPPING_PLANAR_1)
outCoord.texcoord[1] = ComputePlanarXZCoord(input.positionWS, _LayerSize1);
outCoord.isTriplanar[1] = false;
#elif defined(_LAYER_MAPPING_TRIPLANAR_1)
outCoord.texcoord[1] = input.texCoord0;
outCoord.isTriplanar[1] = true;
#else
outCoord.texcoord[1] = input.texCoord0;
outCoord.isTriplanar[1] = false;
#endif
#if defined(_LAYER_MAPPING_UV1_2)
outCoord.texcoord[2] = input.texCoord1;
outCoord.isTriplanar[2] = false;
#elif defined(_LAYER_MAPPING_PLANAR_2)
outCoord.texcoord[2] = ComputePlanarXZCoord(input.positionWS, _LayerSize2);
outCoord.isTriplanar[2] = false;
#elif defined(_LAYER_MAPPING_TRIPLANAR_2)
outCoord.texcoord[2] = input.texCoord0;
outCoord.isTriplanar[2] = true;
#else
outCoord.texcoord[2] = input.texCoord0;
outCoord.isTriplanar[2] = false;
#endif
#if defined(_LAYER_MAPPING_UV1_3)
outCoord.texcoord[3] = input.texCoord1;
outCoord.isTriplanar[3] = false;
#elif defined(_LAYER_MAPPING_PLANAR_3)
outCoord.texcoord[3] = ComputePlanarXZCoord(input.positionWS, _LayerSize3);
outCoord.isTriplanar[3] = false;
#elif defined(_LAYER_MAPPING_TRIPLANAR_3)
outCoord.texcoord[3] = input.texCoord0;
outCoord.isTriplanar[3] = true;
#else
outCoord.texcoord[3] = input.texCoord0;
outCoord.isTriplanar[3] = false;
#endif
}
void GetSurfaceAndBuiltinData(FragInput input, out SurfaceData surfaceData, out BuiltinData builtinData)
{
LayerCoordinates layerCoord;
ComputeLayerCoordinates(layerCoord, input);
// Mask Values : Layer 1, 2, 3 are r, g, b
float3 maskValues = float3(0.0, 0.0, 0.0);
#if defined(_LAYER_MASK_MAP)
maskValues = SAMPLE_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, input.texCoord0).rgb;
#endif
#if defined(_LAYER_MASK_VERTEX_COLOR)
maskValues = input.vertexColor.rgb;
#endif
#if defined(_LAYER_MASK_MAP) && defined(_LAYER_MASK_VERTEX_COLOR)
maskValues = input.vertexColor.rgb * SAMPLE_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, input.texCoord0).rgb;
#endif
float weights[_MAX_LAYER];
ComputeMaskWeights(maskValues, weights);
PROP_DECL(float3, baseColor);
PROP_SAMPLE(baseColor, _BaseColorMap, layerCoord, rgb);
PROP_MUL(baseColor, _BaseColor, rgb);
PROP_BLEND_COLOR(baseColor, weights);
surfaceData.baseColor = baseColor;
PROP_DECL(float, alpha);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
PROP_ASSIGN(alpha, _BaseColor, a);
#else
PROP_SAMPLE(alpha, _BaseColorMap, layerCoord, a);
PROP_MUL(alpha, _BaseColor, a);
#endif
PROP_BLEND_SCALAR(alpha, weights);
#ifdef _ALPHATEST_ON
clip(alpha - _AlphaCutoff);
#endif
builtinData.opacity = alpha;
PROP_DECL(float, specularOcclusion);
#ifdef _SPECULAROCCLUSIONMAP
// TODO: Do something. For now just take alpha channel
PROP_SAMPLE(specularOcclusion, _SpecularOcclusionMap, layerCoord, a);
#else
// Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087
//surfaceData.specularOcclusion = saturate(1.0 + horizonFade * dot(r, input.tangentToWorld[2].xyz);
// smooth it
//surfaceData.specularOcclusion *= surfaceData.specularOcclusion;
PROP_ASSIGN_VALUE(specularOcclusion, 1.0);
#endif
PROP_BLEND_SCALAR(specularOcclusion, weights);
surfaceData.specularOcclusion = specularOcclusion;
// TODO: think about using BC5
float3 vertexNormalWS = input.tangentToWorld[2].xyz;
#ifdef _NORMALMAP
#ifdef _NORMALMAP_TANGENT_SPACE
float3 normalTS0 = UnpackNormalAG(SampleLayer(TEXTURE2D_PARAM(_NormalMap0, sampler_NormalMap0), layerCoord, 0));
float3 normalTS1 = UnpackNormalAG(SampleLayer(TEXTURE2D_PARAM(_NormalMap1, sampler_NormalMap0), layerCoord, 1));
float3 normalTS2 = UnpackNormalAG(SampleLayer(TEXTURE2D_PARAM(_NormalMap2, sampler_NormalMap0), layerCoord, 2));
float3 normalTS3 = UnpackNormalAG(SampleLayer(TEXTURE2D_PARAM(_NormalMap3, sampler_NormalMap0), layerCoord, 3));
float3 normalTS = BlendLayeredNormal(normalTS0, normalTS1, normalTS2, normalTS3, weights);
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#else // Object space (TODO: We need to apply the world rotation here!)
surfaceData.normalWS = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0).rgb;
#endif
#else
surfaceData.normalWS = vertexNormalWS;
#endif
#if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR)
#ifdef _DOUBLESIDED_LIGHTING_FLIP
float3 oppositeNormalWS = -surfaceData.normalWS;
#else
// Mirror the normal with the plane define by vertex normal
float3 oppositeNormalWS = reflect(surfaceData.normalWS, vertexNormalWS);
#endif
// TODO : Test if GetOdddNegativeScale() is necessary here in case of normal map, as GetOdddNegativeScale is take into account in CreateTangentToWorld();
surfaceData.normalWS = IS_FRONT_VFACE(input.cullFace, GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS, -GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS);
#endif
PROP_DECL(float, perceptualSmoothness);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
PROP_SAMPLE(perceptualSmoothness, _BaseColorMap, layerCoord, a);
#elif defined(_MASKMAP)
PROP_SAMPLE(perceptualSmoothness, _MaskMap, layerCoord, a);
#else
PROP_ASSIGN_VALUE(perceptualSmoothness, 1.0);
#endif
PROP_MUL(perceptualSmoothness, _Smoothness, r);
PROP_BLEND_SCALAR(perceptualSmoothness, weights);
surfaceData.perceptualSmoothness = perceptualSmoothness;
surfaceData.materialId = 0;
// MaskMap is Metallic, Ambient Occlusion, (Optional) - emissive Mask, Optional - Smoothness (in alpha)
PROP_DECL(float, metallic);
PROP_DECL(float, ambientOcclusion);
#ifdef _MASKMAP
PROP_SAMPLE(metallic, _MaskMap, layerCoord, a);
PROP_SAMPLE(ambientOcclusion, _MaskMap, layerCoord, g);
#else
PROP_ASSIGN_VALUE(metallic, 1.0);
PROP_ASSIGN_VALUE(ambientOcclusion, 1.0);
#endif
PROP_MUL(metallic, _Metallic, r);
PROP_BLEND_SCALAR(metallic, weights);
PROP_BLEND_SCALAR(ambientOcclusion, weights);
surfaceData.metallic = metallic;
surfaceData.ambientOcclusion = ambientOcclusion;
surfaceData.tangentWS = float3(1.0, 0.0, 0.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);
// Builtin Data
// 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
PROP_DECL(float, emissiveIntensity);
PROP_ASSIGN(emissiveIntensity, _EmissiveIntensity, r);
PROP_BLEND_SCALAR(emissiveIntensity, weights);
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
PROP_DECL(float3, emissiveColor);
#ifdef _EMISSIVE_COLOR
#ifdef _EMISSIVE_COLOR_MAP
PROP_SAMPLE(emissiveColor, _EmissiveColorMap, layerCoord, rgb);
#else
PROP_ASSIGN(emissiveColor, _EmissiveColor, rgb);
#endif
#elif defined(_MASKMAP) // If we have a MaskMap, use emissive slot as a mask on baseColor
PROP_SAMPLE(emissiveColor, _MaskMap, layerCoord, bbb);
PROP_MUL(emissiveColor, baseColor, rgb);
#else
PROP_ASSIGN_VALUE(emissiveColor, float3(0.0, 0.0, 0.0));
#endif
PROP_BLEND_COLOR(emissiveColor, weights);
builtinData.emissiveColor = emissiveColor * builtinData.emissiveIntensity;
builtinData.velocity = CalculateVelocity(input.positionCS, input.previousPositionCS);
builtinData.distortion = float2(0.0, 0.0);
builtinData.distortionBlur = 0.0;
}
#endif