public ParallaxTerrainSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); var scene = _graphicsScreen.Scene; Services.Register(typeof(IScene), null, scene); // Add standard game objects. var cameraGameObject = new CameraObject(Services, 5000); cameraGameObject.ResetPose(new Vector3(0, 2, 0), 0, 0); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); GameObjectService.Objects.Add(new GrabObject(Services)); GameObjectService.Objects.Add(new DynamicSkyObject(Services, true, false, true) { EnableCloudShadows = false, }); GameObjectService.Objects.Add(new ObjectCreatorObject(Services)); // Create terrain. _terrainObject = new TerrainObject(Services); GameObjectService.Objects.Add(_terrainObject); // To see parallax occlusion mapping, we need a detail texture with a height map. // In this sample we reuse the pavement texture of the ParallaxMappingSample and // add it to the terrain. for (int row = 0; row < 2; row++) { for (int column = 0; column < 2; column++) { var terrainTile = _terrainObject.TerrainNode.Terrain.Tiles[row * 2 + column]; string tilePostfix = "-" + row + "-" + column; // e.g. "-0-1" var materialPavement = new TerrainMaterialLayer(GraphicsService) { DiffuseColor = new Vector3(1), SpecularColor = new Vector3(5), SpecularPower = 20, DiffuseTexture = ContentManager.Load <Texture2D>("Parallax/AgedPavement_diffuse"), NormalTexture = ContentManager.Load <Texture2D>("Parallax/AgedPavement_normal"), SpecularTexture = ContentManager.Load <Texture2D>("Parallax/AgedPavement_specular"), HeightTexture = ContentManager.Load <Texture2D>("Parallax/AgedPavement_height"), TileSize = 0.005f * 512, BlendTexture = ContentManager.Load <Texture2D>("Terrain/Terrain001-Blend-Grass" + tilePostfix), BlendTextureChannel = 0, BlendHeightInfluence = 0.5f, BlendThreshold = 0.5f, BlendRange = 0.5f, }; terrainTile.Layers.Add(materialPavement); } } // Replace the terrain effects with effects which support parallax occlusion mapping. UpdateTerrainMaterial(true); CreateGuiControls(); }
public TerrainTextureSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); var scene = _graphicsScreen.Scene; Services.Register(typeof(IScene), null, scene); // Add gravity and damping to the physics simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services, 60); cameraGameObject.ResetPose(new Vector3F(0, 1.8f, 0), 0, 0); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; for (int i = 0; i < 10; i++) { GameObjectService.Objects.Add(new DynamicObject(Services, 1)); } GameObjectService.Objects.Add(new DynamicSkyObject(Services, true, false, true)); // Create a simple flat terrain. var terrain = new Terrain(); _terrainTile = new TerrainTile(GraphicsService) { OriginX = -100, OriginZ = -100, CellSize = 1, }; terrain.Tiles.Add(_terrainTile); // Create a flat dummy height texture. float[] heights = new float[200 * 200]; Texture2D heightTexture = null; TerrainHelper.CreateHeightTexture( GraphicsService.GraphicsDevice, heights, 200, 200, false, ref heightTexture); _terrainTile.HeightTexture = heightTexture; var shadowMapEffect = ContentManager.Load <Effect>("DigitalRune/Terrain/TerrainShadowMap"); var gBufferEffect = ContentManager.Load <Effect>("DigitalRune/Terrain/TerrainGBuffer"); var materialEffect = ContentManager.Load <Effect>("DigitalRune/Terrain/TerrainMaterial"); var material = new Material { { "ShadowMap", new EffectBinding(GraphicsService, shadowMapEffect, null, EffectParameterHint.Material) }, { "GBuffer", new EffectBinding(GraphicsService, gBufferEffect, null, EffectParameterHint.Material) }, { "Material", new EffectBinding(GraphicsService, materialEffect, null, EffectParameterHint.Material) } }; var terrainNode = new TerrainNode(terrain, material) { DetailClipmap = { CellsPerLevel = 1364, NumberOfLevels = 9, EnableMipMap = true, }, }; scene.Children.Add(terrainNode); // Add 3 detail textures layers: gravel, rock, snow. float detailCellSize = terrainNode.DetailClipmap.CellSizes[0]; var materialGravel = new TerrainMaterialLayer(GraphicsService) { DiffuseTexture = ContentManager.Load <Texture2D>("Terrain/Gravel-Diffuse"), NormalTexture = ContentManager.Load <Texture2D>("Terrain/Gravel-Normal"), SpecularTexture = ContentManager.Load <Texture2D>("Terrain/Gravel-Specular"), TileSize = detailCellSize * 512, BlendRange = 0.1f, }; _terrainTile.Layers.Add(materialGravel); var noiseTexture = NoiseHelper.GetNoiseTexture(GraphicsService, 128, 60); var materialRock = new TerrainMaterialLayer(GraphicsService) { DiffuseTexture = ContentManager.Load <Texture2D>("Terrain/Rock-02-Diffuse"), NormalTexture = ContentManager.Load <Texture2D>("Terrain/Rock-02-Normal"), SpecularTexture = ContentManager.Load <Texture2D>("Terrain/Rock-02-Specular"), HeightTexture = ContentManager.Load <Texture2D>("Terrain/Rock-02-Height"), TileSize = detailCellSize * 1024, DiffuseColor = new Vector3F(1 / 0.702f), BlendTexture = noiseTexture, BlendTextureChannel = 0, BlendRange = 0.1f, TerrainHeightBlendRange = 0.1f, }; _terrainTile.Layers.Add(materialRock); var materialSnow = new TerrainMaterialLayer(GraphicsService) { DiffuseTexture = ContentManager.Load <Texture2D>("Terrain/Snow-Diffuse"), NormalTexture = ContentManager.Load <Texture2D>("Terrain/Snow-Normal"), SpecularTexture = ContentManager.Load <Texture2D>("Terrain/Snow-Specular"), TileSize = detailCellSize * 512, BlendTexture = noiseTexture, BlendTextureChannel = 1, BlendRange = 0.1f, }; _terrainTile.Layers.Add(materialSnow); // Create a flat plane for collision detection. var rigidBody = new RigidBody(new PlaneShape(), new MassFrame(), null) { MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(rigidBody); CreateGuiControls(); }
// Initialize the terrain layers which define the detail textures which are painted onto // the terrain. private void InitializeTerrainLayers(ContentManager content) { // The appearance of each terrain tile can be specified using layers. Each layer usually // specifies one material type, e.g. grass, rock, snow. Layers can also be used to add // decals or roads to the terrain, which is demonstrated in other samples. for (int row = 0; row < 2; row++) { for (int column = 0; column < 2; column++) { var terrainTile = _tiles[row, column].TerrainTile; string tilePostfix = "-" + row + "-" + column; // e.g. "-0-1" // This first layer contains only a base tint texture which is visible where no other // detail material layers are rendered (e.g. in the distance). var tintTexture = content.Load<Texture2D>("Terrain/Terrain001-Tint" + tilePostfix); var baseColorLayer = new TerrainMaterialLayer(_graphicsService) { TintTexture = tintTexture, TintStrength = 1, }; terrainTile.Layers.Add(baseColorLayer); // The tiling of the detail textures can be visible and unattractive in the distance. // To avoid this, we can fade-out the detail material layers. int fadeOutStart = 4; // The fade-out starts in clipmap level 4. int fadeOutEnd = 6; // The fade-out ends in clipmap level 6, which means the layer is // not drawn into the detail clipmap levels >= 6. // Add a gravel texture which covers the whole terrain near the camera and fades // out in the distance. var materialGravel = new TerrainMaterialLayer(_graphicsService) { // The tiling detail material textures. DiffuseTexture = content.Load<Texture2D>("Terrain/Gravel-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Gravel-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Gravel-Specular"), // The size of one tile in world space units. TileSize = DetailCellSize * 512, // The diffuse detail texture is multiplied with the tint texture. TintTexture = tintTexture, TintStrength = 1.0f, // The diffuse color is set to 1 / average texture color. This turns the average // detail texture color and conserve the color of the tint texture. // (To determine the average color manually: Load the texture in a image-processing // tool, like GIMP. Blur the texture until it is one solid color. Pick the color using // a color picker tool. If the image-processing tool uses sRGB, then convert the color // to linear RGB: colorLinear = colorSRgb^2.2) DiffuseColor = new Vector3(1 / 0.246f, 1 / 0.205f, 1 / 0.171f), SpecularColor = new Vector3(0.5f), SpecularPower = 20, FadeOutStart = fadeOutStart, FadeOutEnd = fadeOutEnd, }; terrainTile.Layers.Add(materialGravel); // Over the gravel we add a layer of grass. // A blend texture contains a mask which defines where the grass is visible. // The blend range determines how quickly the width of the transition between grass // and the underlying layers. float blendRange = 0.6f; var materialGrass = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load<Texture2D>("Terrain/Grass-Dry-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Grass-Dry-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Grass-Dry-Specular"), TileSize = DetailCellSize * 1024, TintTexture = tintTexture, TintStrength = 1, DiffuseColor = new Vector3(1 / 0.25f), SpecularColor = new Vector3(1), SpecularPower = 20, BlendTexture = content.Load<Texture2D>("Terrain/Terrain001-Blend-Grass" + tilePostfix), // The blend texture can contain a blend mask in each channel (R, G, B or A). // Use the red channel (channel 0) BlendTextureChannel = 0, BlendRange = blendRange, FadeOutStart = fadeOutStart, FadeOutEnd = fadeOutEnd, }; terrainTile.Layers.Add(materialGrass); // Side note: Terrain layers can also be defined using .drmat files: //terrainTile.Layers.Add(new TerrainMaterialLayer(content.Load<Material>("Terrain/MyLayerMaterial"))); // Let's add a layer of sand. Sand occurs only in the tiles 1/0 and 1/1. if (row == 1) { var materialSand = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load<Texture2D>("Terrain/Sand-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Sand-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Sand-Specular"), TileSize = DetailCellSize * 512, TintTexture = tintTexture, TintStrength = 1f, DiffuseColor = new Vector3(1 / 0.429f, 1 / 0.347f, 1 / 0.275f), SpecularColor = new Vector3(10), SpecularPower = 50, BlendTexture = content.Load<Texture2D>("Terrain/Terrain001-Blend-Sand" + tilePostfix), BlendTextureChannel = 0, BlendRange = blendRange, FadeOutStart = fadeOutStart, FadeOutEnd = fadeOutEnd, }; terrainTile.Layers.Add(materialSand); } // The dirt layer is used on the brown rocks near the beach. To make the rocks more // interesting we use a rock texture with a larger tile size. This is also visible // in the distance. // Then we also mix-in the gravel texture to add more detail near the camera. var materialDirt = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load<Texture2D>("Terrain/Rock-02-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Rock-02-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Rock-02-Specular"), HeightTexture = content.Load<Texture2D>("Terrain/Rock-02-Height"), TileSize = DetailCellSize * 1024 * 10, TintTexture = tintTexture, TintStrength = 1f, DiffuseColor = new Vector3(1 / 0.702f) * new Vector3(0.9f, 1, 0.9f), SpecularColor = new Vector3(2), SpecularPower = 100, BlendTexture = content.Load<Texture2D>("Terrain/Terrain001-Blend-Dirt" + tilePostfix), BlendTextureChannel = 0, BlendRange = blendRange, }; terrainTile.Layers.Add(materialDirt); var materialDirtDetail = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load<Texture2D>("Terrain/Gravel-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Gravel-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Gravel-Specular"), TileSize = DetailCellSize * 512, TintTexture = tintTexture, TintStrength = 1f, DiffuseColor = new Vector3(1 / 0.59f, 1 / 0.537f, 1 / 0.5f), SpecularColor = new Vector3(0.5f), SpecularPower = 20, // This layer is transparent to blend with the underlying rock texture. Alpha = 0.5f, BlendTexture = content.Load<Texture2D>("Terrain/Terrain001-Blend-Dirt" + tilePostfix), BlendTextureChannel = 0, BlendRange = blendRange, FadeOutStart = fadeOutStart, FadeOutEnd = fadeOutEnd, }; terrainTile.Layers.Add(materialDirtDetail); // The gray rocks use two layered rock textures. var materialRock = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load<Texture2D>("Terrain/Rock-02-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Rock-02-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Rock-02-Specular"), HeightTexture = content.Load<Texture2D>("Terrain/Rock-02-Height"), TileSize = DetailCellSize * 1024 * 20, TintTexture = tintTexture, TintStrength = 1f, DiffuseColor = new Vector3(1 / 0.702f) * 1, SpecularColor = new Vector3(2), SpecularPower = 100, BlendTexture = content.Load<Texture2D>("Terrain/Terrain001-Blend-Rock" + tilePostfix), BlendTextureChannel = 0, BlendRange = blendRange, }; terrainTile.Layers.Add(materialRock); var materialRockDetail = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load<Texture2D>("Terrain/Rock-02-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Rock-02-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Rock-02-Specular"), HeightTexture = content.Load<Texture2D>("Terrain/Rock-02-Height"), TileSize = DetailCellSize * 1024, TintTexture = tintTexture, TintStrength = 1f, DiffuseColor = new Vector3(1 / 0.702f) * 1, SpecularColor = new Vector3(2), SpecularPower = 100, Alpha = 0.5f, BlendTexture = content.Load<Texture2D>("Terrain/Terrain001-Blend-Rock" + tilePostfix), BlendTextureChannel = 0, BlendRange = blendRange, FadeOutStart = fadeOutStart, FadeOutEnd = fadeOutEnd, }; terrainTile.Layers.Add(materialRockDetail); // Add some gravel from hydraulic erosion over the rocks. var materialFlow = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load<Texture2D>("Terrain/Gravel-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Gravel-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Gravel-Specular"), TileSize = DetailCellSize * 512, TintTexture = tintTexture, TintStrength = 1f, DiffuseColor = new Vector3(1 / 0.246f, 1 / 0.205f, 1 / 0.171f), SpecularColor = new Vector3(1), BlendRange = blendRange, BlendTexture = content.Load<Texture2D>("Terrain/Terrain001-Blend-Flow" + tilePostfix), BlendTextureChannel = 0, SpecularPower = 20, FadeOutStart = fadeOutStart, FadeOutEnd = fadeOutEnd, }; terrainTile.Layers.Add(materialFlow); // Add snow in the tiles 0/0 and 0/1. if (row == 0) { var materialSnow = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load<Texture2D>("Terrain/Snow-Diffuse"), NormalTexture = content.Load<Texture2D>("Terrain/Snow-Normal"), SpecularTexture = content.Load<Texture2D>("Terrain/Snow-Specular"), TileSize = DetailCellSize * 512, TintTexture = tintTexture, TintStrength = 0.0f, DiffuseColor = new Vector3(1), SpecularColor = new Vector3(10), SpecularPower = 100, BlendTexture = content.Load<Texture2D>("Terrain/Terrain001-Blend-Snow" + tilePostfix), BlendTextureChannel = 0, BlendRange = 0.5f, BlendThreshold = 0.4f, BlendNoiseInfluence = 0.5f, NoiseTileSize = 20, }; terrainTile.Layers.Add(materialSnow); } } } }
// Initialize the terrain layers which define the detail textures which are painted onto // the terrain. // The materials are blended based on the terrain heights and slopes. private void InitializeTerrainLayers(ContentManager content) { var materialGravel = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load <Texture2D>("Terrain/Gravel-Diffuse"), NormalTexture = content.Load <Texture2D>("Terrain/Gravel-Normal"), SpecularTexture = content.Load <Texture2D>("Terrain/Gravel-Specular"), DiffuseColor = new Vector3F(1 / 0.246f, 1 / 0.205f, 1 / 0.171f) * new Vector3F(0.042f, 0.039f, 0.027f), TileSize = DetailCellSize * 512, }; _terrainTile.Layers.Add(materialGravel); var materialGrass = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load <Texture2D>("Terrain/Grass-Dry-Diffuse"), NormalTexture = content.Load <Texture2D>("Terrain/Grass-Dry-Normal"), SpecularTexture = content.Load <Texture2D>("Terrain/Grass-Dry-Specular"), DiffuseColor = new Vector3F(0.17f, 0.20f, 0.11f), TileSize = DetailCellSize * 1024, TerrainHeightMin = -1000, TerrainHeightMax = 40, TerrainSlopeMin = -1, TerrainSlopeMax = 0.3f, }; _terrainTile.Layers.Add(materialGrass); var materialGrassDry = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load <Texture2D>("Terrain/Grass-Dry-Diffuse"), NormalTexture = content.Load <Texture2D>("Terrain/Grass-Dry-Normal"), SpecularTexture = content.Load <Texture2D>("Terrain/Grass-Dry-Specular"), DiffuseColor = new Vector3F(0.15f, 0.18f, 0.12f), TileSize = DetailCellSize * 1024, TerrainHeightMin = -1000, TerrainHeightMax = 60, TerrainHeightBlendRange = 10, TerrainSlopeMin = 0.3f, TerrainSlopeMax = 0.4f, }; _terrainTile.Layers.Add(materialGrassDry); var materialRock = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load <Texture2D>("Terrain/Rock-02-Diffuse"), NormalTexture = content.Load <Texture2D>("Terrain/Rock-02-Normal"), SpecularTexture = content.Load <Texture2D>("Terrain/Rock-02-Specular"), HeightTexture = content.Load <Texture2D>("Terrain/Rock-02-Height"), TileSize = DetailCellSize * 1024 * 10, DiffuseColor = new Vector3F(0.15f, 0.15f, 0.12f), SpecularColor = new Vector3F(2), SpecularPower = 100, TerrainHeightMin = -1000, TerrainHeightMax = 1000, TerrainHeightBlendRange = 20, TerrainSlopeMin = 0.5f, TerrainSlopeMax = 3, }; _terrainTile.Layers.Add(materialRock); var materialRockDetail = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load <Texture2D>("Terrain/Rock-02-Diffuse"), NormalTexture = content.Load <Texture2D>("Terrain/Rock-02-Normal"), SpecularTexture = content.Load <Texture2D>("Terrain/Rock-02-Specular"), HeightTexture = content.Load <Texture2D>("Terrain/Rock-02-Height"), TileSize = DetailCellSize * 1024, DiffuseColor = new Vector3F(0.15f, 0.15f, 0.13f), SpecularColor = new Vector3F(0.5f), SpecularPower = 20, Alpha = 0.7f, FadeOutStart = 4, FadeOutEnd = 6, TerrainHeightMin = -1000, TerrainHeightMax = 1000, TerrainHeightBlendRange = 10, TerrainSlopeMin = 0.5f, TerrainSlopeMax = 3, BlendHeightInfluence = 1, }; _terrainTile.Layers.Add(materialRockDetail); var materialSnow = new TerrainMaterialLayer(_graphicsService) { DiffuseTexture = content.Load <Texture2D>("Terrain/Snow-Diffuse"), NormalTexture = content.Load <Texture2D>("Terrain/Snow-Normal"), SpecularTexture = content.Load <Texture2D>("Terrain/Snow-Specular"), TileSize = DetailCellSize * 512, DiffuseColor = new Vector3F(1), SpecularColor = new Vector3F(1), SpecularPower = 100, TerrainHeightMin = 60, TerrainHeightMax = 1000, TerrainHeightBlendRange = 1, TerrainSlopeMin = -1, TerrainSlopeMax = 0.5f, TerrainSlopeBlendRange = 0.1f, }; _terrainTile.Layers.Add(materialSnow); }