; float4x4 viMatrix : ViewInverse ; // Textures ////////////////// texture texmap : Diffuse < string ResourceName = "dm1.jpg"; >; texture dispmap < string ResourceName = "dm1.tga"; >; texture dispindxmap < string ResourceName = "displace_indxmap.tga"; >; sampler2D texmap_sampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = None; }; sampler2D dispmap_sampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = None; AddressU = Clamp; AddressV = Clamp; }; sampler2D dispindxmap_sampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = None; AddressU = Clamp; AddressV = Clamp; }; // Tweakable parameters //////////////////////// float tile < string UIWidget = "slider"; float UIMin = 1; float UIMax = .0; float UIStep = 1; string UIName = "tile"; > = 10.0; float4 constants < string UIName = "constants"; > = {32,32,0.03125,0.03125}; float depth < string UIName = "depth"; > = 3.38478; float4 base0 < string UIName = "base0"; > = {-1,-1,0,0}; float4 base1 < string UIName = "base1"; > = {1,0,0,2}; float4 base2 < string UIName = "base2"; > = {0,1,0,2}; float4 diffuse < string UIName = "diffuse"; string UIWidget = "Color"; > = {1,1,1,1}; float4 specular < string UIName = "specular"; string UIWidget = "Color"; > = {0.75,0.75,0.75,100}; float4 lightpos : Position < string Object = "PointLight"; string Space = "World"; > = {-1.0f, 1.0f, -1.5f, 1.0f}; float4 lightcolor < string UIWidget = "Color"; > = {1.0f, 1.0f, 1.0f, 1.0f}; // structures /////////////////////////////////// struct a2v { float4 pos : POSITION; }; struct v2f { float4 hpos : POSITION; float4 opos : TEXCOORD0; float4 eyepos : TEXCOORD1; }; // shaders ////////////////////////////////// v2f displace_map_vert( a2v IN, uniform float4x4 WorldViewProj, uniform float4x4 ViewInv) { v2f OUT; OUT.hpos=mul(IN.pos,WorldViewProj); OUT.opos=IN.pos; OUT.eyepos=ViewInv[3]; return OUT; } float4 displace_map_frag( v2f IN, uniform float depthfactor, uniform sampler2D texmap, uniform sampler2D dispmap, uniform sampler2D dispindxmap) : COLOR { float4 t,color; float3 viewdir,opos,lightdir,halfdir; float2 uv,uv1,uv2; float HdotL,NdotL; // view direction is AB index (uv1) viewdir=normalize(IN.opos.xyz-IN.eyepos.xyz); // full computation // uv1.x=1.0-acos(viewdir.x/sqrt(1.0-viewdir.y*viewdir.y))/3.1415927; // uv1.y=1.0-acos(viewdir.y)/3.1415927; // simplified computation uv1=viewdir.xy*0.5+0.5; t=tex2D(dispindxmap,uv1); uv1=t.xy+t.zw*0.005; // tile position is XY index (uv2) opos=IN.opos.xyz-base0.xyz; uv.x=dot(opos,base1.xyz)/base1.w; uv.y=dot(opos,base2.xyz)/base2.w; uv2=fmod(uv*tile,1.0); // compose ABXY index for 4D texture (uv=f(uv1,uv2)) uv=(floor(uv1*constants.xy)+uv2.xy)*constants.zw; // get pixel normal and depth from displace map t=tex2D(dispmap,uv); t.xyz=2.0*t.xyz-1.0; if (depth<0.01) t=float4(0.0,0.0,1.0,0.0); // displace pixel and compute new texture coordinates opos+=viewdir*t.w*depthfactor; uv.x=dot(opos,base1.xyz)/base1.w; uv.y=dot(opos,base2.xyz)/base2.w; // illuminate for a point light with diffuse and specular diffuse*=tex2D(texmap,uv*tile); lightdir=normalize(opos+base0.xyz-lightpos.xyz); halfdir=normalize(lightdir+viewdir); HdotL=max(0.0,dot(halfdir,t.xyz)); NdotL=max(0.0,dot(lightdir,t.xyz)); HdotL=HdotL*HdotL; HdotL=HdotL*HdotL; HdotL=HdotL*HdotL; color.xyz=diffuse.xyz*NdotL+specular.xyz*pow(HdotL,specular.w); color.w=1.0; /* // clamp edges if (length(uv-clamp(uv,0.0,1.0))>0.0) color.w=0.0; */ return color; } //////// techniques //////////// technique displacemap { pass p0 { Zenable = true; ZWriteEnable = true; CullMode = CW; VertexShader = compile vs_1_1 displace_map_vert( wvpMatrix,viMatrix); PixelShader = compile ps_2_0 displace_map_frag( depth*base1.w/tile, texmap_sampler,dispmap_sampler,dispindxmap_sampler); } } ]]>; float4x4 wMatrix : World ; float4x4 viMatrix : WorldViewInverse ; // textures ////////////////////////////// texture texmap : Diffuse < string ResourceName = "dm2.jpg"; >; texture dispmap < string ResourceName = "dm2.tga"; >; texture dispindxmap < string ResourceName = "displace_indxmap.tga"; >; sampler2D texmap_sampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = None; }; sampler2D dispmap_sampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = None; AddressU = Clamp; AddressV = Clamp; }; sampler2D dispindxmap_sampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = None ; AddressU = Clamp; AddressV = Clamp; }; // User Tweakables //////////////////////////////// float tile < string UIWidget = "slider"; float UIMin = 1; float UIMax = 32.0; float UIStep = 1; string UIName = "tile"; > = 10.0; float4 constants < string UIName = "constants"; > = {32,32,0.03125,0.03125}; float depth < string UIName = "depth"; > = 12.0313; float4 base0 < string UIName = "base0"; > = {-1,-1,0,0}; float4 base1 < string UIName = "base1"; > = {1,0,0,2}; float4 base2 < string UIName = "base2"; > = {0,1,0,2}; float4 diffuse < string UIName = "diffuse"; string UIWidget = "Color"; > = {1,1,1,1}; float4 specular < string UIName = "specular"; string UIWidget = "Color"; > = {0.75,0.75,0.75,100}; float4 lightpos : Position < string Object = "PointLight"; string Space = "World"; > = {-1.0f, 1.0f, -1.5f, 1.0f}; float4 lightcolor < string UIWidget = "Color"; > = {1.0f, 1.0f, 1.0f, 1.0f}; // structs /////////////////////////// struct a2v { float4 pos : POSITION; }; struct v2f { float4 hpos : POSITION; float4 opos : TEXCOORD0; float4 eyepos : TEXCOORD1; }; // shaders ///////////////////// v2f displace_map_vert( a2v IN, uniform float4x4 WorldViewProj, uniform float4x4 World, uniform float4x4 ViewInv) { v2f OUT; OUT.hpos=mul(IN.pos,WorldViewProj); OUT.opos=mul(IN.pos,World); OUT.eyepos=ViewInv[3]; return OUT; } float4 displace_map_frag( v2f IN, uniform float depthfactor, uniform sampler2D texmap, uniform sampler2D dispmap, uniform sampler2D dispindxmap) : COLOR { float4 t,color; float3 viewdir,opos,lightdir,halfdir; float2 uv,uv1,uv2; float HdotL,NdotL; // view direction is AB index (uv1) viewdir=normalize(IN.opos.xyz-IN.eyepos.xyz); // full computation (exceeds ps_2_0 limits) // uv1.x=1.0-acos(viewdir.x/sqrt(1.0-viewdir.y*viewdir.y))/3.1415927; // uv1.y=1.0-acos(viewdir.y)/3.1415927; // simplified computation uv1=viewdir.xy*0.5+0.5; t=tex2D(dispindxmap,uv1); uv1=t.xy+t.zw*0.005; // tile position is XY index (uv2) opos=IN.opos.xyz-base0.xyz; uv.x=dot(opos,base1.xyz)/base1.w; uv.y=dot(opos,base2.xyz)/base2.w; uv2=fmod(uv*tile,1.0); // compose ABXY index for 4D texture (uv=f(uv1,uv2)) uv=(floor(uv1*constants.xy)+uv2.xy)*constants.zw; // get pixel normal and depth from displace map t=tex2D(dispmap,uv); t.xyz=2.0*t.xyz-1.0; if (depth<0.01) t=float4(0.0,0.0,1.0,0.0); // displace pixel and compute new texture coordinates opos+=viewdir*t.w*depthfactor; uv.x=dot(opos,base1.xyz)/base1.w; uv.y=dot(opos,base2.xyz)/base2.w; // illuminate for a point light with diffuse and specular diffuse*=tex2D(texmap,uv*tile); lightdir=-normalize(lightpos.xyz-opos-base0.xyz); halfdir=normalize(lightdir+viewdir); HdotL=max(0.0,dot(halfdir,t.xyz)); NdotL=max(0.0,dot(lightdir,t.xyz)); color.xyz=diffuse.xyz*NdotL+specular.xyz*pow(HdotL,specular.w); color.w=1.0; /* // clamp edges if (length(uv-clamp(uv,0.0,1.0))>0.0) color.w=0.0; */ return color; } // techniques //////////////////////////////// technique displacemap2 { pass p0 { Zenable = true; ZWriteEnable = true; CullMode = CW; VertexShader = compile vs_1_1 displace_map_vert( wvpMatrix,wMatrix,viMatrix); PixelShader = compile ps_2_0 displace_map_frag( depth*base1.w/tile, texmap_sampler,dispmap_sampler,dispindxmap_sampler); } } ]]>