Unity中获取地形的法线 您所在的位置:网站首页 中国室内设计史论文范文 Unity中获取地形的法线

Unity中获取地形的法线

2024-01-20 22:47| 来源: 网络整理| 查看: 265

之前,生成了地形图:(42条消息) 从灰度图到地形图_averagePerson的博客-CSDN博客

那末,地形的法线贴图怎么获取?

大概分为两个部分吧,先拿到法线数据,再画到纹理中去。

关于法线 计算

Unity - Scripting API: Mesh.RecalculateNormals (unity3d.com)

这个链接讲的是法线的计算,它是什么空间下的?无所谓了……

这里也不对地形搞什么几何变换,而且它是方向,模型空间世界空间是一个结果。

获取

Unity - Scripting API: Mesh.normals (unity3d.com)

直接一个等于号,然后这个法线是对顶点不是对三角形面片。

就这两点,没了。

存到纹理中 构造

Unity - Scripting API: Texture2D (unity3d.com)

这个变量,好像在unity shader里也经常出现嘞

要把法线数据存到Texture2D里,首先得构造一下对象啊,构造函数是什么?

Unity - Scripting API: Texture2D.Texture2D (unity3d.com)

RGBA32,构造RenderTexture的时候也有你。

怎么赋值?

赋值

Unity - Scripting API: Texture2D.SetPixels (unity3d.com)

直接传数组

数组要展平【mesh.normals其实就是一维的,那就可以直接用了】

最后需要Apply

从左到右从下到上【地形顶点正好也是这个顺序的】

官方示例代码:

using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { void Start() { Renderer rend = GetComponent(); // duplicate the original texture and assign to the material Texture2D texture = Instantiate(rend.material.mainTexture) as Texture2D; rend.material.mainTexture = texture; // colors used to tint the first 3 mip levels Color[] colors = new Color[3]; colors[0] = Color.red; colors[1] = Color.green; colors[2] = Color.blue; int mipCount = Mathf.Min(3, texture.mipmapCount); // tint each mip level for (int mip = 0; mip < mipCount; ++mip) { Color[] cols = texture.GetPixels(mip); for (int i = 0; i < cols.Length; ++i) { cols[i] = Color.Lerp(cols[i], colors[mip], 0.33f); } texture.SetPixels(cols, mip); } // actually apply all SetPixels, don't recalculate mip levels texture.Apply(false); } } 试一试

根据文档,调api就行了。

代码

计算法线的

using System.Collections; using System.Collections.Generic; using UnityEngine; public class Terrian : MonoBehaviour { public int N = 10; public Texture2D texture2dHeightMap; [Range(1,100)] public float heightRatio = 30.0f;//一个系数,控制地形总体的高度的 public Texture2D normalTex; MeshRenderer meshRenderer; MeshFilter meshFilter; // 用来存放顶点数据 List verts; List indices; Vector3[] normals; private void Awake() { } private void Start() { verts = new List(); indices = new List(); meshRenderer = GetComponent(); meshFilter = GetComponent(); //normalTex = new Texture2D(texture2dHeightMap.width, texture2dHeightMap.height, TextureFormat.RGB24,-1,false); normalTex = new Texture2D(N,N, TextureFormat.RGB24, -1, false);//2.5D的地形,顶点的法线,法线贴图规模不是灰度图规模 } private void Update() { Generate(); normals = new Vector3[N * N]; normals = meshFilter.mesh.normals; for(int i = 0; i < 10; ++i) { print(normals[i]); } Color[] colors = new Color[N * N]; for(int i = 0; i < N * N; ++i) { colors[i] = new Color(normals[i].x, normals[i].y, normals[i].z); } normalTex.SetPixels(colors); normalTex.Apply(false); } public void Generate() { ClearMeshData(); // 把数据填写好 AddMeshData(); // 把数据传递给Mesh,生成真正的网格 Mesh mesh = new Mesh(); mesh.vertices = verts.ToArray(); mesh.triangles = indices.ToArray(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); meshFilter.mesh = mesh; } void ClearMeshData() { verts.Clear(); indices.Clear(); } void AddMeshData() { //01填充顶点数据 for (int z = 0; z < N; ++z)//按先x后z的顶点排列顺序,所以先循环的是z { for(int x = 0; x < N; ++x) { int u = Mathf.FloorToInt(1.0f * x / N * texture2dHeightMap.width); int v = Mathf.FloorToInt(1.0f * z / N * texture2dHeightMap.height); float grayValue = texture2dHeightMap.GetPixel(u,v).grayscale; float height = grayValue*heightRatio; Vector3 temp = new Vector3(x, height, z); verts.Add(temp); } } //02填充索引数据 for(int z = 0; z < N - 1; ++z) { for(int x = 0; x < N - 1; ++x) { int index_lb = z * N + x;//index of the left bottom vertex. lb = left bottom int index_lt = (z + 1) * N + x; int index_rt = (z + 1) * N + x + 1; int index_rb = z * N + x + 1; indices.Add(index_lb);indices.Add(index_lt);indices.Add(index_rt); indices.Add(index_rt);indices.Add(index_rb);indices.Add(index_lb); } } } }

显示法线贴图的。这个是在摄像机上的——屏幕后处理嘛!

using System.Collections; using System.Collections.Generic; using UnityEngine; public class ShowTexture2D : MonoBehaviour { public Terrian terrian; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } private void OnRenderImage(RenderTexture source, RenderTexture destination) { Graphics.Blit(terrian.normalTex, destination); } } 结果

看着……走势差不多吧。而且,绿色的,表示向上,符合的。

对不对?在这种情况下,没法看出来。只能接着往下做,然后拔出萝卜带出泥巴。

纯平面是纯绿色

高度系数越大,颜色越深



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有