Hi Community!
I want to make an Editor Extension which is a terrain painter with advanced functions. I already know how to set alpha maps and modify them, but I want to know how can I get the alphamap area under the brush. In other words, can someone give me a good idea or working code (even better) to effectively carry out terrain painting in the same way that the Unity Terrain Engine does? Like if we choose a star brush, the texture will be painted in that shape and size?
EDIT:
I already can paint the texture on the terrain, but not in the correct shape.
The stars are from Unity’s Terrain Engine (which I want to simulate) and the squares are painted from my script:
Terrain terrain;
TerrainData terrainData;
TerrainPointData[] points;
float[] strength;
int size;
float GetStrength(int x, int y)
{
x = Mathf.Clamp(x, 0, size - 1);
y = Mathf.Clamp(y, 0, size - 1);
return strength[y * size + x];
}
public void Initialize(Texture2D brushTexture, int size)
{
if (terrain == null)
terrain = GetComponent<Terrain>();
terrainData = terrain.terrainData;
points = new TerrainPointData[terrainData.alphamapHeight * terrainData.alphamapWidth];
for (int y = 0; y < terrainData.alphamapHeight; y++) {
for (int x = 0; x < terrainData.alphamapWidth; x++) {
//Normalize Coordinates
float x01 = (float)x / terrainData.alphamapWidth;
float y01 = (float)y / terrainData.alphamapHeight;
//Get Height at point
float height = terrainData.GetHeight(Mathf.RoundToInt(y01 * terrainData.heightmapHeight), Mathf.RoundToInt(x01 * terrainData.heightmapWidth));
//Get Normal at point
//Vector3 normal = terrainData.GetInterpolatedNormal(y01, x01);
//Get Steepness at point
float steepness = terrainData.GetSteepness(y01, x01);
points[y * terrainData.alphamapHeight + x] = new TerrainPointData(x, y, height, steepness);//, normal);
}
}
this.size = size;
//size = brushTexture.height;
strength = new float[size * size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
strength[i * size + j] = brushTexture.GetPixelBilinear((float)j / size, (float)i / size).a;
}
}
}
public void Paint(Vector2 mousePosition, int textureIndex = 1, float opacity = 1)
{
int Size = 8 * size;
int num = Mathf.FloorToInt(mousePosition.x * terrainData.alphamapWidth);
int num2 = Mathf.FloorToInt(mousePosition.y * terrainData.alphamapHeight);
int num3 = Mathf.RoundToInt((float)size) / 2;
int num4 = Mathf.RoundToInt((float)size) % 2;
int x = Mathf.Clamp(num - num3, 0, terrainData.alphamapWidth - 1);
int y = Mathf.Clamp(num2 - num3, 0, terrainData.alphamapHeight - 1);
int num7 = Mathf.Clamp((num + num3) + num4, 0, terrainData.alphamapWidth);
int num8 = Mathf.Clamp((num2 + num3) + num4, 0, terrainData.alphamapHeight);
int width = num7 - x;
int height = num8 - y;
float[, ,] splatmapData = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int ix = (x + j) - ((num - num3) + num4);
int iy = (y + i) - ((num2 - num3) + num4);
splatmapData[y + i, x + j, textureIndex] = GetStrength(ix / size, iy / size) * opacity;
}
}
terrainData.SetAlphamaps(0, 0, splatmapData);
}
Please ignore the TerrainPointData array, that is for my experimentation.
@judah4 @FreebordMAD I saw your assets, could you just tell me how you implemented the different brushes for texturing your terrain? I spent 6 hours yesterday but couldn’t find a solution. Sorry for the direct reference.
Thanks!

