#region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; #endregion namespace XNAGame { /// /// This is the main type for your game /// public class Game1 : Microsoft.Xna.Framework.Game { private GraphicsDeviceManager graphics; private ContentManager content; //Camera functions private Matrix worldMatrix; private Matrix viewMatrix; private Matrix projectionMatrix; //Position of the Camera in world space, for our view matrix private Vector3 cameraPosition = new Vector3(0.0f, 10.0f, 55.0f); //for the custom .fx file private Effect effect; //Our models private Model FarmModel; Texture2D[] FarmTextures; private Model BarrelModel; Texture2D[] BarrelTextures; private Model HouseModel; Texture2D HouseTexture; private Model ToiletModel; Texture2D[] ToiletTextures; //Lamp positions Vector4[] lampPostPos; //Terrain variables private Terrain terrain; //Sky variables private Sky sky; //Water variables private Water water; //HUD variables private HUD hud; //Texture variables private Texture2D texture; //Movement variables private Vector3 avatarPosition = new Vector3(0, 0, -20); private float forwardSpeed = 50.0f / 60.0f; private MouseState previousMouseState; Vector3 moveVector = new Vector3(); //Camera variables private Vector3 cameraReference = new Vector3(0, -10, -55); private float mouseX, mouseY; static float nearClip = 1.0f; static float farClip = 10000.0f; static float viewAngle = MathHelper.PiOver4; //Lighting variables Vector4 lightpos = new Vector4(-18, 2, 5, 1); private float lightpower; private Texture2D carLight; //Variable for the shadow mapping private Matrix lightworldviewproj; //Variables to enable shadows as textures private RenderTarget2D renderTarget; private Texture2D texturedRenderedTo; //Variables to enable refraction mapping on the water RenderTarget2D refractionRenderTarget; Texture2D refractionMap; //Variables to enable reflection mapping on the water private RenderTarget2D reflectionRenderTarget; private Texture2D reflectionMap; private Matrix reflectionViewMatrix; //Water variables private float waterHeight = 20.0f; //Realizes moving water and clouds private float elapsedTime; public Game1() { graphics = new GraphicsDeviceManager(this); content = new ContentManager(Services); if (GraphicsAdapter.DefaultAdapter.GetCapabilities(DeviceType.Hardware).MaxPixelShaderProfile < ShaderProfile.PS_2_0) { graphics.PreparingDeviceSettings += new EventHandler(SetToReference); } } private void initializeXNADevice() { graphics.PreferredBackBufferWidth = 1000; graphics.PreferredBackBufferHeight = 500; graphics.IsFullScreen = false; graphics.ApplyChanges(); Window.Title = "Riemer's XNA Tutorials -- Series 3"; renderTarget = new RenderTarget2D(graphics.GraphicsDevice, 512, 512, 1, SurfaceFormat.Color); refractionRenderTarget = new RenderTarget2D(graphics.GraphicsDevice, 512, 512, 1, SurfaceFormat.Color); reflectionRenderTarget = new RenderTarget2D(graphics.GraphicsDevice, 512, 512, 1, SurfaceFormat.Color); } void SetToReference(object sender, PreparingDeviceSettingsEventArgs e) { e.GraphicsDeviceInformation.CreationOptions = CreateOptions.SoftwareVertexProcessing; e.GraphicsDeviceInformation.DeviceType = DeviceType.Reference; e.GraphicsDeviceInformation.PresentationParameters.MultiSampleType = MultiSampleType.None; } private void initializeEffect() { effect = content.Load("effect"); effect.Parameters["xMaxDepth"].SetValue(60); effect.Parameters["xAmbient"].SetValue(0.4f); cameraPosition = new Vector3(-25, 18, 13); viewMatrix = Matrix.CreateLookAt(cameraPosition, new Vector3(0, 12, 2), new Vector3(0, 0, 1)); projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)this.Window.ClientBounds.Width / (float)this.Window.ClientBounds.Height, 1.0f, 200.0f); effect.Parameters["xUserTexture"].SetValue(texture); } private void initializeModels() { //Load the farm model from a file FarmModel = content.Load("Models\\farm1\\farm1"); // Initialize the farm effects FarmTextures = new Texture2D[14]; int j = 0; foreach (ModelMesh mesh in FarmModel.Meshes) foreach (BasicEffect currenteffect in mesh.Effects) FarmTextures[j++] = currenteffect.Texture; foreach (ModelMesh modmesh in FarmModel.Meshes) foreach (ModelMeshPart modmeshpart in modmesh.MeshParts) modmeshpart.Effect = effect.Clone(graphics.GraphicsDevice); //Load the barrel model from a file BarrelModel = content.Load("Models\\barrel\\barrel"); // Initialize the barrel effects BarrelTextures = new Texture2D[14]; j = 0; foreach (ModelMesh mesh in BarrelModel.Meshes) foreach (BasicEffect currenteffect in mesh.Effects) BarrelTextures[j++] = currenteffect.Texture; foreach (ModelMesh modmesh in BarrelModel.Meshes) foreach (ModelMeshPart modmeshpart in modmesh.MeshParts) modmeshpart.Effect = effect.Clone(graphics.GraphicsDevice); //Load the house model from a file HouseModel = content.Load("Models\\house1\\house1"); // Initialize the house effects foreach (ModelMesh mesh in HouseModel.Meshes) foreach (BasicEffect currenteffect in mesh.Effects) HouseTexture = currenteffect.Texture; foreach (ModelMesh modmesh in HouseModel.Meshes) foreach (ModelMeshPart modmeshpart in modmesh.MeshParts) modmeshpart.Effect = effect.Clone(graphics.GraphicsDevice); //Load the toilet model from a file ToiletModel = content.Load("Models\\toilet\\klo_uv"); // Initialize the toilet effects ToiletTextures = new Texture2D[14]; j = 0; foreach (ModelMesh mesh in ToiletModel.Meshes) foreach (BasicEffect currenteffect in mesh.Effects) ToiletTextures[j++] = currenteffect.Texture; foreach (ModelMesh modmesh in ToiletModel.Meshes) foreach (ModelMeshPart modmeshpart in modmesh.MeshParts) modmeshpart.Effect = effect.Clone(graphics.GraphicsDevice); } private void initializeTerrain() { terrain = new Terrain(); terrain.Initialize(graphics.GraphicsDevice, content); } private void initializeSky() { sky = new Sky(); sky.Initialize(graphics.GraphicsDevice, content); } private void initializeWater() { water = new Water(waterHeight); water.Initialize(graphics.GraphicsDevice, content); } private void initializeHUD() { hud = new HUD(); hud.Initialize(graphics.GraphicsDevice, content, Window); } private void initializeMouse() { Mouse.SetPosition(Window.ClientBounds.Width / 2, Window.ClientBounds.Height / 2); previousMouseState = Mouse.GetState(); } /// /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// protected override void Initialize() { base.Initialize(); } /// /// Load your graphics content. If loadAllContent is true, you should /// load content from both ResourceManagementMode pools. Otherwise, just /// load ResourceManagementMode.Manual content. /// /// Which type of content to load. protected override void LoadGraphicsContent(bool loadAllContent) { if (loadAllContent) { HouseTexture = content.Load("Models\\house1\\fw12b"); initializeXNADevice(); initializeEffect(); initializeTerrain(); initializeSky(); initializeHUD(); initializeModels(); initializeMouse(); } } /// /// Unload your graphics content. If unloadAllContent is true, you should /// unload content from both ResourceManagementMode pools. Otherwise, just /// unload ResourceManagementMode.Manual content. Manual content will get /// Disposed by the GraphicsDevice during a Reset. /// /// Which type of content to unload. protected override void UnloadGraphicsContent(bool unloadAllContent) { if (unloadAllContent == true) { content.Unload(); } } private void ProcessInput(float amountOfMovement) { Vector3 moveVector = new Vector3(); KeyboardState keys = Keyboard.GetState(); if (keys.IsKeyDown(Keys.W)) { moveVector.Y += amountOfMovement * forwardSpeed; } if (keys.IsKeyDown(Keys.S)) { moveVector.Y -= amountOfMovement * forwardSpeed; } if (keys.IsKeyDown(Keys.A)) { moveVector.X -= amountOfMovement * forwardSpeed; } if (keys.IsKeyDown(Keys.D)) { moveVector.X += amountOfMovement * forwardSpeed; } Matrix cameraRotation = Matrix.CreateRotationX(mouseY) * Matrix.CreateRotationZ(mouseX); cameraPosition += Vector3.Transform(moveVector, cameraRotation); if (keys.IsKeyDown(Keys.LeftShift)) { forwardSpeed = 3.0f; } else { forwardSpeed = 50.0f / 60.0f; } if (keys.IsKeyDown(Keys.Escape)) { this.Exit(); } //Mouse input MouseState currentMouseState = Mouse.GetState(); if (currentMouseState.X != previousMouseState.X) { mouseX -= amountOfMovement / 80.0f * (currentMouseState.X - previousMouseState.X); } if (currentMouseState.Y != previousMouseState.Y) { mouseY -= amountOfMovement / 80.0f * (currentMouseState.Y - previousMouseState.Y); } Mouse.SetPosition(Window.ClientBounds.Width / 2, Window.ClientBounds.Height / 2); } private void processMouse(float amountOfMovement) { MouseState currentMouseState = Mouse.GetState(); if (currentMouseState.X != previousMouseState.X) { mouseX -= amountOfMovement / 80.0f * (currentMouseState.X - previousMouseState.X); } if (currentMouseState.Y != previousMouseState.Y) { mouseY -= amountOfMovement / 80.0f * (currentMouseState.Y - previousMouseState.Y); } Mouse.SetPosition(Window.ClientBounds.Width / 2, Window.ClientBounds.Height / 2); } private void UpdateCamera() { Matrix rotationMatrix = Matrix.CreateRotationX(mouseY) * Matrix.CreateRotationZ(mouseX); Vector3 cameraLookat = cameraPosition + Vector3.Transform(new Vector3(0, 1, 0), rotationMatrix); Vector3 upVector = Vector3.Transform(new Vector3(0, 0, 1), rotationMatrix); viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookat, upVector); projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)this.Window.ClientBounds.Width / (float)this.Window.ClientBounds.Height, 1.0f, 1000.0f); //Determine the reflection coordinates float reflectionCamZCoord = -cameraPosition.Z + 2 * waterHeight; Vector3 reflectionCamPosition = new Vector3(cameraPosition.X, cameraPosition.Y, reflectionCamZCoord); float reflectionTargetZCoord = -cameraLookat.Z + 2 * waterHeight; Vector3 reflectionCamTarget = new Vector3(cameraLookat.X, cameraLookat.Y, reflectionTargetZCoord); //Determine the up vector Vector3 forwardVector = reflectionCamTarget - reflectionCamPosition; Vector3 sideVector = Vector3.Transform(new Vector3(1, 0, 0), rotationMatrix); Vector3 reflectionCamUp = Vector3.Cross(sideVector, forwardVector); reflectionViewMatrix = Matrix.CreateLookAt(reflectionCamPosition, reflectionCamTarget, reflectionCamUp); } public void updateLightData(Vector4 lightpos) { this.lightpos = lightpos; lampPostPos = new Vector4[2]; lampPostPos[0] = new Vector4(3.0f, 5.0f, 11f, 1); lampPostPos[1] = new Vector4(3.0f, 35.0f, 11f, 1); lightpower = 2f; lightworldviewproj = Matrix.CreateLookAt(new Vector3(lightpos.X, lightpos.Y, lightpos.Z), new Vector3(-2, 10, -3), new Vector3(0, 0, 1)) * Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, (float)this.Window.ClientBounds.Width / (float)this.Window.ClientBounds.Height, 1f, 100f); } /// /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input and playing audio. /// /// Provides a snapshot of timing values. protected override void Update(GameTime gameTime) { // Allows the default game to exit on Xbox 360 and Windows if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); ProcessInput((float)gameTime.ElapsedGameTime.Milliseconds / 30.0f); UpdateCamera(); lightpos.Y += 0.01f; updateLightData(new Vector4(-18, lightpos.Y, 5, 1)); elapsedTime += (float)gameTime.ElapsedGameTime.Milliseconds / 100000.0f; base.Update(gameTime); } private void drawModel(string technique, Model currentModel, Matrix worldMatrix, Texture2D[] textures, bool useBrownInsteadOfTextures) { int i = 0; Matrix[] transforms = new Matrix[currentModel.Bones.Count]; currentModel.CopyAbsoluteBoneTransformsTo(transforms); foreach (ModelMesh modmesh in currentModel.Meshes) { foreach (Effect currenteffect in modmesh.Effects) { currenteffect.CurrentTechnique = effect.Techniques[technique]; currenteffect.Parameters["xCameraViewProjection"].SetValue(viewMatrix * projectionMatrix); currenteffect.Parameters["xUserTexture"].SetValue(textures[i++]); currenteffect.Parameters["xUseBrownInsteadOfTextures"].SetValue(useBrownInsteadOfTextures); //Set lighting data currenteffect.Parameters["xLightPos"].SetValue(lightpos); currenteffect.Parameters["xLightPower"].SetValue(lightpower); currenteffect.Parameters["xWorld"].SetValue(transforms[modmesh.ParentBone.Index] * worldMatrix); //Set shadow data currenteffect.Parameters["xLightViewProjection"].SetValue(lightworldviewproj); currenteffect.Parameters["xShadowMap"].SetValue(texturedRenderedTo); //Set ambient light data currenteffect.Parameters["xLampPostPos"].SetValue(lampPostPos); currenteffect.Parameters["xCameraPos"].SetValue(new Vector4(cameraPosition.X, cameraPosition.Y, cameraPosition.Z, 1)); } modmesh.Draw(); } } //Method to map a given model on the underlying terrain //Useful for placing houses, trees etc. private void drawModelOnTerrain(string technique, Model currentModel, Matrix worldMatrix, float x, float y, Texture2D[] textures, bool useBrownInsteadOfTextures) { //generate the right worldMatrix Vector3 modelPos = terrain.getHeightValue(x, y); worldMatrix *= Matrix.CreateTranslation(modelPos); worldMatrix *= Matrix.CreateTranslation(new Vector3(0.0f, 0.0f, currentModel.Root.Transform.M43 * 2)); drawModel(technique, currentModel, worldMatrix, textures, useBrownInsteadOfTextures); } private void drawModelWithSingleTexture(string technique, Model currentModel, Matrix worldMatrix, Texture2D texture) { Matrix[] transforms = new Matrix[currentModel.Bones.Count]; currentModel.CopyAbsoluteBoneTransformsTo(transforms); foreach (ModelMesh modmesh in currentModel.Meshes) { foreach (Effect currenteffect in modmesh.Effects) { currenteffect.CurrentTechnique = effect.Techniques[technique]; currenteffect.Parameters["xCameraViewProjection"].SetValue(viewMatrix * projectionMatrix); currenteffect.Parameters["xUserTexture"].SetValue(texture); //Set lighting data currenteffect.Parameters["xLightPos"].SetValue(lightpos); currenteffect.Parameters["xLightPower"].SetValue(lightpower); currenteffect.Parameters["xWorld"].SetValue(transforms[modmesh.ParentBone.Index] * worldMatrix); //Set shadow data currenteffect.Parameters["xLightViewProjection"].SetValue(lightworldviewproj); currenteffect.Parameters["xShadowMap"].SetValue(texturedRenderedTo); //Set ambient light data currenteffect.Parameters["xLampPostPos"].SetValue(lampPostPos); currenteffect.Parameters["xCameraPos"].SetValue(new Vector4(cameraPosition.X, cameraPosition.Y, cameraPosition.Z, 1)); } modmesh.Draw(); } } private void drawModelOnTerrainWithSingleTexture(string technique, Model currentModel, Matrix worldMatrix, float x, float y, float scale, Texture2D texture) { //generate the right worldMatrix Vector3 modelPos = terrain.getHeightValue(x, y); worldMatrix *= Matrix.CreateTranslation(modelPos); worldMatrix *= Matrix.CreateTranslation(new Vector3(0.0f, 0.0f, (scale * Math.Abs(currentModel.Root.Transform.M43)) * 1.5f)); drawModelWithSingleTexture(technique, currentModel, worldMatrix, texture); } private void drawScene(string technique) { effect.CurrentTechnique = effect.Techniques[technique]; effect.Parameters["xCameraViewProjection"].SetValue(viewMatrix * projectionMatrix); effect.Parameters["xLightPos"].SetValue(lightpos); effect.Parameters["xLightPower"].SetValue(lightpower); effect.Parameters["xWorld"].SetValue(Matrix.Identity); effect.Parameters["xLightViewProjection"].SetValue(lightworldviewproj); effect.Parameters["xShadowMap"].SetValue(texturedRenderedTo); effect.Parameters["xLampPostPos"].SetValue(lampPostPos); effect.Parameters["xCameraPos"].SetValue(new Vector4(cameraPosition.X, cameraPosition.Y, cameraPosition.Z, 1)); //draw the farm into the level worldMatrix = Matrix.CreateScale(1.0f, 1.0f, 1.0f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ((float)Math.PI / 2); drawModelOnTerrain(technique, FarmModel, worldMatrix, 5, 80, FarmTextures, false); worldMatrix = Matrix.CreateScale(1.0f, 1.0f, 1.0f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(2.0f * (float)Math.PI / 2); drawModelOnTerrain(technique, FarmModel, worldMatrix, 5, 75, FarmTextures, false); worldMatrix = Matrix.CreateScale(1.0f, 1.0f, 1.0f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(2.2f * (float)Math.PI / 2); drawModelOnTerrain(technique, FarmModel, worldMatrix, 5, 60, FarmTextures, false); worldMatrix = Matrix.CreateScale(1.0f, 1.0f, 1.0f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(2.7f * (float)Math.PI / 2); drawModelOnTerrain(technique, FarmModel, worldMatrix, 10, 78, FarmTextures, false); worldMatrix = Matrix.CreateScale(1.0f, 1.0f, 1.0f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(1.8f * (float)Math.PI / 2); drawModelOnTerrain(technique, FarmModel, worldMatrix, 10, 84, FarmTextures, false); //Barrel Tile float x = 10.0f; float y = 86.0f; worldMatrix = Matrix.CreateScale(0.02f, 0.02f, 0.02f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(1.3f * (float)Math.PI / 2); drawModelOnTerrain(technique, BarrelModel, worldMatrix, x, y, BarrelTextures, false); worldMatrix *= Matrix.CreateRotationY((float)Math.PI / 2); drawModelOnTerrain(technique, BarrelModel, worldMatrix, x, (y + .2f), BarrelTextures, false); x = 5.0f; y = 81.0f; worldMatrix = Matrix.CreateScale(0.02f, 0.02f, 0.02f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(1.3f * (float)Math.PI / 2); drawModelOnTerrain(technique, BarrelModel, worldMatrix, x, y, BarrelTextures, false); worldMatrix *= Matrix.CreateRotationY((float)Math.PI / 2); drawModelOnTerrain(technique, BarrelModel, worldMatrix, x, (y + .2f), BarrelTextures, false); //Houses worldMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(1.8f * (float)Math.PI / 2); //We need an extra parameter scale = 0.01f to tell the model that its size has been modified. //This is needed, because otherwise the translation will not fit to the terrain anymore. drawModelOnTerrainWithSingleTexture(technique, HouseModel, worldMatrix, 10, 88, 0.01f, HouseTexture); worldMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(2.8f * (float)Math.PI / 2); //We need an extra parameter scale = 0.01f to tell the model that its size has been modified. //This is needed, because otherwise the translation will not fit to the terrain anymore. drawModelOnTerrainWithSingleTexture(technique, HouseModel, worldMatrix, 10, 68, 0.01f, HouseTexture); worldMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(1.3f * (float)Math.PI / 2); //We need an extra parameter scale = 0.01f to tell the model that its size has been modified. //This is needed, because otherwise the translation will not fit to the terrain anymore. drawModelOnTerrainWithSingleTexture(technique, HouseModel, worldMatrix, 15, 70, 0.01f, HouseTexture); worldMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(2.4f * (float)Math.PI / 2); //We need an extra parameter scale = 0.01f to tell the model that its size has been modified. //This is needed, because otherwise the translation will not fit to the terrain anymore. drawModelOnTerrainWithSingleTexture(technique, HouseModel, worldMatrix, 8, 76, 0.01f, HouseTexture); //Toilets worldMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f) * Matrix.CreateRotationX((float)Math.PI / 2) * Matrix.CreateRotationZ(1.8f * (float)Math.PI / 2); //We need an extra parameter scale = 0.01f to tell the model that its size has been modified. //This is needed, because otherwise the translation will not fit to the terrain anymore. drawModelOnTerrain(technique, ToiletModel, worldMatrix, 10, 90, ToiletTextures, false); } private void drawRefractionMap(GameTime gameTime, Matrix viewMatrix, Matrix projectionMatrix) { Vector3 planeNormalDirection = new Vector3(0, 0, -1); planeNormalDirection.Normalize(); Vector4 planeCoefficients = new Vector4(planeNormalDirection, waterHeight + 1.0f); Matrix invCamMatrix = Matrix.Invert(viewMatrix * projectionMatrix); invCamMatrix = Matrix.Transpose(invCamMatrix); planeCoefficients = Vector4.Transform(planeCoefficients, invCamMatrix); Plane refractionClipPlane = new Plane(planeCoefficients); graphics.GraphicsDevice.ClipPlanes[0].Plane = refractionClipPlane; graphics.GraphicsDevice.ClipPlanes[0].IsEnabled = true; graphics.GraphicsDevice.SetRenderTarget(0, refractionRenderTarget); graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0); terrain.Draw(gameTime, viewMatrix, projectionMatrix); graphics.GraphicsDevice.ResolveRenderTarget(0); refractionMap = refractionRenderTarget.GetTexture(); graphics.GraphicsDevice.SetRenderTarget(0, null); graphics.GraphicsDevice.ClipPlanes[0].IsEnabled = false; } private void DrawReflectionMap(GameTime gameTime, Matrix viewMatrix, Matrix projectionMatrix) { Vector3 planeNormalDirection = new Vector3(0, 0, 1); planeNormalDirection.Normalize(); Vector4 planeCoefficients = new Vector4(planeNormalDirection, -waterHeight + 1.0f); Matrix camMatrix = reflectionViewMatrix * projectionMatrix; Matrix invCamMatrix = Matrix.Invert(camMatrix); invCamMatrix = Matrix.Transpose(invCamMatrix); planeCoefficients = Vector4.Transform(planeCoefficients, invCamMatrix); Plane refractionClipPlane = new Plane(planeCoefficients); graphics.GraphicsDevice.ClipPlanes[0].Plane = refractionClipPlane; graphics.GraphicsDevice.ClipPlanes[0].IsEnabled = true; graphics.GraphicsDevice.SetRenderTarget(0, reflectionRenderTarget); graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.CornflowerBlue, 1.0f, 0); terrain.Draw(gameTime, reflectionViewMatrix, projectionMatrix); sky.Draw(gameTime, reflectionViewMatrix, projectionMatrix, cameraPosition); drawScene("ShadowMap"); drawScene("ShadowedScene"); graphics.GraphicsDevice.ResolveRenderTarget(0); reflectionMap = reflectionRenderTarget.GetTexture(); graphics.GraphicsDevice.SetRenderTarget(0, null); graphics.GraphicsDevice.ClipPlanes[0].IsEnabled = false; } /// /// This is called when the game should draw itself. /// /// Provides a snapshot of timing values. protected override void Draw(GameTime gameTime) { drawRefractionMap(gameTime, viewMatrix, projectionMatrix); DrawReflectionMap(gameTime, viewMatrix, projectionMatrix); //Clear the device, otherwise we see the blue reflection stripes. graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.CornflowerBlue, 1.0f, 0); //Draw the objects graphics.GraphicsDevice.SetRenderTarget(0, renderTarget); drawScene("ShadowMap"); graphics.GraphicsDevice.ResolveRenderTarget(0); texturedRenderedTo = renderTarget.GetTexture(); graphics.GraphicsDevice.SetRenderTarget(0, null); graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.CornflowerBlue, 1.0f, 0); drawScene("ShadowedScene"); //Draw the terrain graphics.GraphicsDevice.RenderState.CullMode = CullMode.None; terrain.Draw(gameTime, viewMatrix, projectionMatrix); sky.Draw(gameTime, viewMatrix, projectionMatrix, cameraPosition); initializeWater(); //If we go under water, we want to look through the water if we tilt our head. graphics.GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace; water.Draw(viewMatrix, projectionMatrix, reflectionViewMatrix, reflectionMap, refractionMap, cameraPosition, elapsedTime); hud.Draw(gameTime); base.Draw(gameTime); } } }