예제 #1
0
        public void ScatterHeightmap(string editorUndoName)
        {
            var blitMaterial = TerrainPaintUtility.GetHeightBlitMaterial();

            blitMaterial.SetFloat("_Height_Offset", 0.0f);
            blitMaterial.SetFloat("_Height_Scale", 1.0f);

            ScatterInternal(
                t => t.terrain.terrainData.heightmapTexture,
                "PaintContext.ScatterHeightmap",
                blitMaterial: blitMaterial,
                beforeBlit: t =>
            {
                onTerrainTileBeforePaint?.Invoke(t, ToolAction.PaintHeightmap, editorUndoName);
                blitMaterial.SetFloat("_Height_Offset", (heightWorldSpaceMin - t.terrain.GetPosition().y) / t.terrain.terrainData.size.y * kNormalizedHeightScale);
                blitMaterial.SetFloat("_Height_Scale", heightWorldSpaceSize / t.terrain.terrainData.size.y);
            },
                afterBlit: t =>
            {
                t.terrain.terrainData.DirtyHeightmapRegion(t.clippedTerrainPixels, t.terrain.drawInstanced ? TerrainHeightmapSyncControl.None : TerrainHeightmapSyncControl.HeightOnly);
                OnTerrainPainted(t, ToolAction.PaintHeightmap);
            });
        }
예제 #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, RenderTextureFormat.ARGB32);

            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
        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();

            for (int i = 0; i < m_TerrainTiles.Count; i++)
            {
                TerrainTile terrainTile = m_TerrainTiles[i];
                if (terrainTile.clippedLocalPixels.width == 0 || terrainTile.clippedLocalPixels.height == 0)
                {
                    continue;
                }

                if (onTerrainTileBeforePaint != null)
                {
                    onTerrainTileBeforePaint(terrainTile, ToolAction.PaintTexture, editorUndoName);
                }

                var rtdesc = new RenderTextureDescriptor(destinationRenderTexture.width, destinationRenderTexture.height, RenderTextureFormat.ARGB32);
                rtdesc.sRGB             = false;
                rtdesc.useMipMap        = false;
                rtdesc.autoGenerateMips = false;
                RenderTexture destTarget = RenderTexture.GetTemporary(rtdesc);
                RenderTexture.active = destTarget;

                RectInt writeRect = terrainTile.clippedPCPixels;

                Rect readRect = new Rect(
                    writeRect.x / (float)pixelRect.width,
                    writeRect.y / (float)pixelRect.height,
                    writeRect.width / (float)pixelRect.width,
                    writeRect.height / (float)pixelRect.height);

                destinationRenderTexture.filterMode = FilterMode.Point;

                int       mapIndex               = terrainTile.mapIndex;
                int       channelIndex           = terrainTile.channelIndex;
                Texture2D sourceTexTargetChannel = terrainTile.terrain.terrainData.alphamapTextures[mapIndex];

                for (int j = 0; j < terrainTile.terrain.terrainData.alphamapTextureCount; j++)
                {
                    Texture2D sourceTex = terrainTile.terrain.terrainData.alphamapTextures[j];
                    if ((sourceTex.width != targetTextureWidth) || (sourceTex.height != targetTextureHeight))
                    {
                        Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain);
                        continue;
                    }

                    Rect combineRect = new Rect(
                        terrainTile.clippedLocalPixels.x / (float)sourceTex.width,
                        terrainTile.clippedLocalPixels.y / (float)sourceTex.height,
                        terrainTile.clippedLocalPixels.width / (float)sourceTex.width,
                        terrainTile.clippedLocalPixels.height / (float)sourceTex.height);

                    copyTerrainLayerMaterial.SetTexture("_MainTex", destinationRenderTexture);
                    copyTerrainLayerMaterial.SetTexture("_OldAlphaMapTexture", sourceRenderTexture);
                    copyTerrainLayerMaterial.SetTexture("_OriginalTargetAlphaMap", sourceTexTargetChannel);

                    copyTerrainLayerMaterial.SetTexture("_AlphaMapTexture", sourceTex);
                    copyTerrainLayerMaterial.SetVector("_LayerMask", j == mapIndex ? layerMasks[channelIndex] : Vector4.zero);
                    copyTerrainLayerMaterial.SetVector("_OriginalTargetAlphaMask", layerMasks[channelIndex]);
                    copyTerrainLayerMaterial.SetPass(1);

                    GL.PushMatrix();
                    GL.LoadPixelMatrix(0, destTarget.width, 0, destTarget.height);

                    GL.Begin(GL.QUADS);
                    GL.Color(new Color(1.0f, 1.0f, 1.0f, 1.0f));

                    GL.MultiTexCoord2(0, readRect.x, readRect.y);
                    GL.MultiTexCoord2(1, combineRect.x, combineRect.y);
                    GL.Vertex3(writeRect.x, writeRect.y, 0.0f);
                    GL.MultiTexCoord2(0, readRect.x, readRect.yMax);
                    GL.MultiTexCoord2(1, combineRect.x, combineRect.yMax);
                    GL.Vertex3(writeRect.x, writeRect.yMax, 0.0f);
                    GL.MultiTexCoord2(0, readRect.xMax, readRect.yMax);
                    GL.MultiTexCoord2(1, combineRect.xMax, combineRect.yMax);
                    GL.Vertex3(writeRect.xMax, writeRect.yMax, 0.0f);
                    GL.MultiTexCoord2(0, readRect.xMax, readRect.y);
                    GL.MultiTexCoord2(1, combineRect.xMax, combineRect.y);
                    GL.Vertex3(writeRect.xMax, writeRect.y, 0.0f);

                    GL.End();
                    GL.PopMatrix();

                    if (TerrainPaintUtility.paintTextureUsesCopyTexture)
                    {
                        var rtdesc2 = new RenderTextureDescriptor(sourceTex.width, sourceTex.height, RenderTextureFormat.ARGB32);
                        rtdesc2.sRGB             = false;
                        rtdesc2.useMipMap        = true;
                        rtdesc2.autoGenerateMips = false;
                        var mips = RenderTexture.GetTemporary(rtdesc2);
                        if (!mips.IsCreated())
                        {
                            mips.Create();
                        }

                        // Composes mip0 in a RT with full mipchain.
                        Graphics.CopyTexture(sourceTex, 0, 0, mips, 0, 0);
                        Graphics.CopyTexture(destTarget, 0, 0, writeRect.x, writeRect.y, writeRect.width, writeRect.height, mips, 0, 0, terrainTile.clippedLocalPixels.x, terrainTile.clippedLocalPixels.y);
                        mips.GenerateMips();

                        // Copy them into sourceTex.
                        Graphics.CopyTexture(mips, sourceTex);

                        RenderTexture.ReleaseTemporary(mips);
                    }
                    else
                    {
                        GraphicsDeviceType deviceType = SystemInfo.graphicsDeviceType;
                        if (deviceType == GraphicsDeviceType.Metal || deviceType == GraphicsDeviceType.OpenGLCore)
                        {
                            sourceTex.ReadPixels(new Rect(writeRect.x, writeRect.y, writeRect.width, writeRect.height), terrainTile.clippedLocalPixels.x, terrainTile.clippedLocalPixels.y);
                        }
                        else
                        {
                            sourceTex.ReadPixels(new Rect(writeRect.x, destTarget.height - writeRect.y - writeRect.height, writeRect.width, writeRect.height), terrainTile.clippedLocalPixels.x, terrainTile.clippedLocalPixels.y);
                        }
                        sourceTex.Apply();
                    }
                }

                RenderTexture.active = null;
                RenderTexture.ReleaseTemporary(destTarget);

                OnTerrainPainted(terrainTile, ToolAction.PaintTexture);
            }
        }
예제 #5
0
        public void GatherAlphamap(TerrainLayer inputLayer, bool addLayerIfDoesntExist = true)
        {
            if (inputLayer == null)
            {
                return;
            }

            int terrainLayerIndex = TerrainPaintUtility.FindTerrainLayerIndex(originTerrain, inputLayer);

            if (terrainLayerIndex == -1 && addLayerIfDoesntExist)
            {
                terrainLayerIndex = TerrainPaintUtility.AddTerrainLayer(originTerrain, inputLayer);
            }

            RenderTexture.active = sourceRenderTexture;
            GL.Clear(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f));
            GL.PushMatrix();
            GL.LoadPixelMatrix(0, pixelRect.width, 0, pixelRect.height);

            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();

            for (int i = 0; i < m_TerrainTiles.Count; i++)
            {
                TerrainTile terrainTile = m_TerrainTiles[i];
                if (terrainTile.clippedLocalPixels.width == 0 || terrainTile.clippedLocalPixels.height == 0)
                {
                    continue;
                }

                int tileLayerIndex = TerrainPaintUtility.FindTerrainLayerIndex(terrainTile.terrain, inputLayer);
                if (tileLayerIndex == -1)
                {
                    if (!addLayerIfDoesntExist)
                    {
                        // setting these to zero will prevent them from being used later
                        terrainTile.clippedLocalPixels.width  = 0;
                        terrainTile.clippedLocalPixels.height = 0;
                        terrainTile.clippedPCPixels.width     = 0;
                        terrainTile.clippedPCPixels.height    = 0;
                        continue;
                    }
                    tileLayerIndex = TerrainPaintUtility.AddTerrainLayer(terrainTile.terrain, inputLayer);
                }

                terrainTile.mapIndex     = tileLayerIndex >> 2;
                terrainTile.channelIndex = tileLayerIndex & 0x3;

                Texture sourceTexture = TerrainPaintUtility.GetTerrainAlphaMapChecked(terrainTile.terrain, terrainTile.mapIndex);
                if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight))
                {
                    Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored. (" +
                                     sourceTexture.width + " x " + sourceTexture.height + ") != (" + targetTextureWidth + " x " + targetTextureHeight + ")",
                                     terrainTile.terrain);
                    continue;
                }

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

                copyTerrainLayerMaterial.SetVector("_LayerMask", layerMasks[terrainTile.channelIndex]);
                copyTerrainLayerMaterial.SetTexture("_MainTex", sourceTexture);
                copyTerrainLayerMaterial.SetPass(0);

                TerrainPaintUtility.DrawQuad(terrainTile.clippedPCPixels, terrainTile.clippedLocalPixels, sourceTexture);

                sourceTexture.filterMode = oldFilterMode;
            }

            GL.PopMatrix();

            RenderTexture.active = oldRenderTexture;
        }
예제 #6
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, RenderTextureFormat.ARGB32);

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

            RenderTexture.active = destTarget;

            for (int i = 0; i < m_TerrainTiles.Count; i++)
            {
                TerrainTile terrainTile = m_TerrainTiles[i];
                if (terrainTile.clippedLocalPixels.width == 0 || terrainTile.clippedLocalPixels.height == 0)
                {
                    continue;
                }

                onTerrainTileBeforePaint?.Invoke(terrainTile, ToolAction.PaintTexture, editorUndoName);

                RectInt writeRect = terrainTile.clippedPCPixels;

                Rect readRect = new Rect(
                    writeRect.x / (float)pixelRect.width,
                    writeRect.y / (float)pixelRect.height,
                    writeRect.width / (float)pixelRect.width,
                    writeRect.height / (float)pixelRect.height);

                destinationRenderTexture.filterMode = FilterMode.Point;

                int mapIndex         = terrainTile.mapIndex;
                int channelIndex     = terrainTile.channelIndex;
                var terrainData      = terrainTile.terrain.terrainData;
                var alphamapTextures = terrainData.alphamapTextures;
                for (int j = 0; j < alphamapTextures.Length; j++)
                {
                    Texture2D sourceTex = alphamapTextures[j];
                    if ((sourceTex.width != targetTextureWidth) || (sourceTex.height != targetTextureHeight))
                    {
                        Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain);
                        continue;
                    }

                    Rect combineRect = new Rect(
                        terrainTile.clippedLocalPixels.x / (float)sourceTex.width,
                        terrainTile.clippedLocalPixels.y / (float)sourceTex.height,
                        terrainTile.clippedLocalPixels.width / (float)sourceTex.width,
                        terrainTile.clippedLocalPixels.height / (float)sourceTex.height);

                    copyTerrainLayerMaterial.SetTexture("_MainTex", destinationRenderTexture);
                    copyTerrainLayerMaterial.SetTexture("_OldAlphaMapTexture", sourceRenderTexture);
                    copyTerrainLayerMaterial.SetTexture("_OriginalTargetAlphaMap", alphamapTextures[mapIndex]);

                    copyTerrainLayerMaterial.SetTexture("_AlphaMapTexture", sourceTex);
                    copyTerrainLayerMaterial.SetVector("_LayerMask", j == mapIndex ? layerMasks[channelIndex] : Vector4.zero);
                    copyTerrainLayerMaterial.SetVector("_OriginalTargetAlphaMask", layerMasks[channelIndex]);
                    copyTerrainLayerMaterial.SetPass(1);

                    GL.PushMatrix();
                    GL.LoadPixelMatrix(0, destTarget.width, 0, destTarget.height);

                    GL.Begin(GL.QUADS);
                    GL.Color(new Color(1.0f, 1.0f, 1.0f, 1.0f));

                    GL.MultiTexCoord2(0, readRect.x, readRect.y);
                    GL.MultiTexCoord2(1, combineRect.x, combineRect.y);
                    GL.Vertex3(writeRect.x, writeRect.y, 0.0f);
                    GL.MultiTexCoord2(0, readRect.x, readRect.yMax);
                    GL.MultiTexCoord2(1, combineRect.x, combineRect.yMax);
                    GL.Vertex3(writeRect.x, writeRect.yMax, 0.0f);
                    GL.MultiTexCoord2(0, readRect.xMax, readRect.yMax);
                    GL.MultiTexCoord2(1, combineRect.xMax, combineRect.yMax);
                    GL.Vertex3(writeRect.xMax, writeRect.yMax, 0.0f);
                    GL.MultiTexCoord2(0, readRect.xMax, readRect.y);
                    GL.MultiTexCoord2(1, combineRect.xMax, combineRect.y);
                    GL.Vertex3(writeRect.xMax, writeRect.y, 0.0f);

                    GL.End();
                    GL.PopMatrix();

                    terrainData.CopyActiveRenderTextureToTexture(TerrainData.AlphamapTextureName, j, writeRect, terrainTile.clippedLocalPixels.min, true);
                }

                OnTerrainPainted(terrainTile, ToolAction.PaintTexture);
            }

            RenderTexture.active = null;
            RenderTexture.ReleaseTemporary(destTarget);
        }
 internal static void DrawQuad(RectInt destinationPixels, RectInt sourcePixels, Texture sourceTexture)
 {
     TerrainPaintUtility.DrawQuad2(destinationPixels, sourcePixels, sourceTexture, sourcePixels, sourceTexture);
 }