#pragma tdm_define "LEGACY_BITANGENTS"

#ifdef VERTEX_SHADER

#ifdef LEGACY_BITANGENTS

out mat3 var_TangentBitangentNormalMatrix; 
out vec3 var_LightDirLocal;  
out vec3 var_ViewDirLocal;  

void sendTBN() {
	// construct tangent-bitangent-normal 3x3 matrix   
	var_TangentBitangentNormalMatrix = mat3( clamp(attr_Tangent,-1,1), clamp(attr_Bitangent,-1,1), clamp(attr_Normal,-1,1) );
	var_LightDirLocal = (u_lightOrigin.xyz - var_Position).xyz * var_TangentBitangentNormalMatrix;
	var_ViewDirLocal = (u_viewOrigin.xyz - var_Position).xyz * var_TangentBitangentNormalMatrix;
}

#else

out vec3 var_Normal;  

void sendTBN() {
    var_Normal = attr_Normal;
}

#endif

#else

#ifdef LEGACY_BITANGENTS

in mat3 var_TangentBitangentNormalMatrix; 
in vec3 var_LightDirLocal;  
in vec3 var_ViewDirLocal;

void calcNormals() {
    // compute normal from normal map, move from [0, 1] to [-1, 1] range, normalize 
	if (u_hasTextureDNS[1] != 0) {
/*		vec4 bumpTexel = texture (u_normalTexture, var_TexNormal.st) * 2. - 1.;
		RawN = u_RGTC == 1.0
			? vec3(bumpTexel.x, bumpTexel.y, sqrt(max(1. - bumpTexel.x*bumpTexel.x - bumpTexel.y*bumpTexel.y, 0)))
			: normalize(bumpTexel.wyz);
		N = var_TangentBitangentNormalMatrix * RawN;*/
		vec4 bumpTexel = texture ( u_normalTexture, var_TexNormal.st ) * 2. - 1.;
    	RawN = u_RGTC == 1. 
	    	? vec3(bumpTexel.x, bumpTexel.y, sqrt(max(1.-bumpTexel.x*bumpTexel.x-bumpTexel.y*bumpTexel.y, 0)))
		    : normalize( bumpTexel.wyz ); 
    	N = var_TangentBitangentNormalMatrix * RawN; 
	}
	else {
		RawN = vec3(0, 0, 1);
		N = var_TangentBitangentNormalMatrix[2];
	}
}

#else

in vec3 var_Normal;  
vec3 var_LightDirLocal;  
vec3 var_ViewDirLocal;  
mat3 var_TangentBitangentNormalMatrix;

mat3 cotangent_frame( vec3 N, vec3 p, vec2 uv ) {
	/* get edge vectors of the pixel triangle */
	vec3 dp1 = dFdx( p );
	vec3 dp2 = dFdy( p );
	vec2 duv1 = dFdx( uv );
	vec2 duv2 = dFdy( uv );

	/* solve the linear system */
	vec3 dp2perp = cross( dp2, N );
	vec3 dp1perp = cross( N, dp1 );
	vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
	vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;

	/* construct a scale-invariant frame */
	float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
	return mat3( T * invmax, B * invmax, N );
}

vec3 perturb_normal( vec3 N, vec3 V, vec2 texcoord ) {
	/* assume N, the interpolated vertex normal and V, the view vector (vertex to eye) */
	RawN = texture( u_normalTexture, texcoord ).wyz;
	// WITH_NORMALMAP_UNSIGNED
	RawN = RawN * 2 - 1;
	// WITH_NORMALMAP_2CHANNEL
	// map.z = sqrt( 1. - dot( map.xy, map.xy ) );
	// WITH_NORMALMAP_GREEN_UP
	// map.y = -map.y;
	mat3 TBN = cotangent_frame( N, -V, texcoord );
	if (u_advanced == 1.0) {
		var_LightDirLocal = (u_lightOrigin.xyz - var_Position).xyz * TBN;
		var_ViewDirLocal = (u_viewOrigin.xyz - var_Position).xyz * TBN;	
	}
	return normalize( TBN * RawN );
}

void calcNormals() {
	if (u_hasTextureDNS[1] != 0) 
		N = perturb_normal( normalize( var_Normal ), V, var_TexNormal.st );
	else
		N = var_TangentBitangentNormalMatrix[2] = var_Normal;
}

#endif

#endif