Unity 3D 使用高度图创建地形|| Unity 3D 使用笔刷绘制地形
Posted 爱编程的鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 3D 使用高度图创建地形|| Unity 3D 使用笔刷绘制地形相关的知识,希望对你有一定的参考价值。
Unity 3D 使用高度图创建地形
在 Unity 3D 中编辑地形有两种方法:
- 通过地形编辑器编辑地形。
- 通过导入一幅预先渲染好的灰度图来快速地为地形建模。
地形上每个点的高度被表示为一个矩阵中的一列值。这个矩阵可以用一个被称为高度图(heightmap
)的灰度图来表示。
灰度图是一种使用二维图形来表示三维的高度变化的图片。近黑色的、较暗的颜色表示较低的点,接近白色的、较亮的颜色表示较高的点。
通常可以用 Photoshop 或其他三维软件导出灰度图,灰度图的格式为 RAW 格式
,Unity 3D 可以支持 16 位
的灰度图。
Unity 提供了为地形导入、导出高度图的选项。
- 单击
Settings tool
按钮,找到标记为Import RAW
和Export RAW
的按钮。
- 这两个按钮允许从标准
RAW 格式
中读出或者写入高度图,并且兼容大部分图片和地表编辑器。
案例构思
在 Unity 3D 中支持 RAW 格式
的高度图导入。
RAW 格式
相当于各种图片格式的“源文件”,它的转换是不可逆的。
注:
- 在 Photoshop 软件中可以使用滤镜功能制作高度图。
本案例根据在 Photoshop 中制作好的高度图导入 Unity 3D 系统,自动生成地形。
案例设计
本案例通过 Photoshop 中制作好的高度图在 Unity 3D 中创建一个简单的地形,在地形参数列表里设置导入高度图的信息,导入的高度图地形效果。
案例实施
- 创建地形。执行
GameObject
→3D Object
→Terrain
菜单命令。
- 在 Inspector 面板中单击
Import Raw 按钮
添加地形,如下图所示。
- 设置地形参数。
- 进行测试,即可观察到基于高度图创建出来的地形效果。
参数列表
参数 | 含义 | 描述 |
---|---|---|
Depth | 深度 | 根据文件格式设置,可以是8位或16位。 |
Width | 宽度 | 设置高度图的宽。 |
Height | 高度 | 设置高度图的高。 |
Byte Order | 字节顺序 | 根据文件格式设置,可以是Mac 或Windows 。 |
Terrain Size | 地形大小 | 定义地形的大小。 |
Unity 3D 使用笔刷绘制地形
在 Unity 3D 中,除了使用高度图来创建地形外,还可以使用笔刷绘制地形。
刚创建的初始地表只有一块巨大的平面。Unity 3D 提供了一些归纳于地形菜单栏的工具,可供游戏开发者在该平面上创建很多地表元素。
地形菜单栏一共有7个按钮,含义分别为
- 编辑地形高度。
- 编辑地形特定高度。
- 平滑过渡地形。
- 地形贴图。
- 添加树模型。
- 添加草与网格模型。
- 其他设置。
如下图所示,每个按钮都可以激活相应的子菜单对地形进行操作和编辑。
地形高度绘制
在地形编辑器中,前 3 个工具用来绘制地形在高度上的变化。
左边第一个按钮激活 Raise/Lower Height 工具
,如下图所示。
当使用这个工具时,高度将随着鼠标在地形上扫过而升高。如果在一处固定鼠标,高度将逐渐增加。这类似于在图像编辑器中的喷雾器工具。
如果鼠标操作时按下 Shift 键
,高度将会降低。不同的刷子可以用来创建不同的效果。
例如:
- 创建丘陵地形时,可以通过
soft-edged
刷子进行高度抬升。
- 而对于陡峭的山峰和山谷,可以使用
hard-edged
刷子进行高度削减。
Paint Height
,类似于Raise/Lower 工具
,但多了一个属性Height
,用来设置目标高度,如下图所示(左边第二个)。
- 当在地形对象上绘制时,此高度的上方区域会下降,下方的区域会上升。
- 游戏开发者可以使用高度属性来手动设置高度,也可以使用在地形上
Shift + 单击
对鼠标位置的高度进行取样。
- 在高度属性旁边是一个
Flatten 按钮
,它简单地拉平整个地形到选定的高度,这对设置一个凸起的地平线很有用。
Paint Height
绘制的地表包含高出水平线和低于水平线的部分,(例如在场景中创建高原以及添加人工元素——道路、平台和台阶等)都很方便。
Smooth Height
并不会明显地抬升或降低地形高度,但会平均化附近的区域。这缓和了地表,降低了陡峭变化,类似于图片处理中的模糊工具(blur tool)。
Smooth Height
可以用于缓和地表上尖锐、粗糙的岩石。参数列表如下:
参数 | 含义 | 描述 |
---|---|---|
Brushes | 笔刷 | 设置笔刷的样式。 |
Setting | 设置 | |
Brushes Size | 笔刷尺寸 | 设置笔刷的大小。 |
Opacity | 不透明度 | 设置笔刷绘制时的高度。 |
Height | 高度 | 设置绘制高度的数值。 |
地形纹理绘制
在地形的表面上可以添加纹理图片以创造色彩和良好的细节。
由于地形是如此巨大的对象,在实践中标准的做法是使用一个无空隙地(即连续地)重复的纹理,在表面上用它成片地覆盖,可以绘制不同的纹理区域以模拟不同的地面,如草地、沙漠和雪地。
绘制出的纹理可以在不同的透明度下使用,这样就可以在不同地形纹理间形成渐变,效果更自然。
地形编辑器左边第四个按钮是纹理绘制工具,单击该按钮并且在菜单中执行 Add Texture 命令
,可以看到一个窗口,在其中可以设置一个纹理和它的属性。
添加的第一个纹理将作为背景使用而覆盖地形。如果想添加更多的纹理,可以使用刷子工具,通过设置刷子尺寸、透明度及目标强度(Target Strength)选项,实现不同纹理的贴图效果,如下图所示。
参数列表:
参数 | 含义 | 描述 |
---|---|---|
Brushes | 笔刷 | 设置笔刷的样式。 |
Setting | 设置 | |
Opacity | 不透明度 | 设置笔刷绘制时的高度。 |
Textures | 纹理 | 设置绘制地形纹理图片样式。 |
Brush Size | 笔刷尺寸 | 设置绘制纹理的笔刷的大小。 |
Target Strength | 目标强度 | 设置所绘制的贴图纹理产生的影响。 |
树木绘制
Unity 3D 地形可以布置树木。可以像绘制高度图和使用纹理那样将树木绘制到地形上,但树木是固定的、从表面生长出的三维对象。
Unity 3D 使用了优化(例如,对远距离树木应用广告牌效果)来保证好的渲染效果,所以一个地形可以拥有上千棵树组成的茂密森林,同时保持可接受的帧率。
单击 Edit Trees 按钮
并且选择 Add Tree 命令
,将弹出一个窗口,从中选择一种树木资源。
- 当一棵树被选中时,可以在地表上用绘制纹理或高度图的方式来绘制树木,按住
Shift 键
可从区域中移除树木,按住Ctrl 键
则只绘制或移除当前选中的树木。树木绘制面板如下图所示。
- 参数列表:
参数 | 含义 | 描述 |
---|---|---|
Tree Density | 树木密度 | 设置树的间距。 |
Setting | 设置 | |
Tree Height | 树木高度 | 设置树的高度,勾选Random选项 ,可以出现树木高度 在指定范围内随机变化的效果。 |
Lock Width to Height | 锁定树木的宽高比 | 锁定树木宽高比。 |
Brush Size | 笔刷尺寸 | 设置种植树时笔刷的大小。 |
Tree Width | 树木宽度 | 设置树的宽度,勾选Random选项 ,可以出现树木宽度 在指定范围内随机变化的效果。 |
Random Tree Rotation | 树木随机旋转 | 设置树木随机旋转一定的角度。 |
草和其他细节
一个地形表面可以有草丛和其他小物体,比如覆盖表面的石头。草地使用二维图像进行渲染来表现草丛,而其他细节从标准网格中生成。
在地形编辑器中单击 Edit Details 按钮
,在出现的菜单中将看到 Add Grass Texture
和 Add Detail Mesh 选项
,选择 Add Grass Texture
,在出现的窗口中选择合适的草资源,如下图所示。
参数列表:
参数 | 含义 | 描述 |
---|---|---|
Detail Texture | 细节纹理 | 指定图片作为草的纹理。 |
Min Width | 最小宽度 | 设置草的最小宽度值。 |
Max Width | 最大宽度 | 设置草的最大宽度值。 |
Min Height | 最小高度 | 设置草的最小高度值。 |
Max Height | 最大高度 | 设置草的最大高度值。 |
Noise Spread | 噪波范围 | 控制草产生簇的大小。 |
Healthy Color | 健康颜色 | 设置草的健康颜色,此颜色在噪波中心处较为明显。 |
Dry Color | 干燥颜色 | 设置草的干燥颜色,此颜色在噪波中心处较为明显。 |
Billboard | 广告牌 | 草将随着摄像机同步转动,永远面向摄像机。 |
地形设置
单击地形编辑器最右边的按钮可以打开地形设置面板,如下图所示。该面板用于设置地形参数,如下表所示。
基本地形参数:
参数 | 含义 | 描述 |
---|---|---|
Draw | 绘制 | 绘制地形。 |
Pixel Error | 像素容差 | 显示地形网格时允许的像素容差。 |
Base Map Dist | 基本地图距离 | 设置地形高度的分辨率。 |
Cast Shadows | 投影 | 设置地形是否有投影。 |
Material | 材质 | 为地形添加材质。 |
树和细节参数:
参数 | 含义 | 描述 |
---|---|---|
Draw | 绘制 | 设置是否渲染除地形以外的对象。 |
Detail Distance | 细节距离 | 设置摄像机停止对细节渲染的距离。 |
Detail Density | 细节密度 | 设置细节密度。 |
Tree Distance | 树木距离 | 设置摄像机停止对树进行渲染的距离。 |
Billboard Start | 开始广告牌 | 设置摄像机将树渲染为广告牌的距离。 |
Fade Length | 渐变距离 | 控制所有树的总量上限。 |
Max Mesh Trees | 网格渲染树木最大数量 | 设置使用网格形式进行渲染的树木最大数量。 |
风参数:
参数 | 含义 | 描述 |
---|---|---|
Speed | 速度 | 风吹过草地的速度。 |
Size | 大小 | 同一时间受到风影响的草的数量。 |
Bending | 弯曲 | 设置草跟随风弯曲的强度。 |
Grass Tint | 草的色调 | 设置地形上的所有草和细节网格的总体渲染颜色。 |
风域
地形中的草丛在运行测试时可以随风摆动,如果要实现树木的枝叶如同现实中一样随风摇摆的效果,就需要加入风域。
执行 GameObject
→ 3D Object
→ Wind Zone
菜单命令,创建一个风域,风域的参数如下图所示。
参数列表:
参数 | 含义 | 描述 |
---|---|---|
Mode | 风域模式 | 设置风域模式:Directional模式下整个场景中的树木都受影 响,Spherical模式下只影响球体包裹范围内的树木。 |
Main | 主风 | 设置主要风力,产生风压柔和变化。 |
Turbulence | 湍流 | 设置湍流风,产生一个瞬息万变的风压。 |
Pulse Magnitude | 波动幅度 | 定义风力随时间的变化。 |
Pulse Frequency | 波动频率 | 定义风向改变的频率。 |
风域不仅能实现风吹树木的效果,还能模拟爆炸时树木受到波及的效果。
需要注意的是,风域只能作用于树木,对其他游戏对象没有效果。场景中不同模式下的风域参数设置如下表所示。
OpenGL高度图地形渲染不绘制
【中文标题】OpenGL高度图地形渲染不绘制【英文标题】:OpenGL heightmap terrain render does not draw 【发布时间】:2015-06-12 07:24:59 【问题描述】:我有一个从 dted 文件创建的位图。我想使用该位图并创建 3d 地形渲染。我正在尝试使用顶点向量来做到这一点,但我根本无法达到我的目标。这是我的paintGL代码:
void render::paintGL()
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0,0,-100);
for(int z=0;z<dted.width()-1;z++)
glBegin(GL_TRIANGLE_STRIP);
for(int x = 0; x<dted.height()-1; x++)
glColor3f(matrix[x][z], matrix[x][z], matrix[x][z]);
glVertex3f(x, matrix[x][z], -z);
//vertex0 ends here
glColor3f(matrix[x+1][z], matrix[x+1][z], matrix[x+1][z]);
glVertex3f(x+1, matrix[x+1][z], -z);
//vertex1 ends here
glColor3f(matrix[x][z+1], matrix[x][z+1], matrix[x][z+1]);
glVertex3f(x, matrix[x][z+1], -z-1);
//vertex2 ends here
glColor3f(matrix[x+1][z+1], matrix[x+1][z+1], matrix[x+1][z+1]);
glVertex3f(x+1, matrix[x+1][z+1], -z-1);
//vertex3 ends here
glEnd();
由于互联网问题,我不得不编写代码而不是复制粘贴。所以可能有些事情我忘记了,但我已经尽力了。让我解释一下上面的变量和其他内容:
dted 是我创建的 dted 图像,我设置了图像宽度和高度值的边界。矩阵是一个二维矩阵,它保存了我从预先创建的 dted 图像像素中获得的高程值。
在上面的所有代码之后,我无法渲染地形。我不知道它是否渲染了地形,但它只是没有显示或者根本没有渲染。如果您解释我的错误在哪里并提出解决方案,那就太好了。
如果我犯了语法错误,我很抱歉,我希望我能很好地解释我的问题。如果我提供的代码不够用,请随意提及,其他部分我也可以写下来。
祝你有美好的一天。
编辑:好的,我在这里得到了一个新消息。在克服了鼠标问题的一些控制之后,我设法画了一个平原。但是,当我尝试获得幅度时,它什么也没显示。那是因为我猜幅度太大了,但是当我将它除以一个像 15 这样的常数时,同样的平原再次出现。这是因为我使用了 GL_TRIANGLE_STRIP
吗?
【问题讨论】:
首先,确保您能够绘图:从硬编码位置的一个三角形开始。第二:matrix
值在 0 和 1 之间?如果您将它们输入到glColor3f
,它们应该是。你能检查一下吗?
我检查了它,发现它不是。但是,我将它划分为 255(像素值从 0 到 255),它仍然没有显示任何内容。顺便说一句,我已经画了一个立方体,它显示得很好。
现在你必须检查你的相机:是不是太远了?平面是否垂直于它(这样就变成了一条细线)?尝试用乘数夸大 Y 值
我为此设置了一个鼠标事件,右键单击时缩小,左键单击时放大,这会改变 translatef 函数的 z 值。我确实将 Y 的幅度乘以 15 (matrix[x][z]*15),不出所料,我看不到它。你认为问题出在相机上吗?
是的,它可以指向其他地方
【参考方案1】:
您的渲染代码看起来很奇怪:您使用退化的三角形构建您的三条带,并且可能会访问不存在的数据。我猜到了你的其他方法,并试图修复你的方法。试试这个:
void render::paintGL()
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0,0,-100);
for(int z = 0; z < dted.width() - 2; z++)
glBegin(GL_TRIANGLE_STRIP);
for(int x = 0; x < dted.height() - 1; x++)
glColor3f(matrix[x][z], matrix[x][z], matrix[x][z]);
glVertex3f(x, matrix[x][z], -z);
//vertex0 ends here
glColor3f(matrix[x][z + 1], matrix[x][z + 1], matrix[x][z + 1]);
glVertex3f(x, matrix[x][z + 1], -z - 1);
//vertex1 ends here
glEnd();
除此之外,三角条也可以。如果您仍然看不到任何内容,请按照 Sga 的建议使用 GL_POINTS。然后修复你的相机/其他渲染代码,直到你看到它们。
【讨论】:
我已经设法渲染了一些东西,但它似乎太大而无法看到,无论我缩小多远,它似乎都不是一个可以理解的渲染对象。对于有角度的视图,我添加了以下代码:'glRotatef(45,0,1,0)' 三角条有必要吗?我可以使用多边形或四边形吗?这更适合我的目的,因为我想逐块渲染它,就像逐像素渲染 2d 图像一样。 我发布的渲染代码相当简约,应该可以工作。如果几何是“极端的”,请检查您通过矩阵类获得的值。作为测试,您可以(再次)用零或任何其他常量替换所有“matrix[][]”。如果它仍然不起作用,请检查您用作模型视图和投影的矩阵。我觉得很奇怪,在调用 glMatrixMode 之前调用 glLoadIdentity()。 ... 顺便说一下,TRIANGLE_STRIP 是您想要使用的。 QUAD 或 POLYGON 在现代图形中不受欢迎,最好避免这些。为了您的理解,与像素等效的不是四边形(或三角形),而是顶点。三角形指定连接,例如插值的结构。 感谢大家的帮助。我终于能够做到了。没有你们的帮助,我做不到。非常感谢...【参考方案2】:对于正在寻找解决方案的其他人:确保您的 glFrustum 的 zNear 参数足够远,可以看到东西。我的要关闭,当我增加它时,问题就解决了。
【讨论】:
以上是关于Unity 3D 使用高度图创建地形|| Unity 3D 使用笔刷绘制地形的主要内容,如果未能解决你的问题,请参考以下文章