- Home /
Random Heightmap decals
I want to add a bit of detail to chunk heightmaps on a terrain I'm working on, but I don't have a clue how I can distribute a decal texture to random positions on my heigtmap. I use a perlin noise function to generate a heightmap for my every chunk, but how can i distribute decals ( a crater texture for example) on my heightmap so that they don't just get cut of at the end of a chunk and are randomly splattered?
Comment
Answer by Simeon · Jul 30, 2013 at 03:06 PM
I thought of a solution, altho it's quite the brute force approach. I know this could be done on the GPU with texture bombing, but i needed a solution that worked in script because my noise generation is on the CPU;
using UnityEngine;
using System.Collections;
public class TextureBombing : MonoBehaviour {
public Texture2D texture;
Color[,] texturePixels;
public int TextureSize;
Texture2D final;
Color[] finalPixels;
public Color BgColor;
public float GridScale;
public float Scale;
public Vector2 Offset;
public float Rotation;
public Vector2 RandomRotation,RandomScale;
float scale;
public Vector2 MaxOffset;
void OnGUI()
{
GUI.DrawTexture(new Rect(0, 0, TextureSize, TextureSize), final);
}
void Update()
{
Offset += Vector2.up * Time.deltaTime * 100 * Input.GetAxis("Horizontal");
Offset += Vector2.right * Time.deltaTime * 100 * Input.GetAxis("Vertical");
}
Color p;
void Start()
{
finalPixels = new Color[TextureSize * TextureSize];
final = new Texture2D(TextureSize, TextureSize);
StartCoroutine(CreateTexture(TextureSize));
}
IEnumerator CreateTexture(int size)
{
while (true)
{
int index = 0;
for (int x = -size / 2; x < size / 2; x++)
{
for (int y = -size / 2; y < size / 2; y++)
{
p = GetPixel(x + size / 2 + (int)Offset.x, y + size / 2 + (int)Offset.y, Rotation);
finalPixels[index] = p;
index++;
}
}
final.SetPixels(finalPixels);
final.Apply();
yield return new WaitForEndOfFrame();
}
}
Color c;
Vector2 cell;
float randomOffsetX, randomOffsetY, rndRot, rndScale;
float cellWidthX,cellHeightY,scaledHalfTextureHeightX,scaledHalfTextureHeightY,halfTextureHeight,halfTextureWidth,halfGridCellScale;
float X, Y;
float X1, Y1;
Color GetPixel(int x, int y,float degree)
{
RandomGen.setSeed((int)(cell.x + 1) + (int)(cell.y + 1) * (int)(cell.y + 1));
degree*= Mathf.Deg2Rad;
cell = new Vector2(Mathf.Floor(x / GridScale), Mathf.Floor(y / GridScale));
cellWidthX = (cell.x * GridScale);
cellHeightY = (cell.y * GridScale);
scaledHalfTextureHeightX = (texture.width * Scale) / 2f;
scaledHalfTextureHeightY = (texture.height * Scale) / 2f;
halfTextureWidth = texture.width / 2f;
halfTextureHeight = texture.height / 2f;
halfGridCellScale = GridScale / 2f;
randomOffsetX = Mathf.Clamp(RandomGen.Float(-MaxOffset.x / 2f, MaxOffset.x / 2f),-scaledHalfTextureHeightX,scaledHalfTextureHeightX);
randomOffsetY = Mathf.Clamp(RandomGen.Float(-MaxOffset.y / 2f, MaxOffset.y / 2f),-scaledHalfTextureHeightX,scaledHalfTextureHeightX);
rndScale = RandomGen.Float(RandomScale.x,RandomScale.y);
X = (x + randomOffsetX - cellWidthX - halfGridCellScale + scaledHalfTextureHeightX) / (Scale + rndScale);
Y = (y + randomOffsetY - cellHeightY - halfGridCellScale + scaledHalfTextureHeightY) / (Scale + rndScale);
rndRot = RandomGen.Float(RandomRotation.x, RandomRotation.y) * Mathf.Deg2Rad;
X1 = (X - halfTextureWidth) * Mathf.Cos(degree + rndRot) - (Y - halfTextureHeight) * Mathf.Sin(degree + rndRot) + halfTextureWidth;
Y1 = (X - halfTextureWidth) * Mathf.Sin(degree + rndRot) + (Y - halfTextureHeight) * Mathf.Cos(degree + rndRot) + halfTextureHeight;
if (X1 <= 0 || X1 >= texture.width || Y1 <= 0 || Y1 >= texture.height)
return BgColor;
else
{
c = texture.GetPixel((int)X1, (int)Y1);
if (c.a < 1)
return BgColor + c;
else
return c;
}
}
}