public override void DoCreateTile(int level, int tx, int ty, List <Slot> slot) { GPUSlot gpuSlot = slot[0] as GPUSlot; int tileWidth = gpuSlot.Owner.TileSize; int tileSize = tileWidth - 4; GPUSlot parentGpuSlot = null; Tile parentTile = null; if (level > 0) { parentTile = FindTile(level - 1, tx / 2, ty / 2, false, true); if (parentTile != null) { parentGpuSlot = parentTile.GetSlot(0) as GPUSlot; } else { throw new MissingTileException("Find parent tile failed"); } } m_upsampleMat.SetFloat(m_uniforms.tileWidth, tileWidth); if (level > 0) { RenderTexture tex = parentGpuSlot.Texture; m_upsampleMat.SetTexture(m_uniforms.coarseLevelSampler, tex); float dx = (tx % 2) * (tileSize / 2); float dy = (ty % 2) * (tileSize / 2); Vector4 coarseLevelOSL = new Vector4((dx + 0.5f) / tex.width, (dy + 0.5f) / tex.height, 1.0f / tex.width, 0.0f); m_upsampleMat.SetVector(m_uniforms.coarseLevelOSL, coarseLevelOSL); } else { m_upsampleMat.SetVector(m_uniforms.coarseLevelOSL, new Vector4(-1.0f, -1.0f, -1.0f, -1.0f)); } if (m_orthoCPUProducer != null && m_orthoCPUProducer.HasTile(level, tx, ty)) { Tile orthoCPUTile = m_orthoCPUProducer.FindTile(level, tx, ty, false, true); CPUSlot <byte> orthoCPUSlot = null; if (orthoCPUTile != null) { orthoCPUSlot = orthoCPUTile.GetSlot(0) as CPUSlot <byte>; } else { throw new MissingTileException("Find orthoCPU tile failed"); } int c = m_orthoCPUProducer.Channels; Color32 col = new Color32(); byte[] data = orthoCPUSlot.Data; for (int x = 0; x < tileWidth; x++) { for (int y = 0; y < tileWidth; y++) { col.r = data[(x + y * tileWidth) * c]; if (c > 1) { col.g = data[(x + y * tileWidth) * c + 1]; } if (c > 2) { col.b = data[(x + y * tileWidth) * c + 2]; } if (c > 3) { col.a = data[(x + y * tileWidth) * c + 3]; } m_residueTex.SetPixel(x, y, col); } } m_residueTex.Apply(); m_upsampleMat.SetTexture(m_uniforms.residualSampler, m_residueTex); m_upsampleMat.SetVector(m_uniforms.residualOSH, new Vector4(0.5f / tileWidth, 0.5f / tileWidth, 1.0f / tileWidth, 0.0f)); } else { m_upsampleMat.SetTexture(m_uniforms.residualSampler, null); m_upsampleMat.SetVector(m_uniforms.residualOSH, new Vector4(-1, -1, -1, -1)); } float rs = level < m_noiseAmp.Length ? m_noiseAmp[level] : 0.0f; int noiseL = 0; int face = TerrainNode.Face; if (rs != 0.0f) { if (face == 1) { int offset = 1 << level; int bottomB = m_noise.Noise2D(tx + 0.5f, ty + offset) > 0.0f ? 1 : 0; int rightB = (tx == offset - 1 ? m_noise.Noise2D(ty + offset + 0.5f, offset) : m_noise.Noise2D(tx + 1.0f, ty + offset + 0.5f)) > 0.0f ? 2 : 0; int topB = (ty == offset - 1 ? m_noise.Noise2D((3.0f * offset - 1.0f - tx) + 0.5f, offset) : m_noise.Noise2D(tx + 0.5f, ty + offset + 1.0f)) > 0.0f ? 4 : 0; int leftB = (tx == 0 ? m_noise.Noise2D((4.0f * offset - 1.0f - ty) + 0.5f, offset) : m_noise.Noise2D(tx, ty + offset + 0.5f)) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } else if (face == 6) { int offset = 1 << level; int bottomB = (ty == 0 ? m_noise.Noise2D((3.0f * offset - 1.0f - tx) + 0.5f, 0) : m_noise.Noise2D(tx + 0.5f, ty - offset)) > 0.0f ? 1 : 0; int rightB = (tx == offset - 1.0f ? m_noise.Noise2D((2.0f * offset - 1.0f - ty) + 0.5f, 0) : m_noise.Noise2D(tx + 1.0f, ty - offset + 0.5f)) > 0.0f ? 2 : 0; int topB = m_noise.Noise2D(tx + 0.5f, ty - offset + 1.0f) > 0.0f ? 4 : 0; int leftB = (tx == 0 ? m_noise.Noise2D(3.0f * offset + ty + 0.5f, 0) : m_noise.Noise2D(tx, ty - offset + 0.5f)) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } else { int offset = (1 << level) * (face - 2); int bottomB = m_noise.Noise2D(tx + offset + 0.5f, ty) > 0.0f ? 1 : 0; int rightB = m_noise.Noise2D((tx + offset + 1) % (4 << level), ty + 0.5f) > 0.0f ? 2 : 0; int topB = m_noise.Noise2D(tx + offset + 0.5f, ty + 1.0f) > 0.0f ? 4 : 0; int leftB = m_noise.Noise2D(tx + offset, ty + 0.5f) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } } int[] noiseRs = new int[] { 0, 0, 1, 0, 2, 0, 1, 0, 3, 3, 1, 3, 2, 2, 1, 0 }; int noiseR = noiseRs[noiseL]; int[] noiseLs = new int[] { 0, 1, 1, 2, 1, 3, 2, 4, 1, 2, 3, 4, 2, 4, 4, 5 }; noiseL = noiseLs[noiseL]; m_upsampleMat.SetTexture(m_uniforms.noiseSampler, m_noiseTextures[noiseL]); m_upsampleMat.SetVector(m_uniforms.noiseUVLH, new Vector4(noiseR, (noiseR + 1) % 4, 0.0f, m_hsv ? 1.0f : 0.0f)); if (m_hsv) { Vector4 col = m_noiseColor * rs / 255.0f; col.w *= 2.0f; m_upsampleMat.SetVector(m_uniforms.noiseColor, col); } else { Vector4 col = m_noiseColor * rs * 2.0f / 255.0f; col.w *= 2.0f; m_upsampleMat.SetVector(m_uniforms.noiseColor, col); } m_upsampleMat.SetVector(m_uniforms.noiseRootColor, m_rootNoiseColor); Graphics.Blit(null, gpuSlot.Texture, m_upsampleMat); base.DoCreateTile(level, tx, ty, slot); }
/// <summary> /// This function creates the elevations data and is called by the CreateTileTask when the task is run by the schedular /// The functions needs the tiles parent data to have already been created. If it has not the program will abort. /// </summary> public override void DoCreateTile(int level, int tx, int ty, List <Slot> slot) { GPUSlot gpuSlot = slot[0] as GPUSlot; int tileWidth = gpuSlot.Owner.TileSize; int b = Border * 2 + 1; int tileSize = tileWidth - b; GPUSlot parentGpuSlot = null; Tile parentTile = null; if (level > 0) { parentTile = FindTile(level - 1, tx / 2, ty / 2, false, true); if (parentTile != null) { parentGpuSlot = parentTile.GetSlot(0) as GPUSlot; } else { throw new MissingTileException("Find parent tile failed"); } } float rootQuadSize = (float)TerrainNode.Root.Length; Vector4 tileWSD = new Vector4(); tileWSD.x = tileWidth; tileWSD.y = rootQuadSize / (1 << level) / tileSize; tileWSD.z = (tileWidth - b) / (World.GridResolution - 1.0f); tileWSD.w = 0.0f; m_upsampleMat.SetVector(m_uniforms.tileWSD, tileWSD); if (level > 0) { RenderTexture tex = parentGpuSlot.Texture; m_upsampleMat.SetTexture(m_uniforms.coarseLevelSampler, tex); float dx = (tx % 2) * (tileSize / 2); float dy = (ty % 2) * (tileSize / 2); Vector4 coarseLevelOSL = new Vector4(dx / tex.width, dy / tex.height, 1.0f / tex.width, 0.0f); m_upsampleMat.SetVector(m_uniforms.coarseLevelOSL, coarseLevelOSL); } else { m_upsampleMat.SetVector(m_uniforms.coarseLevelOSL, new Vector4(-1.0f, -1.0f, -1.0f, -1.0f)); } if (m_residualProducer != null && m_residualProducer.HasTile(level, tx, ty)) { Tile residualTile = m_residualProducer.FindTile(level, tx, ty, false, true); CPUSlot <float> residualSlot = null; if (residualTile != null) { residualSlot = residualTile.GetSlot(0) as CPUSlot <float>; } else { throw new MissingTileException("Find residual tile failed"); } //Must clear residual tex before use or terrain will have artifacts at the seams. Not sure why. RTUtility.ClearColor(m_residualTex, Color.clear); m_residualBuffer.SetData(residualSlot.Data); CBUtility.WriteIntoRenderTexture(m_residualTex, 1, m_residualBuffer, World.WriteData); m_upsampleMat.SetTexture(m_uniforms.residualSampler, m_residualTex); m_upsampleMat.SetVector(m_uniforms.residualOSH, new Vector4(0.25f / tileWidth, 0.25f / tileWidth, 2.0f / tileWidth, 1.0f)); } else { m_upsampleMat.SetTexture(m_uniforms.residualSampler, null); m_upsampleMat.SetVector(m_uniforms.residualOSH, new Vector4(0.0f, 0.0f, 1.0f, 0.0f)); } float rs = level < m_noiseAmp.Length ? m_noiseAmp[level] : 0.0f; int noiseL = 0; int face = TerrainNode.Face; if (rs != 0.0f) { if (face == 1) { int offset = 1 << level; int bottomB = m_noise.Noise2D(tx + 0.5f, ty + offset) > 0.0f ? 1 : 0; int rightB = (tx == offset - 1 ? m_noise.Noise2D(ty + offset + 0.5f, offset) : m_noise.Noise2D(tx + 1.0f, ty + offset + 0.5f)) > 0.0f ? 2 : 0; int topB = (ty == offset - 1 ? m_noise.Noise2D((3.0f * offset - 1.0f - tx) + 0.5f, offset) : m_noise.Noise2D(tx + 0.5f, ty + offset + 1.0f)) > 0.0f ? 4 : 0; int leftB = (tx == 0 ? m_noise.Noise2D((4.0f * offset - 1.0f - ty) + 0.5f, offset) : m_noise.Noise2D(tx, ty + offset + 0.5f)) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } else if (face == 6) { int offset = 1 << level; int bottomB = (ty == 0 ? m_noise.Noise2D((3.0f * offset - 1.0f - tx) + 0.5f, 0) : m_noise.Noise2D(tx + 0.5f, ty - offset)) > 0.0f ? 1 : 0; int rightB = (tx == offset - 1.0f ? m_noise.Noise2D((2.0f * offset - 1.0f - ty) + 0.5f, 0) : m_noise.Noise2D(tx + 1.0f, ty - offset + 0.5f)) > 0.0f ? 2 : 0; int topB = m_noise.Noise2D(tx + 0.5f, ty - offset + 1.0f) > 0.0f ? 4 : 0; int leftB = (tx == 0 ? m_noise.Noise2D(3.0f * offset + ty + 0.5f, 0) : m_noise.Noise2D(tx, ty - offset + 0.5f)) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } else { int offset = (1 << level) * (face - 2); int bottomB = m_noise.Noise2D(tx + offset + 0.5f, ty) > 0.0f ? 1 : 0; int rightB = m_noise.Noise2D((tx + offset + 1) % (4 << level), ty + 0.5f) > 0.0f ? 2 : 0; int topB = m_noise.Noise2D(tx + offset + 0.5f, ty + 1.0f) > 0.0f ? 4 : 0; int leftB = m_noise.Noise2D(tx + offset, ty + 0.5f) > 0.0f ? 8 : 0; noiseL = bottomB + rightB + topB + leftB; } } int[] noiseRs = new int[] { 0, 0, 1, 0, 2, 0, 1, 0, 3, 3, 1, 3, 2, 2, 1, 0 }; int noiseR = noiseRs[noiseL]; int[] noiseLs = new int[] { 0, 1, 1, 2, 1, 3, 2, 4, 1, 2, 3, 4, 2, 4, 4, 5 }; noiseL = noiseLs[noiseL]; m_upsampleMat.SetTexture(m_uniforms.noiseSampler, m_noiseTextures[noiseL]); m_upsampleMat.SetVector(m_uniforms.noiseUVLH, new Vector4(noiseR, (noiseR + 1) % 4, 0, rs)); Graphics.Blit(null, gpuSlot.Texture, m_upsampleMat); base.DoCreateTile(level, tx, ty, slot); }