Posted By: XNASorcerer
Realtime water reflections shader - 02/03/05 10:32
How can I do that?
In Antwort auf:
using a clipping plane at the surface of the water, this must be done in a DLL i think.
Quote:
I will post the code with a "how to implement" text soon.
In Antwort auf:
Or have you got an dll like the zeraphine x3 engine plugin to do this?
In Antwort auf:
You'll have to use Render To Texture only available in the pro demo to get realtime reflection in the water in your open source demo. Right Oliver?
Quote:
Assuming your water plane is at y = 0, and y is the up axis, then the easiest method is to simply multiply the view matrix with a mirror matrix like this one:
1 0 0 0
0 -1 0 0
0 0 1 0
0 0 0 1
That will flip the geometry (or the camera, it's the same, just seen from a different coordinate frame) around the Y axis.
If your plane is not exactly at y=0, then you need to adjust the translation part accordingly.
Quote:
looks like it would work.. also i need to make a user clip plane, but frankl;y i dont get how the plane is setup.. you have any idea how to setup a clip plane in D3D?
Quote:
sweet, will this be anohter "ultimate" shader?
or "ultimate" dll?
AlphaBlendEnable = True;
ZwriteEnable = True;
ZEnable = True;
// Main point is that pixelShaderConstant 'W' will control the alpha tranparency. The XYZ will adjust some coloring.
PixelShaderConstant[0] = {0.80,0.80,0.92,0.88}; // x, y, z, w
Quote:
... put this in the pixel shader input
float4 fresnel:COLOR0 ...
float4x4 matWorldViewProj: register(c0);
texture entSkin1;
texture entSkin2;
texture entSkin3;
vector vecSkill41;
float1 mtlSkill1;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD0;
float3 eyeLinear: TEXCOORD1;
};
VS_OUTPUT VS_p0(float4 Pos: POSITION)
{
VS_OUTPUT Out;
float4 pos = float4(1 * Pos.x, 1 * Pos.y - 1, 1 * Pos.z, 1);
float4 pPos = mul(float4(pos.xyz,1), matWorldViewProj);
Out.Pos = pPos;
Out.texCoord.x = Pos.x * 0.5;
Out.texCoord.y = Pos.z * 0.5;
Out.eyeLinear.x = 0.5 * (pPos.z + pPos.x);
Out.eyeLinear.y = 0.5 * (pPos.z - pPos.y);
Out.eyeLinear.z = pPos.z * 1;
return Out;
}
sampler BumpMap = sampler_state
{
texture=(entSkin3);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
sampler RefractionMap = sampler_state
{
texture=(entSkin2);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
sampler ReflectionMap = sampler_state
{
texture=(entSkin1);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
float4 PS_p0( float2 texCoord: TEXCOORD0,float3 eyeLinear: TEXCOORD1) : COLOR
{
// addiere die Geschindigkeit von vecSkill41 hinzu für Wellenbewegung
float2 waterCoord = texCoord.xy * 0.001 * vecSkill41;
// die Bumpmap mit der waterCoord Koordinaten
float4 bump = tex2D(BumpMap, waterCoord) * 2 - 1;
bump = normalize(bump);
float2 mid = eyeLinear.xy / eyeLinear.z + bump.xy * 0.1f ;
// Reflektierte Wasseroberfläche
float4 reflection = tex2D(ReflectionMap, mid);
float4 final=reflection;
// Output
return reflection;
}
technique water
{
pass p1
{
VertexShader = compile vs_1_1 VS_p0();
PixelShader = compile ps_2_0 PS_p0();
}
}
float4x4 matWorldViewProj: register(c0);
///////////////////////////////////////////////////
float4 matWorld;
float4 vecViewPos;
///////////////////////////////////////////////////
texture entSkin1;
texture entSkin2;
texture entSkin3;
vector vecSkill41;
float1 mtlSkill1;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD0;
float3 eyeLinear: TEXCOORD1;
//////////////////////////////////////////////////////////
float4 fresnel: COLOR0;
//////////////////////////////////////////////////////////
};
VS_OUTPUT VS_p0(float4 Pos: POSITION)
{
VS_OUTPUT Out;
float4 pos = float4(1 * Pos.x, 1 * Pos.y - 1, 1 * Pos.z, 1);
float4 pPos = mul(float4(pos.xyz,1), matWorldViewProj);
Out.Pos = pPos;
Out.texCoord.x = Pos.x * 0.5;
Out.texCoord.y = Pos.z * 0.5;
Out.eyeLinear.x = 0.5 * (pPos.z + pPos.x);
Out.eyeLinear.y = 0.5 * (pPos.z - pPos.y);
Out.eyeLinear.z = pPos.z * 1;
///////////////////////////////////////////////////////
float3 PositionWorld = mul(Pos, matWorld);
float dist=distance(PositionWorld, vecViewPos);
if (dist<=300)
{
Out.fresnel.xyzw=dist*0.005;
}
if (dist>300)
{
Out.fresnel.xyzw=1.0;
}
/////////////////////////////////////////////////////////
return Out;
}
sampler BumpMap = sampler_state
{
texture=(entSkin3);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
sampler RefractionMap = sampler_state
{
texture=(entSkin2);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
sampler ReflectionMap = sampler_state
{
texture=(entSkin1);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
float4 PS_p0( float2 texCoord: TEXCOORD0,float3 eyeLinear: TEXCOORD1, float4 fresnel: COLOR0) : COLOR //////////////
{
// addiere die Geschindigkeit von vecSkill41 hinzu für Wellenbewegung
float2 waterCoord = texCoord.xy * 0.001 * vecSkill41;
// die Bumpmap mit der waterCoord Koordinaten
float4 bump = tex2D(BumpMap, waterCoord) * 2 - 1;
bump = normalize(bump);
float2 mid = eyeLinear.xy / eyeLinear.z + bump.xy * 0.1f ;
// Reflektierte Wasseroberfläche
float4 reflection = tex2D(ReflectionMap, mid);
float4 final=reflection;
///////////////////////////////////////////////////////
float3 watercolor=(0.58,0.65,0.63); //adjust this change water coloring
final.rgb*=watercolor;
final.w=(1*fresnel)*0.8;
////////////////////////////////////////////////////////
// Output
return reflection;
}
technique water
{
pass p1
{
/////////////////////////////////////////////////////////
zwriteenable=false;
zenable=true;
alphablendenable=true;
/////////////////////////////////////////////////////////
VertexShader = compile vs_1_1 VS_p0();
PixelShader = compile ps_2_0 PS_p0();
}
}
sampler BumpMap = sampler_state
{
texture=(entSkin3);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
sampler RefractionMap = sampler_state
{
texture=(entSkin2);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
sampler ReflectionMap = sampler_state
{
texture=(entSkin1);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
sampler BumpMap = sampler_state
{
texture=(entSkin3);
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
sampler ReflectionMap = sampler_state
{
texture=(entSkin1);
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
AddressW = CLAMP;
};
MATERIAL terrain_clipping //for clipping the terrain underwater in the mirror view
{
event = render_event();
flags = enable_view;
effect=
"
float4x4 matWorldViewProj: register(c0);
texture entSkin1;
vector vecSkill41;
float1 mtlSkill1;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD0;
float3 eyeLinear: TEXCOORD1;
};
VS_OUTPUT VS_p0(float4 Pos1: POSITION, float2 basemap: TEXCOORD0)
{
VS_OUTPUT Out;
Out.Pos = mul(Pos1, matWorldViewProj);
Out.texCoord = basemap;
Out.eyeLinear.x = Pos1.x;
Out.eyeLinear.y = Pos1.y;
Out.eyeLinear.z = Pos1.z;
return Out;
}
sampler BaseMap = sampler_state
{
texture=(entSkin1);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
float4 PS_p0( float2 texCoord: TEXCOORD0,
float3 eyeLinear: TEXCOORD1) : COLOR
{
float4 base = tex2D(BaseMap, texCoord);
clip((eyeLinear.y-vecSkill41)*mtlSkill1);
// Output
return base * 1.2;
}
technique water
{
pass p1
{
VertexShader = compile vs_1_1 VS_p0();
PixelShader = compile ps_2_0 PS_p0();
}
}
";
}
ACTION terrainobject
{
var hoch1;
my.material = terrain_clipping;
my.nofog = on;
hoch1 = water_ent.z*0.049;
while(1)
{
my.skill41 = float(hoch1);
wait(1);
}
}
// shader_test.wdl
var video_mode = 7;
var video_depth = 32;
var d3d_mipmapping = 3;
var d3d_anisotropy = 16;
var clip_range = 200000;
var clip_factor = 1;
var clip_size = 0;
var clip_factor= 1;
var fps_max = 70;
var fps_min = 35;
var max_entities = 1000;
var d3d_transform = on;
var move_friction = 0;
var d3d_antialias = 6;
var logo = 0;
var video_screen = 1;
var bumpness = 100;
var speed = 1;
bmap slider_tga = "slider.tga";
bmap mauszeiger_bmp = "mauszeiger.bmp";
bmap slider_box_tga = "slider_box.tga";
PANEL pan_sliders
{
bmap = slider_box_tga;
hslider = 492, 4, 610, slider_tga, 0, 500, bumpness;
hslider = 492, 30, 610, slider_tga, 0, 10, speed;
}
FUNCTION loadfx();
function main
{
d3d_autotransparency = on;
level_load("water_shader.wmb");
}
SKY himmel1
{
type = <himmel3+6.tga>;
layer = 3;
flags = cube,visible;
z = 0;
}
VIEW mirror
{
layer = 10;
}
entity* water_ent;
function render_event();
MATERIAL waterfx
{
}
var hoch;
var hoch1 = 3.2;
ACTION water
{
var count;
var count1;
var a = 180;
var b;
water_ent = me;
my.nofog = on;
// my.invisible = on;
my.material = waterfx;
my.scale_x = 40;
my.scale_y = 40;
my.z += 20;
hoch = my.z;
while(1)
{
my.z = hoch;
my.skill41=float(count);
my.skill42=float(count1);
my.skill43=float(0);
my.skill44=float(0);
a += speed*time;
a %= 360;
b += speed*time;
b %= 360;
count = sin(a)+bumpness;
count1 = cos(b)+bumpness;
hoch1 = my.z*0.049;
wait(1);
}
}
STARTER init_water
{
wait(2);
camera.x = -1552;
camera.y = -935;
camera.z = 98;
camera.pan = 43;
camera.tilt = -4;
mirror.size_x = camera.size_x;
mirror.size_y = camera.size_y;
d3d_fogcolor1.red = 128;
d3d_fogcolor1.green = 128;
d3d_fogcolor1.blue = 150;
fog_color = 1;
camera.fog_start = 20;
camera.fog_end = 5000;
mirror.fog_start = 20;
mirror.fog_end = 5000;
camera.clip_near = 0;
mirror.clip_near = 0;
mirror.nocull = on;
/*If you have A6 Pro Version*/
mirror.bmap = bmap_for_entity(water_ent,1);
// refrview.bmap = bmap_for_entity(water_ent,2);
mirror.aspect = -1;
mirror.visible = on;
// refrview.visible = on;
/*If you have A6 Com Version
IF(d3d_shaderversion < 2020)
{
pan_sliders.visible = off;
while(1)
{
draw_text("You need a video card with Pixelshader 2.0",screen_size.x-520,screen_size.y-280,vector(0,0,0));
wait(1);
}
}
make_mirror();
mirror.aspect = -1;*/
mouse_map = mauszeiger_bmp;
proc_late();
while(1)
{
mirror.x = camera.x;
mirror.y = camera.y;
mirror.z = -camera.z+ (2*water_ent.z);
mirror.pan = camera.pan;
mirror.tilt = -camera.tilt;
mouse_pos.x = pointer.x;
mouse_pos.y = pointer.y;
pan_sliders.pos_x = (screen_size.x/2)-800;
pan_sliders.pos_y = screen_size.y-52;
wait(1);
}
}
/*FUNCTION make_mirror
{
mirror.visible = on;
pan_sliders.visible = off;
mouse_mode = 0;
mirror.size_x = camera.size_x;
mirror.size_y = camera.size_y;
water_ent.visible = off;
wait(1);
bmap_for_screen(bmap_for_entity(water_ent,1),1,0);
mirror.visible = off;
water_ent.visible = on;
pan_sliders.visible = on;
mouse_mode = 2;*/
loadfx();
}
MATERIAL terrain_clipping //for clipping the terrain underwater in the mirror view
{
event = render_event();
flags = enable_view;
effect=
"
float4x4 matWorldViewProj: register(c0);
texture entSkin1;
vector vecSkill41;
float1 mtlSkill1;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD0;
float3 eyeLinear: TEXCOORD1;
};
VS_OUTPUT VS_p0(float4 Pos1: POSITION, float2 basemap: TEXCOORD0)
{
VS_OUTPUT Out;
Out.Pos = mul(Pos1, matWorldViewProj);
Out.texCoord = basemap;
Out.eyeLinear.x = Pos1.x;
Out.eyeLinear.y = Pos1.y;
Out.eyeLinear.z = Pos1.z;
return Out;
}
sampler BaseMap = sampler_state
{
texture=(entSkin1);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
float4 PS_p0( float2 texCoord: TEXCOORD0,
float3 eyeLinear: TEXCOORD1) : COLOR
{
float4 base = tex2D(BaseMap, texCoord);
clip((eyeLinear.y-vecSkill41)*mtlSkill1);
// Output
return base * 1.2;
}
technique water
{
pass p1
{
VertexShader = compile vs_1_1 VS_p0();
PixelShader = compile ps_2_0 PS_p0();
}
}
";
}
FUNCTION loadfx
{
effect_load(terrain_clipping,"clip.fx");
effect_load(waterfx,"water.fx");
}
ACTION terrainobject
{
IF(d3d_shaderversion < 2020) { return; }
my.material = terrain_clipping;
my.nofog = on;
while(1)
{
my.skill41 = float(hoch1);
wait(1);
}
}
function render_event()
{
if(render_view == camera)
{
mtl.skill1 = float(0);
}
if(render_view == mirror)
{
mtl.skill1 = float(1);
}
}
var bumpness =24;
var speed = 1;
bind <water.fx>;
entity* water_ent;
var temp2[3];
var hoch;
var hoch1 = 3.2;
SKY himmel1
{
type = SkyCube+6.tga;
layer = 3;
flags = cube,visible;
z = 0;
}
VIEW mirror
{
layer = 10;
}
function render_event();
MATERIAL waterfx
{
}
var hoch;
var hoch1 = 3.2;
ACTION water
{
water_ent = me;
var count;
var count1;
var a = 180;
var b;
my.transparent = on;
my.nofog = on;
my.material = waterfx;
my.scale_x = 50;
my.scale_y = 50;
my.z += 20;
hoch = my.z;
while(1)
{
my.z = hoch;
my.skill41=float(count);
my.skill42=float(count1);
my.skill43=float(0);
my.skill44=float(0);
a += speed*time;
a %= 360;
b += speed*time;
b %= 360;
count = sin(a)+bumpness;
count1 = cos(b)+bumpness;
hoch1 = my.z*0.049;
wait(1);
}
}
STARTER init_water
{
wait(2);
while(water_ent==null){wait(1);}
mirror.size_x = camera.size_x;
mirror.size_y = camera.size_y;
d3d_fogcolor1.red = 128;
d3d_fogcolor1.green = 128;
d3d_fogcolor1.blue = 150;
fog_color = 1;
camera.fog_start = 8000;
camera.fog_end = 10000;
mirror.fog_start = 8000;
mirror.fog_end = 10000;
camera.clip_near = 0;
mirror.clip_near = 0;
mirror.nocull = on;
mirror.bmap = bmap_for_entity(water_ent,1);
mirror.bmap = bmap_for_entity(water_ent2,1);
mirror.aspect = -1;
mirror.visible = on;
IF(d3d_shaderversion < 2020)
{
while(1)
{
draw_text("You need a video card with Pixelshader 2.0",screen_size.x-520,screen_size.y-280,vector(0,0,0));
wait(1);
}
}
loadfx();
mirror.aspect = -1;
proc_late();
while(1)
{
mirror.x = camera.x;
mirror.y = camera.y;
mirror.z = -camera.z+ (2*water_ent.z);
mirror.z = -camera.z+ (2*water_ent2.z);
mirror.pan = camera.pan;
mirror.tilt = -camera.tilt;
wait(1);
}
}
MATERIAL terrain_clipping //for clipping the terrain underwater in the mirror view
{
event = render_event();
flags = enable_view;
effect=
"
float4x4 matWorldViewProj: register(c0);
texture entSkin1;
vector vecSkill41;
float1 mtlSkill1;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD0;
float3 eyeLinear: TEXCOORD1;
};
VS_OUTPUT VS_p0(float4 Pos1: POSITION, float2 basemap: TEXCOORD0)
{
VS_OUTPUT Out;
Out.Pos = mul(Pos1, matWorldViewProj);
Out.texCoord = basemap;
Out.eyeLinear.x = Pos1.x;
Out.eyeLinear.y = Pos1.y;
Out.eyeLinear.z = Pos1.z;
return Out;
}
sampler BaseMap = sampler_state
{
texture=(entSkin1);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
float4 PS_p0( float2 texCoord: TEXCOORD0,
float3 eyeLinear: TEXCOORD1) : COLOR
{
float4 base = tex2D(BaseMap, texCoord);
clip((eyeLinear.y-vecSkill41)*mtlSkill1);
// Output
return base * 1.2;
}
technique water
{
pass p1
{
VertexShader = compile vs_1_1 VS_p0();
PixelShader = compile ps_2_0 PS_p0();
}
}
";
}
FUNCTION loadfx
{
effect_load(terrain_clip ping,"clip.fx");
effect_load(waterfx,"water.fx");
}
ACTION terrainobject
{
IF(d3d_shaderversion < 2020) { return; }
while(water_ent==null){wait(1);}
var hoch1;
my.material = terrain_clipping;
my.nofog = on;
while(1)
{
my.skill41 = float(hoch1);
wait(1);
}
}
function render_event()
{
if(render_view == camera)
{
mtl.skill1 = float(0);
}
if(render_view == mirror)
{
mtl.skill1 = float(1);
}
}
float4x4 matWorldViewProj: register(c0);
float4 matWorld;
float4 vecViewPos;
texture entSkin1;
texture entSkin2;
texture entSkin3;
vector vecSkill41;
float1 mtlSkill1;
sampler BumpMap = sampler_state
{
texture=(entSkin3);
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
sampler ReflectionMap = sampler_state
{
texture=(entSkin1);
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
AddressW = CLAMP;
};
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD0;
float3 eyeLinear: TEXCOORD1;
float4 fresnel: COLOR0;
};
VS_OUTPUT VS_p0(float4 Pos: POSITION)
{
VS_OUTPUT Out;
float4 pos = float4(1 * Pos.x, 1 * Pos.y - 1, 1 * Pos.z, 1);
float4 pPos = mul(float4(pos.xyz,1), matWorldViewProj);
Out.Pos = pPos;
Out.texCoord.x = Pos.x * 0.5;
Out.texCoord.y = Pos.z * 0.5;
Out.eyeLinear.x = 0.5 * (pPos.z + pPos.x);
Out.eyeLinear.y = 0.5 * (pPos.z - pPos.y);
Out.eyeLinear.z = pPos.z * 1;
float3 PositionWorld = mul(Pos, matWorld);
float dist=distance(PositionWorld, vecViewPos);
if (dist<=300)
{
Out.fresnel.xyzw=dist*0.005;
}
if (dist>300)
{
Out.fresnel.xyzw=1.0;
}
return Out;
}
float4 PS_p0( float2 texCoord: TEXCOORD0,float3 eyeLinear: TEXCOORD1, float4 fresnel: COLOR0) : COLOR
{
// addiere die Geschindigkeit von vecSkill41 hinzu für Wellenbewegung
float2 waterCoord = texCoord.xy * 0.001 * vecSkill41;
// die Bumpmap mit der waterCoord Koordinaten
float4 bump = tex2D(BumpMap, waterCoord) * 2 - 1;
bump = normalize(bump);
float2 mid = eyeLinear.xy / eyeLinear.z + bump.xy * 0.1f;
// Reflektierte Wasseroberfläche
float4 reflection = tex2D(ReflectionMap, mid);
float4 final=reflection;
float3 watercolor=(0.93,0.93,0.75); //adjust this change water coloring
final.rgb*=watercolor;
final.w=(1*fresnel)*0.93;//0.8;
// Output
//return reflection;
return final;
}
technique water
{
pass p1
{
zwriteenable=false;
zenable=true;
alphablendenable=true;
VertexShader = compile vs_1_1 VS_p0();
PixelShader = compile ps_2_0 PS_p0();
}
}
float4x4 matWorldViewProj: register(c0);
texture entSkin1;
vector vecSkill41;
vector mtlSkill1;
struct VS_OUTPUT
{
float4 Pos: POSITION;
float2 texCoord: TEXCOORD0;
float3 eyeLinear: TEXCOORD1;
};
VS_OUTPUT VS_p0(float4 Pos1: POSITION, float2 basemap: TEXCOORD0)
{
VS_OUTPUT Out;
Out.Pos = mul(Pos1, matWorldViewProj);
Out.texCoord = basemap;
Out.eyeLinear.x = Pos1.x;
Out.eyeLinear.y = Pos1.y;
Out.eyeLinear.z = Pos1.z;
return Out;
}
sampler BaseMap = sampler_state
{
texture=(entSkin1);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
float4 PS_p0( float2 texCoord: TEXCOORD0,
float3 eyeLinear: TEXCOORD1) : COLOR
{
float4 base = tex2D(BaseMap, texCoord);
clip((eyeLinear.y-vecSkill41)*mtlSkill1);
// Output
return base * 1.2;
}
technique water
{
pass p1
{
VertexShader = compile vs_1_1 VS_p0();
PixelShader = compile ps_2_0 PS_p0();
}
}