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); copyTerrainLayerMaterial.SetVector("_LayerMask", layerMasks[userData.channelIndex]); }); }
private SplatmapUserData GetTerrainLayerUserData(ITerrainInfo context, TerrainLayer terrainLayer = null, bool addLayerIfDoesntExist = false) { // look up existing user data, if any SplatmapUserData userData = (context.userData as SplatmapUserData); if (userData != null) { // check if it is appropriate, return if so if ((terrainLayer == null) || (terrainLayer == userData.terrainLayer)) { return(userData); } else { userData = null; } } // otherwise let's build it if (userData == null) { int tileLayerIndex = -1; if (terrainLayer != null) { // look for the layer on the terrain tileLayerIndex = TerrainPaintUtility.FindTerrainLayerIndex(context.terrain, terrainLayer); if ((tileLayerIndex == -1) && (addLayerIfDoesntExist)) { onTerrainTileBeforePaint?.Invoke(context, ToolAction.AddTerrainLayer, "Adding Terrain Layer"); tileLayerIndex = TerrainPaintUtility.AddTerrainLayer(context.terrain, terrainLayer); } } // if we found the layer, build user data if (tileLayerIndex != -1) { userData = new SplatmapUserData(); userData.terrainLayer = terrainLayer; userData.terrainLayerIndex = tileLayerIndex; userData.mapIndex = tileLayerIndex >> 2; userData.channelIndex = tileLayerIndex & 0x3; } context.userData = userData; } return(userData); }
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); }