!!VP1.0
/*
	Vertex program to generate cubic Bezier curves
	Control points are stored in constants, parameter t is sent per vertex.
	Calculates position on curve for given t.
	Tangent vector is also calculated and used for anisotropic lighting.

	sgreen@nvidia.com 11/2000

	TO DO:
	Local lighting?
	Strip/ribbon version with width
*/

#include "constants.h"

#define T		R0
#define B0		R1
#define B1		R2
#define B2		R3
#define B3		R4

#define TEMP1	R5
#define OMT		R6	// one minus t
#define OMT2	R7	// (1-t)^2
#define T2		R8	// t^2

#define P		R9
#define DP		R10
#define DPE		R11

/*
	Cubic Bernstein blending functions:
	B0(t) = (1-t)^3	
	B1(t) = 3t(1-t)^2
	B2(t) = 3t^2(1-t)
	B3(t) = t^3
*/

MUL	T, v[VT], c[TSCALE];

// evaluate Bernstein blending functions in parallel for t
ADD	OMT, ONE, -T;		// OMT = 1-t
MUL	OMT2, OMT, OMT;		// B1 = (1-t)^2
MUL	B0, OMT2, OMT;		// B0 = (1-t)^2 * (1-t) = (1-t)^3
MUL	TEMP1, THREE, T;	// TEMP2 = 3*t
MUL	B1, OMT2, TEMP1;	// B1 = (1-t)^2 * 3*t
MUL	B2, TEMP1, T;		// B2 = 3*t*t = 3t^2
MUL	B2, B2, OMT;		// B2 = 3t^2 * (1-t)
MUL	T2, T, T;			// B3 = t*t
MUL	B3, T2, T;			// B3 = t*t*t

// calculate vertex position
// P(t) = B0(t)*P0 + B1(t)*P1 + B2(t)*P2 + B3(t)*P3

#if CONST_CVS
MUL	P, c[CV0], B0.x;
MAD	P, c[CV1], B1.x, P;
MAD	P, c[CV2], B2.x, P;
MAD	P, c[CV3], B3.x, P;
#else
MUL	P, v[CV0], B0.x;
MAD	P, v[CV1], B1.x, P;
MAD	P, v[CV2], B2.x, P;
MAD	P, v[CV3], B3.x, P;
#endif

//MOV o[COL0], v[COL0];

// transform vertex to eye space
DP4 o[HPOS].x, c[MVP_MATRIX_X], P;
DP4 o[HPOS].y, c[MVP_MATRIX_Y], P;
DP4 o[HPOS].z, c[MVP_MATRIX_Z], P;
DP4 o[HPOS].w, c[MVP_MATRIX_W], P;


#if 0
/*
	Differentiated basis functions for tangent:
	B'0(t) = -3(1-t)^2
	B'1(t) = 3(1-t)^2 - 6t(1-t)
	B'2(t) = 6t(1-t) - 3t^2
	B'3(t) = 3t^2
*/

MUL	B0, -THREE, OMT2;
MUL TEMP1, SIX, T;
MUL	TEMP1, TEMP1, OMT;		// TEMP1 = 6t(1-t)
ADD	B1, -B0, -TEMP1;
MUL	B3, T2, THREE;
ADD	B2, TEMP1, -B3;

// calculate tangent
// P(t) = B0(t)*P0 + B1(t)*P1 + B2(t)*P2 + B3(t)*P3

#if CONST_CVS
MUL	DP, c[CV0], B0.x;
MAD	DP, c[CV1], B1.x, DP;
MAD	DP, c[CV2], B2.x, DP;
MAD	DP, c[CV3], B3.x, DP;
#else
MUL	DP, v[CV0], B0.x;
MAD	DP, v[CV1], B1.x, DP;
MAD	DP, v[CV2], B2.x, DP;
MAD	DP, v[CV3], B3.x, DP;
#endif

#else

// Use partial difference for tangent
// P'(t) = P(t+1) - P(t)

#if CONST_CVS
MUL	DP, c[CV0], B0.y;
MAD	DP, c[CV1], B1.y, DP;
MAD	DP, c[CV2], B2.y, DP;
MAD	DP, c[CV3], B3.y, DP;
#else
MUL	DP, v[CV0], B0.y;
MAD	DP, v[CV1], B1.y, DP;
MAD	DP, v[CV2], B2.y, DP;
MAD	DP, v[CV3], B3.y, DP;
#endif

ADD	DP, DP, -P;

#endif

// normalize tangent
DP3 DP.w, DP, DP;
RSQ DP.w, DP.w;
MUL DP, DP, DP.w;

// transform tangent to eye space
DP3 DPE.x, c[NORMAL_MATRIX_X], DP;
DP3 DPE.y, c[NORMAL_MATRIX_Y], DP;
DP3 DPE.z, c[NORMAL_MATRIX_Z], DP;

//MOV o[COL0], DPE;

/*
	Banks-style Anisotropic lighting model
	based on L.T, V.T
	diffuse = L.N' = sqrt(1-(L.T)^2)
	specular = V.R = ( (L.T)(V.T) - sqrt(1-(L.T)^2) * sqrt(1-(V.T)^2) ) ^ n
*/

DP3	R2.x, c[LIGHT_POSITION], DPE;	// R2 = L.T
MAD	R1.x, -R2.x, R2.x, ONE;
RSQ	R1.x, R1.x;
RCP	R1.x, R1.x;						// R1.x = sqrt(1-(L.T)^2)

// specular
DP3	R3.x, c[VIEW_DIR_EYE], DPE;		// R3 = V.T
MAD	R4.x, -R3.x, R3.x, ONE;
RSQ	R4.x, R4.x;
RCP	R4.x, R4.x;						// R4 = sqrt(1-(V.T)^2)

MUL	R1.y, R2.x, R3.x;				// R1.y = (L.T)(V.T)
MAD	R1.y, R1.x, R4.x, -R1.y;

MOV R1.w, c[LIGHT_SPECULAR].w;
LIT R1, R1;

// hack - multiply lighting by t to make curves darker at the bottom
//MUL	R1, R1, v[VT].x;

MUL	R0, c[LIGHT_DIFFUSE], R1.y;
ADD o[COL0].xyz, R0, c[GLOBAL_AMBIENT];
//MUL	o[COL0].xyz, c[LIGHT_DIFFUSE], R1.y;

MUL	o[COL1].xyz, c[LIGHT_SPECULAR], R1.z;

END
