尝试通过代码根据图像纹理颜色设置高度图
Trying to set heightmaps depending on image texture colors through code
好吧,我正在尝试从图像/纹理颜色(从像素)设置地形的高度图,我做了这个简单的例子:
using UnityEngine;
public class TerrainExample : MonoBehaviour
{
public Texture2D map, grassTexture;
public float amp = 8;
public Color waterColor = new Color(0.427f, 0.588f, 0.737f); //new Color32(127, 168, 200, 255); //0.427, 0.588, 0.737
private Vector3 mapPlane = new Vector3(4200, 0, 3000);
public void Start()
{
GameObject TerrainObj = new GameObject("TerrainObj");
TerrainData _TerrainData = new TerrainData();
Debug.Log(new Vector3(mapPlane.x, 600, mapPlane.z));
_TerrainData.size = new Vector3(mapPlane.x / (1.6f * amp), 600, mapPlane.z / (1.6f * amp));
_TerrainData.heightmapResolution = 4096;
_TerrainData.baseMapResolution = 1024;
_TerrainData.SetDetailResolution(1024, 16);
//Set terrain data
int _heightmapWidth = _TerrainData.heightmapWidth,
_heightmapHeight = _TerrainData.heightmapHeight;
float[,] heights = new float[_heightmapWidth, _heightmapHeight];
float stepX = (float)map.width / _heightmapWidth, stepY = (float)map.height / _heightmapHeight;
int w = 0;
for (float i = 0; i < map.width; i += stepX)
for (float k = 0; k < map.height; k += stepY)
{
int ii = (int)i, kk = (int)k, i2 = (int)(i / stepX), k2 = (int)(k / stepY);
heights[i2, k2] = map.GetPixel(ii, kk) == waterColor ? .25f : .5f;
}
_TerrainData.SetHeights(0, 0, heights);
//Set terrain grass texture
SplatPrototype terrainTexture = new SplatPrototype();
terrainTexture.texture = grassTexture;
SplatPrototype[] splatPrototype = new SplatPrototype[1] { terrainTexture };
_TerrainData.splatPrototypes = splatPrototype;
TerrainCollider _TerrainCollider = TerrainObj.AddComponent<TerrainCollider>();
Terrain _Terrain2 = TerrainObj.AddComponent<Terrain>();
_TerrainCollider.terrainData = _TerrainData;
_Terrain2.terrainData = _TerrainData;
TerrainObj.transform.position = -mapPlane * 10 / 2 + Vector3.up * 100;
}
}
我的地图纹理如下:
原图有7000x5000像素,我的高度图有4096个单位。因此,我必须通过计算每次迭代的步长来做一点翻译(如您在 第 25 行 中所见)
我做的很简单,我只在有水的时候放了0.25f的高度(600/4 = 150),在有水的时候放了0.5f的高度(600 / 2 = 300)水。 (第 31 行)
但出于某种原因,我只在地形上看到了这条奇怪的线:
我错过了什么???
这里是Unitypackage.
我真的懒得分配纹理,我会让你这样做。
- 创建新场景
- 添加地形
- 添加以下组件
代码:
using UnityEngine;
namespace Assets
{
public class Test : MonoBehaviour
{
public Texture2D Texture2D;
private void OnEnable()
{
var terrain = GetComponent<Terrain>();
var data = terrain.terrainData;
var hw = data.heightmapWidth;
var hh = data.heightmapHeight;
var heights = data.GetHeights(0, 0, hw, hh);
for (var y = 0; y < hh; y++)
{
for (var x = 0; x < hw; x++)
{
// normalize coordinates
var x1 = 1.0f / hw * x * Texture2D.width;
var y1 = 1.0f / hh * y * Texture2D.height;
// get color height
var pixel = Texture2D.GetPixel((int) x1, (int) y1);
var f = pixel.grayscale; // defines height
var g = f * f * f; // some smoothing
var s = 0.025f; // some scaling
heights[x, y] = g * s;
}
}
data.SetHeights(0, 0, heights);
}
}
}
其中最有趣的是平滑,它显着改善了输出。
此外,您可以从 pre-defined 列表(例如水、草)和 interpolate/smooth.
中找到 which color the pixel is close to
此外,您可能需要调整代码,因为我对 TerrainData
不是很熟悉。
好吧,我正在尝试从图像/纹理颜色(从像素)设置地形的高度图,我做了这个简单的例子:
using UnityEngine;
public class TerrainExample : MonoBehaviour
{
public Texture2D map, grassTexture;
public float amp = 8;
public Color waterColor = new Color(0.427f, 0.588f, 0.737f); //new Color32(127, 168, 200, 255); //0.427, 0.588, 0.737
private Vector3 mapPlane = new Vector3(4200, 0, 3000);
public void Start()
{
GameObject TerrainObj = new GameObject("TerrainObj");
TerrainData _TerrainData = new TerrainData();
Debug.Log(new Vector3(mapPlane.x, 600, mapPlane.z));
_TerrainData.size = new Vector3(mapPlane.x / (1.6f * amp), 600, mapPlane.z / (1.6f * amp));
_TerrainData.heightmapResolution = 4096;
_TerrainData.baseMapResolution = 1024;
_TerrainData.SetDetailResolution(1024, 16);
//Set terrain data
int _heightmapWidth = _TerrainData.heightmapWidth,
_heightmapHeight = _TerrainData.heightmapHeight;
float[,] heights = new float[_heightmapWidth, _heightmapHeight];
float stepX = (float)map.width / _heightmapWidth, stepY = (float)map.height / _heightmapHeight;
int w = 0;
for (float i = 0; i < map.width; i += stepX)
for (float k = 0; k < map.height; k += stepY)
{
int ii = (int)i, kk = (int)k, i2 = (int)(i / stepX), k2 = (int)(k / stepY);
heights[i2, k2] = map.GetPixel(ii, kk) == waterColor ? .25f : .5f;
}
_TerrainData.SetHeights(0, 0, heights);
//Set terrain grass texture
SplatPrototype terrainTexture = new SplatPrototype();
terrainTexture.texture = grassTexture;
SplatPrototype[] splatPrototype = new SplatPrototype[1] { terrainTexture };
_TerrainData.splatPrototypes = splatPrototype;
TerrainCollider _TerrainCollider = TerrainObj.AddComponent<TerrainCollider>();
Terrain _Terrain2 = TerrainObj.AddComponent<Terrain>();
_TerrainCollider.terrainData = _TerrainData;
_Terrain2.terrainData = _TerrainData;
TerrainObj.transform.position = -mapPlane * 10 / 2 + Vector3.up * 100;
}
}
我的地图纹理如下:
原图有7000x5000像素,我的高度图有4096个单位。因此,我必须通过计算每次迭代的步长来做一点翻译(如您在 第 25 行 中所见)
我做的很简单,我只在有水的时候放了0.25f的高度(600/4 = 150),在有水的时候放了0.5f的高度(600 / 2 = 300)水。 (第 31 行)
但出于某种原因,我只在地形上看到了这条奇怪的线:
我错过了什么???
这里是Unitypackage.
我真的懒得分配纹理,我会让你这样做。
- 创建新场景
- 添加地形
- 添加以下组件
代码:
using UnityEngine;
namespace Assets
{
public class Test : MonoBehaviour
{
public Texture2D Texture2D;
private void OnEnable()
{
var terrain = GetComponent<Terrain>();
var data = terrain.terrainData;
var hw = data.heightmapWidth;
var hh = data.heightmapHeight;
var heights = data.GetHeights(0, 0, hw, hh);
for (var y = 0; y < hh; y++)
{
for (var x = 0; x < hw; x++)
{
// normalize coordinates
var x1 = 1.0f / hw * x * Texture2D.width;
var y1 = 1.0f / hh * y * Texture2D.height;
// get color height
var pixel = Texture2D.GetPixel((int) x1, (int) y1);
var f = pixel.grayscale; // defines height
var g = f * f * f; // some smoothing
var s = 0.025f; // some scaling
heights[x, y] = g * s;
}
}
data.SetHeights(0, 0, heights);
}
}
}
其中最有趣的是平滑,它显着改善了输出。
此外,您可以从 pre-defined 列表(例如水、草)和 interpolate/smooth.
中找到 which color the pixel is close to此外,您可能需要调整代码,因为我对 TerrainData
不是很熟悉。