private void GenerateRandomTerrain() { var hm2 = new HeightMap(Info.HeightMapWidth, Info.HeightMapHeight, 2.0f); _heightMap.CreateRandomHeightMapParallel(Info.Seed, Info.NoiseSize1, Info.Persistence1, Info.Octaves1, true); hm2.CreateRandomHeightMapParallel(Info.Seed, Info.NoiseSize2, Info.Persistence2, Info.Octaves2, true); hm2.Cap(hm2.MaxHeight * 0.4f); _heightMap *= hm2; }
private void SmoothBlendMap(HeightMap hm, List<Color4> colors) { for (int y = 0; y < _heightMap.HeightMapHeight; y++) { for (int x = 0; x < _heightMap.HeightMapWidth; x++) { var sum = colors[x + y * hm.HeightMapHeight]; var num = 0; for (int y1 = y - 1; y1 < y + 2; y1++) { for (int x1 = x - 1; x1 < x + 1; x1++) { if (hm.InBounds(y1, x1)) { sum += colors[x1 + y1 * hm.HeightMapHeight]; num++; } } } colors[x + y * hm.HeightMapHeight] = new Color4(sum.Alpha / num, sum.Red / num, sum.Green / num, sum.Blue / num); } } }
private ShaderResourceView CreateBlendMap(HeightMap hm, Device device) { var colors = new List<Color4>(); for (int y = 0; y < _heightMap.HeightMapHeight; y++) { for (int x = 0; x < _heightMap.HeightMapWidth; x++) { var elev = _heightMap[y, x]; var color = new Color4(0); if (elev > hm.MaxHeight * (0.05f + MathF.Rand(-0.05f, 0.05f))) { // dark green grass texture color.Red = elev / (hm.MaxHeight) + MathF.Rand(-0.05f, 0.05f); } if (elev > hm.MaxHeight * (0.4f + MathF.Rand(-0.15f, 0.15f))) { // stone texture color.Green = elev / hm.MaxHeight + MathF.Rand(-0.05f, 0.05f); } if (elev > hm.MaxHeight * (0.75f + MathF.Rand(-0.1f, 0.1f))) { // snow texture color.Alpha = elev / hm.MaxHeight + MathF.Rand(-0.05f, 0.05f); } colors.Add(color); } D3DApp.GD3DApp.ProgressUpdate.Draw(0.95f + 0.05f * ((float)y / _heightMap.HeightMapHeight), "Generating blendmap"); } SmoothBlendMap(hm, colors); SmoothBlendMap(hm, colors); var texDec = new Texture2DDescription { ArraySize = 1, BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.None, Format = Format.R32G32B32A32_Float, SampleDescription = new SampleDescription(1, 0), Height = _heightMap.HeightMapHeight, Width = _heightMap.HeightMapWidth, MipLevels = 1, OptionFlags = ResourceOptionFlags.None, Usage = ResourceUsage.Default }; var blendTex = new Texture2D( device, texDec, new DataRectangle( _heightMap.HeightMapWidth * Marshal.SizeOf(typeof(Color4)), new DataStream(colors.ToArray(), false, false) ) ) {DebugName = "terrain blend texture"}; var srvDesc = new ShaderResourceViewDescription { Format = texDec.Format, Dimension = ShaderResourceViewDimension.Texture2D, MostDetailedMip = 0, MipLevels = -1 }; var srv = new ShaderResourceView(device, blendTex, srvDesc); Util.ReleaseCom(ref blendTex); return srv; }
public void Init(Device device, DeviceContext dc, InitInfo info) { D3DApp.GD3DApp.ProgressUpdate.Draw(0, "Initializing terrain"); if (device.FeatureLevel == FeatureLevel.Level_11_0) { _useTessellation = true; } Info = info; NumPatchVertRows = ((Info.HeightMapHeight - 1) / CellsPerPatch) + 1; NumPatchVertCols = ((Info.HeightMapWidth - 1) / CellsPerPatch) + 1; _numPatchVertices = NumPatchVertRows * NumPatchVertCols; _numPatchQuadFaces = (NumPatchVertRows - 1) * (NumPatchVertCols - 1); if (Info.Material.HasValue) { _material = Info.Material.Value; } _heightMap = new HeightMap(Info.HeightMapWidth, Info.HeightMapHeight, Info.HeightScale); if (!string.IsNullOrEmpty(Info.HeightMapFilename)) { D3DApp.GD3DApp.ProgressUpdate.Draw(0.1f, "Loading terrain from file"); _heightMap.LoadHeightmap(Info.HeightMapFilename); } else { D3DApp.GD3DApp.ProgressUpdate.Draw(0.1f, "Generating random terrain"); GenerateRandomTerrain(); } D3DApp.GD3DApp.ProgressUpdate.Draw(0.50f, "Smoothing terrain"); _heightMap.Smooth(true); D3DApp.GD3DApp.ProgressUpdate.Draw(0.75f, "Building terrain patches"); if (_useTessellation) { CalcAllPatchBoundsY(); BuildQuadPatchVB(device); BuildQuadPatchIB(device); } else { BuildPatches(device); } D3DApp.GD3DApp.ProgressUpdate.Draw(0.85f, "Loading textures"); _heightMapSRV = _heightMap.BuildHeightmapSRV(device); var layerFilenames = new List<string> { Info.LayerMapFilename0 ?? "textures/null.bmp", Info.LayerMapFilename1 ?? "textures/null.bmp", Info.LayerMapFilename2 ?? "textures/null.bmp", Info.LayerMapFilename3 ?? "textures/null.bmp", Info.LayerMapFilename4 ?? "textures/null.bmp" }; _layerMapArraySRV = Util.CreateTexture2DArraySRV(device, dc, layerFilenames.ToArray(), Format.R8G8B8A8_UNorm); if (!string.IsNullOrEmpty(Info.BlendMapFilename)) { D3DApp.GD3DApp.ProgressUpdate.Draw(0.95f, "Loading blendmap from file"); _blendMapSRV = ShaderResourceView.FromFile(device, Info.BlendMapFilename); _blendMapSRV.Resource.DebugName = Info.BlendMapFilename; } else { _blendMapSRV = CreateBlendMap(_heightMap, device); } _bvh = new BVH { Root = BuildBvh(new Vector2(0, 0), new Vector2((Info.HeightMapWidth - 1), (Info.HeightMapHeight - 1))) }; if (DebugBvh) { BuildBVHDebugBuffers(device); } D3DApp.GD3DApp.ProgressUpdate.Draw(1.0f, "Terrain initialized"); }
public void Init(Device device, DeviceContext dc, InitInfo info) { D3DApp.GD3DApp.ProgressUpdate.Draw(0, "Initializing terrain"); Info = info; HeightMap = new HeightMap(Info.HeightMapWidth, Info.HeightMapHeight, Info.HeightScale); if (!string.IsNullOrEmpty(Info.HeightMapFilename)) { D3DApp.GD3DApp.ProgressUpdate.Draw(0.1f, "Loading terrain from file"); HeightMap.LoadHeightmap(Info.HeightMapFilename); } else { D3DApp.GD3DApp.ProgressUpdate.Draw(0.1f, "Generating random terrain"); GenerateRandomTerrain(); D3DApp.GD3DApp.ProgressUpdate.Draw(0.50f, "Smoothing terrain"); HeightMap.Smooth(true); } InitTileMap(); D3DApp.GD3DApp.ProgressUpdate.Draw(0.55f, "Building picking quadtree..."); QuadTree = new QuadTree { Root = BuildQuadTree(new Vector2(0, 0), new Vector2((Info.HeightMapWidth - 1), (Info.HeightMapHeight - 1))) }; Renderer.Init(device, dc, this); }
// procedural heightmap stuff public static HeightMap operator *(HeightMap lhs, HeightMap rhs) { var hm = new HeightMap(lhs.HeightMapWidth, lhs.HeightMapHeight, lhs.MaxHeight); for (int y = 0; y < lhs.HeightMapHeight; y++) { for (int x = 0; x < lhs.HeightMapWidth; x++) { var a = lhs[y, x] / lhs.MaxHeight; var b = 1.0f; if (rhs.InBounds(y, x)) { b = rhs[y, x] / rhs.MaxHeight; } hm[y, x] = a * b * hm.MaxHeight; } } return hm; }
private static void SmoothBlendMap(HeightMap hm, List<Color4> colors, Terrain terrain) { for (var y = 0; y < terrain.HeightMap.HeightMapHeight; y++) { for (var x = 0; x < terrain.HeightMap.HeightMapWidth; x++) { var sum = colors[x + y * hm.HeightMapHeight]; var num = 0; for (var y1 = y - 1; y1 < y + 2; y1++) { for (var x1 = x - 1; x1 < x + 1; x1++) { if (!hm.InBounds(y1, x1)) { continue; } sum += colors[x1 + y1 * hm.HeightMapHeight]; num++; } } colors[x + y * hm.HeightMapHeight] = new Color4(sum.Alpha / num, sum.Red / num, sum.Green / num, sum.Blue / num); } } }