public override void DoCreateTile(int level, int tx, int ty, List <TileStorage.Slot> slot) { var levelLength = level + DeltaLevel - RootLevel; if (!(levelLength >= 0 && (tx >> levelLength) == RootTx && (ty >> levelLength) == RootTy)) { return; } level = levelLength; tx = tx - (RootTx << level); ty = ty - (RootTy << level); CPUTileStorage.CPUSlot <float> cpuSlot = slot[0] as CPUTileStorage.CPUSlot <float>; if (cpuSlot == null) { throw new NullReferenceException("cpuSlot"); } cpuSlot.ClearData(); ReadTile(level, tx, ty, cpuSlot.Data); base.DoCreateTile(level, tx, ty, slot); }
public override void DoCreateTile(int level, int tx, int ty, List <TileStorage.Slot> slot) { var gpuSlot = slot[0] as GPUTileStorage.GPUSlot; if (gpuSlot == null) { throw new NullReferenceException("gpuSlot"); } var tileWidth = gpuSlot.Owner.TileSize; var tileSize = tileWidth - 4; GPUTileStorage.GPUSlot parentGpuSlot = null; if (level > 0) { var parentTile = FindTile(level - 1, tx / 2, ty / 2, false, true); if (parentTile != null) { parentGpuSlot = parentTile.GetSlot(0) as GPUTileStorage.GPUSlot; } else { throw new MissingTileException("Find parent tile failed"); } } if (parentGpuSlot == null && level > 0) { throw new NullReferenceException("parentGpuSlot"); } UpSampleMaterial.SetFloat(uniforms.tileWidth, tileWidth); if (level > 0) { var tex = parentGpuSlot.Texture; UpSampleMaterial.SetTexture(uniforms.coarseLevelSampler, tex); var dx = (float)(tx % 2) * (float)(tileSize / 2.0f); var dy = (float)(ty % 2) * (float)(tileSize / 2.0f); var coarseLevelOSL = new Vector4((dx + 0.5f) / (float)tex.width, (dy + 0.5f) / (float)tex.height, 1.0f / (float)tex.width, 0.0f); UpSampleMaterial.SetVector(uniforms.coarseLevelOSL, coarseLevelOSL); } else { UpSampleMaterial.SetVector(uniforms.coarseLevelOSL, new Vector4(-1.0f, -1.0f, -1.0f, -1.0f)); } if (OrthoCPUProducer != null && OrthoCPUProducer.HasTile(level, tx, ty)) { var orthoCPUTile = OrthoCPUProducer.FindTile(level, tx, ty, false, true); CPUTileStorage.CPUSlot <byte> orthoCPUSlot = null; if (orthoCPUTile != null) { orthoCPUSlot = orthoCPUTile.GetSlot(0) as CPUTileStorage.CPUSlot <byte>; } else { throw new MissingTileException("Find orthoCPU tile failed"); } if (orthoCPUSlot == null) { throw new NullReferenceException("orthoCPUSlot"); } var channels = OrthoCPUProducer.Channels; var color = new Color32(); var data = orthoCPUSlot.Data; for (int x = 0; x < tileWidth; x++) { for (int y = 0; y < tileWidth; y++) { color.r = data[(x + y * tileWidth) * channels]; if (channels > 1) { color.g = data[(x + y * tileWidth) * channels + 1]; } if (channels > 2) { color.b = data[(x + y * tileWidth) * channels + 2]; } if (channels > 3) { color.a = data[(x + y * tileWidth) * channels + 3]; } ResidualTexture.SetPixel(x, y, color); } } ResidualTexture.Apply(); UpSampleMaterial.SetTexture(uniforms.residualSampler, ResidualTexture); UpSampleMaterial.SetVector(uniforms.residualOSH, new Vector4(0.5f / (float)tileWidth, 0.5f / (float)tileWidth, 1.0f / (float)tileWidth, 0.0f)); } else { UpSampleMaterial.SetTexture(uniforms.residualSampler, null); UpSampleMaterial.SetVector(uniforms.residualOSH, new Vector4(-1, -1, -1, -1)); } var rs = level < NoiseAmplitudes.Length ? NoiseAmplitudes[level] : 0.0f; var noiseL = 0; if (rs != 0.0f) { if (TerrainNode.Face == 1) { int offset = 1 << level; int bottomB = Noise.Noise2D(tx + 0.5f, ty + offset) > 0.0f ? 1 : 0; int rightB = (tx == offset - 1 ? Noise.Noise2D(ty + offset + 0.5f, offset) : Noise.Noise2D(tx + 1.0f, ty + offset + 0.5f)) > 0.0f ? 2 : 0; int topB = (ty == offset - 1 ? Noise.Noise2D((3.0f * offset - 1.0f - tx) + 0.5f, offset) : Noise.Noise2D(tx + 0.5f, ty + offset + 1.0f)) > 0.0f ? 4 : 0; int leftB = (tx == 0 ? Noise.Noise2D((4.0f * offset - 1.0f - ty) + 0.5f, offset) : Noise.Noise2D(tx, ty + offset + 0.5f)) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } else if (TerrainNode.Face == 6) { int offset = 1 << level; int bottomB = (ty == 0 ? Noise.Noise2D((3.0f * offset - 1.0f - tx) + 0.5f, 0) : Noise.Noise2D(tx + 0.5f, ty - offset)) > 0.0f ? 1 : 0; int rightB = (tx == offset - 1.0f ? Noise.Noise2D((2.0f * offset - 1.0f - ty) + 0.5f, 0) : Noise.Noise2D(tx + 1.0f, ty - offset + 0.5f)) > 0.0f ? 2 : 0; int topB = Noise.Noise2D(tx + 0.5f, ty - offset + 1.0f) > 0.0f ? 4 : 0; int leftB = (tx == 0 ? Noise.Noise2D(3.0f * offset + ty + 0.5f, 0) : Noise.Noise2D(tx, ty - offset + 0.5f)) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } else { int offset = (1 << level) * (TerrainNode.Face - 2); int bottomB = Noise.Noise2D(tx + offset + 0.5f, ty) > 0.0f ? 1 : 0; int rightB = Noise.Noise2D((tx + offset + 1) % (4 << level), ty + 0.5f) > 0.0f ? 2 : 0; int topB = Noise.Noise2D(tx + offset + 0.5f, ty + 1.0f) > 0.0f ? 4 : 0; int leftB = Noise.Noise2D(tx + offset, ty + 0.5f) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } } var noiseRs = new int[] { 0, 0, 1, 0, 2, 0, 1, 0, 3, 3, 1, 3, 2, 2, 1, 0 }; var noiseR = noiseRs[noiseL]; var noiseLs = new int[] { 0, 1, 1, 2, 1, 3, 2, 4, 1, 2, 3, 4, 2, 4, 4, 5 }; noiseL = noiseLs[noiseL]; UpSampleMaterial.SetTexture(uniforms.noiseSampler, NoiseTextures[noiseL]); UpSampleMaterial.SetVector(uniforms.noiseUVLH, new Vector4(noiseR, (noiseR + 1) % 4, 0.0f, HSV ? 1.0f : 0.0f)); if (HSV) { Vector4 col = NoiseColor * rs / 255.0f; col.w *= 2.0f; UpSampleMaterial.SetVector(uniforms.noiseColor, col); } else { Vector4 col = NoiseColor * rs * 2.0f / 255.0f; col.w *= 2.0f; UpSampleMaterial.SetVector(uniforms.noiseColor, col); } UpSampleMaterial.SetVector(uniforms.noiseRootColor, RootNoiseColor); Graphics.Blit(null, gpuSlot.Texture, UpSampleMaterial); base.DoCreateTile(level, tx, ty, slot); }
/// <summary> /// This function creates the elevations data and is called by the <see cref="Tile.Tasks.CreateTileTask"/> when the task is run by the <see cref="Utilities.Schedular"/>. /// The functions needs the tiles parent data to have already been created. If it has not the program will abort. /// </summary> /// <param name="level"></param> /// <param name="tx"></param> /// <param name="ty"></param> /// <param name="slot"></param> public override void DoCreateTile(int level, int tx, int ty, List <TileStorage.Slot> slot) { var gpuSlot = slot[0] as GPUTileStorage.GPUSlot; if (gpuSlot == null) { throw new NullReferenceException("gpuSlot"); } var tileWidth = gpuSlot.Owner.TileSize; var tileSize = tileWidth - (1 + GetBorder() * 2); GPUTileStorage.GPUSlot parentGpuSlot = null; var upsample = level > 0; var parentTile = FindTile(level - 1, tx / 2, ty / 2, false, true); // TODO : Make it classwide... var residualTileSize = GetTileSize(0); var residualTexture = RTExtensions.CreateRTexture(residualTileSize, 0, RenderTextureFormat.RFloat, FilterMode.Point, TextureWrapMode.Clamp); var residualBuffer = new ComputeBuffer(residualTileSize * residualTileSize, sizeof(float)); if (ResidualProducer != null) { if (ResidualProducer.HasTile(level, tx, ty)) { if (ResidualProducer.IsGPUProducer) { GPUTileStorage.GPUSlot residualGpuSlot = null; var residualTile = ResidualProducer.FindTile(level, tx, ty, false, true); if (residualTile != null) { residualGpuSlot = residualTile.GetSlot(0) as GPUTileStorage.GPUSlot; } else { throw new MissingTileException("Find residual tile failed"); } if (residualGpuSlot == null) { throw new MissingTileException("Find parent tile failed"); } UpSampleMaterial.SetTexture("_ResidualSampler", residualGpuSlot.Texture); UpSampleMaterial.SetVector("_ResidualOSH", new Vector4(0.25f / (float)tileWidth, 0.25f / (float)tileWidth, 2.0f / (float)tileWidth, 1.0f)); } else { CPUTileStorage.CPUSlot <float> residualCPUSlot = null; var residualTile = ResidualProducer.FindTile(level, tx, ty, false, true); if (residualTile != null) { residualCPUSlot = residualTile.GetSlot(0) as CPUTileStorage.CPUSlot <float>; } else { throw new MissingTileException("Find residual tile failed"); } if (residualCPUSlot == null) { throw new MissingTileException("Find parent tile failed"); } residualBuffer.SetData(residualCPUSlot.Data); RTUtility.ClearColor(residualTexture); CBUtility.WriteIntoRenderTexture(residualTexture, CBUtility.Channels.R, residualBuffer, GodManager.Instance.WriteData); //RTUtility.SaveAs8bit(residualTileSize, residualTileSize, CBUtility.Channels.R, string.Format("Residual_{0}_{1}-{2}-{3}", TerrainNode.name, level, tx, ty), "/Resources/Preprocess/Textures/Debug/", residualCPUSlot.Data); UpSampleMaterial.SetTexture("_ResidualSampler", residualTexture); UpSampleMaterial.SetVector("_ResidualOSH", new Vector4(0.25f / (float)tileWidth, 0.25f / (float)tileWidth, 2.0f / (float)tileWidth, 1.0f)); } } else { UpSampleMaterial.SetTexture("_ResidualSampler", null); UpSampleMaterial.SetVector("_ResidualOSH", new Vector4(0.0f, 0.0f, 1.0f, 0.0f)); } } else { UpSampleMaterial.SetTexture("_ResidualSampler", null); UpSampleMaterial.SetVector("_ResidualOSH", new Vector4(0.0f, 0.0f, 1.0f, 0.0f)); } if (upsample) { if (parentTile != null) { parentGpuSlot = parentTile.GetSlot(0) as GPUTileStorage.GPUSlot; } else { throw new MissingTileException(string.Format("Find parent tile failed! {0}:{1}-{2}", level - 1, tx / 2, ty / 2)); } } if (parentGpuSlot == null && upsample) { throw new NullReferenceException("parentGpuSlot"); } var rootQuadSize = TerrainNode.TerrainQuadRoot.Length; var tileWSD = Vector4.zero; tileWSD.x = (float)tileWidth; tileWSD.y = (float)rootQuadSize / (float)(1 << level) / (float)tileSize; tileWSD.z = (float)tileSize / (float)(TerrainNode.ParentBody.GridResolution - 1); tileWSD.w = 0.0f; var tileScreenSize = (0.5 + (float)GetBorder()) / (tileWSD.x - 1 - (float)GetBorder() * 2); var tileSD = new Vector2d(tileScreenSize, 1.0 + tileScreenSize * 2.0); UpSampleMaterial.SetVector("_TileWSD", tileWSD); UpSampleMaterial.SetVector("_TileSD", tileSD.ToVector2()); if (upsample) { var parentTexture = parentGpuSlot.Texture; var dx = (float)(tx % 2) * (float)(tileSize / 2.0f); var dy = (float)(ty % 2) * (float)(tileSize / 2.0f); var coarseLevelOSL = new Vector4(dx / (float)parentTexture.width, dy / (float)parentTexture.height, 1.0f / (float)parentTexture.width, 0.0f); UpSampleMaterial.SetTexture("_CoarseLevelSampler", parentTexture); UpSampleMaterial.SetVector("_CoarseLevelOSL", coarseLevelOSL); } else { UpSampleMaterial.SetTexture("_CoarseLevelSampler", null); UpSampleMaterial.SetVector("_CoarseLevelOSL", new Vector4(-1.0f, -1.0f, -1.0f, -1.0f)); } var rs = level < NoiseAmplitudes.Length ? NoiseAmplitudes[level] : 0.0f; var offset = new Vector4d(((double)tx / (1 << level) - 0.5) * rootQuadSize, ((double)ty / (1 << level) - 0.5) * rootQuadSize, rootQuadSize / (1 << level), TerrainNode.ParentBody.Size); UpSampleMaterial.SetFloat("_Amplitude", rs / (TerrainNode.ParentBody.Amplitude / 10.0f)); UpSampleMaterial.SetFloat("_Frequency", TerrainNode.ParentBody.Frequency * (1 << level)); UpSampleMaterial.SetVector("_Offset", offset.ToVector4()); UpSampleMaterial.SetMatrix("_LocalToWorld", TerrainNode.FaceToLocal.ToMatrix4x4()); if (TerrainNode.ParentBody.TCCPS != null) { TerrainNode.ParentBody.TCCPS.SetUniforms(UpSampleMaterial); } Graphics.Blit(null, gpuSlot.Texture, UpSampleMaterial); residualTexture.ReleaseAndDestroy(); residualBuffer.ReleaseAndDisposeBuffer(); base.DoCreateTile(level, tx, ty, slot); }