Example #1
0
        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);
        }