Unity 根据高度图生成地形

发表于2018-10-22
评论0 4.8k浏览
今天翻官方案例看到这个不错的功能,地形组件也有导入高度图的功能,但试了下没成功,下面就给大家介绍下地形高度图生成的实现脚本。

这个脚本直接自建模型,放入张贴图(最好是灰度图,尺寸是2的次方),做联机游戏可以考虑用高度图来共享地形,方法如下:

js版:
// This script is placed in public domain. The author takes no responsibility for any possible harm.
var heightMap : Texture2D;
var material : Material;
var size = Vector3(200, 30, 200);
function Start ()
{
	GenerateHeightmap();
}
function GenerateHeightmap ()
{
	// Create the game object containing the renderer
	gameObject.AddComponent(MeshFilter);
	gameObject.AddComponent.<MeshRenderer>();
	if (material)
		GetComponent.<Renderer>().material = material;
	else
		GetComponent.<Renderer>().material.color = Color.white;
	// Retrieve a mesh instance
	var mesh : Mesh = GetComponent(MeshFilter).mesh;
	var width : int = Mathf.Min(heightMap.width, 255);
	var height : int = Mathf.Min(heightMap.height, 255);
	var y = 0;
	var x = 0;
	// Build vertices and UVs
	var vertices = new Vector3[height * width];
	var uv = new Vector2[height * width];
	var tangents = new Vector4[height * width];
	var uvScale = Vector2 (1.0 / (width - 1), 1.0 / (height - 1));
	var sizeScale = Vector3 (size.x / (width - 1), size.y, size.z / (height - 1));
	for (y=0;y<height;y++)
	{
		for (x=0;x<width;x++)
		{
			var pixelHeight = heightMap.GetPixel(x, y).grayscale;
			var vertex = Vector3 (x, pixelHeight, y);
			vertices[y*width + x] = Vector3.Scale(sizeScale, vertex);
			uv[y*width + x] = Vector2.Scale(Vector2 (x, y), uvScale);
			// Calculate tangent vector: a vector that goes from previous vertex
			// to next along X direction. We need tangents if we intend to
			// use bumpmap shaders on the mesh.
			var vertexL = Vector3( x-1, heightMap.GetPixel(x-1, y).grayscale, y );
			var vertexR = Vector3( x+1, heightMap.GetPixel(x+1, y).grayscale, y );
			var tan = Vector3.Scale( sizeScale, vertexR - vertexL ).normalized;
			tangents[y*width + x] = Vector4( tan.x, tan.y, tan.z, -1.0 );
		}
	}
	// Assign them to the mesh
	mesh.vertices = vertices;
	mesh.uv = uv;
	// Build triangle indices: 3 indices into vertex array for each triangle
	var triangles = new int[(height - 1) * (width - 1) * 6];
	var index = 0;
	for (y=0;y<height-1;y++)
	{
		for (x=0;x<width-1;x++)
		{
			// For each grid cell output two triangles
			triangles[index++] = (y     * width) + x;
			triangles[index++] = ((y+1) * width) + x;
			triangles[index++] = (y     * width) + x + 1;
			triangles[index++] = ((y+1) * width) + x;
			triangles[index++] = ((y+1) * width) + x + 1;
			triangles[index++] = (y     * width) + x + 1;
		}
	}
	// And assign them to the mesh
	mesh.triangles = triangles;
	// Auto-calculate vertex normals from the mesh
	mesh.RecalculateNormals();
	// Assign tangents after recalculating normals
	mesh.tangents = tangents;
}

C#的:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tex2DToModel : MonoBehaviour 
{
	public Texture2D heightMap;//设置Advanced.Read/Write Enable为true
	public Material material;
	public Vector3 size=new Vector3(256,30,256);
	// Use this for initialization
	void Start () 
	{
		GenerateHeightmap ();	
	}
	void GenerateHeightmap()
	{
		// Create the game object containing the renderer
		gameObject.AddComponent<MeshFilter>();
		gameObject.AddComponent<MeshRenderer>();
		if (material) 
		{
			GetComponent<Renderer> ().material = material;
		} 
		else 
		{
			GetComponent<Renderer> ().material.color = Color.white;
		}
		// Retrieve a mesh instance
		Mesh mesh = GetComponent<MeshFilter>().mesh;
		int width = Mathf.Min(heightMap.width, 255);
		int height = Mathf.Min(heightMap.height, 255);
		int y = 0;
		int x = 0;
		// Build vertices and UVs
		Vector3[] vertices = new Vector3[height * width];
		Vector2[] uv = new Vector2[height * width];
		Vector4[] tangents = new Vector4[height * width];
		Vector2 uvScale = new Vector2 (1.0f / (width - 1) , 1.0f / (height - 1) );
		Vector3 sizeScale = new Vector3 (size.x / (width - 1), size.y, size.z / (height - 1));
		for (y=0;y<height;y++)
		{
			for (x=0;x<width;x++)
			{
				float pixelHeight = heightMap.GetPixel(x, y).grayscale;
				Vector3 vertex = new Vector3 (x, pixelHeight, y);
				vertices[y*width + x] = Vector3.Scale(sizeScale, vertex);
				uv[y*width + x] = Vector2.Scale(new Vector2 (x, y), uvScale);
				// Calculate tangent vector: a vector that goes from previous vertex
				// to next along X direction. We need tangents if we intend to
				// use bumpmap shaders on the mesh.
				Vector3 vertexL = new Vector3( x-1, heightMap.GetPixel(x-1, y).grayscale, y );
				Vector3 vertexR = new Vector3( x+1, heightMap.GetPixel(x+1, y).grayscale, y );
				Vector3 tan = Vector3.Scale( sizeScale, vertexR - vertexL ).normalized;
				tangents[y*width + x] = new Vector4( tan.x, tan.y, tan.z, -1.0f );
			}
		}
		// Assign them to the mesh
		mesh.vertices = vertices;
		mesh.uv = uv;
		// Build triangle indices: 3 indices into vertex array for each triangle
		int[] triangles = new int[(height - 1) * (width - 1) * 6];
		int index = 0;
		for (y=0;y<height-1;y++)
		{
			for (x=0;x<width-1;x++)
			{
				// For each grid cell output two triangles
				triangles[index++] = (y     * width) + x;
				triangles[index++] = ((y+1) * width) + x;
				triangles[index++] = (y     * width) + x + 1;
				triangles[index++] = ((y+1) * width) + x;
				triangles[index++] = ((y+1) * width) + x + 1;
				triangles[index++] = (y     * width) + x + 1;
			}
		}
		// And assign them to the mesh
		mesh.triangles = triangles;
		// Auto-calculate vertex normals from the mesh
		mesh.RecalculateNormals();
		// Assign tangents after recalculating normals
		mesh.tangents = tangents;
	}
}

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: