/// <summary> /// Executes the modifiers in order and generates the necessary splatmaps /// </summary> /// <param name="layer"></param> /// <param name="modifiers"></param> /// <param name="output"></param> public static void Execute(Terrain terrain, TerrainLayer layer, List <Modifier> modifiers) { Graphics.ClearRandomWriteTargets(); Graphics.SetRenderTarget(alphaMap); //Start with a full white base Graphics.Blit(Texture2D.whiteTexture, alphaMap); //Reverse order for (int i = modifiers.Count - 1; i >= 0; i--) { modifiers[i].Configure(filterMat); modifiers[i].Execute(alphaMap); } //Scale splatmap to fit in terrain Vector2 scaledSplatmapSize = new Vector2((terrain.terrainData.size.x / m_resolution) * m_resolution, (terrain.terrainData.size.z / m_resolution) * m_resolution); //PaintContext handles creation of splatmaps. Subtracting the weights of a splatmap, from the ones before it. //A single pixels of all combined alpha maps must not exceed a value of one. The 2nd pass of Hidden/TerrainEngine/TerrainLayerUtils is used internally to do this //Note: Paintcontext must use a serialized terrain reference, otherwise breaks when executing "ApplyDelayedActions" when the project is saved! PaintContext c = TerrainPaintUtility.BeginPaintTexture(terrain, new Rect(0, 0, scaledSplatmapSize.x, scaledSplatmapSize.y), layer); Graphics.Blit(alphaMap, c.destinationRenderTexture); TerrainPaintUtility.EndPaintTexture(c, "Painted terrain"); }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushXform.GetBrushXYBounds(), m_SelectedTerrainLayer); if (paintContext == null) { return(false); } Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); // apply brush float targetAlpha = 1.0f; // always 1.0 now -- no subtractive painting (we assume this in the ScatterAlphaMap) Vector4 brushParams = new Vector4(editContext.brushStrength, targetAlpha, 0.0f, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.PaintTexture); TerrainPaintUtility.EndPaintTexture(paintContext, "Terrain Paint - Texture"); return(true); }
public void Release(PaintContext paintContext) { if (ReferenceEquals(paintContext, m_HeightmapContext)) { if (m_WriteToHeightmap) { TerrainPaintUtility.EndPaintHeightmap(m_HeightmapContext, $"{m_Name} - Heightmap"); } else { TerrainPaintUtility.ReleaseContextResources(m_HeightmapContext); } m_HeightmapContext = null; } else if (ReferenceEquals(paintContext, m_NormalmapContext)) { TerrainPaintUtility.ReleaseContextResources(m_NormalmapContext); m_NormalmapContext = null; } else if (ReferenceEquals(paintContext, m_TextureContext)) { if (m_WriteToTexture) { TerrainPaintUtility.EndPaintTexture(m_TextureContext, $"{m_Name} - Texture"); } else { TerrainPaintUtility.ReleaseContextResources(m_TextureContext); } m_TextureContext = null; } }
private bool PaintTexture(Terrain terrain, IOnPaint editContext, Vector2 currUV) { // the brush size is relative to the main brush size float brushSize = editContext.brushSize * paintBrushSize / 100f; BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, currUV, brushSize, 0.0f); PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushXform.GetBrushXYBounds(), m_SelectedInnerTerrainLayer); if (paintContext == null) { return(false); } Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); float targetAlpha = 1.0f; // always 1.0 now -- no subtractive painting (we assume this in the ScatterAlphaMap) float brushStrength = paintBrushStrength / 100f; // editContext.brushStrength // apply brush Vector4 brushParams = new Vector4(brushStrength, targetAlpha, 0.0f, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.PaintTexture); TerrainPaintUtility.EndPaintTexture(paintContext, "Terrain Paint - Texture"); return(true); }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { BrushTransform targetBrushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 1); Material mat = GetPaintMaterial(); Vector4 brushParams = new Vector4(editContext.brushStrength, 0, 0, 0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); Rect targetRect = targetBrushXform.GetBrushXYBounds(); int numSampleTerrainLayers = terrain.terrainData.terrainLayers.Length; for (int i = 0; i < numSampleTerrainLayers; ++i) { TerrainLayer layer = terrain.terrainData.terrainLayers[i]; if (layer == null) { continue; } int layerIndex = TerrainPaintUtility.FindTerrainLayerIndex(terrain, layer); Texture2D layerTexture = TerrainPaintUtility.GetTerrainAlphaMapChecked(terrain, layerIndex >> 2); PaintContext targetContext = PaintContext.CreateFromBounds(terrain, targetRect, layerTexture.width, layerTexture.height); targetContext.CreateRenderTargets(RenderTextureFormat.R8); targetContext.GatherAlphamap(layer, true); Graphics.Blit(targetContext.sourceRenderTexture, targetContext.destinationRenderTexture, mat, 0); TerrainPaintUtility.EndPaintTexture(targetContext, "Terrain Paint - Smooth Splatmaps"); } return(false); }
private void PaintAlphamap(Rect writeBrushRect, Terrain terrain, Material mat) { // paint each layer from the sample to the clone location (adds layer if not present already) for (int i = 0; i < m_Sample.m_Terrain.terrainData.terrainLayers.Length; ++i) { TerrainPaintUtility.PaintContext write = TerrainPaintUtility.BeginPaintTexture(terrain, writeBrushRect, m_Sample.m_Terrain.terrainData.terrainLayers[i]); if (write == null) { continue; } // read created manually to force read to not add the layer if it wasnt already on the terrain, and to use write's rect with offset TerrainPaintUtility.PaintContext read = new TerrainPaintUtility.PaintContext(); read.brushRect = new RectInt(write.brushRect.position + m_CloneRectPixelOffsetFromStampRect, write.brushRect.size); // TODO(wyatt): Uncomment this once Andrew's API changes make it to trunk read.CreateTerrainTiles(m_Sample.m_Terrain, m_Sample.m_Terrain.terrainData.alphamapWidth, m_Sample.m_Terrain.terrainData.alphamapHeight); read.CreateRenderTargets(RenderTextureFormat.R8); read.GatherAlphamap(m_Sample.m_Terrain, m_Sample.m_Terrain.terrainData.terrainLayers[i], false); // render mix of clone and stamp areas StampRender(read, write, mat, (int)ShaderPasses.CloneAlphamap); TerrainPaintUtility.ReleaseContextResources(read); TerrainPaintUtility.EndPaintTexture(write, "Terrain Paint - Clone Stamp Tool (Alphamap layer " + i + ")"); } }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { if (splatPaintRules == null) { return(false); } Material mat = GetPaintMaterial(); mat.SetTexture("_BrushTex", editContext.brushTexture); // gathering heightmap BrushTransform brushXformForGatheringHeightmap = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); PaintContext paintContextForGatheringHeightmap = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXformForGatheringHeightmap.GetBrushXYBounds(), 1); if (paintContextForGatheringHeightmap == null) { return(false); } RenderTexture gatheredHeightmap = RenderTexture.GetTemporary(terrain.terrainData.heightmapTexture.descriptor); Graphics.Blit(paintContextForGatheringHeightmap.sourceRenderTexture, gatheredHeightmap); //, TerrainPaintUtility.GetBlitMaterial(), 0); TerrainPaintUtility.ReleaseContextResources(paintContextForGatheringHeightmap); // painting alphamap BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushXform.GetBrushXYBounds(), m_SelectedTerrainLayer); if (paintContext == null) { return(false); } float targetAlpha = 1.0f; // always 1.0 now -- no subtractive painting (we assume this in the ScatterAlphaMap) Vector4 brushParams = new Vector4(editContext.brushStrength, targetAlpha, splatPaintRules.useHeightTransition ? 1f : 0f, splatPaintRules.useAngleTransition ? 1f : 0f); Vector4 paintRulesParametersHeight = new Vector4(splatPaintRules.minHeightStart, splatPaintRules.minHeightEnd, splatPaintRules.maxHeightStart, splatPaintRules.maxHeightEnd); Vector4 paintRulesParametersAngle = new Vector4(splatPaintRules.minAngleStart, splatPaintRules.minAngleEnd, splatPaintRules.maxAngleStart, splatPaintRules.maxAngleEnd); Vector4 paintRulesInversionAndUsage = new Vector4(splatPaintRules.inverseHeightRule ? 1f : 0f, splatPaintRules.inverseAngleRule ? 1f : 0f, splatPaintRules.applyHeightRule ? 1f : 0f, splatPaintRules.applyAngleRule ? 1f : 0f); mat.SetVector("_BrushParams", brushParams); mat.SetVector("_TerrainSize", (Vector4)terrain.terrainData.size); mat.SetVector("_PaintRulesParametersHeight", paintRulesParametersHeight); mat.SetVector("_PaintRulesParametersAngle", paintRulesParametersAngle); mat.SetVector("_PaintRulesInversionAndUsage", paintRulesInversionAndUsage); mat.SetTexture("_Heightmap", gatheredHeightmap); TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, 0); TerrainPaintUtility.EndPaintTexture(paintContext, "Terrain Paint - Texture"); RenderTexture.ReleaseTemporary(gatheredHeightmap); return(true); }
/// <summary> /// Executes the modifiers in order and generates the necessary splatmaps /// </summary> /// <param name="layer"></param> /// <param name="modifiers"></param> /// <param name="output"></param> public static void ProcessSingleLayer(Terrain terrain, LayerSettings settings) { //Disable or with no settings (result in a fill with black) if (settings.enabled == false) { return; } Graphics.SetRenderTarget(alphaMap); //Start with a full white base Graphics.Blit(Texture2D.whiteTexture, alphaMap); //Reverse order for (int i = settings.modifierStack.Count - 1; i >= 0; i--) { settings.modifierStack[i].Configure(filterMat); settings.modifierStack[i].Execute(alphaMap); } //Scale splatmap to fit in terrain Vector2 scaledSplatmapSize = new Vector2((terrain.terrainData.size.x / m_resolution) * m_resolution, (terrain.terrainData.size.z / m_resolution) * m_resolution); //PaintContext handles creation of splatmaps. Subtracting the weights of a splatmap, from the ones before it. //A single pixels of all combined alpha maps must not exceed a value of one. The 2nd pass of Hidden/TerrainEngine/TerrainLayerUtils is used internally to do this //Note: Paintcontext must use a serialized terrain reference, otherwise breaks when executing "ApplyDelayedActions" when the project is saved! PaintContext c = TerrainPaintUtility.BeginPaintTexture(terrain, new Rect(0, 0, scaledSplatmapSize.x, scaledSplatmapSize.y), settings.layer); Graphics.Blit(alphaMap, c.destinationRenderTexture); TerrainPaintUtility.EndPaintTexture(c, UndoActionName); }
public void Release(PaintContext paintContext) { if (ReferenceEquals(paintContext, m_HeightmapContext)) { if (m_WriteToHeightmap) { TerrainPaintUtility.EndPaintHeightmap(m_HeightmapContext, $"{m_Name} - Heightmap"); } else { TerrainPaintUtility.ReleaseContextResources(m_HeightmapContext); } m_HeightmapContext = null; } else if (ReferenceEquals(paintContext, m_NormalmapContext)) { TerrainPaintUtility.ReleaseContextResources(m_NormalmapContext); m_NormalmapContext = null; } else if (ReferenceEquals(paintContext, m_TextureContext)) { if (m_WriteToTexture) { TerrainPaintUtility.EndPaintTexture(m_TextureContext, $"{m_Name} - Texture"); } else { TerrainPaintUtility.ReleaseContextResources(m_TextureContext); } m_TextureContext = null; } #if UNITY_2019_3_OR_NEWER else if (ReferenceEquals(paintContext, m_HolesContext)) { if (m_WriteToHoles) { TerrainPaintUtility.EndPaintHoles(m_HolesContext, "Terrain Paint - Paint Holes"); } else { TerrainPaintUtility.ReleaseContextResources(m_HolesContext); } m_HolesContext = null; } #endif }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushRect, m_SelectedTerrainLayer); if (paintContext == null) { return(false); } Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); // apply brush Vector4 brushParams = new Vector4(editContext.brushStrength, m_SplatAlpha, 0.0f, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.PaintTexture); TerrainPaintUtility.EndPaintTexture(paintContext, "Terrain Paint - Texture"); return(true); }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { commonUI.OnPaint(terrain, editContext); if (!commonUI.allowPaint) { return(true); } if (Event.current.type == EventType.MouseDown) { m_PrevBrushPos = editContext.uv; return(false); } if (Event.current.type == EventType.MouseDrag && m_PreviousEvent == EventType.MouseDrag) { Vector2 uv = editContext.uv; if (commonUI.ScatterBrushStamp(ref terrain, ref uv)) { Material mat = GetPaintMaterial(); Vector2 smudgeDir = uv - m_PrevBrushPos; BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, uv, commonUI.brushSize, commonUI.brushRotation); Vector4 brushParams = new Vector4(commonUI.brushStrength, smudgeDir.x, smudgeDir.y, 0); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); //smudge splat map if (m_AffectMaterials) { for (int i = 0; i < terrain.terrainData.terrainLayers.Length; i++) { TerrainLayer layer = terrain.terrainData.terrainLayers[i]; if (layer == null) { continue; // nothing to paint if the layer is NULL } PaintContext sampleContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushXform.GetBrushXYBounds(), layer); Graphics.Blit(sampleContext.sourceRenderTexture, sampleContext.destinationRenderTexture, mat, 0); TerrainPaintUtility.EndPaintTexture(sampleContext, "Terrain Paint - Twist Brush (Texture)"); } } //smudge the height map if (m_AffectHeight) { PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, 0); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Twist Brush (Height)"); } m_PrevBrushPos = uv; } } m_PreviousEvent = Event.current.type; return(false); }
public static void EndFillTexture(PaintContext ctx, string editorUndoString) { TerrainPaintUtility.EndPaintTexture(ctx, editorUndoString); }
private bool DoPaint(Terrain terrain, float brushStrength, Texture brushTexture, Rect rect, BrushTransform brushXform) { if (disablePaint) { return(false); } m_SelectedTerrainLayer = terrain.terrainData.terrainLayers[m_textureIndex]; PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, rect, m_SelectedTerrainLayer); if (paintContext == null) { return(false); } PaintContext heightContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, rect, 1); if (heightContext == null) { return(false); } if (terrain.normalmapTexture == null) { Debug.Log("Please check the Draw Instanced option under terrain settings to use this tool"); return(false); } PaintContext normalContext = TerrainPaintUtility.CollectNormals(terrain, rect, 0); Material mat = GetPaintMaterial(); float extent = textureParams[m_textureIndex].heightExtent; float blend = textureParams[m_textureIndex].heightBlend; float height = textureParams[m_textureIndex].heightMaxPoint; if (textureParams[m_textureIndex].heightRelative) { extent /= relativeHeightMult; height /= relativeHeightMult; } else { extent /= terrain.terrainData.size.y; height /= terrain.terrainData.size.y; } Vector4 brushParams = new Vector4(brushStrength, height, textureParams[m_textureIndex].heightMask ? extent * (1.0f - blend) : 10000.0f, extent * blend); extent = textureParams[m_textureIndex].slopeExtent; blend = textureParams[m_textureIndex].slopeBlend; Vector4 slopeParams = new Vector4(textureParams[m_textureIndex].slopeMaxPoint, textureParams[m_textureIndex].slopeMask ? extent * (1.0f - blend) : 1.0f, extent * blend, textureParams[m_textureIndex].maxValue); PaintContext maskContext = null; if (textureParams[m_textureIndex].textureMask || textureParams[m_textureIndex].textureStencil) { TerrainLayer maskTerrainLayer = terrain.terrainData.terrainLayers[textureParams[m_textureIndex].textureMask ? textureParams[m_textureIndex].maskIndex : textureParams[m_textureIndex].stencilIndex]; maskContext = TerrainPaintUtility.BeginPaintTexture(terrain, rect, maskTerrainLayer); if (maskContext == null) { return(false); } mat.SetTexture("_MaskTex", maskContext.sourceRenderTexture); } mat.SetInt("_MaskStencil", textureParams[m_textureIndex].textureMask ? 1 : (textureParams[m_textureIndex].textureStencil ? 2 : 0)); mat.SetTexture("_BrushTex", brushTexture); mat.SetTexture("_HeightTex", heightContext.sourceRenderTexture); mat.SetTexture("_NormalTex", normalContext.sourceRenderTexture); mat.SetVector("_BrushParams", brushParams); mat.SetVector("_SlopeParams", slopeParams); mat.SetFloat("_FeatureSize", textureParams[m_textureIndex].heightRelative?textureParams[m_textureIndex].heightFeatureSize:0.0f); if (brushTexture == null) { mat.SetFloat("_AspectRatio", terrain.terrainData.size.x / terrain.terrainData.size.z); } else { mat.SetFloat("_AspectRatio", (float)paintContext.sourceRenderTexture.height / (float)paintContext.sourceRenderTexture.width); } TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, 0); TerrainPaintUtility.EndPaintTexture(paintContext, "Terrain Paint - Masked Texture"); TerrainPaintUtility.ReleaseContextResources(heightContext); TerrainPaintUtility.ReleaseContextResources(normalContext); if (maskContext != null) { TerrainPaintUtility.ReleaseContextResources(maskContext); } return(true); }