 		ambient_light = ambient_accum.rgb / ambient_accum.a;
 	}
 #endif
+#endif
+
+	{
+
+#if defined(DIFFUSE_TOON)
+		//simplify for toon, as
+		specular_light *= specular * metallic * albedo * 2.0;
+#else
+
+		// scales the specular reflections, needs to be be computed before lighting happens,
+		// but after environment, GI, and reflection probes are added
+		// Environment brdf approximation (Lazarov 2013)
+		// see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
+		const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
+		const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
+		vec4 r = roughness * c0 + c1;
+		float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0);
+		float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
+		vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
+
+		vec3 f0 = F0(metallic, specular, albedo);
+		specular_light *= env.x * f0 + env.y;
+#endif
+	}
+
+#if defined(USE_LIGHT_DIRECTIONAL)
+
+	vec3 light_attenuation = vec3(1.0);
+
+	float depth_z = -vertex.z;
+#ifdef LIGHT_DIRECTIONAL_SHADOW
+#if !defined(SHADOWS_DISABLED)
+
+#ifdef LIGHT_USE_PSSM4
+	if (depth_z < shadow_split_offsets.w) {
+#elif defined(LIGHT_USE_PSSM2)
+	if (depth_z < shadow_split_offsets.y) {
+#else
+	if (depth_z < shadow_split_offsets.x) {
+#endif //LIGHT_USE_PSSM4
+
+		vec3 pssm_coord;
+		float pssm_fade = 0.0;
+
+#ifdef LIGHT_USE_PSSM_BLEND
+		float pssm_blend;
+		vec3 pssm_coord2;
+		bool use_blend = true;
+#endif
+
+#ifdef LIGHT_USE_PSSM4
+
+		if (depth_z < shadow_split_offsets.y) {
+
+			if (depth_z < shadow_split_offsets.x) {
+
+				highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0));
+				pssm_coord = splane.xyz / splane.w;
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+
+				splane = (shadow_matrix2 * vec4(vertex, 1.0));
+				pssm_coord2 = splane.xyz / splane.w;
+				pssm_blend = smoothstep(0.0, shadow_split_offsets.x, depth_z);
+#endif
+
+			} else {
+
+				highp vec4 splane = (shadow_matrix2 * vec4(vertex, 1.0));
+				pssm_coord = splane.xyz / splane.w;
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+				splane = (shadow_matrix3 * vec4(vertex, 1.0));
+				pssm_coord2 = splane.xyz / splane.w;
+				pssm_blend = smoothstep(shadow_split_offsets.x, shadow_split_offsets.y, depth_z);
+#endif
+			}
+		} else {
+
+			if (depth_z < shadow_split_offsets.z) {
+
+				highp vec4 splane = (shadow_matrix3 * vec4(vertex, 1.0));
+				pssm_coord = splane.xyz / splane.w;
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+				splane = (shadow_matrix4 * vec4(vertex, 1.0));
+				pssm_coord2 = splane.xyz / splane.w;
+				pssm_blend = smoothstep(shadow_split_offsets.y, shadow_split_offsets.z, depth_z);
+#endif
+
+			} else {
+
+				highp vec4 splane = (shadow_matrix4 * vec4(vertex, 1.0));
+				pssm_coord = splane.xyz / splane.w;
+				pssm_fade = smoothstep(shadow_split_offsets.z, shadow_split_offsets.w, depth_z);
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+				use_blend = false;
+
+#endif
+			}
+		}
+
+#endif //LIGHT_USE_PSSM4
+
+#ifdef LIGHT_USE_PSSM2
+
+		if (depth_z < shadow_split_offsets.x) {
+
+			highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0));
+			pssm_coord = splane.xyz / splane.w;
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+
+			splane = (shadow_matrix2 * vec4(vertex, 1.0));
+			pssm_coord2 = splane.xyz / splane.w;
+			pssm_blend = smoothstep(0.0, shadow_split_offsets.x, depth_z);
+#endif
+
+		} else {
+			highp vec4 splane = (shadow_matrix2 * vec4(vertex, 1.0));
+			pssm_coord = splane.xyz / splane.w;
+			pssm_fade = smoothstep(shadow_split_offsets.x, shadow_split_offsets.y, depth_z);
+#if defined(LIGHT_USE_PSSM_BLEND)
+			use_blend = false;
+
+#endif
+		}
+
+#endif //LIGHT_USE_PSSM2
+
+#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2)
+		{ //regular orthogonal
+			highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0));
+			pssm_coord = splane.xyz / splane.w;
+		}
+#endif
+
+		//one one sample
+
+		float shadow = sample_shadow(directional_shadow, directional_shadow_pixel_size, pssm_coord.xy, pssm_coord.z, light_clamp);
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+
+		if (use_blend) {
+			shadow = mix(shadow, sample_shadow(directional_shadow, directional_shadow_pixel_size, pssm_coord2.xy, pssm_coord2.z, light_clamp), pssm_blend);
+		}
+#endif
+
+#ifdef USE_CONTACT_SHADOWS
+		if (shadow > 0.01 && shadow_color_contact.a > 0.0) {
+
+			float contact_shadow = contact_shadow_compute(vertex, -light_direction_attenuation.xyz, shadow_color_contact.a);
+			shadow = min(shadow, contact_shadow);
+		}
+#endif
+		light_attenuation = mix(mix(shadow_color_contact.rgb, vec3(1.0), shadow), vec3(1.0), pssm_fade);
+	}
+
+#endif // !defined(SHADOWS_DISABLED)
+#endif //LIGHT_DIRECTIONAL_SHADOW
+
+#ifdef USE_VERTEX_LIGHTING
+	diffuse_light *= mix(vec3(1.0), light_attenuation, diffuse_light_interp.a);
+	specular_light *= mix(vec3(1.0), light_attenuation, specular_light_interp.a);
+
+#else
+	light_compute(normal, -light_direction_attenuation.xyz, eye_vec, binormal, tangent, light_color_energy.rgb, light_attenuation, albedo, transmission, light_params.z * specular_blob_intensity, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light);
+#endif
+
+#endif //#USE_LIGHT_DIRECTIONAL
+
+#ifdef USE_FORWARD_LIGHTING
 
 #ifdef USE_VERTEX_LIGHTING
 

	ambient_light *= ambient_energy;

	float specular_blob_intensity = 1.0;
#if defined(SPECULAR_TOON)
	specular_blob_intensity *= specular * 2.0;
#endif

	// scales the specular reflections, needs to be be computed before lighting happens,
	// but after environment and reflection probes are added
	// Environment brdf approximation (Lazarov 2013)
	// see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
	const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
	const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
	vec4 r = roughness * c0 + c1;
	float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0);
	float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
	vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;

	vec3 f0 = F0(metallic, specular, albedo);
	env_reflection_light *= env.x * f0 + env.y;

#if defined(USE_LIGHT_DIRECTIONAL)

	vec3 light_attenuation = vec3(1.0);

	float depth_z = -vertex.z;
#ifdef LIGHT_DIRECTIONAL_SHADOW
#if !defined(SHADOWS_DISABLED)

#ifdef LIGHT_USE_PSSM4
	if (depth_z < shadow_split_offsets.w) {
#elif defined(LIGHT_USE_PSSM2)
	if (depth_z < shadow_split_offsets.y) {
#else
	if (depth_z < shadow_split_offsets.x) {
#endif //LIGHT_USE_PSSM4

		vec3 pssm_coord;
		float pssm_fade = 0.0;

#ifdef LIGHT_USE_PSSM_BLEND
		float pssm_blend;
		vec3 pssm_coord2;
		bool use_blend = true;
#endif

#ifdef LIGHT_USE_PSSM4

		if (depth_z < shadow_split_offsets.y) {

			if (depth_z < shadow_split_offsets.x) {

				highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0));
				pssm_coord = splane.xyz / splane.w;

#if defined(LIGHT_USE_PSSM_BLEND)

				splane = (shadow_matrix2 * vec4(vertex, 1.0));
				pssm_coord2 = splane.xyz / splane.w;
				pssm_blend = smoothstep(0.0, shadow_split_offsets.x, depth_z);
#endif

			} else {

				highp vec4 splane = (shadow_matrix2 * vec4(vertex, 1.0));
				pssm_coord = splane.xyz / splane.w;

#if defined(LIGHT_USE_PSSM_BLEND)
				splane = (shadow_matrix3 * vec4(vertex, 1.0));
				pssm_coord2 = splane.xyz / splane.w;
				pssm_blend = smoothstep(shadow_split_offsets.x, shadow_split_offsets.y, depth_z);
#endif
			}
		} else {

			if (depth_z < shadow_split_offsets.z) {

				highp vec4 splane = (shadow_matrix3 * vec4(vertex, 1.0));
				pssm_coord = splane.xyz / splane.w;

#if defined(LIGHT_USE_PSSM_BLEND)
				splane = (shadow_matrix4 * vec4(vertex, 1.0));
				pssm_coord2 = splane.xyz / splane.w;
				pssm_blend = smoothstep(shadow_split_offsets.y, shadow_split_offsets.z, depth_z);
#endif

			} else {

				highp vec4 splane = (shadow_matrix4 * vec4(vertex, 1.0));
				pssm_coord = splane.xyz / splane.w;
				pssm_fade = smoothstep(shadow_split_offsets.z, shadow_split_offsets.w, depth_z);

#if defined(LIGHT_USE_PSSM_BLEND)
				use_blend = false;

#endif
			}
		}

#endif //LIGHT_USE_PSSM4

#ifdef LIGHT_USE_PSSM2

		if (depth_z < shadow_split_offsets.x) {

			highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0));
			pssm_coord = splane.xyz / splane.w;

#if defined(LIGHT_USE_PSSM_BLEND)

			splane = (shadow_matrix2 * vec4(vertex, 1.0));
			pssm_coord2 = splane.xyz / splane.w;
			pssm_blend = smoothstep(0.0, shadow_split_offsets.x, depth_z);
#endif

		} else {
			highp vec4 splane = (shadow_matrix2 * vec4(vertex, 1.0));
			pssm_coord = splane.xyz / splane.w;
			pssm_fade = smoothstep(shadow_split_offsets.x, shadow_split_offsets.y, depth_z);
#if defined(LIGHT_USE_PSSM_BLEND)
			use_blend = false;

#endif
		}

#endif //LIGHT_USE_PSSM2

#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2)
		{ //regular orthogonal
			highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0));
			pssm_coord = splane.xyz / splane.w;
		}
#endif

		//one one sample

		float shadow = sample_shadow(directional_shadow, directional_shadow_pixel_size, pssm_coord.xy, pssm_coord.z, light_clamp);

#if defined(LIGHT_USE_PSSM_BLEND)

		if (use_blend) {
			shadow = mix(shadow, sample_shadow(directional_shadow, directional_shadow_pixel_size, pssm_coord2.xy, pssm_coord2.z, light_clamp), pssm_blend);
		}
#endif

#ifdef USE_CONTACT_SHADOWS
		if (shadow > 0.01 && shadow_color_contact.a > 0.0) {

			float contact_shadow = contact_shadow_compute(vertex, -light_direction_attenuation.xyz, shadow_color_contact.a);
			shadow = min(shadow, contact_shadow);
		}
#endif
		light_attenuation = mix(mix(shadow_color_contact.rgb, vec3(1.0), shadow), vec3(1.0), pssm_fade);
	}

#endif // !defined(SHADOWS_DISABLED)
#endif //LIGHT_DIRECTIONAL_SHADOW

#ifdef USE_VERTEX_LIGHTING
	diffuse_light *= mix(vec3(1.0), light_attenuation, diffuse_light_interp.a);
	specular_light *= mix(vec3(1.0), light_attenuation, specular_light_interp.a);

#else
	light_compute(normal, -light_direction_attenuation.xyz, eye_vec, binormal, tangent, light_color_energy.rgb, light_attenuation, albedo, transmission, light_params.z * specular_blob_intensity, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light);
#endif

#endif //#USE_LIGHT_DIRECTIONAL

#ifdef USE_GI_PROBES
	gi_probes_compute(vertex, normal, roughness, env_reflection_light, ambient_light);

	// base color remapping
	diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point
	ambient_light *= 1.0 - metallic;

	if (fog_color_enabled.a > 0.5) {

