unity 读取灰度图生成按高程分层设色地形模型
准备灰度图
1、高程按比例对应hue色相(hsv)生成mesh效果
o.color = float4(hsv2rgb(float3(v.vertex.y/100.0, 0.5, 0.75)), 1.0);
unity shader
Shader "Unlit/vertexColor 1" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; float4 color:COLOR; }; sampler2D _MainTex; float4 _MainTex_ST; float3 hsv2rgb(float3 c) { float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www); return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y); } v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.color = float4(hsv2rgb(float3(v.vertex.y/100.0, 0.5, 0.75)), 1.0); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture //fixed4 col = tex2D(_MainTex, i.uv); fixed4 col = i.color; // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
2、高程按比例对应色带生成mesh效果
准备色带图
unity shder
Shader "Unlit/colorRamp" { Properties { _MainTex ("Texture", 2D) = "white" {} _ColorRamp("Color Ramp", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; float2 colorUV : TEXCOORD1; }; sampler2D _MainTex; sampler2D _ColorRamp; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); o.colorUV = float2(v.vertex.y / 100.0,0); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_ColorRamp,i.colorUV); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
mesh创建脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class meshCreate2 : MonoBehaviour { private Texture textureGray;//灰度图 private Texture textureGrass;//草地贴图 private int tGrayWidth = 0, tGrayHeight = 0;//灰度图的宽和高 private bool bCreate = false;//是否完成创建 private List<GameObject> meshList;//mesh集合 private Texture2D texture2dGray; public float zScale = 100;//高度参数 [Tooltip("传入mesh使用的材质")] public Material meshMaterial; void Start() { StartCoroutine(loadImage("IGray.png", (t) => textureGray = t)); StartCoroutine(loadImage("IGrass.jpg", (t) => textureGrass = t)); meshList = new List<GameObject>(); } void Update() { if (textureGray != null && textureGrass != null) { if (bCreate == false) { tGrayWidth = textureGray.width; tGrayHeight = textureGray.height; meshMaterial.mainTexture = textureGrass;//设置材质贴图 //mesh顶点数目最大65000,则取mes为250*250=62500 int xNum = 1 + tGrayWidth / 250;//x方向mesh个数 int zNum = 1 + tGrayHeight / 250; //z方向mesh个数 texture2dGray = (Texture2D)textureGray; //根据灰度图创建mesh for (int i = 0; i < xNum; i++) { for (int j = 0; j < zNum; j++) { if (i < xNum - 1 && j < zNum - 1) { meshList.Add( createMesh("meshX" + i.ToString() + "Z" + j.ToString(), 251, 251, i * new Vector3(2500, 0, 0) + j * new Vector3(0, 0,2500), (i + 1) * new Vector3(2500, 0, 0) + (j + 1) * new Vector3(0, 0,2500) + new Vector3(10, 0,10), i * new Vector2(250, 0) + j * new Vector2(0, 250), (i + 1) * new Vector2(250, 0) + (j + 1) * new Vector2(0, 250) + new Vector2(1, 1))); } else if (i == xNum - 1 && j < zNum - 1) { meshList.Add(createMesh("meshX" + i.ToString() + "Z" + j.ToString(), tGrayWidth % 250, 251, i * new Vector3(2500, 0, 0) + j * new Vector3(0, 0,2500), i * new Vector3(2500, 0, 0) + new Vector3(10 * (tGrayWidth % 250), 0,10) + (j + 1) * new Vector3(0, 0,2500), i * new Vector2(250, 0) + j * new Vector2(0, 250), i * new Vector2(250, 0) + new Vector2(tGrayWidth % 250, 1) + (j + 1) * new Vector2(0, 250))); } else if (i < xNum - 1 && j == zNum - 1) { meshList.Add(createMesh("meshX" + i.ToString() + "Z" + j.ToString(), 251, tGrayHeight % 250, i * new Vector3(2500, 0, 0) + j * new Vector3(0, 0,2500), (i + 1) * new Vector3(2500, 0, 0) + j * new Vector3(0, 0,2500) + new Vector3(10, 0, 10 * (tGrayHeight % 250)), i * new Vector2(250, 0) + j * new Vector2(0, 250), (i + 1) * new Vector2(250, 0) + j * new Vector2(0, 150) + new Vector2(1, tGrayHeight % 250))); } else if (i == xNum - 1 && j == zNum - 1) { meshList.Add(createMesh("meshX" + i.ToString() + "Z" + j.ToString(), tGrayWidth % 250, tGrayHeight % 250, i * new Vector3(2500, 0, 0) + j * new Vector3(0, 0, 2500), i * new Vector3(2500, 0, 0) + j * new Vector3(0, 0, 2500) + new Vector3(10 * (tGrayWidth % 250), 0, 10 * (tGrayHeight % 250)), i * new Vector2(250, 0) + j * new Vector2(0, 250), i * new Vector2(250, 0) + j * new Vector2(0, 250) + new Vector2(tGrayWidth % 250, tGrayHeight % 250))); } } } bCreate = true; } } } //加载图片 IEnumerator loadImage(string imagePath, System.Action<Texture> action) { WWW www = new WWW("file://" + Application.streamingAssetsPath + "/" + imagePath); yield return www; if (www.error == null) { action(www.texture); } } /// <summary> ///创建mesh /// </summary> /// <param name="meshName">mesh名称</param> /// <param name="row">行数</param> /// <param name="col">列数</param> /// <param name="minPoint">最小点位置</param> /// <param name="maxPoint">最大点位置</param> /// <param name="minImgPosition">最小点灰度图位置</param> /// <param name="maxImgPosition">最大点灰度图位置</param> /// <returns></returns> /// private GameObject createMesh(string meshName, int row, int col, Vector3 minPoint, Vector3 maxPoint, Vector2 minImgPosition, Vector2 maxImgPosition) { GameObject meshObject = new GameObject(meshName); int verticeNum = row * col; Vector3[] vertices = new Vector3[verticeNum];//顶点数组大小 int[] triangles = new int[verticeNum * 3 * 2];//三角集合数组,保存顶点索引 // Vector3[] normals = new Vector3[verticeNum];//顶点法线数组大小 Vector2[] uvs = new Vector2[verticeNum]; float rowF = (float)row; float colF = (float)col; Vector3 xStep = new Vector3((maxPoint.x - minPoint.x) / rowF, 0, 0); Vector3 zSetp = new Vector3(0, 0, (maxPoint.z - minPoint.z) / colF); int k = 0; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { float tempZ = texture2dGray.GetPixel((int)minImgPosition.x + i, (int)minImgPosition.y + j).grayscale; vertices[i + j * row] = minPoint + xStep * i + zSetp * j + new Vector3(0, tempZ * zScale,0); uvs[i + j * row] = new Vector2((float)i / rowF, (float)j / colF); if (j < col - 1 && i < row - 1) { triangles[k++] = j * row + i; triangles[k++] = j * row + i + row; triangles[k++] = j * row + i + 1; triangles[k++] = j * row + i + row; triangles[k++] = j * row + i + row + 1; triangles[k++] = j * row + i + 1; } } } Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = triangles; // mesh.normals = normals; mesh.uv = uvs; mesh.RecalculateBounds(); mesh.RecalculateNormals(); meshObject.AddComponent<MeshFilter>(); meshObject.AddComponent<MeshRenderer>(); meshObject.GetComponent<MeshFilter>().mesh = mesh; meshObject.GetComponent<MeshRenderer>().material = meshMaterial; return meshObject; } }
相机漫游控制脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MyCameraControl : MonoBehaviour { public Camera mainCam; //旋转变量; private float m_deltX = 0f; private float m_deltY = 0f; //缩放变量; private float m_distance = 10f; private float m_mSpeed = 5f; //移动变量; private Vector3 m_mouseMovePos = Vector3.zero; //平移速度 float Speed = 200f; void Start() { // transform.localPosition = new Vector3(0, m_distance, 0); } void Update() { if (Input.GetKey(KeyCode.W)) { transform.Translate(Vector3.forward * Time.deltaTime * Speed); } if (Input.GetKey(KeyCode.A)) { transform.Translate(Vector3.left * Time.deltaTime * Speed); } if (Input.GetKey(KeyCode.S)) { transform.Translate(Vector3.forward * Time.deltaTime * -Speed); } if (Input.GetKey(KeyCode.D)) { transform.Translate(Vector3.left * Time.deltaTime * -Speed); } //鼠标左键控制旋转 if (Input.GetMouseButton(0)) { m_deltX += Input.GetAxis("Mouse X") * m_mSpeed; m_deltY -= Input.GetAxis("Mouse Y") * m_mSpeed; m_deltX = ClampAngle(m_deltX, -360, 360);//旋转幅度 左右 m_deltY = ClampAngle(m_deltY, -70, 70);//旋转幅度 上下 transform.rotation = Quaternion.Euler(m_deltY, m_deltX, 0); } //鼠标滑轮缩放 if (Input.GetAxis("Mouse ScrollWheel") != 0) { //自由缩放方式; m_distance = Input.GetAxis("Mouse ScrollWheel") * 10f; transform.localPosition = transform.position + transform.forward * m_distance; } //相机位置跳到点击处; if (Input.GetMouseButtonDown(1)) //0-左键 1-右键 2-滑轮 { Ray ray = mainCam.ScreenPointToRay(Input.mousePosition);//从摄像机发出到点击坐标的射线 RaycastHit hitInfo; if (Physics.Raycast(ray, out hitInfo)) { m_mouseMovePos = hitInfo.point; transform.localPosition = m_mouseMovePos; } } } float ClampAngle(float angle, float minAngle, float maxAgnle) { if (angle <= -360) angle += 360; if (angle >= 360) angle -= 360; return Mathf.Clamp(angle, minAngle, maxAgnle); } }
本文链接
https://www.cnblogs.com/gucheng/p/10945429.html