Description
This project was a series of tutorials on my graphics programming blog [link]. It presents key frame animation for cameras based on natural cubic spline interpolation, and also includes water rendering with reflection and refraction. It allows the user to navigate the scene and save key frames and build the camera path at run time. The application was developed in C# with the XNA framework. Another example of camera animation can be found in the dual-paraboloid mapping project. The cubic spline interpolation is derived from: http://www.cse.unsw.edu.au/~lambert/splines/natcubic.html
Features
Linear and cubic spline interpolation for camera animation
Water with reflection and refraction based on the Fresnel term
Allows playing, pausing, rewinding, and free navigation
Screen Shots
Video
Source Snippet
//Water.fx effect shader float4 WaterPS2(float3 toEyeW : TEXCOORD0, float2 tex0 : TEXCOORD1, float2 tex1 : TEXCOORD2, float4 projTexC : TEXCOORD3, float eyeVertDist : TEXCOORD4, float4 pos : TEXCOORD5) : COLOR { projTexC.xyz /= projTexC.w; projTexC.x = 0.5f*projTexC.x + 0.5f; projTexC.y = -0.5f*projTexC.y + 0.5f; projTexC.z = .1f / projTexC.z; toEyeW = normalize(toEyeW); SunDirection = normalize(SunDirection); // Light vector is opposite the direction of the light. float3 lightVecW = -SunDirection; // Sample normal map. float3 normalT0 = tex2D(WaveMapS0, tex0); float3 normalT1 = tex2D(WaveMapS1, tex1); //unroll the normals retrieved from the normalmaps normalT0.yz = normalT0.zy; normalT1.yz = normalT1.zy; normalT0 = 2.0f*normalT0 - 1.0f; normalT1 = 2.0f*normalT1 - 1.0f; float3 normalT = normalize(0.5f*(normalT0 + normalT1)); float3 n1 = float3(0,1,0); //just use unit y to calculate fresnel //get the reflection vector from the eye float3 R = normalize(reflect(toEyeW,normalT)); float4 finalColor; finalColor.a = 1; //compute the fresnel term to blend reflection and refraction maps float ang = saturate(dot(-toEyeW,n1)); float f = R0 + (1.0f-R0) * pow(1.0f-ang,5.0); //also blend based on distance f = min(1.0f, f + 0.007f * EyePos.y); //compute the reflection from sunlight, hacked in color, should be a variable float3 sunlight = 1.5f * pow(saturate(dot(R, lightVecW)),250.0f) * SunColor; float4 refl = tex2D(ReflectMapS,projTexC.xy+projTexC.z*normalT.xz); float4 refr = tex2D(RefractMapS, projTexC.xy-projTexC.z*normalT.xz); //only use the refraction map if we're under water if(EyePos.y < pos.y) f = 0.0f; float4 WaterColor = float4(0.5f, 0.79f, 0.75f, 1.00f); //interpolate the reflection and refraction maps based on the fresnel term and add the sunlight finalColor.rgb = WaterColor * lerp( refr, refl, f) + sunlight; return finalColor; }
Downloads
Binary: XNA 3.0 Redist and .Net 3.5 Framework is required to be installed in order to run the demo.
Source: XNA Game Studio 3.0 and DirectX is required to be installed in order to build and run the source.