!!ARBvp1.0 OPTION ARB_position_invariant ;
# SteveL #3879: Do not distort where the sampled texel would come from a surface closer than
# the water surface. Fix for water distorting player weapon etc. Amendments to frag prog.
#
# input:
#
# attrib[8] (former texcoord[0]) TEX0 texcoords
#
# local[0] scroll
# local[1] deform magnitude (1.0 is reasonable, 2.0 is twice as wavy, 0.5 is half as wavy, etc)
#
# output:
#
# texture 0 is _currentRender
# texture 1 is a normal map that we will use to deform texture 0
#
# texCoord[1] is the model surface texture coords
# texCoord[2] is the copied deform magnitude
TEMP R0, R1, R2;
# texture 1 takes the texture coordinates and adds a scroll
ADD result.texcoord[1], vertex.attrib[8], program.local[0];
# texture 2 takes the deform magnitude and scales it by the projection distance
PARAM vec = { 1, 0, 0, 1 };
MOV R0, vec;
DP4 R0.z, vertex.position, state.matrix.modelview.row[2];
DP4 R1, R0, state.matrix.projection.row[0];
DP4 R2, R0, state.matrix.projection.row[3];
# don't let the recip get near zero for polygons that cross the view plane
MAX R2, R2, 1;
RCP R2, R2.w;
MUL R1, R1, R2;
# clamp the distance so the the deformations don't get too wacky near the view
MIN R1, R1, 0.02;
MUL result.texcoord[2], R1, program.local[1];
END
#======================================================================
!!ARBfp1.0
OPTION ARB_precision_hint_fastest;
# texture 0 is _currentRender
# texture 1 is a normal map that we will use to deform texture 0
# texture 2 is _currentDepth
#
# env[0] is the 1.0 to _currentRender conversion
# env[1] is the fragment.position to 0.0 - 1.0 conversion
TEMP localNormal, R0;
PARAM subOne = { -1, -1, -1, -1 };
PARAM scaleTwo = { 2, 2, 2, 2 };
# load the filtered normal map and convert to -1 to 1 range
TEX localNormal, fragment.texcoord[1], texture[1], 2D;
MOV localNormal.x, localNormal.a;
MAD localNormal, localNormal, scaleTwo, subOne;
# calculate the screen texcoord in the 0.0 to 1.0 range
MUL R0, fragment.position, program.env[1];
# offset by the scaled localNormal and clamp it to 0.0 - 1.0
MAD_SAT R0, localNormal, fragment.texcoord[2], R0;
# scale by the screen non-power-of-two-adjust
MUL R0, R0, program.env[0];
# Get the displaced color
TEMP displacedColor;
TEX displacedColor, R0, texture[0], 2D;
# Fix foreground object distortion. Get another sample from the opposite direction,
# to use if the sample came from the foreground.
TEMP altCoord, altColor, origCoord;
MUL origCoord, program.env[0], program.env[1]; # Screen space to
MUL origCoord, origCoord, fragment.position.xyxy; # tex coord conversion
SUB altCoord.xy, R0, origCoord; # Diff between original coord and distorted coord
ADD altCoord, origCoord, -altCoord; # Now distorted in the opposite direction
TEX altColor, altCoord, texture[0], 2D;
# Test whether the samples came from the foreground, rejecting them if so.
# Start with the original undistorted color. We'll use this if both samples came
# from the foreground.
TEMP depth, chosenColor;
TEX chosenColor, origCoord, texture[0], 2D;
# Test whether the alt color came from the background, and use it in preference if so
MUL altCoord.xy, altCoord, program.env[4].zwzw; # zw holds the ratio of _currentRender size to _currentDepth size
TEX depth, altCoord, texture[2], 2D;
SUB depth, depth.z, fragment.position.z;
CMP chosenColor, depth, chosenColor, altColor;
# Test whether the displaced color came from the background, and use it in preference if so
MUL R0.xy, R0, program.env[4].zwzw;
TEX depth, R0, texture[2], 2D;
SUB depth, depth.z, fragment.position.z;
CMP result.color, depth, chosenColor, displacedColor;
END