//
// Asura_D3D_VS_Skin_Order2SH_NormalMapped.cpp
//
// Created by KJFL - 2004-07-26
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

// This file's header.
#include "Rendering/Asura_Direct3D_Shaders.h"

static Direct3D_VertexElement g_axCharacter_Vertex_Decl[] = 
{
	{0,  0,  D3DDECLTYPE_FLOAT3,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,		0},
	{0,  12, D3DDECLTYPE_FLOAT3,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,			0},
	{0,  24, D3DDECLTYPE_FLOAT2,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,		0},
	{0,  32, D3DDECLTYPE_FLOAT4,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,	0},
	{0,	 48, D3DDECLTYPE_FLOAT4,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,	0},
	{0,	 64, D3DDECLTYPE_FLOAT3,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,		0},
	{0,	 76, D3DDECLTYPE_FLOAT3,	D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,		0},

	D3DDECL_END()
};


static char* g_szVertexShader =
{
	"vs.2.0 \n"

	"dcl_position		v0 \n"
	"dcl_normal			v1 \n"
	"dcl_texcoord		v2 \n"
	"dcl_blendindices	v3 \n"
	"dcl_blendweight	v4 \n"
	"dcl_tangent		v5 \n"
	"dcl_binormal		v6 \n"
	
	// get index of first bone					
	"mova a0.x, v3.x \n"
	// rotate and translate the vertex by the first bone's transform
	"dp4 r1.x, c[a0.x+12], v0 \n"
	"dp4 r1.y, c[a0.x+13], v0 \n"
	"dp4 r1.z, c[a0.x+14], v0 \n"
	// scale the result by the weighting
	"mul r1.xyz, r1, v4.x \n"

	// now rotate the normal by the first bone (ignore translation)
	"dp3 r3.x, c[a0.x+12], v1 \n"
	"dp3 r3.y, c[a0.x+13], v1 \n"
	"dp3 r3.z, c[a0.x+14], v1 \n"
	// set r3.w to 1.0f to allow for dp4 processing
	"mov r3.w, v0.w	\n"
				
	// now rotate the tangent by the first bone (ignore translation)
	"dp3 r4.x, c[a0.x+12], v5 \n"
	"dp3 r4.y, c[a0.x+13], v5 \n"
	"dp3 r4.z, c[a0.x+14], v5 \n"
	// set r4.w to 1.0f to allow for dp4 processing
	"mov r4.w, v0.w	\n"
				

	// now rotate the binormal by the first bone (ignore translation)
	"dp3 r5.x, c[a0.x+12], v6 \n"
	"dp3 r5.y, c[a0.x+13], v6 \n"
	"dp3 r5.z, c[a0.x+14], v6 \n"
	// set r5.w to 1.0f to allow for dp4 processing
	"mov r5.w, v0.w	\n"
				


	// rotate and translate the vertex by the second bone's transform,
	// then accumulate result taking weighting into account
	"mova a0.x, v3.y \n"
	"dp4 r2.x, c[a0.x+12], v0 \n"
	"dp4 r2.y, c[a0.x+13], v0 \n"
	"dp4 r2.z, c[a0.x+14], v0 \n"
	"mad r1.xyz, r2, v4.y, r1 \n"
												
	// rotate and translate the vertex by the third bone's transform,
	// then accumulate result taking weighting into account
	"mova a0.x, v3.z \n"
	"dp4 r2.x, c[a0.x+12], v0 \n"
	"dp4 r2.y, c[a0.x+13], v0 \n"
	"dp4 r2.z, c[a0.x+14], v0 \n"
	"mad r1.xyz, r2, v4.z, r1 \n"
												
	// rotate and translate the vertex by the forth bone's transform,
	// then accumulate result taking weighting into account
	"mova a0.x, v3.w \n"
	"dp4 r2.x, c[a0.x+12], v0 \n"
	"dp4 r2.y, c[a0.x+13], v0 \n"
	"dp4 r2.z, c[a0.x+14], v0 \n"
	"mad r1.xyz, r2, v4.w, r1 \n"

	// touch up r1.w so it's 1.0f
	"mov r1.w, v0.w \n"

	// calculate the camera vector (i.e. from vertex to camera)
	"add r6, -r1, c[8] \n"

	// Rotate camera vector into the space described by our normal, binormal, and tangent
	"dp3 r7.x, r4, r6 \n" // Tangent
	"dp3 r7.y, r5, r6 \n" // Binormal
	"dp3 r7.z, r3, r6 \n" // Normal

	// normalise it
	"dp3 r6.x, r7.xyz, r7.xyz \n"
	"rsq r6.xyz, r6.x \n"
	"mul r7, r7.xyz, r6.xyz \n"

	// Stuff in first output texture coord register
	"mov oT0.xyz, r7.xyz \n"

	// Rotate light vector into the space described by our normal, binormal, and tangent
	"dp3 r7.x, r4, c[9] \n" // Tangent
	"dp3 r7.y, r5, c[9] \n" // Binormal
	"dp3 r7.z, r3, c[9] \n" // Normal

	// normalise it
	"dp3 r6.x, r7.xyz, r7.xyz \n"
	"rsq r6.xyz, r6.x \n"
	"mul r7, r7.xyz, r6.xyz \n"

	// Stuff in second output texture coord register
	"mov oT1.xyz, r7.xyz \n"

	// Rotate spherical harmonic into tangent space
	// Red
	"dp3 oT3.x, r4, c[4] \n" // Tangent
	"dp3 oT3.y, r5, c[4] \n" // Binormal
	"dp3 oT3.z, r3, c[4] \n" // Normal
	"mov oT3.w, c[4].w \n"
	// Green
	"dp3 oT4.x, r4, c[5] \n" // Tangent
	"dp3 oT4.y, r5, c[5] \n" // Binormal
	"dp3 oT4.z, r3, c[5] \n" // Normal
	"mov oT4.w, c[5].w \n"
	// Blue
	"dp3 oT5.x, r4, c[6] \n" // Tangent
	"dp3 oT5.y, r5, c[6] \n" // Binormal
	"dp3 oT5.z, r3, c[6] \n" // Normal
	"mov oT5.w, c[6].w \n"

	// output uv co-ords				
	//"mov oT0.xy, v2 \n"
	"mov oT2.xy, v2 \n"
	//"mov oT1.xy, v2 \n"

	// fog
	//"mov oFog, c[7].y \n"
	"mov oFog, c[7].y \n"

    // Transform to screen space and write to output position register.
    //"m4x4 oPos, r1, c0 \n"
    "m4x4 oPos, r1, c0 \n"
};

static Asura_Direct3D_VertexShader xShader( ASURA_D3D_VS_SKIN_ORDER2SH_4BONES_NORMALMAPPED, g_szVertexShader, g_axCharacter_Vertex_Decl, 3.0f);
