分割为mesh之后的地形shader编写——2
https://blog.csdn.net/wodownload2/article/details/106071916
继续我们的地形shader之旅。
我们的阿泰被染色成了下面的丫子:
是的,我们多了一个层,这个层的贴图这个样子:
有两个图,就需要进行混合。
这里即涉及到三个图的处理:
1、贴图1(金泰熙)
2、贴图2(上面的那个泥土地)
3、混合图(权重图)
贴图1和贴图2好处理,就是美术给的素材。
混合图是啥?
当我们用笔刷,刷好地形之后,再地形数据的下面,就会有一个或者多个混合图出现。上面出现了一张,为啥时一张?
因为我们有两个图进行混合,一个图可以支持四个图(因为有rgba四个通道)。
加入有5个图,那么则会有2个混合图出现。这里不展开讲述。
ok,有了混合图之后,这个混合图是一个整体,其分辨率是多少呢?
这个控制图,就是混合图的分辨率。
ok,我们要将地形分成的是5x5块,上一篇文章已经讲过了,请参考上一篇。
那么混合图也需要分成5x5这么多块,ok,分割代码如下:
private static void CreateSplitAlphamap(Texture2D alphamap, int blockX, int blockZ){Texture2D tex = new Texture2D(m_blockAlphamapWidth, m_blockAlphamapHeight, TextureFormat.ARGB32, false);for (int i = 0; i < m_blockAlphamapHeight; ++i){for (int j = 0; j < m_blockAlphamapWidth; ++j){int x = j + blockX * m_blockAlphamapWidth;int y = i + blockZ * m_blockAlphamapHeight;Color color = alphamap.GetPixel(x, y);tex.SetPixel(j, i, color);}}//https://blog.csdn.net/hakukou/article/details/104667576/string texName = m_sceneData.sceneName + "_alphamap_" + blockX + "_" + blockZ;string assetPath = PathManager.m_splitTexesDir + "/" + texName + ".png";if (File.Exists(assetPath)) File.Delete(assetPath);byte[] data = tex.EncodeToPNG();File.WriteAllBytes(assetPath, data);AssetDatabase.Refresh();}
ok,分割之后的丫子:
最后一步,是如何使用这个混合图,我们有25块分割之后的mesh,那么就需要有25个材质,每个材质有三个属性,如下:
将其每个材质,拖拽到左边的mesh上去,对应起来,不要乱,同时混合图要一个一个拖到每个材质球上去:
混合图的uv怎么弄?
我这里只给出思想,具体实现,就要看下面的代码了:
1、我们将地形分成了25块
2、每块加入是分成64x64个小格子
3、每块有65x65个顶点,那么每个顶点的uv,应该等于所在的坐标(x,z)/64,x和z从0~64
4、用这个uv去采样每块的混合图就可以了
private static void SplitTerrainMesh(int x, int z, int step){BlockData blockData = new BlockData();int id = x + z * m_sceneData.splitX;blockData.id = id;blockData.x = x;blockData.z = z;//采样,创建mesh,保存meshMesh mesh = new Mesh();int verticesCount = (m_blockHeightmapWidth / step + 1) * (m_blockHeightmapHeight / step + 1);Vector3[] vertices = new Vector3[verticesCount];int[] triangleIndices = new int[m_blockHeightmapWidth * m_blockHeightmapHeight * 2 * 3];Vector2[] uvs = new Vector2[verticesCount];int vertexIndex = 0;int triangleIndex = 0;float[,] heights = m_terrain.terrainData.GetHeights(0, 0, m_heightmapWidth, m_heightmapHeight);for (int i = 0; i <= m_blockHeightmapHeight; i += step){for (int j = 0; j <= m_blockHeightmapWidth; j += step){int indexX = x * m_blockHeightmapWidth + j;int indexZ = z * m_blockHeightmapHeight + i;float height = heights[indexZ, indexX];float posX = indexX / m_scaleX;float posZ = indexZ / m_scaleZ;float posY = height * m_terrainY; //GetHeights存储的是0~1的值,需要乘以高度的最大值,才能得到实际的地形高度,并且第一维存储的是z值,第二维存储的是x值//参考:https://docs.unity3d.com/ScriptReference/TerrainData.GetHeights.html//float h = m_terrain.terrainData.GetHeight((int)posX, (int)posZ);//https://docs.unity3d.com/ScriptReference/TerrainData.GetHeight.html GetHeight得到的是地形的实际高度Vector3 scale = m_terrain.terrainData.heightmapScale;vertices[vertexIndex] = new Vector3(posX, posY, posZ);float u = j * 1.0f / m_blockHeightmapWidth;float v = i * 1.0f / m_blockHeightmapHeight;uvs[vertexIndex] = new Vector2(u, v);if (j < m_blockHeightmapWidth && i < m_blockHeightmapHeight){triangleIndices[triangleIndex++] = vertexIndex;triangleIndices[triangleIndex++] = vertexIndex + m_blockHeightmapWidth + 1;triangleIndices[triangleIndex++] = vertexIndex + m_blockHeightmapWidth + 2;triangleIndices[triangleIndex++] = vertexIndex;triangleIndices[triangleIndex++] = vertexIndex + m_blockHeightmapWidth + 2;triangleIndices[triangleIndex++] = vertexIndex + 1;}vertexIndex++;}}mesh.vertices = vertices;mesh.triangles = triangleIndices;mesh.uv = uvs;string meshName = SceneManager.GetActiveScene().name + "_mesh_" + x + "_" + z;string meshPath = PathManager.m_splitMeshesDir + "/" + meshName + ".asset";if (File.Exists(meshPath)){File.Delete(meshName);}AssetDatabase.CreateAsset(mesh, meshPath);AssetDatabase.Refresh();}
最后,我们给出混合了两个贴图的地形shader:
Shader "Unlit/TerrainShader"
{Properties{_BlendTex("_BlendTex", 2D) = "white"{}_SplatTex0("_SplatTex0", 2D) = "white" {}_SplatTex1("_SplatTex1", 2D) = "white" {}}SubShader{Tags { "RenderType" = "Opaque" }Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float4 vertex : SV_POSITION;float4 worldPosition:TEXCOORD2;float2 uv : TEXCOORD0;};sampler2D _BlendTex;sampler2D _SplatTex0;sampler2D _SplatTex1;v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.worldPosition = mul(unity_ObjectToWorld, v.vertex);o.uv = v.uv;return o;}fixed4 frag(v2f i) : SV_Target{float4 blendColor = tex2D(_BlendTex, i.uv);float2 uv0 = i.worldPosition.xz * (1.0f / 320); //这个是上节的知识你还记得吗?float4 color0 = tex2D(_SplatTex0, uv0);float4 color1 = tex2D(_SplatTex1, uv0);float4 color = blendColor.r * color0 + blendColor.g * color1;return color;}ENDCG}}
}
最后的结果:
左图是我们的分割之后的mesh效果,右图是unity原始地形的效果。
分割为mesh之后的地形shader编写——2相关推荐
- 编写和调试Shader程序(1)
编写和调试Shader程序 (1)DirectX EffectEdit JohnsonFeng 常用的Shader编写程序有ATI Render Monkey和NVIDIA FX Composer,另 ...
- Ogre天龙八部地形mesh部分的C++源码
Ogre的地形部分历来受人诟病,基本没什么用.听说将来的的Ogre1.7版本会重写地形.期待中... 在没有合适的地形可用的情况下,自己手动生成mesh来当地形是一个不错的选择. 由于很多人问我天龙八 ...
- 【Unity】Unity插件:地形编辑器MTE(Mesh Terrain Editor)
文章目录 地形编辑器MTE 下载方式 文档及教程 主要功能 地表类型 创建工具 示例文件 创建地图 绘制地图 快捷键 提升.降低高度 绘制高度 平滑高度 绘制纹理 细节问题处理 地形编辑器MTE MT ...
- unity如何往下挖地形_Unity3D分割地形Terrain
在制作地形的时候通常是直接刷出整个地形,但是在实际使用中也许地形过大,我们不能直接把整个地形完全加载,这样对内存的消耗很高,所以有时需要一小块一小块的加载地形.这时就需要把制作好的地形分割成几块后, ...
- 为新手准备的 Codea 着色器(Shader)教程
为新手准备的 Codea 着色器(Shader) 教程 原文标题:<Shaders for dummies> 作者:Ignatz 译者:FreeBlues 译文链接:http://m ...
- [专栏精选]2018.3地形更新详解
本文节选自洪流学堂公众号技术专栏<大话Unity2018>,未经允许不可转载. 洪流学堂公众号回复专栏,查看更多专栏文章. 大智:"Unity2018.3已经发布有一段时间了,这 ...
- 在Unity中使用四叉树算法绘制地形
四叉树算法在游戏中获得了广泛的应用,前几年3D引擎实现的地形绘制大部分都是用四叉树生成的,因为移动端在硬件方面的限制,我们的地形使用的是美术自己制作的地形,对于程序来说省去了不少工作量,但是作为程序开 ...
- unity Shader 入门精要 EX
unity Shader 入门精要: 1.shader概念 2.shader分类(顶点Shader.像素Shader) 3.Shader编程语言 4.Unity Shader 4.1概述 4.2分类( ...
- 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 第一个Shader的书写
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...
最新文章
- Serializer反序列化使用之验证和保存
- 随机采样池化--S3Pool: Pooling with Stochastic Spatial Sampling
- AXI DMA DRIVER 阶段性 kernel driver 构建并测试(三 )
- 【MATLAB】数据类型 ( 元胞数组 | 单位阵 | 幻方 | 结构体 | 元胞数组值获取 )
- 网络IO超时的几种实现
- java代码实现python2中aes加密经历
- 以新ICT构建全联接的电力物联网,迈入能源智能时代
- CVPR 2020|打脸SOTA!不能忍,谷歌发起图像匹配挑战赛
- 图片资源添加出现问题: No resource found that matches the given name
- 如何解决Greenplum pg_dump备份时的分布策略缺失等问题
- java 二进制置位,重置
- 关于MYSQL ERROR1045 报错的解决办法
- 正则表达式(待补充)
- 在更新查询中可以使用计算机功能,ACCESS试题1.doc
- 怪物猎人世界pc服务器在哪个文件夹,关于PC怪物猎人世界拆包文件的一些问题...
- Linux内核下载缓慢解决方法
- 海康摄像头拍照(java版,拿走即用)
- WebGL压缩纹理实践
- uniapp 空格怎么打?
- 经济学十大原理(七)政府有时候可以改善市场结果
热门文章
- 计算机设计压力容器过程,压力容器及过程设备设计
- 自考计算机软件基础真题,计算机软件基础历年自考真题及答案
- 红杉资本中国基金:创业者背后的创业者
- 基于BiGRU-Attention网络的 新型冠状病毒肺炎疫情预测学习记录
- php 逗号千分位,php如何去掉千分位
- 10.如何查看80端口是否被占用
- 树莓派3B控制28步进电机
- android麦克风的权限是什么,和平精英麦克风权限怎么开?麦克风权限开启方法[视频][多图]...
- 企业内部薪酬差距测算2005-2021年(数据+代码)管理层平均薪酬VS员工平均薪酬
- 计算机视觉-计算机视觉入坑(一):计算机视觉入坑前的信息采集和了解