!!ARBvp1.0

#textures:
#texture[0], 2D		- normal map with water noise normals
#texture[1], 2D		- reflection texture from pass 1
#texture[2], 2D		- foam texture (fixme, not yet)
#texture[3], 2D		- amount of foam (fixme, not yet)

ATTRIB inputpos = vertex.position;		# object space
ATTRIB normalraw = vertex.normal; 		# object space

PARAM mvp[4] = { state.matrix.mvp };
PARAM mvinv[4] = { state.matrix.modelview.inverse };
PARAM mvinvcol3 = state.matrix.modelview.invtrans.row[3];
PARAM lightpos = state.light[0].position;	# world space
PARAM viewpos = program.local[0];		# needed for computation of foam projection coordinates.
PARAM upwelltop = program.local[1];		# upwelling color, top of waves
PARAM upwellbot = program.local[2];		# upwelling color, bottom of waves
PARAM upwelltopbot = program.local[3];		# upwelling color, difference top - bottom

PARAM yaxis = { 0, 1, 0, 1 };

PARAM virtualplaneheight = { 12.0, 0, 0, 0 };	# for mirror distorsion, depends on height of waves...?

PARAM texmatnoise[4] = { state.matrix.texture[0] };	# fixme check that c++ program use the same matrix
PARAM texmatrefl[4] = { state.matrix.texture[1] };	# fixme check that c++ program use the same matrix

OUTPUT outputpos = result.position;		# world space
OUTPUT noisetexcout = result.texcoord[0];	# only x,y used
OUTPUT reflectiontexc = result.texcoord[1];	# only x,y,w used
OUTPUT viewerdirout = result.texcoord[2];	# only x,y,z used
OUTPUT halfangleout = result.texcoord[3];	# only x,y,z used
OUTPUT outputcolor = result.color;
# we also need special (modified) reflectiontexc for the foam (x,y,w). These values are coded in
# noisetexcout.zw and reflectiontexc.z

# for foam we need texture coordinates for the foam and the amount of foam map.
# foam is mapped similar to normal map, and amount similar to reflection.
# so we can use the same coordinates!

TEMP	tangentx;
TEMP	tangenty;
TEMP	normal;
TEMP	viewerdir;
TEMP	tmp;


#fixme: the normals of the water quads seem to be strange, i.e.
#the tangent space doesn't change smoothly over the faces.
#can be seen with constant noise normal e.g. (0,0,1)



# 1. normalize normal
DP3	normal.w, normalraw, normalraw;
RSQ	normal.w, normal.w;
MUL	normal, normal.w, normalraw;


# 1.1. compute upwelling color (slope dependent)
#float colorfac = (coord.z + viewpos.z + 3) / 9 + (N.z - 0.8f);
#that is (inputpos.z + viewpos.z + 3) / 9 + (normal.z - 0.8);
# or (inputpos.z + viewpos.z) / 9 + normal.z + 1/3 - 0.8
# or (inputpos.z + viewpos.z) * 1/9 + normal.z - 7/15
# 1/9 = 0.1111111 , 7/15 = 0.466667
#set output color as mix
ADD	tmp.x, viewpos.z, inputpos.z;
ADD	tmp.y, normal.z, -0.4666667;
MAD	tmp.w, tmp.x, 0.1111111, tmp.y;
MAX	tmp.w, tmp.w, 0;
MIN	tmp.w, tmp.w, 1;
# now interpolate between upwelltop and upwellbot with tmp.x (tmp.x=1 -> upwelltop full)
MAD	outputcolor, tmp.w, upwelltopbot, upwellbot;


# 2. compute tangentx = (0,1,0).cross(normal), because v coordinate
#    increases with vertex y coordinate => tangentx is (nz, 0, -nx)
XPD	tmp, yaxis, normal;
DP3	tmp.w, tmp, tmp;
RSQ	tmp.w, tmp.w;
MUL	tangentx.xyz, tmp.w, tmp;


# 3. compute tangenty
XPD	tangenty, normal, tangentx;


# 4. compute direction to viewer (E)
# 4.1. compute in object space (mvinv*(0,0,0,1) - inputpos) and normalize it
SUB	tmp, mvinvcol3, inputpos;
DP3	tmp.w, tmp, tmp;
RSQ	tmp.w, tmp.w;
MUL	viewerdir.xyz, tmp.w, tmp;

# 4.2. transform viewerdir to tangent space
DP3	viewerdirout.x, tangentx, viewerdir;
DP3	viewerdirout.y, tangenty, viewerdir;
DP3	viewerdirout.z, normal, viewerdir;


# 5. transform vertex to projection space (clip coordinates)
DP4	outputpos.x, mvp[0], inputpos;
DP4	outputpos.y, mvp[1], inputpos;
DP4	outputpos.z, mvp[2], inputpos;
DP4	outputpos.w, mvp[3], inputpos;


# 6. compute halfangle between direction to viewer and direction to light
# 6.1. transform light pos to object space. we assume mvinv has no projection coefficients.
#fixme: light is directional, so why use DP4, not DP3???
#doesn't matter because: lightpos.w is zero (directional light!!!)
DP4	tmp.x, mvinv[0], lightpos;
DP4	tmp.y, mvinv[1], lightpos;
DP4	tmp.z, mvinv[2], lightpos;

# 6.2. normalize it, add L+E to H and normalize
# we assume light is always directional (sun!), so lightpos.normal is the same as lightdir!
#fixme: normalization can be done once in the main program
DP3	tmp.w, tmp, tmp;
RSQ	tmp.w, tmp.w;
MAD	tmp.xyz, tmp.w, tmp, viewerdir;	# add E to result (L), now tmp = L + E = H

# 6.3. normalize H, which is kept in tmp
DP3	tmp.w, tmp, tmp;
RSQ	tmp.w, tmp.w;
MUL	tmp.xyz, tmp.w, tmp;

# 6.4. transform to tangent space
DP3	halfangleout.x, tmp, tangentx;
DP3	halfangleout.y, tmp, tangenty;
DP3	halfangleout.z, tmp, normal;


# 7. transform inputpos.xy with texture matrix to get texture coodinates
DP4	noisetexcout.x, texmatnoise[0], inputpos;
DP4	noisetexcout.y, texmatnoise[1], inputpos;


# 8. compute reflection texture coordinates
# fixme should be computed per pixel. but we would need real pos and normal for that...
# per vertex would be ok, when the mesh is dense enough.
#formula to compute them from inputpos (coord):
#vector3f texc = coord + N * (VIRTUAL_PLANE_HEIGHT * N.z);
#texc.z -= VIRTUAL_PLANE_HEIGHT;
#uv1[ptr] = texc;
#after that mulitply with texture matrix!
MUL	tmp.x, virtualplaneheight.x, normal.z;
MAD	tmp, tmp.x, normal, inputpos;
SUB	tmp.z, tmp.z, virtualplaneheight.x;
DP4	reflectiontexc.x, texmatrefl[0], tmp;
DP4	reflectiontexc.y, texmatrefl[1], tmp;
DP4	reflectiontexc.w, texmatrefl[3], tmp;

## without distorsion:
#DP4	reflectiontexc.x, texmatrefl[0], inputpos;
#DP4	reflectiontexc.y, texmatrefl[1], inputpos;
##DP4	reflectiontexc.z, texmatrefl[2], inputpos;	# value not needed.
#DP4	reflectiontexc.w, texmatrefl[3], inputpos;

MOV	tmp, inputpos;
MOV	tmp.z, -viewpos.z;
DP4	noisetexcout.z, texmatrefl[0], tmp;
DP4	noisetexcout.w, texmatrefl[1], tmp;
DP4	reflectiontexc.z, texmatrefl[3], tmp;

END
