﻿#ifndef NOSTALGIA_TILES_STANDARDCORE_INCLUDED
#define NOSTALGIA_TILES_STANDARDCORE_INCLUDED

#include "UnityStandardCore.cginc"
#include "./TileCG.cginc"

struct VertexOutputTilesForwardBase
{
	UNITY_POSITION(pos);
	float4 tex							: TEXCOORD0;
	float3 eyeVec                       : TEXCOORD1;
	float4 tangentToWorldAndPackedData[3]	: TEXCOORD2;    // [3x3:tangentToWorld | 1x3:viewDirForParallax or worldPos]
	half4 ambientOrLightmapUV             : TEXCOORD5;    // SH or Lightmap UV
	UNITY_LIGHTING_COORDS(6, 7)

	// next ones would not fit into SM2.0 limits, but they are always for SM3.0+
	#if UNITY_REQUIRE_FRAG_WORLDPOS && !UNITY_PACK_WORLDPOS_WITH_TANGENT
        float3 posWorld                 : TEXCOORD8;
    #endif

	float4 color						: COLOR0;

	UNITY_VERTEX_OUTPUT_STEREO
};

float4 TexCoordTiles(appdata_full v)
{
	return float4(AnimateUV(v.texcoord.xy, v.texcoord1), 0, 0);
}

inline half4 VertexGIForwardTiles(float3 posWorld, half3 normalWorld)
{
	half4 ambientOrLightmapUV = 0;

	// Static lightmaps
	#if UNITY_SHOULD_SAMPLE_SH
		#ifdef VERTEXLIGHT_ON
			// Approximated illumination from non-important point lights
			ambientOrLightmapUV.rgb = Shade4PointLights (
				unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
				unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
				unity_4LightAtten0, posWorld, normalWorld);
		#endif
		ambientOrLightmapUV.rgb = ShadeSHPerVertex (normalWorld, ambientOrLightmapUV.rgb);		
	#endif

	return ambientOrLightmapUV;
}

VertexOutputTilesForwardBase vertTilesForwardBase(appdata_full v)
{
	VertexOutputTilesForwardBase o;
	UNITY_INITIALIZE_OUTPUT(VertexOutputTilesForwardBase, o);

	float4 posWorld = ObjectToWorld(v.vertex);

	#if UNITY_REQUIRE_FRAG_WORLDPOS
        #if UNITY_PACK_WORLDPOS_WITH_TANGENT
            o.tangentToWorldAndPackedData[0].w = posWorld.x;
            o.tangentToWorldAndPackedData[1].w = posWorld.y;
            o.tangentToWorldAndPackedData[2].w = posWorld.z;
        #else
            o.posWorld = posWorld.xyz;
        #endif
    #endif

	float4 pos = UnityObjectToClipPos(v.vertex);

	#if defined(PIXELSNAP_ON)
		pos = UnityPixelSnap(pos);
	#endif
	o.pos = pos;
	o.tex = TexCoordTiles(v);

	o.eyeVec.xyz = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
	float3 normalWorld = UnityObjectToWorldNormal(v.normal);
	#ifdef _TANGENT_TO_WORLD
		float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);

		float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
		o.tangentToWorldAndPackedData[0].xyz = tangentToWorld[0];
		o.tangentToWorldAndPackedData[1].xyz = tangentToWorld[1];
		o.tangentToWorldAndPackedData[2].xyz = tangentToWorld[2];
	#else
		o.tangentToWorldAndPackedData[0].xyz = 0;
		o.tangentToWorldAndPackedData[1].xyz = 0;
		o.tangentToWorldAndPackedData[2].xyz = normalWorld;
	#endif

	//We need this for shadow receving
	TRANSFER_VERTEX_TO_FRAGMENT(o);

	o.ambientOrLightmapUV = VertexGIForwardTiles(posWorld, normalWorld);

	o.color = v.color;

	return o;
}

half4 fragTilesForwardBase(VertexOutputTilesForwardBase i) : SV_Target
{
	FRAGMENT_SETUP(s);

	UnityLight mainLight = MainLight();

	UNITY_LIGHT_ATTENUATION(atten, i, s.posWorld);

	half occlusion = Occlusion(i.tex.xy);
	UnityGI gi = FragmentGI(s, occlusion, i.ambientOrLightmapUV, atten, mainLight);

	half4 c = UNITY_BRDF_PBS(s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect) * i.color;
	c.rgb += Emission(i.tex.xy);
	return OutputForward(c, s.alpha);
}

struct VertexOutputTilesForwardAdd
{
	UNITY_POSITION(pos);
	float4 tex							: TEXCOORD0;
	float3 eyeVec                       : TEXCOORD1;
	float4 tangentToWorldAndLightDir[3]	: TEXCOORD2;	// [3x3:tangentToWorld | 1x3:lightDir]
	float3 posWorld						: TEXCOORD5;
	UNITY_LIGHTING_COORDS(6, 7)

	float4 color						: COLOR0;

	UNITY_VERTEX_OUTPUT_STEREO
};

VertexOutputTilesForwardAdd vertTilesForwardAdd(appdata_full v)
{
	VertexOutputTilesForwardAdd o;
	UNITY_INITIALIZE_OUTPUT(VertexOutputTilesForwardAdd, o);
	UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

	float4 posWorld = ObjectToWorld(v.vertex);
	o.pos = ObjectToClipPos(v.vertex);

	o.tex = TexCoordTiles(v);
	o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
	o.posWorld = posWorld.xyz;
	float3 normalWorld = UnityObjectToWorldNormal(v.normal);
	#ifdef _TANGENT_TO_WORLD
		float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);

		float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
		o.tangentToWorldAndLightDir[0].xyz = tangentToWorld[0];
		o.tangentToWorldAndLightDir[1].xyz = tangentToWorld[1];
		o.tangentToWorldAndLightDir[2].xyz = tangentToWorld[2];
	#else
		o.tangentToWorldAndLightDir[0].xyz = 0;
		o.tangentToWorldAndLightDir[1].xyz = 0;
		o.tangentToWorldAndLightDir[2].xyz = normalWorld;
	#endif

	//We need this for shadow receiving
	TRANSFER_VERTEX_TO_FRAGMENT(o);

	float3 lightDir = _WorldSpaceLightPos0.xyz - posWorld.xyz * _WorldSpaceLightPos0.w;
	#ifndef USING_DIRECTIONAL_LIGHT
		lightDir = NormalizePerVertexNormal(lightDir);
	#endif
	o.tangentToWorldAndLightDir[0].w = lightDir.x;
	o.tangentToWorldAndLightDir[1].w = lightDir.y;
	o.tangentToWorldAndLightDir[2].w = lightDir.z;

	o.color = v.color;

	return o;
}

half4 fragTilesForwardAdd(VertexOutputTilesForwardAdd i) : SV_Target		// backward compatibility (this used to be the fragment entry function)
{
	FRAGMENT_SETUP_FWDADD(s)

	UNITY_LIGHT_ATTENUATION(atten, i, s.posWorld)
	UnityLight light = AdditiveLight (IN_LIGHTDIR_FWDADD(i), atten);
	UnityIndirect noIndirect = ZeroIndirect();

	half4 c = UNITY_BRDF_PBS(s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, light, noIndirect);
	c *= i.color;

	return OutputForward(c, s.alpha);
}

#endif // NOSTALGIA_TILES_STANDARDCORE_INCLUDED
