예제 #1
0
        public void GatherAlphamap(TerrainLayer inputLayer, bool addLayerIfDoesntExist = true)
        {
            if (inputLayer == null)
            {
                return;
            }

            Material copyTerrainLayerMaterial = TerrainPaintUtility.GetCopyTerrainLayerMaterial();

            Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) };

            GatherInternal(
                t =>
            {       // return the texture to be gathered from this terrain tile
                SplatmapUserData userData = GetTerrainLayerUserData(t, inputLayer, addLayerIfDoesntExist);
                if (userData != null)
                {
                    return(TerrainPaintUtility.GetTerrainAlphaMapChecked(t.terrain, userData.mapIndex));
                }
                else
                {
                    return(null);
                }
            },

                new Color(0.0f, 0.0f, 0.0f, 0.0f),
                "PaintContext.GatherAlphamap",
                copyTerrainLayerMaterial, 0,
                t =>
            {       // before blit -- setup layer mask in the material
                SplatmapUserData userData = GetTerrainLayerUserData(t);
                if (userData == null)
                {
                    return;
                }
                copyTerrainLayerMaterial.SetVector("_LayerMask", layerMasks[userData.channelIndex]);
            });
        }
예제 #2
0
        public void ScatterAlphamap(string editorUndoName)
        {
            Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) };
            Material  copyTerrainLayerMaterial = TerrainPaintUtility.GetCopyTerrainLayerMaterial();

            var rtdesc = new RenderTextureDescriptor(destinationRenderTexture.width, destinationRenderTexture.height, GraphicsFormat.R8G8B8A8_UNorm, GraphicsFormat.None);

            rtdesc.sRGB             = false;
            rtdesc.useMipMap        = false;
            rtdesc.autoGenerateMips = false;
            RenderTexture tempTarget = RenderTexture.GetTemporary(rtdesc);

            ScatterInternal(
                t => // We're going to do ALL of the work in this terrainToRT function, as it is very custom, and we'll just return null to skip the ScatterInternal rendering
            {
                SplatmapUserData userData = GetTerrainLayerUserData(t);
                if (userData != null)
                {
                    onTerrainTileBeforePaint?.Invoke(t, ToolAction.PaintTexture, editorUndoName);

                    int targetAlphamapIndex         = userData.mapIndex;
                    int targetChannelIndex          = userData.channelIndex;
                    Texture2D targetAlphamapTexture = t.terrain.terrainData.alphamapTextures[targetAlphamapIndex];

                    destinationRenderTexture.filterMode = FilterMode.Point;
                    sourceRenderTexture.filterMode      = FilterMode.Point;

                    // iterate all alphamaps to modify them (have to modify all to renormalize)
                    for (int i = 0; i <= t.terrain.terrainData.alphamapTextureCount; i++)       // NOTE: this is a non-standard for loop
                    {
                        // modify the target index last, (skip it the first time)
                        if (i == targetAlphamapIndex)
                        {
                            continue;
                        }
                        int alphamapIndex = (i == t.terrain.terrainData.alphamapTextureCount) ? targetAlphamapIndex : i;

                        Texture2D alphamapTexture = t.terrain.terrainData.alphamapTextures[alphamapIndex];
                        if ((alphamapTexture.width != targetTextureWidth) || (alphamapTexture.height != targetTextureHeight))
                        {
                            Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", t.terrain);
                            continue;
                        }

                        RenderTexture.active = tempTarget;
                        GL.PushMatrix();
                        GL.LoadPixelMatrix(0, tempTarget.width, 0, tempTarget.height);
                        {
                            copyTerrainLayerMaterial.SetTexture("_MainTex", destinationRenderTexture);
                            copyTerrainLayerMaterial.SetTexture("_OldAlphaMapTexture", sourceRenderTexture);
                            copyTerrainLayerMaterial.SetTexture("_OriginalTargetAlphaMap", targetAlphamapTexture);

                            copyTerrainLayerMaterial.SetTexture("_AlphaMapTexture", alphamapTexture);
                            copyTerrainLayerMaterial.SetVector("_LayerMask", alphamapIndex == targetAlphamapIndex ? layerMasks[targetChannelIndex] : Vector4.zero);
                            copyTerrainLayerMaterial.SetVector("_OriginalTargetAlphaMask", layerMasks[targetChannelIndex]);
                            copyTerrainLayerMaterial.SetPass(1);

                            TerrainPaintUtility.DrawQuad2(t.clippedPCPixels, t.clippedPCPixels, destinationRenderTexture, t.clippedTerrainPixels, alphamapTexture);
                        }
                        GL.PopMatrix();

                        t.terrain.terrainData.CopyActiveRenderTextureToTexture(TerrainData.AlphamapTextureName, alphamapIndex, t.clippedPCPixels, t.clippedTerrainPixels.min, true);
                    }

                    RenderTexture.active = null;
                    OnTerrainPainted(t, ToolAction.PaintTexture);
                }
                return(null);
            },
                "PaintContext.ScatterAlphamap",
                copyTerrainLayerMaterial, 0);

            RenderTexture.ReleaseTemporary(tempTarget);
        }
예제 #3
0
        private void ScatterInternal(
            Func <ITerrainInfo, RenderTexture> terrainToRT,
            string operationName,
            Material blitMaterial            = null,
            int blitPass                     = 0,
            Action <ITerrainInfo> beforeBlit = null,
            Action <ITerrainInfo> afterBlit  = null)
        {
            var oldRT = RenderTexture.active;

            if (blitMaterial == null)
            {
                blitMaterial = TerrainPaintUtility.GetBlitMaterial();
            }

            for (int i = 0; i < m_TerrainTiles.Count; i++)
            {
                TerrainTile terrainTile = m_TerrainTiles[i];
                if (!terrainTile.scatterEnable)
                {
                    continue;
                }

                RenderTexture target = terrainToRT(terrainTile);
                if ((target == null) || (!terrainTile.scatterEnable)) // double check scatterEnable in case terrainToRT modified it
                {
                    continue;
                }

                if ((target.width != targetTextureWidth) || (target.height != targetTextureHeight))
                {
                    Debug.LogWarning(operationName + " requires the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain);
                    continue;
                }

                beforeBlit?.Invoke(terrainTile);
                if (!terrainTile.scatterEnable)   // check again, beforeBlit may have modified it
                {
                    continue;
                }

                RenderTexture.active = target;
                GL.PushMatrix();
                GL.LoadPixelMatrix(0, target.width, 0, target.height);
                {
                    FilterMode oldFilterMode = destinationRenderTexture.filterMode;
                    destinationRenderTexture.filterMode = FilterMode.Point;

                    blitMaterial.SetTexture("_MainTex", destinationRenderTexture);
                    blitMaterial.SetPass(blitPass);
                    TerrainPaintUtility.DrawQuad(terrainTile.clippedTerrainPixels, terrainTile.clippedPCPixels, destinationRenderTexture);

                    destinationRenderTexture.filterMode = oldFilterMode;
                }
                GL.PopMatrix();

                afterBlit?.Invoke(terrainTile);
            }

            RenderTexture.active = oldRT;
        }
예제 #4
0
        private void GatherInternal(
            Func <ITerrainInfo, Texture> terrainToTexture,
            Color defaultColor,
            string operationName,
            Material blitMaterial            = null,
            int blitPass                     = 0,
            Action <ITerrainInfo> beforeBlit = null,
            Action <ITerrainInfo> afterBlit  = null)
        {
            if (blitMaterial == null)
            {
                blitMaterial = TerrainPaintUtility.GetBlitMaterial();
            }

            RenderTexture.active = sourceRenderTexture;
            GL.Clear(true, true, defaultColor);

            GL.PushMatrix();
            GL.LoadPixelMatrix(0, pixelRect.width, 0, pixelRect.height);
            for (int i = 0; i < m_TerrainTiles.Count; i++)
            {
                TerrainTile terrainTile = m_TerrainTiles[i];
                if (!terrainTile.gatherEnable)
                {
                    continue;
                }

                Texture sourceTexture = terrainToTexture(terrainTile);
                if ((sourceTexture == null) || (!terrainTile.gatherEnable))   // double check gatherEnable in case terrainToTexture modified it
                {
                    continue;
                }

                if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight))
                {
                    Debug.LogWarning(operationName + " requires the same resolution texture for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain);
                    continue;
                }

                beforeBlit?.Invoke(terrainTile);
                if (!terrainTile.gatherEnable) // check again, beforeBlit may have modified it
                {
                    continue;
                }

                FilterMode oldFilterMode = sourceTexture.filterMode;
                sourceTexture.filterMode = FilterMode.Point;

                blitMaterial.SetTexture("_MainTex", sourceTexture);
                blitMaterial.SetPass(blitPass);
                // Draw padded quads to support extended-edge sampling of each terrain tile into empty regions.
                TerrainPaintUtility.DrawQuadPadded(terrainTile.clippedPCPixels, terrainTile.paddedPCPixels,
                                                   terrainTile.clippedTerrainPixels, terrainTile.paddedTerrainPixels, sourceTexture);

                sourceTexture.filterMode = oldFilterMode;

                afterBlit?.Invoke(terrainTile);
            }
            GL.PopMatrix();
            RenderTexture.active = oldRenderTexture;
        }