- Home /
Question by
B3causeSc1ence · Apr 10, 2018 at 04:03 AM ·
texture2dprocedural generationperlin noiseprocedural-generation
Strange texture2d behaviour
Hello, I am having a problem with a procedurally generated texture. I am making a game that involves a procedurally generated Texture2D, generated from perlin noise. It looks something like this:
There is just a small problem occurring when the scale value (see first script, variable named mapScale) is set to anything above roughly 256, below is a screenshot of the problem:
Here is the code that generates the terrain: This is the first script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapGenerator : MonoBehaviour {
public enum DrawMode { NoiseMap, ColorMap };
public DrawMode drawMode = DrawMode.ColorMap;
public int mapWidth = 1024;
public int mapHeight = 1024;
public float mapScale = 512;
public int octaves = 2;
public float persistance = 0.5f;
public float lacunarity = 2;
public int seed = 1337;
public Vector2 offset = Vector2.zero;
public TerrainType[] terrainTypes;
public bool autoUpdate = true;
public bool randomiseSeed = true;
public void Awake() {
GenerateMap();
}
public void GenerateMap() {
if (randomiseSeed) {
seed = Random.Range(-1000000, 1000000);
}
float[,] noiseMap = Noise.GenerateNoiseMap(mapWidth, mapHeight, seed, mapScale, octaves, persistance, lacunarity, offset);
Color[] colorMap = new Color[mapWidth * mapHeight];
for (int y = 0; y < mapHeight; y++)
{
for (int x = 0; x < mapWidth; x++)
{
float pointHeight = noiseMap[x, y];
for (int i = 0; i < terrainTypes.Length; i++)
{
if (pointHeight <= terrainTypes[i].height) {
colorMap[y * mapWidth + x] = terrainTypes[i].color;
break;
}
}
}
}
MapDisplay display = FindObjectOfType<MapDisplay>();
if (drawMode == DrawMode.NoiseMap) {
display.DrawTexture(TextureGenerator.TextureFromHeightMap(noiseMap), mapWidth, mapHeight);
} else if (drawMode == DrawMode.ColorMap) {
display.DrawTexture(TextureGenerator.TextureFromColorMap(colorMap, mapWidth, mapHeight), mapWidth, mapHeight);
}
}
}
[System.Serializable]
public struct TerrainType {
public float height;
public Color color;
public string terrainName;
}
This is the second script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class Noise {
public static float[,] GenerateNoiseMap(int width, int height, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset) {
if (scale <= 0) {
scale = 0.000000001f;
}
float[,] noiseMap = new float[width, height];
System.Random psuedoRandomNumberGenerator = new System.Random(seed);
Vector2[] octaveOffsets = new Vector2[octaves];
for (int i = 0; i < octaves; i++)
{
float offsetx = psuedoRandomNumberGenerator.Next(-100000, 100000) + offset.x;
float offsety = psuedoRandomNumberGenerator.Next(-100000, 100000) + offset.y;
octaveOffsets[i] = new Vector2(offsetx, offsety);
}
float maxNoiseHeight = float.MinValue;
float minNoiseHeight = float.MaxValue;
float halfWidth = width / 2;
float halfHeight = height / 2;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float amplitude = 1f;
float frequency = 1f;
float noiseHeight = 0;
for (int i = 0; i < octaves; i++) {
float sampleX = (x - halfWidth) / scale * frequency + octaveOffsets[i].x;
float sampleY = (y - halfHeight) / scale * frequency + octaveOffsets[i].y;
float perlin = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
noiseHeight += perlin * amplitude;
amplitude *= persistance;
frequency *= lacunarity;
}
if (noiseHeight > maxNoiseHeight) {
maxNoiseHeight = noiseHeight;
} else if (noiseHeight < minNoiseHeight) {
minNoiseHeight = noiseHeight;
}
noiseMap[x, y] = noiseHeight;
}
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
noiseMap[x, y] = Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, noiseMap[x, y]);
}
}
return noiseMap;
}
}
This is the third script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class TextureGenerator {
public static Texture2D TextureFromColorMap(Color[] colorMap, int width, int height) {
Texture2D texture = new Texture2D(width, height);
texture.wrapMode = TextureWrapMode.Clamp;
texture.filterMode = FilterMode.Point;
texture.SetPixels(colorMap);
texture.Apply();
return texture;
}
public static Texture2D TextureFromHeightMap(float[,] heightMap) {
int width = heightMap.GetLength(0);
int height = heightMap.GetLength(1);
Color[] colorArray = new Color[width * height];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
colorArray[y * width + x] = Color.Lerp(Color.white, Color.black, heightMap[x, y]);
}
}
return TextureFromColorMap(colorArray, width, height);
}
}
This is the final script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapDisplay : MonoBehaviour {
public GameObject terrainSprite;
public void DrawTexture (Texture2D texture, int mapWidth, int mapHeight) {
//terrainSprite.transform.localScale = new Vector2(texture.width, texture.height);
terrainSprite.GetComponent<SpriteRenderer>().sprite = Sprite.Create(texture, new Rect(Vector2.zero, new Vector2(mapWidth, mapHeight)), new Vector2(0.5f, 0.5f));
}
}
Thank you so much :D
,
screen-shot-2018-04-10-at-14913-pm.png
(34.3 kB)
screen-shot-2018-04-10-at-15501-pm.png
(21.3 kB)
Comment