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相关推荐

  1. 编写和调试Shader程序(1)

    编写和调试Shader程序 (1)DirectX EffectEdit JohnsonFeng 常用的Shader编写程序有ATI Render Monkey和NVIDIA FX Composer,另 ...

  2. Ogre天龙八部地形mesh部分的C++源码

    Ogre的地形部分历来受人诟病,基本没什么用.听说将来的的Ogre1.7版本会重写地形.期待中... 在没有合适的地形可用的情况下,自己手动生成mesh来当地形是一个不错的选择. 由于很多人问我天龙八 ...

  3. 【Unity】Unity插件:地形编辑器MTE(Mesh Terrain Editor)

    文章目录 地形编辑器MTE 下载方式 文档及教程 主要功能 地表类型 创建工具 示例文件 创建地图 绘制地图 快捷键 提升.降低高度 绘制高度 平滑高度 绘制纹理 细节问题处理 地形编辑器MTE MT ...

  4. unity如何往下挖地形_Unity3D分割地形Terrain

    在制作地形的时候通常是直接刷出整个地形,但是在实际使用中也许地形过大,我们不能直接把整个地形完全加载,这样对内存的消耗很高,所以有时需要一小块一小块的加载地形.这时就需要把制作好的地形分割成几块后, ...

  5. 为新手准备的 Codea 着色器(Shader)教程

    为新手准备的 Codea 着色器(Shader) 教程 原文标题:<Shaders for dummies>  作者:Ignatz  译者:FreeBlues  译文链接:http://m ...

  6. [专栏精选]2018.3地形更新详解

    本文节选自洪流学堂公众号技术专栏<大话Unity2018>,未经允许不可转载. 洪流学堂公众号回复专栏,查看更多专栏文章. 大智:"Unity2018.3已经发布有一段时间了,这 ...

  7. 在Unity中使用四叉树算法绘制地形

    四叉树算法在游戏中获得了广泛的应用,前几年3D引擎实现的地形绘制大部分都是用四叉树生成的,因为移动端在硬件方面的限制,我们的地形使用的是美术自己制作的地形,对于程序来说省去了不少工作量,但是作为程序开 ...

  8. unity Shader 入门精要 EX

    unity Shader 入门精要: 1.shader概念 2.shader分类(顶点Shader.像素Shader) 3.Shader编程语言 4.Unity Shader 4.1概述 4.2分类( ...

  9. 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 第一个Shader的书写

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...

最新文章

  1. Serializer反序列化使用之验证和保存
  2. 随机采样池化--S3Pool: Pooling with Stochastic Spatial Sampling
  3. AXI DMA DRIVER 阶段性 kernel driver 构建并测试(三 )
  4. 【MATLAB】数据类型 ( 元胞数组 | 单位阵 | 幻方 | 结构体 | 元胞数组值获取 )
  5. 网络IO超时的几种实现
  6. java代码实现python2中aes加密经历
  7. 以新ICT构建全联接的电力物联网,迈入能源智能时代
  8. CVPR 2020|打脸SOTA!不能忍,谷歌发起图像匹配挑战赛
  9. 图片资源添加出现问题: No resource found that matches the given name
  10. 如何解决Greenplum pg_dump备份时的分布策略缺失等问题
  11. java 二进制置位,重置
  12. 关于MYSQL ERROR1045 报错的解决办法
  13. 正则表达式(待补充)
  14. 在更新查询中可以使用计算机功能,ACCESS试题1.doc
  15. 怪物猎人世界pc服务器在哪个文件夹,关于PC怪物猎人世界拆包文件的一些问题...
  16. Linux内核下载缓慢解决方法
  17. 海康摄像头拍照(java版,拿走即用)
  18. WebGL压缩纹理实践
  19. uniapp 空格怎么打?
  20. 经济学十大原理(七)政府有时候可以改善市场结果

热门文章

  1. 计算机设计压力容器过程,压力容器及过程设备设计
  2. 自考计算机软件基础真题,计算机软件基础历年自考真题及答案
  3. 红杉资本中国基金:创业者背后的创业者
  4. 基于BiGRU-Attention网络的 新型冠状病毒肺炎疫情预测学习记录
  5. php 逗号千分位,php如何去掉千分位
  6. 10.如何查看80端口是否被占用
  7. 树莓派3B控制28步进电机
  8. android麦克风的权限是什么,和平精英麦克风权限怎么开?麦克风权限开启方法[视频][多图]...
  9. 企业内部薪酬差距测算2005-2021年(数据+代码)管理层平均薪酬VS员工平均薪酬
  10. 计算机视觉-计算机视觉入坑(一):计算机视觉入坑前的信息采集和了解