First, My vs codes is:
vs.1.0
m4x4 r0, v0, c4 //v0 - Vertex Position
//c4-7 - Composite World-View-Projection Matrix
mov oPos,r0
//c0 - { 0.0, 0.5, 1.0, 2.0}
add r0.x, r0.w, r0.x // r0.x = (pos.w + pos.x) * 0.5
mul r0.x, r0.x, c0.y
add r0.y, r0.w, -r0.y // r0.y = (pos.w - pos.y ) * 0.5
mul r0.y, r0.y, c0.y
rcp r2.w, r0.w // r0.xyz/=pos.w
mul r0.xyz, r0, r2.w
mov oT1, r0
mov oT3, r0
and texture stage states is:
// stage1 ColorOp[1] = SelectArg1; ColorArg1[1] = Texture; ... // stage3 ColorOp[3] = BlendDiffuseAlpha; ColorArg1[3] = Texture; ColorArg2[3] = Current;
These codes gets a halfway success: when camera is faraway to water surface, everything looks well; but if camera close to water, the projected texture looks distorted and chapped. see below screenshot:

After many attempts, I've found the solution finally: remove the w-division from
vertex shader, and do the division by setting TextureStageState - D3DTSS_TEXTURETRANSFORMFLAGS. So the modified vs codes is:
vs.1.0
m4x4 r0, v0, c4 //v0 - Vertex Position
//c4-7 - Composite World-View-Projection Matrix
mov oPos,r0
//c0 - { 0.0, 0.5, 1.0, 2.0}
add r0.x, r0.w, r0.x // r0.x = (pos.w + pos.x) * 0.5
mul r0.x, r0.x, c0.y
add r0.y, r0.w, -r0.y // r0.y = (pos.w - pos.y ) * 0.5
mul r0.y, r0.y, c0.y
mov oT1, r0
mov oT3, r0
and modified texture stage states is:
// stage1 ColorOp[1] = SelectArg1; ColorArg1[1] = Texture; TextureTransformFlags[1] = Count3|Projected; ... // stage3 ColorOp[3] = BlendDiffuseAlpha; ColorArg1[3] = Texture; ColorArg2[3] = Current; TextureTransformFlags[3] = Count3|Projected;
This time the result is satisfying, the water looks well from anywhere:

So I have a question: why do the w-division in vertex shader cause the distortion? (Is it perspective-correction correlative? Is there a method to disable perspective-correction in D3D 8.1?)












