Terrain のハイトマップの変更
以下のサンプルコードは、ビルトインのペインティングマテリアルを使用して Terrain (地形) のハイトマップを変更し、シーンビューでブラシのプレビューをレンダリングするよう Unity に指示します。
using UnityEngine;
using UnityEditor;
using UnityEditor.TerrainTools;
internal class CustomTerrainTool : TerrainPaintTool<CustomTerrainTool>
{
private float m_BrushOpacity;
private float m_BrushSize;
private float m_BrushRotation;
// Terrain ツールの名前。ツールの UI に表示されます。
public override string GetName()
{
return "Examples/Custom Terrain Tool";
}
// Terrain ツールの説明。ツールの UI に表示されます。
public override string GetDescription()
{
return "This is a custom Terrain Tool that modifies the Terrain heightmap.";
}
public override void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext)
{
editContext.ShowBrushesGUI(5, BrushGUIEditFlags.Select);
m_BrushOpacity = EditorGUILayout.Slider("Opacity", m_BrushOpacity, 0, 1);
m_BrushSize = EditorGUILayout.Slider("Size", m_BrushSize, .001f, 100f);
m_BrushRotation = EditorGUILayout.Slider("Rotation", m_BrushRotation, 0, 360);
}
// 変更された Terrain テクスチャのデータを PaintContext にレンダリングできる使いやすい関数です。OnRenderBrushPreview と OnPaint の両方で使用されます。
private void RenderIntoPaintContext(UnityEngine.TerrainTools.PaintContext paintContext, Texture brushTexture, UnityEngine.TerrainTools.BrushTransform brushXform)
{
// ビルトインのペインティングマテリアルの参照を取得します
Material mat = UnityEngine.TerrainTools.TerrainPaintUtility.GetBuiltinPaintMaterial();
// 現在のブラシテクスチャをバインドします
mat.SetTexture("_BrushTex", brushTexture);
// ツール固有のシェーダープロパティをバインドします
var opacity = Event.current.control ? -m_BrushOpacity : m_BrushOpacity;
mat.SetVector("_BrushParams", new Vector4(opacity, 0.0f, 0.0f, 0.0f));
// PaintContext のテクスチャデータの読み取りと書き込み用のマテリアルを設定します。UV を適切にトランスフォームし、シェーダー内のテクスチャをサンプリングできるよう、適切なシェーダープロパティを設定するために必要なステップです
UnityEngine.TerrainTools.TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat);
// ビルトインのペインティングマテリアルを使用して、PaintContext の destinationRenderTexture にレンダリングします。Raise/Lower パスの ID は 0 です。
Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, 0);
}
// シーンビューでの Render ツールのプレビュー
public override void OnRenderBrushPreview(Terrain terrain, IOnSceneGUI editContext)
{
// これが Repaint ではない場合はプレビューをレンダリングしません
if (Event.current.type != EventType.Repaint) return;
// ユーザーのマウスが有効な Terrain にヒットした場合のみ、残りの処理を実行します
if (!editContext.hitValidTerrain) return;
// Terrain を基準として、マウスの位置にある現在の BrushTransform を取得します
UnityEngine.TerrainTools.BrushTransform brushXform = UnityEngine.TerrainTools.TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, m_BrushSize, m_BrushRotation);
// 現在の BrushTransform の PaintContext を取得します。既存の Terrain テクスチャデータの読み取り元になる sourceRenderTexture が含まれます
UnityEngine.TerrainTools.PaintContext paintContext = UnityEngine.TerrainTools.TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1);
// ブラシのプレビューをレンダリングするためにビルトインのマテリアルを取得します
Material previewMaterial = TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial();
// sourceRenderTexture のブラシのプレビューをレンダリングします。Terrain の上にレンダリングされる投影されたブラシメッシュとして表示されます
TerrainPaintUtilityEditor.DrawBrushPreview(paintContext, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 0);
// 変更内容を PaintContext destinationRenderTexture にレンダリングします
RenderIntoPaintContext(paintContext, editContext.brushTexture, brushXform);
// 古いレンダーターゲットを復元します。
RenderTexture.active = paintContext.oldRenderTexture;
// sourceRenderTexture をプレビューのマテリアルにバインドします。高さの変化量を計算するために使用されます
previewMaterial.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture);
// ソースの Terrain テクスチャデータからの高さの変化量とディスプレイスメントを表示するプロシージャルメッシュをレンダリングします。Terrain の高さを変更すると、次のペイント処理によって Terrain の高さがどの程度変化するかが表示されます
TerrainPaintUtilityEditor.DrawBrushPreview(paintContext, TerrainBrushPreviewMode.DestinationRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 1);
// リソースをクリーンアップします
UnityEngine.TerrainTools.TerrainPaintUtility.ReleaseContextResources(paintContext);
}
// Terrain テクスチャデータを変更するペインティング処理を実行します
public override bool OnPaint(Terrain terrain, IOnPaint editContext)
{
// Terrain を基準としてマウスの位置にある現在の BrushTransform を取得します
UnityEngine.TerrainTools.BrushTransform brushXform = UnityEngine.TerrainTools.TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, m_BrushSize, m_BrushRotation);
// 現在の BrushTransform の PaintContext を取得します。既存の Terrain テクスチャデータの読み取り元になる sourceRenderTexture と
// 新しい Terrain テクスチャデータの書き込み先になる destinationRenderTexture が含まれます
UnityEngine.TerrainTools.PaintContext paintContext = UnityEngine.TerrainTools.TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds());
// OnRenderBrushPreview と OnPaint で使用される共通のレンダリング関数を呼び出します
RenderIntoPaintContext(paintContext, editContext.brushTexture, brushXform);
// 取り消し操作を追跡するために指定された文字列を指定して変更済みの PaintContext をコミットします。この関数は取り消しとリソースのクリーンアップを処理します
UnityEngine.TerrainTools.TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Raise or Lower Height");
// この Terrain ツールを使用してペイントしているときに、樹木やディテールを非表示にするかどうかを返します。
return true;
}
}