/*
	Shader for transforming a vertex into clip space and lighting it.
	Blending between trwo weights.
	This is explained in more detail on the web page
*/

/*
CONSTANT AREA MAP

C00 = 4.0f, 22.0f, 1.0f, IndexOffset
c01 = free
c02 = light 0: position 
c03 = light 0: attenuation
c04 = light 0: color
c05 = light 1: position 
c06 = light 1: attenuation
c07 = light 1: color
c08 = light 2: position 
c09 = light 2: attenuation
c10 = light 2: color
c11 = light 3: position 
c12 = light 3: attenuation
c13 = light 3: color

c14 - c17 = world transformation matrix
c18 - c21 = (View x Projection) matrix

c22 - c96 = plane matrices
*/

; normalizes a vector
; puts d*d in VectorToNormalize.w
; puts d in Result.w
; normalized vector in Result.xyz

#define NORMALIZE(Result, VectorToNormalize)													\
dp3	VectorToNormalize.w, VectorToNormalize, VectorToNormalize	; d*d = (x*x) + (y*y) + (z*z)	\
rsq	Result.w, VectorToNormalize.w								; d = squareroot(d*d)			\
mul	Result.xyz,	VectorToNormalize.xyz, Result.w					; x/d, y/d, z/d



#define V_POSITION		v0
#define V_WEIGHT		v1
#define V_INDICES		v2
#define V_NORMAL		v3
#define V_TEXTURE		v7

#define POS_WORLD		r9
#define	CV_ZERO	c1.xxxx

#define CV_EACH_BONEMAT_HEIGHT		c0.x
#define CV_BONE_MAT_START_INDEX		c0.y
#define CV_BONE_OFFSET				c0.w


#include ".\\Source\\PlaneBlendVS.h"

vs.1.1							; Shader version 1.1


add	r0,			V_INDICES, -CV_BONE_OFFSET							; get the effective index of influence into the matrix array
mad	r0,			r0, CV_EACH_BONEMAT_HEIGHT, CV_BONE_MAT_START_INDEX	; multiply index by 4 and add by 22
max	r0,			r0, CV_ZERO									; don't let the index go negative

; multiply the bone matrix with the input vertex co-ordinates

; first influence
mov	a0.x,		r0.x
dp4	r4.x,		V_POSITION, c[a0.x]			; vector1.x -- Calculate X of first influence
dp4	r4.y,		V_POSITION, c[a0.x+1]		; vector1.y -- Calculate Y of first influence
dp4	r4.z,		V_POSITION, c[a0.x+2]		; vector1.z -- Calculate Z of first influence

; blend normals also
dp4	r10.x,		V_NORMAL, c[a0.x]			; vector1.x -- Calculate X of first influence
dp4	r10.y,		V_NORMAL, c[a0.x+1]			; vector1.y -- Calculate Y of first influence
dp4	r10.z,		V_NORMAL, c[a0.x+2]			; vector1.z -- Calculate Z of first influence


; second influence
mov	a0.x,		r0.y
dp4	r5.x,		V_POSITION, c[a0.x]			; vector2.x -- Calculate X of second influence
dp4	r5.y,		V_POSITION, c[a0.x+1]		; vector2.y -- Calculate Y of second influence
dp4	r5.z,		V_POSITION, c[a0.x+2]		; vector2.z -- Calculate Z of second influence

; blend normals also
dp4	r11.x,		V_NORMAL, c[a0.x]			; vector1.x -- Calculate X of first influence
dp4	r11.y,		V_NORMAL, c[a0.x+1]			; vector1.y -- Calculate Y of first influence
dp4	r11.z,		V_NORMAL, c[a0.x+2]			; vector1.z -- Calculate Z of first influence


; start blending. vectorize multiplications
mul	r8.xyz,		V_WEIGHT.x, r4.xyz
mad	r8.xyz,		V_WEIGHT.y, r5.xyz, r8.xyz


; blending normals. vectorize multiplications
mul	r1.xyz,		V_WEIGHT.x, r10.xyz
mad	r1.xyz,		V_WEIGHT.y, r11.xyz, r1.xyz


; 1.0f out of thin air
sge	r8.w,		c0, c0				; result.w = 1.0f


; r8 now has the final blended vertex position

; multiply by world transformation matrix
dp4	POS_WORLD.x,		r8, c[CV_WORLD_0]			; Final world position.x
dp4	POS_WORLD.y,		r8, c[CV_WORLD_1]			; Final world position.y
dp4	POS_WORLD.z,		r8, c[CV_WORLD_2]			; Final world position.z
dp4	POS_WORLD.w,		r8, c[CV_WORLD_3]			; Final world position.w

; multiply by (ViewxProjection) matrix
dp4	oPos.x,		POS_WORLD, c[CV_VIEWPROJ_0]		; position in clip space .x
dp4	oPos.y,		POS_WORLD, c[CV_VIEWPROJ_1]		; position in clip space .y
dp4	oPos.z,		POS_WORLD, c[CV_VIEWPROJ_2]		; position in clip space .z
dp4	oPos.w,		POS_WORLD, c[CV_VIEWPROJ_3]		; position in clip space .w

; r9 has the final world position of the vertex


; start manipulating the blended normal
; r1 has the blended normal

; multiply the normal with the world rotation matrix of the plane.
dp3	r0.x,		r1, c[CV_WORLD_0]			; Multiply normal with the world rotation matrix
dp3	r0.y,		r1, c[CV_WORLD_1]			; 
dp3	r0.z,		r1, c[CV_WORLD_2]			; 

; normalize the vertex normal
NORMALIZE(r0,r0)


; Light calculations

; calculate the L vector, the direction vector from world vertex position to --
; -- world light position for each light.


; r0 has the final transformed vertex normal

add	r10.xyz,	c[CV_LIGHT0_POSITION], -POS_WORLD.xyz		; Calculate world_light_position to world_vertex_position vector
NORMALIZE(r11,r10)									; normalize this vector
dp3	r6.x,		r11, r0								; N.L 
dst	r4,			r10.w, r11.w						; (1, d, d*d, 1/d)
dp3	r5.x,		r4, c[CV_LIGHT0_ATT]				; (a0 + a1*d + a2*d*d)
rcp	r5.x,		r5.x								; 1 / (a0 + a1*d + a2*d*d)


add	r10.xyz,	c[CV_LIGHT1_POSITION], -POS_WORLD.xyz		; Calculate world_light_position to world_vertex_position vector
NORMALIZE(r11,r10)									; normalize this vector
dp3	r6.y,		r11, r0								; N.L 
dst	r4,			r10.w, r11.w						; (1, d, d*d, 1/d)
dp3	r5.y,		r4, c[CV_LIGHT1_ATT]				; (a0 + a1*d + a2*d*d)
rcp	r5.y,		r5.y								; 1 / (a0 + a1*d + a2*d*d)


; vectorize light calculations
max	r6,			r6.xy, CV_ZERO							; max(N.L, 0.0f)
mul	r7,			r6, r5.xy								; factor = max(N.L, 0.0f) * attenuation
mul	r8.xyz,		c[CV_LIGHT0_COLOR].xyz, r7.x			; vertex_color = light_color0 * factor0
mad	oD0.xyz,	c[CV_LIGHT1_COLOR].xyz, r7.y, r8.xyz	; vertex_color = light_color1 * factor1


mov	oT0.xy ,	V_TEXTURE							; copy texture coordinates

