!!ARBvp1.0 OPTION ARB_position_invariant ; # 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[0] is the model surface texture coords unmodified for the mask # texCoord[1] is the model surface texture coords with a scroll # texCoord[2] is the copied deform magnitude TEMP R0, R1, R2; # texture 0 takes the texture coordinates unmodified MOV result.texcoord[0], vertex.attrib[8]; # 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 a mask texture # # env[0] is the 1.0 to _currentRender conversion # env[1] is the fragment.position to 0.0 - 1.0 conversion TEMP localNormal, mask, pos0, pos1, pos2, pos3, pos4; TEMP coord0, coord1, coord2, coord3, coord4; TEMP input0, input1, input2, input3, input4; PARAM subOne = { -1, -1, -1, -1 }; PARAM scaleTwo = { 2, 2, 2, 2 }; # load the distortion map TEX mask, fragment.texcoord[0], texture[2], 2D; # kill the pixel if the distortion wound up being very small SUB mask.xy, mask, 0.01; KIL mask; # 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; MUL localNormal, localNormal, mask; # calculate the screen texcoord in the 0.0 to 1.0 range # greebo: Initialise the positions MOV pos0, fragment.position; MOV pos1, pos0; MOV pos2, pos0; MOV pos3, pos0; MOV pos4, pos0; # greebo: Offset the positions by a certain amount to the left/right/top/bottom ADD pos1.y, pos1.y, -3; ADD pos2.x, pos2.x, 3; ADD pos3.y, pos3.y, 4; ADD pos4.x, pos4.x, -5; # convert pixel's screen position to a fraction of the screen width & height # fraction will be between 0.0 and 1.0. # result is stored in temp1. MUL coord0, pos0, program.env[1]; MUL coord1, pos1, program.env[1]; MUL coord2, pos2, program.env[1]; MUL coord3, pos3, program.env[1]; MUL coord4, pos4, program.env[1]; # scale by the screen non-power-of-two-adjust MUL coord0, coord0, program.env[0]; MUL coord1, coord1, program.env[0]; MUL coord2, coord2, program.env[0]; MUL coord3, coord3, program.env[0]; MUL coord4, coord4, program.env[0]; # offset by the scaled localNormal and clamp it to 0.0 - 1.0 MAD_SAT coord0, localNormal, fragment.texcoord[2], coord0; MAD_SAT coord1, localNormal, fragment.texcoord[2], coord1; MAD_SAT coord2, localNormal, fragment.texcoord[2], coord2; MAD_SAT coord3, localNormal, fragment.texcoord[2], coord3; MAD_SAT coord4, localNormal, fragment.texcoord[2], coord4; # load the screen render TEX input0, coord0, texture[0], 2D; TEX input1, coord1, texture[0], 2D; TEX input2, coord2, texture[0], 2D; TEX input3, coord3, texture[0], 2D; TEX input4, coord4, texture[0], 2D; # greebo: Average the values and pump it into the fragment's color ADD input0, input0, input1; ADD input0, input0, input2; ADD input0, input0, input3; ADD input0, input0, input4; MUL input0, input0, 0.2; MOV result.color.xyz, input0; END