#T#PoiMetallicsAndSpecularProperties
[HideInInspector] m_start_brdf ("Reflections & Specular--{reference_property:_MochieBRDF}", Float) = 0
[HideInInspector][ThryToggle(MOCHIE_PBR)]_MochieBRDF ("Enable", Float) = 0
_MochieReflectionStrength ("Reflection Strength", Range(0, 1)) = 1
_MochieSpecularStrength ("Specular Strength", Range(0, 1)) = 1
_MochieMetallicMultiplier ("Metallic", Range(0, 1)) = 0
_MochieRoughnessMultiplier ("Smoothness", Range(0, 1)) = 1
_MochieReflectionTint ("Reflection Tint--{reference_property:_MochieReflectionTintThemeIndex}", Color) = (1, 1, 1, 1)
[HideInInspector][ThryWideEnum(Off, 0, Theme Color 0, 1, Theme Color 1, 2, Theme Color 2, 3, Theme Color 3, 4, ColorChord 0, 5, ColorChord 1, 6, ColorChord 2, 7, ColorChord 3, 8, AL Theme 0, 9, AL Theme 1, 10, AL Theme 2, 11, AL Theme 3, 12)] _MochieReflectionTintThemeIndex ("", Int) = 0
_MochieSpecularTint ("Specular Tint--{reference_property:_MochieSpecularTintThemeIndex}", Color) = (1, 1, 1, 1)
[HideInInspector][ThryWideEnum(Off, 0, Theme Color 0, 1, Theme Color 1, 2, Theme Color 2, 3, Theme Color 3, 4, ColorChord 0, 5, ColorChord 1, 6, ColorChord 2, 7, ColorChord 3, 8, AL Theme 0, 9, AL Theme 1, 10, AL Theme 2, 11, AL Theme 3, 12)] _MochieSpecularTintThemeIndex ("", Int) = 0
[Space(8)]
[ThryRGBAPacker(R Metallic Map, G Smoothness Map, B Reflection Mask, A Specular Mask)]_MochieMetallicMaps ("Maps [Expand]--{reference_properties:[_MochieMetallicMapsPan, _MochieMetallicMapsUV, _MochieMetallicMapInvert, _MochieRoughnessMapInvert, _MochieReflectionMaskInvert, _MochieSpecularMaskInvert]}", 2D) = "white" { }
[HideInInspector][Vector2]_MochieMetallicMapsPan ("Panning", Vector) = (0, 0, 0, 0)
[HideInInspector][ThryWideEnum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Panosphere, 4, World Pos XZ, 5, Polar UV, 6, Distorted UV, 7)]_MochieMetallicMapsUV ("UV", Int) = 0
[HideInInspector][ToggleUI]_MochieMetallicMapInvert ("Invert Metallic", Float) = 0
[HideInInspector][ToggleUI]_MochieRoughnessMapInvert ("Invert Smoothness", Float) = 0
[HideInInspector][ToggleUI]_MochieReflectionMaskInvert ("Invert Reflection Mask", Float) = 0
[HideInInspector][ToggleUI]_MochieSpecularMaskInvert ("Invert Specular Mask", Float) = 0
[ThryToggleUI(true)]_PBRSplitMaskSample ("<size=13><b>  Split Mask Sampling</b></size>", Float) = 0
_PBRMaskScaleTiling ("ScaleXY TileZW--{condition_showS:(_PBRSplitMaskSample==1)}", Vector) = (1, 1, 0, 0)
[ThryWideEnum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Panosphere, 4, World Pos XZ, 5, Polar UV, 6, Distorted UV, 7)]_MochieMetallicMasksUV ("UV--{condition_showS:(_PBRSplitMaskSample==1)}", Int) = 0
[Vector2]_MochieMetallicMasksPan ("Panning--{condition_showS:(_PBRSplitMaskSample==1)}", Vector) = (0, 0, 0, 0)
[ThryToggleUI(true)]_Specular2ndLayer ("<size=13><b>  2nd Specular</b></size>", Float) = 0
_MochieSpecularStrength2 ("Strength--{condition_showS:(_Specular2ndLayer==1)}", Range(0, 1)) = 1
_MochieRoughnessMultiplier2 ("Smoothness--{condition_showS:(_Specular2ndLayer==1)}", Range(0, 1)) = 1
[ThryToggleUI(true)] _BRDFTPSDepthEnabled ("<size=13><b>  TPS Depth Enabled</b></size>", Float) = 0
_BRDFTPSReflectionMaskStrength ("Reflection Mask Strength--{condition_showS:(_BRDFTPSDepthEnabled==1)}", Range(0, 1)) = 1
_BRDFTPSSpecularMaskStrength ("Specular Mask Strength--{condition_showS:(_BRDFTPSDepthEnabled==1)}", Range(0, 1)) = 1
[ToggleUI]_IgnoreCastedShadows ("Ignore Casted Shadows", Float) = 0

[Space(8)]
[ThryTexture][NoScaleOffset]_MochieReflCube ("Fallback Cubemap", Cube) = "" { }
[ToggleUI]_MochieForceFallback ("Force Fallback", Int) = 0
[ToggleUI]_MochieLitFallback ("Lit Fallback", Float) = 0
[ThryToggleUI(true)]_MochieGSAAEnabled ("<size=13><b>  GSAA</b></size>", Float) = 1
_PoiGSAAVariance ("GSAA Variance", Range(0, 1)) = 0.15
_PoiGSAAThreshold ("GSAA Threshold", Range(0, 1)) = 0.1
_RefSpecFresnel ("Fresnel Reflection", Range(0, 1)) = 1
[HideInInspector] m_end_brdf ("", Float) = 0

[HideInInspector] m_start_clearCoat ("Clear Coat--{reference_property:_ClearCoatBRDF}", Float) = 0
[HideInInspector][ThryToggle(POI_CLEARCOAT)]_ClearCoatBRDF ("Enable", Float) = 0
_ClearCoatStrength ("ClearCoat Strength", Range(0, 1)) = 1
_ClearCoatSmoothness ("Smoothness", Range(0, 1)) = 1
_ClearCoatReflectionStrength ("Reflections Strength", Range(0, 1)) = 1
_ClearCoatSpecularStrength ("Specular Strength", Range(0, 1)) = 1
_ClearCoatReflectionTint ("Reflection Tint--{reference_property:_ClearCoatReflectionTintThemeIndex}", Color) = (1, 1, 1, 1)
[HideInInspector][ThryWideEnum(Off, 0, Theme Color 0, 1, Theme Color 1, 2, Theme Color 2, 3, Theme Color 3, 4, ColorChord 0, 5, ColorChord 1, 6, ColorChord 2, 7, ColorChord 3, 8, AL Theme 0, 9, AL Theme 1, 10, AL Theme 2, 11, AL Theme 3, 12)] _ClearCoatReflectionTintThemeIndex ("", Int) = 0
_ClearCoatSpecularTint ("Specular Tint--{reference_property:_ClearCoatSpecularTintThemeIndex}", Color) = (1, 1, 1, 1)
[HideInInspector][ThryWideEnum(Off, 0, Theme Color 0, 1, Theme Color 1, 2, Theme Color 2, 3, Theme Color 3, 4, ColorChord 0, 5, ColorChord 1, 6, ColorChord 2, 7, ColorChord 3, 8, AL Theme 0, 9, AL Theme 1, 10, AL Theme 2, 11, AL Theme 3, 12)] _ClearCoatSpecularTintThemeIndex ("", Int) = 0
[Space(8)]
[ThryRGBAPacker(ClearCoat Mask, Smoothness Map, Reflection Mask, Specular Mask)]_ClearCoatMaps ("Maps [Expand]--{reference_properties:[_ClearCoatMapsPan, _ClearCoatMapsUV, _ClearCoatMaskInvert, _ClearCoatSmoothnessMapInvert, _ClearCoatReflectionMaskInvert, _ClearCoatSpecularMaskInvert]}", 2D) = "white" { }
[HideInInspector][Vector2]_ClearCoatMapsPan ("Panning", Vector) = (0, 0, 0, 0)
[HideInInspector][ThryWideEnum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Panosphere, 4, World Pos XZ, 5, Polar UV, 6, Distorted UV, 7)]_ClearCoatMapsUV ("UV", Int) = 0
[HideInInspector][ToggleUI]_ClearCoatMaskInvert ("Invert ClearCoat Mask", Float) = 0
[HideInInspector][ToggleUI]_ClearCoatSmoothnessMapInvert ("Invert Smoothness", Float) = 0
[HideInInspector][ToggleUI]_ClearCoatReflectionMaskInvert ("Invert Reflection Mask", Float) = 0
[HideInInspector][ToggleUI]_ClearCoatSpecularMaskInvert ("Invert Specular Mask", Float) = 0
[Space(8)]
[ThryTexture][NoScaleOffset]_ClearCoatFallback ("Fallback Cubemap", Cube) = "" { }
[ToggleUI]_ClearCoatForceFallback ("Force Fallback", Int) = 0
[ToggleUI]_ClearCoatLitFallback ("Lit Fallback", Float) = 0
[ToggleUI]_CCIgnoreCastedShadows ("Ignore Casted Shadows", Float) = 0
[ThryToggleUI(true)]_ClearCoatGSAAEnabled ("<size=13><b>  GSAA</b></size>", Float) = 1
_ClearCoatGSAAVariance ("GSAA Variance", Range(0, 1)) = 0.15
_ClearCoatGSAAThreshold ("GSAA Threshold", Range(0, 1)) = 0.1
[ThryToggleUI(true)] _ClearCoatTPSDepthMaskEnabled ("<size=13><b>  TPS Depth Enabled</b></size>", Float) = 0
_ClearCoatTPSMaskStrength ("Mask Strength--{condition_showS:(_ClearCoatTPSDepthMaskEnabled==1)}", Range(0, 1)) = 1
[HideInInspector] m_end_clearCoat ("", Float) = 0

#T#PoiMetallicsAndSpecularKeywords
#pragma shader_feature_local MOCHIE_PBR
#pragma shader_feature_local POI_CLEARCOAT

#T#PoiMetallicsAndSpecularVariables
float4 _MochieReflCube_HDR;
#ifdef MOCHIE_PBR
	#if defined(PROP_MOCHIEMETALLICMAPS) || !defined(OPTIMIZER_ENABLED)
		Texture2D _MochieMetallicMaps;
	#endif
	float4 _MochieMetallicMaps_ST;
	float2 _MochieMetallicMapsPan;
	float _MochieMetallicMapsUV;
	float _MochieMetallicMapInvert;
	float _MochieRoughnessMapInvert;
	float _MochieReflectionMaskInvert;
	float _MochieSpecularMaskInvert;

	float _MochieReflectionTintThemeIndex;
	float _MochieSpecularTintThemeIndex;

	float _MochieRoughnessMultiplier;
	float _MochieMetallicMultiplier;
	float _MochieReflectionStrength;
	float _MochieSpecularStrength;
	float4 _MochieSpecularTint;
	float4 _MochieReflectionTint;
	float _MochieLitFallback;
	float _IgnoreCastedShadows;
	float _PBRSplitMaskSample;
	float4 _PBRMaskScaleTiling;
	float _MochieMetallicMasksUV;
	float4 _MochieMetallicMasksPan;

	float _Specular2ndLayer;
	float _MochieSpecularStrength2;
	float _MochieRoughnessMultiplier2;
	float _RefSpecFresnel;
	samplerCUBE _MochieReflCube;
	float _MochieForceFallback;
	float _MochieGSAAEnabled;
	float _PoiGSAAVariance;
	float _PoiGSAAThreshold;
	float _BRDFTPSReflectionMaskStrength;
	float _BRDFTPSSpecularMaskStrength;
#endif

#ifdef POI_CLEARCOAT
	#if defined(PROP_CLEARCOATMAPS) || !defined(OPTIMIZER_ENABLED)
		Texture2D _ClearCoatMaps;
		float4 _ClearCoatMaps_ST;
		float2 _ClearCoatMapsPan;
		float _ClearCoatMapsUV;
	#endif
	float _ClearCoatBRDF;
	float _ClearCoatReflectionStrength;
	float _ClearCoatSpecularStrength;
	float _ClearCoatStrength;
	float _ClearCoatSmoothness;
	float4 _ClearCoatReflectionTint;
	float _ClearCoatReflectionTintThemeIndex;
	float4 _ClearCoatSpecularTint;
	float _ClearCoatSpecularTintThemeIndex;
	float _ClearCoatSmoothnessMapInvert;
	float _ClearCoatMaskInvert;
	float _ClearCoatReflectionMaskInvert;
	float _ClearCoatSpecularMaskInvert;
	float _ClearCoatTPSMaskStrength;

	samplerCUBE _ClearCoatFallback;
	float _ClearCoatForceFallback;
	float _ClearCoatLitFallback;
	float _CCIgnoreCastedShadows;
	float _ClearCoatGSAAEnabled;
	float _ClearCoatGSAAVariance;
	float _ClearCoatGSAAThreshold;
#endif

#T#PoiMetallicsAndSpecularFunction
#if defined(MOCHIE_PBR) || defined(POI_CLEARCOAT)

	/*
	* Copyright 2022 orels1
	*
	* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
	*
	* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
	*
	* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
	*/

	// https://github.com/orels1/orels-Unity-Shaders

	float GSAA_Filament(float3 worldNormal, float perceptualRoughness, float gsaaVariance, float gsaaThreshold)
	{
		// Kaplanyan 2016, "Stable specular highlights"
		// Tokuyoshi 2017, "Error Reduction and Simplification for Shading Anti-Aliasing"
		// Tokuyoshi and Kaplanyan 2019, "Improved Geometric Specular Antialiasing"

		// This implementation is meant for deferred rendering in the original paper but
		// we use it in forward rendering as well (as discussed in Tokuyoshi and Kaplanyan
		// 2019). The main reason is that the forward version requires an expensive transform
		// of the float vector by the tangent frame for every light. This is therefore an
		// approximation but it works well enough for our needs and provides an improvement
		// over our original implementation based on Vlachos 2015, "Advanced VR Rendering".

		float3 du = ddx(worldNormal);
		float3 dv = ddy(worldNormal);

		float variance = gsaaVariance * (dot(du, du) + dot(dv, dv));

		float roughness = perceptualRoughness * perceptualRoughness;
		float kernelRoughness = min(2.0 * variance, gsaaThreshold);
		float squareRoughness = saturate(roughness * roughness + kernelRoughness);

		return sqrt(sqrt(squareRoughness));
	}

	/*
	MIT END
	*/


	bool SceneHasReflections()
	{
		float width, height;
		unity_SpecCube0.GetDimensions(width, height);
		return !(width * height < 2);
	}

	float3 GetWorldReflections(float3 reflDir, float3 worldPos, float roughness)
	{
		float3 baseReflDir = reflDir;
		reflDir = BoxProjection(reflDir, worldPos, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
		float4 envSample0 = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflDir, roughness * UNITY_SPECCUBE_LOD_STEPS);
		float3 p0 = DecodeHDR(envSample0, unity_SpecCube0_HDR);
		float interpolator = unity_SpecCube0_BoxMin.w;
		UNITY_BRANCH
		if (interpolator < 0.99999)
		{
			float3 refDirBlend = BoxProjection(baseReflDir, worldPos, unity_SpecCube1_ProbePosition, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
			float4 envSample1 = UNITY_SAMPLE_TEXCUBE_SAMPLER_LOD(unity_SpecCube1, unity_SpecCube0, refDirBlend, roughness * UNITY_SPECCUBE_LOD_STEPS);
			float3 p1 = DecodeHDR(envSample1, unity_SpecCube1_HDR);
			p0 = lerp(p1, p0, interpolator);
		}
		return p0;
	}

	float3 GetReflections(in PoiCam poiCam, in PoiLight pl, in PoiMesh poiMesh, float roughness, float ForceFallback, float LightFallback, samplerCUBE reflectionCube, float3 reflectionDir)
	{
		float3 reflections = 0;
		float3 lighting = pl.finalLighting;
		if (ForceFallback == 0)
		{
			UNITY_BRANCH
			if (SceneHasReflections())
			{
				#ifdef UNITY_PASS_FORWARDBASE
					reflections = GetWorldReflections(reflectionDir, poiMesh.worldPos.xyz, roughness);
				#endif
			}
			else
			{
				#ifdef UNITY_PASS_FORWARDBASE
					reflections = texCUBElod(reflectionCube, float4(reflectionDir, roughness * UNITY_SPECCUBE_LOD_STEPS));
					reflections = DecodeHDR(float4(reflections, 1), _MochieReflCube_HDR) * lerp(1, pl.finalLighting, LightFallback);
				#endif
				#ifdef POI_PASS_ADD
					if (LightFallback)
					{
						reflections = texCUBElod(reflectionCube, float4(reflectionDir, roughness * UNITY_SPECCUBE_LOD_STEPS));
						reflections = DecodeHDR(float4(reflections, 1), _MochieReflCube_HDR) * pl.finalLighting;
					}
				#endif
			}
		}
		else
		{
			#ifdef UNITY_PASS_FORWARDBASE
				reflections = texCUBElod(reflectionCube, float4(reflectionDir, roughness * UNITY_SPECCUBE_LOD_STEPS));
				reflections = DecodeHDR(float4(reflections, 1), _MochieReflCube_HDR) * lerp(1, pl.finalLighting, LightFallback);
			#endif
			#ifdef POI_PASS_ADD
				if (LightFallback)
				{
					reflections = texCUBElod(reflectionCube, float4(reflectionDir, roughness * UNITY_SPECCUBE_LOD_STEPS));
					reflections = DecodeHDR(float4(reflections, 1), _MochieReflCube_HDR) * pl.finalLighting;
				}
			#endif
		}
		reflections *= pl.occlusion;
		return reflections;
	}

	float GetGGXTerm(float nDotL, float nDotV, float nDotH, float roughness)
	{
		float visibilityTerm = 0;
		if (nDotL > 0)
		{
			float rough = roughness;
			float rough2 = roughness * roughness;

			float lambdaV = nDotL * (nDotV * (1 - rough) + rough);
			float lambdaL = nDotV * (nDotL * (1 - rough) + rough);

			visibilityTerm = 0.5f / (lambdaV + lambdaL + 1e-5f);
			float d = (nDotH * rough2 - nDotH) * nDotH + 1.0f;
			float dotTerm = UNITY_INV_PI * rough2 / (d * d + 1e-7f);

			visibilityTerm *= dotTerm * UNITY_PI;
		}
		return visibilityTerm;
	}

	void GetSpecFresTerm(float nDotL, float nDotV, float nDotH, float lDotH, inout float3 specularTerm, inout float3 fresnelTerm, float3 specCol, float roughness)
	{
		specularTerm = GetGGXTerm(nDotL, nDotV, nDotH, roughness);
		fresnelTerm = FresnelTerm(specCol, lDotH);
		specularTerm = max(0, specularTerm * max(0.00001, nDotL));
	}

	float GetRoughness(float smoothness)
	{
		float rough = 1 - smoothness;
		rough *= 1.7 - 0.7 * rough;
		return rough;
	}
#endif

#ifdef MOCHIE_PBR
	void MochieBRDF(inout PoiFragData poiFragData, in PoiCam poiCam, in PoiLight poiLight, in PoiMesh poiMesh, in PoiMods poiMods)
	{
		float smoothness = _MochieRoughnessMultiplier;
		float smoothness2 = _MochieRoughnessMultiplier2;
		float metallic = _MochieMetallicMultiplier;
		float specularMask = 1;
		float reflectionMask = 1;

		#if defined(PROP_MOCHIEMETALLICMAPS) || !defined(OPTIMIZER_ENABLED)
			float4 PRBMaps = POI2D_SAMPLER_PAN(_MochieMetallicMaps, _MainTex, poiUV(poiMesh.uv[_MochieMetallicMapsUV], _MochieMetallicMaps_ST), _MochieMetallicMapsPan.xy);
			UNITY_BRANCH
			if (_PBRSplitMaskSample)
			{
				PRBMaps.zw = POI2D_SAMPLER_PAN(_MochieMetallicMaps, _MainTex, poiUV(poiMesh.uv[_MochieMetallicMasksUV], _PBRMaskScaleTiling), _MochieMetallicMasksPan.xy).zw;
			}
			metallic *= PRBMaps.r;
			smoothness = (smoothness * PRBMaps.g);
			smoothness2 = (smoothness2 * PRBMaps.g);
			reflectionMask *= PRBMaps.b;
			specularMask *= PRBMaps.a;
		#endif
		
		if (_MochieSpecularMaskInvert)
		{
			specularMask = 1 - specularMask;
		}
		if (_MochieReflectionMaskInvert)
		{
			reflectionMask = 1 - reflectionMask;
		}

		#ifdef TPS_Penetrator
			reflectionMask = lerp(0, reflectionMask * TPSBufferedDepth(poiMesh.localPos, poiMesh.vertexColor), _BRDFTPSReflectionMaskStrength);
			specularMask = lerp(0, specularMask * TPSBufferedDepth(poiMesh.localPos, poiMesh.vertexColor), _BRDFTPSSpecularMaskStrength);
		#endif

		#K#MOCHIE_METALLIC_SMOOTHNESS_MOD
		
		if (_MochieRoughnessMapInvert)
		{
			smoothness = 1 - smoothness;
			smoothness2 = 1 - smoothness2;
		}
		float roughness = GetRoughness(smoothness);
		float roughness2 = GetRoughness(smoothness2);
		if (_MochieMetallicMapInvert)
		{
			metallic = 1 - metallic;
		}
		float3 specCol = lerp(unity_ColorSpaceDielectricSpec.rgb, poiFragData.baseColor, metallic);
		float omr = unity_ColorSpaceDielectricSpec.a - metallic * unity_ColorSpaceDielectricSpec.a;
		float percepRough = 1 - smoothness;
		float percepRough2 = 1 - smoothness2;
		UNITY_BRANCH
		if (_MochieGSAAEnabled)
		{
			percepRough = GSAA_Filament(poiMesh.normals[1], percepRough, _PoiGSAAVariance, _PoiGSAAThreshold);
			if (_Specular2ndLayer == 1 && _MochieSpecularStrength2 > 0)
			{
				percepRough2 = GSAA_Filament(poiMesh.normals[1], percepRough2, _PoiGSAAVariance, _PoiGSAAThreshold);
			}
		}
		float brdfRoughness = percepRough * percepRough;
		brdfRoughness = max(brdfRoughness, 0.002);
		
		float brdfRoughness2 = percepRough2 * percepRough2;
		brdfRoughness2 = max(brdfRoughness2, 0.002);

		float3 diffuse = poiFragData.baseColor;
		float3 specular = 0;
		float3 specular2 = 0;
		float3 vSpecular = 0;
		float3 vSpecular2 = 0;
		float3 reflections = 0;
		float3 environment = 0;

		float attenuation = min(poiLight.nDotLSaturated, lerp(poiLight.attenuation, 1, _IgnoreCastedShadows));

		// Specular
		// if (_SpecularMode == 0){
		if (_MochieSpecularStrength > 0)
		{
			float3 fresnelTerm = 1;
			float3 specularTerm = 1;
			GetSpecFresTerm(poiLight.nDotL, poiLight.nDotV, poiLight.nDotH, poiLight.lDotH, specularTerm, fresnelTerm, specCol, brdfRoughness);
			specular = poiLight.directColor * specularTerm * fresnelTerm * specularMask * poiThemeColor(poiMods, _MochieSpecularTint, _MochieSpecularTintThemeIndex) * poiLight.occlusion * attenuation * _MochieSpecularStrength;
			#if defined(VERTEXLIGHT_ON) && defined(POI_VERTEXLIGHT_ON)
				for (int index = 0; index < 4; index++)
				{
					fresnelTerm = 1;
					specularTerm = 1;
					GetSpecFresTerm(poiLight.vDotNL[index], poiLight.nDotV, poiLight.vDotNH[index], poiLight.vDotLH[index], specularTerm, fresnelTerm, specCol, brdfRoughness);
					vSpecular += poiLight.vColor[index] * specularTerm * fresnelTerm * specularMask * poiThemeColor(poiMods, _MochieSpecularTint, _MochieSpecularTintThemeIndex) * poiLight.occlusion * poiLight.vAttenuation[index] * _MochieSpecularStrength;
				}
			#endif
		}

		if (_Specular2ndLayer == 1 && _MochieSpecularStrength2 > 0)
		{
			float3 fresnelTerm = 1;
			float3 specularTerm = 1;
			GetSpecFresTerm(poiLight.nDotL, poiLight.nDotV, poiLight.nDotH, poiLight.lDotH, specularTerm, fresnelTerm, specCol, brdfRoughness2);
			specular2 = poiLight.directColor * specularTerm * fresnelTerm * specularMask * poiThemeColor(poiMods, _MochieSpecularTint, _MochieSpecularTintThemeIndex) * poiLight.occlusion * attenuation * _MochieSpecularStrength2;
			
			#if defined(VERTEXLIGHT_ON) && defined(POI_VERTEXLIGHT_ON)
				for (int index = 0; index < 4; index++)
				{
					fresnelTerm = 1;
					specularTerm = 1;
					GetSpecFresTerm(poiLight.vDotNL[index], poiLight.nDotV, poiLight.vDotNH[index], poiLight.vDotLH[index], specularTerm, fresnelTerm, specCol, brdfRoughness2);
					vSpecular2 += poiLight.vColor[index] * specularTerm * fresnelTerm * specularMask * poiThemeColor(poiMods, _MochieSpecularTint, _MochieSpecularTintThemeIndex) * poiLight.occlusion * poiLight.vAttenuation[index] * _MochieSpecularStrength2;
				}
			#endif
		}

		if (_MochieReflectionStrength > 0)
		{
			float surfaceReduction = (1.0 / (brdfRoughness * brdfRoughness + 1.0));
			float grazingTerm = saturate(smoothness + (1 - omr));
			float3 reflCol = GetReflections(poiCam, poiLight, poiMesh, roughness, _MochieForceFallback, _MochieLitFallback, _MochieReflCube, poiCam.reflectionDir);
			float reflStr = reflectionMask * _MochieReflectionStrength;
			reflections = surfaceReduction * reflCol * lerp(1, FresnelLerp(specCol, grazingTerm, poiLight.nDotV), _RefSpecFresnel);
			reflections *= poiThemeColor(poiMods, _MochieReflectionTint, _MochieReflectionTintThemeIndex);
			reflections *= reflStr;
			#ifdef UNITY_PASS_FORWARDADD
				reflections *= poiLight.attenuation;
			#endif
			diffuse = lerp(diffuse, diffuse * omr, reflStr);
		}

		environment = max(specular + vSpecular, specular2 + vSpecular2);
		environment += reflections;
		diffuse *= poiLight.finalLighting;
		diffuse += environment;
		poiFragData.finalColor = diffuse;
	}
#endif

#ifdef POI_CLEARCOAT
	void poiClearCoat(inout PoiFragData poiFragData, in PoiCam poiCam, in PoiLight poiLight, in PoiMesh poiMesh, in PoiMods poiMods)
	{
		float clearCoatMask = _ClearCoatStrength;
		float smoothness = _ClearCoatSmoothness;
		float reflectionMask = 1;
		float specularMask = 1;

		#if defined(PROP_CLEARCOATMAPS) || !defined(OPTIMIZER_ENABLED)
			float4 PRBMaps = POI2D_SAMPLER_PAN(_ClearCoatMaps, _MainTex, poiUV(poiMesh.uv[_ClearCoatMapsUV], _ClearCoatMaps_ST), _ClearCoatMapsPan);
			clearCoatMask *= PRBMaps.r;
			smoothness *= PRBMaps.g;
			reflectionMask *= PRBMaps.b;
			specularMask *= PRBMaps.a;
		#endif
		
		if (_ClearCoatMaskInvert)
		{
			clearCoatMask = 1 - clearCoatMask;
		}

		#ifdef TPS_Penetrator
			clearCoatMask = lerp(0, clearCoatMask * TPSBufferedDepth(poiMesh.localPos, poiMesh.vertexColor), _ClearCoatTPSMaskStrength);
		#endif

		if (_ClearCoatSmoothnessMapInvert)
		{
			smoothness = 1 - smoothness;
		}
		if (_ClearCoatReflectionMaskInvert)
		{
			reflectionMask = 1 - reflectionMask;
		}
		if (_ClearCoatSpecularMaskInvert)
		{
			specularMask = 1 - specularMask;
		}
		
		float roughness = GetRoughness(smoothness);
		float3 specCol = 0.220916301;
		float omr = unity_ColorSpaceDielectricSpec.a;
		float percepRough = 1 - smoothness;
		UNITY_BRANCH
		if (_ClearCoatGSAAEnabled)
		{
			percepRough = GSAA_Filament(poiMesh.normals[1], percepRough, _ClearCoatGSAAVariance, _ClearCoatGSAAThreshold);
		}
		float brdfRoughness = percepRough * percepRough;
		brdfRoughness = max(brdfRoughness, 0.002);
		
		float3 diffuse = 0;
		float3 specular = 0;
		float3 vSpecular = 0;
		float3 reflections = 0;
		float3 environment = 0;
		float attenuation = min(poiLight.nDotLSaturated, lerp(poiLight.attenuation, 1, _CCIgnoreCastedShadows));
		// Specular
		// if (_SpecularMode == 0){
		if (_ClearCoatSpecularStrength > 0)
		{
			float3 fresnelTerm = 1;
			float3 specularTerm = 1;
			GetSpecFresTerm(poiLight.vertexNDotL, poiLight.vertexNDotV, poiLight.vertexNDotH, poiLight.lDotH, specularTerm, fresnelTerm, specCol, brdfRoughness);
			specular = poiLight.directColor * specularTerm * fresnelTerm * specularMask * poiThemeColor(poiMods, _ClearCoatSpecularTint, _ClearCoatSpecularTintThemeIndex) * poiLight.occlusion * attenuation * _ClearCoatSpecularStrength;
			#if defined(VERTEXLIGHT_ON) && defined(POI_VERTEXLIGHT_ON)
				for (int index = 0; index < 4; index++)
				{
					fresnelTerm = 1;
					specularTerm = 1;
					GetSpecFresTerm(poiLight.vertexVDotNL[index], poiLight.vertexNDotV, poiLight.vertexVDotNH[index], poiLight.vDotLH[index], specularTerm, fresnelTerm, specCol, brdfRoughness);
					vSpecular += poiLight.vColor[index] * specularTerm * fresnelTerm * specularMask * poiThemeColor(poiMods, _ClearCoatSpecularTint, _ClearCoatSpecularTintThemeIndex) * poiLight.occlusion * poiLight.vAttenuation[index] * _ClearCoatSpecularStrength;
				}
			#endif
		}

		if (_ClearCoatReflectionStrength > 0)
		{
			float surfaceReduction = (1.0 / (brdfRoughness * brdfRoughness + 1.0));
			float grazingTerm = saturate(smoothness + (1 - omr));
			float3 reflCol = GetReflections(poiCam, poiLight, poiMesh, roughness, _ClearCoatForceFallback, _ClearCoatLitFallback, _ClearCoatFallback, poiCam.vertexReflectionDir);
			float reflStr = reflectionMask * _ClearCoatReflectionStrength;
			reflections = surfaceReduction * reflCol * FresnelLerp(specCol, grazingTerm, poiLight.vertexNDotV);
			reflections *= poiThemeColor(poiMods, _ClearCoatReflectionTint, _ClearCoatReflectionTintThemeIndex) * reflStr;
			#ifdef UNITY_PASS_FORWARDADD
				reflections *= poiLight.attenuation;
			#endif
			diffuse = lerp(diffuse, diffuse * omr, reflStr);
		}

		environment = specular + vSpecular;
		#ifdef UNITY_PASS_FORWARDBASE
			environment += reflections;
		#endif
		//diffuse *= poiLight.finalLighting;
		diffuse += environment;
		poiFragData.finalColor += saturate(diffuse * clearCoatMask);
	}
#endif

#T#PoiMetallicsAndSpecularFunctionCall
#ifdef MOCHIE_PBR
	MochieBRDF(poiFragData, poiCam, poiLight, poiMesh, poiMods);
#endif
#ifdef POI_CLEARCOAT
	poiClearCoat(poiFragData, poiCam, poiLight, poiMesh, poiMods);
#endif
