!!ARBvp1.0
# Vertex Program for lit, skinned avatars

# Parameters
#PARAM gGravity			= program.env[62];

PARAM gMat[45]			= { program.env[0..44] };
PARAM gWindDir			= program.env[60];								# wind direction with strength stored in w
PARAM gSinWaveParams	= program.env[61];								# frequency, frequency2, frequency, phase
PARAM gMinMaxConstants	= {1.0, 0.166666, 0.0083143, .00018542};	#minimax-generated coefficients
PARAM gPiConstants		= {0.159154943, 6.28318530, 3.141592653, 1.5707963};	# {1/2PI, 2PI, PI, PI/2}
PARAM gProjection[4]	= { state.matrix.projection };		
PARAM gModelAmbient		= state.lightmodel.ambient;
PARAM gMaterialDiffuse	= state.material.diffuse;
PARAM gLightDir0		= state.light[0].position;
PARAM gDiffuseCol0		= state.light[0].diffuse;
PARAM gLightDir1		= state.light[1].position;
PARAM gDiffuseCol1		= state.light[1].diffuse;
PARAM gLightPos2		= state.light[2].position;
PARAM gDiffuseCol2		= state.light[2].diffuse;
PARAM gLightPos3		= state.light[3].position;
PARAM gDiffuseCol3		= state.light[3].diffuse;

# Per vertex inputs
ATTRIB iPos			= vertex.position;
ATTRIB iNormal      = vertex.normal;
ATTRIB iTex0		= vertex.texcoord;
ATTRIB iWeight		= vertex.attrib[1];
ATTRIB iClothing	= vertex.attrib[4];

# Temporaries
TEMP blendedPos;													# weighted sum of tpos0 and tpos1
TEMP blendNorm;													# weighted sum of eyeNormal0 and eyeNormal1
TEMP temp0;															
TEMP temp1;															# another general purpose temp
TEMP temp2;
TEMP windEffect;													# amount of displacement from wind
TEMP blendMatX;
TEMP blendMatY;
TEMP blendMatZ;

ALIAS colorAcc		= temp0;
ALIAS sinWave		= temp0;
ALIAS offsetPos		= temp1;
ALIAS dots			= temp1;										# dot product for lighting calculations
ALIAS posDelta		= windEffect;									# movement of vertex according to joint angle
ALIAS pivot_pos		= windEffect;
ALIAS scaledWeight	= temp0;
ALIAS divisor		= temp2;
ALIAS lightDir		= windEffect;

ADDRESS address;

# Outputs
OUTPUT oPos			= result.position;								# position
OUTPUT oCol0		= result.color;									# primary color
OUTPUT oTex0		= result.texcoord;								# texture coordinate set 0
OUTPUT oFog			= result.fogcoord;								# output fog coordinates

#fix input blending weight
ARL address.x, iWeight.x;
FRC scaledWeight.x, iWeight;

# Blend joint matrices
MUL blendMatX, gMat[address.x + 1], {1,1,1,1};
SUB blendMatX, blendMatX, gMat[address.x + 0];
MAD blendMatX, scaledWeight.x, blendMatX, gMat[address.x + 0];
DP3 blendNorm.x, blendMatX, iNormal;

MUL blendMatY, gMat[address.x + 16], {1,1,1,1};
SUB blendMatY, blendMatY, gMat[address.x + 15];
MAD blendMatY, scaledWeight.x, blendMatY, gMat[address.x + 15];
DP3 blendNorm.y, blendMatY, iNormal;

MUL blendMatZ, gMat[address.x + 31], {1,1,1,1};
SUB blendMatZ, blendMatZ, gMat[address.x + 30];
MAD blendMatZ, scaledWeight.x, blendMatZ, gMat[address.x + 30];
DP3 blendNorm.z, blendMatZ, iNormal;

#wind
DP3 windEffect, blendNorm, gWindDir;
MAD windEffect.xyz, windEffect, gSinWaveParams, gSinWaveParams.w;		# use sin wave params to scale and offset input

#reduce to period of 2 PI
MUL    temp1.xyz, windEffect, gPiConstants.x;						# change input as multiple of [0-2PI] to [0-1]
EXP    temp0, temp1.x;												# find mod(x, 1)
MUL    windEffect.x, temp0.y, gPiConstants.y;						# scale from [0,1] to [0, 2PI]

# offset to [-PI, PI]
ADD    windEffect.xyz, windEffect, {-3.141592, -3.141592, -3.141592, -3.141592};

#calculate sinusoid
MUL    temp1,    windEffect, windEffect;							# x^2
MAD    sinWave, -temp1, gMinMaxConstants.w, gMinMaxConstants.z;		# y = -(x^2)/7! + 1/5!
MAD    sinWave, sinWave, -temp1, gMinMaxConstants.y;					# y = -(x^2) * (-(x^2)/7! + 1/5!) + 1/3!
MAD    sinWave, sinWave, -temp1, gMinMaxConstants.x;					# y = -(x^2) * (-(x^2) * (-(x^2)/7! + 1/5!) + 1/3!) + 1
MUL    sinWave, sinWave, windEffect;								# y = x * (-(x^2) * (-(x^2) * (-(x^2)/7! + 1/5!) + 1/3!) + 1)

# sinWave.x holds sin(norm . wind_direction)+
MUL sinWave.xyz, sinWave, gWindDir.w;								# multiply by wind strength in gWindDir.w [-wind, wind]
SUB sinWave.xyz, sinWave, {0.2, 0.2, 0.2, 0.2};
MUL sinWave.xyz, sinWave, iClothing.w;								# modulate by clothing coverage

DP3 temp2.x, iClothing, iClothing;
MAX temp2.x, temp2, {0, 0, 0, 0.2};
MUL temp2.x, temp2.x, {3, 0, 0, 0};
MUL sinWave.x, sinWave, temp2;

#add pseudo-specular effect
ADD blendNorm, blendNorm, {0, 0, -0.5, 0};

#renormalize normal
DP3 divisor.w, blendNorm, blendNorm;
RSQ divisor.xyz, divisor.w;
MUL blendNorm.xyz, blendNorm, divisor;

#Output position
DP4 blendedPos.x, blendMatX, iPos;
DP4 blendedPos.y, blendMatY, iPos;
DP4 blendedPos.z, blendMatZ, iPos;

MUL offsetPos, gWindDir, sinWave.x;									# multiply wind effect times clothing displacement
MAD blendedPos, {-1.0, -1.0, -1.0, 0.0}, offsetPos, blendedPos;				# add to offset vertex position, and zero out effect from w

MOV blendedPos.w, {0, 0, 0, 1};

#Projection
DP4 oPos.x, gProjection[0], blendedPos;									# projection matrix
DP4 oPos.y, gProjection[1], blendedPos;
DP4 oPos.z, gProjection[2], blendedPos;
DP4 oPos.w, gProjection[3], blendedPos;

#Light 0
DP3 dots.x, blendNorm, gLightDir0;
MAD dots.x, dots.x, {0.55, 0.55, 0.55, 0.55}, {0.3, 0.3, 0.3, 0.3};
MAX dots, dots, {0, 0, 0, 0};

# Accumulate color contributions.
MAD temp2, dots.x, gDiffuseCol0, gModelAmbient;
MOV colorAcc.xyz, temp2;

#Light 1
DP3 dots.x, blendNorm, gLightDir1;

#Light 2
SUB lightDir, gLightPos2, blendedPos;
DP3 divisor.w, lightDir, lightDir;
RSQ divisor.xyz, divisor.w;
MUL lightDir.xyz, lightDir, divisor;

DP3 dots.y, blendNorm, lightDir;

#Light 3
SUB lightDir, gLightPos3, blendedPos;
DP3 divisor.w, lightDir, lightDir;
RSQ divisor.xyz, divisor.w;
MUL lightDir.xyz, lightDir, divisor;

DP3 dots.z, blendNorm, lightDir;

#Apply lights
MAD dots, dots, {0.55, 0.55, 0.55, 0.55}, {0.3, 0.3, 0.3, 0.3};
MAX dots, dots, {0, 0, 0, 0};
MAD colorAcc.xyz, dots.x, gDiffuseCol1, colorAcc;
MAD colorAcc.xyz, dots.y, gDiffuseCol2, colorAcc;
MAD colorAcc.xyz, dots.z, gDiffuseCol3, colorAcc;

#Output fog
# This causes issues on ATI when fog is disabled
MOV oFog.x, blendedPos.z;

#Output color
MOV colorAcc.w, {0, 0, 0, 1.0};
MUL oCol0, gMaterialDiffuse, colorAcc;

#Output tex coordinate
MOV oTex0, iTex0;

END