1、立方体纹理
立方体纹理(CubeMap)是一种特殊的纹理类型,立方体纹理包含6个独立的二维纹理,分别对应一个立方体的六个面
分别为:
- 正X面(右):+X;负X面(左):-X
- 正Y面(上):+Y;负Y面(下):-Y
- 正Z面(前):+Z;负Z面(后):-Z
注意:这个轴向就是Unity中的世界坐标轴向
2、立方体纹理用途
立方体纹理(CubeMap)在图形编程中常见的用途有:
(1)环境映射:
用于模拟反射环境的效果,用立方体纹理存储周围环境的图像,当应用到反射表面时,可以让物体看起来像是在反射其周围的环境。
(2)天空盒
用于渲染天空盒,将立方体纹理的六个面映射到一个立方体内表面,从而模拟天空、云朵、远处的山脉等环境
(3)全景图
用于展示全景图像、视频,通过立方体纹理来存储全景照片、视频的六个部分等等
3、如何采样
对立方体纹理进行采样,我们需要提供一个三维的纹理坐标,该坐标表示了我们在世界空间下的一个三维方向。这个方向向量从立方体的中心出发,当它向外延伸时就会和6个纹理之一相交,采样结果就是由该交点计算而来!
4、优缺点
优点:
- 多用途:可以有效的模拟环境映射和全景效果,如反射、折射、天空盒、环境光照等
- 无缝连接:立方体纹理设计为无缝连接着六个面,减少了可见的接缝和瑕疵
- 兼容性较好:大多数现代图形硬件对立方体纹理都有专门的支持
缺点:
- 内存开销:立方体纹理由6个2D纹理组成,内存占用较高,特别是在高分辨率情况下
- 采样复杂性:采样方式比起传统的2D纹理更加耗性能,计算更多
- 透视变形:6个平面来近似球形环境,有时会出现透视变形的问题
5、天空盒
天空盒(Skybox)是计算机图形学和三维游戏开发中常用于模拟背景的一种方式,它通常由一个立方体构成,字面上理解就是一个用于模拟天空的盒子(但是它不仅可以模拟天空,模拟室内等环境也是可以的)
在游戏场景中使用天空盒时,整个场景就被包围在了一个立方体中。这个立方体的每个面使用的技术就是立方体纹理技术。
主要好处是:
(1)可以创建逼真的背景
天空盒使场景看起来更加逼真,因为它可以展示复杂和详细的背景
(2)可以提高性能
可以减少渲染远景所需的消耗,只需要要纹理贴图就可以模拟远景的效果,而无需实际的在远处创建这些物体
(3)全景视图
天空盒的六个面(前、后、左、右、上、下)共同构成一个完整的环境,无论玩家向哪个方向看,都能看到连贯的背景图像
(4)易于实现
对于开发者来说,制作和应用天空盒相对简单,只需要准备好六个方向的纹理图像,并将它们应用到立方体纹理中即可
在Unity当中使用天空盒非常的简单,无需写任何代码就可以使用天空盒
第一步:创建天空盒材质球
- 创建一个材质球
- 将其Shader设置为Unity自带的天空盒着色器(Skybox / 6 Sided)
- 为了让天空盒接缝处不要出现不匹配的现象,我们将准备的纹理的Wrap Mode(循环模式)设置为Clamp(夹紧)
- 将我们准备好的6张纹理赋值给对应的面
- 修改材质球上的各参数:Tint Color(材质整体颜色),Exposure(天空盒亮度),Rotation(天空盒沿正y轴方向的旋转角度)
第二步:创建测试用场景
- 新建一个测试场景
- 设置天空盒
- 设置全局天空盒(影响所有摄像机)在Lighting面板中设置材质球
- 单独为摄像机设置天空盒(可以覆盖全局设置)为摄像机添加 Skybox 组件并关联材质球
6、动态生成立方体纹理
立方体纹理的其中一个最大的作用就是环境映射,在实现反射、折射等等效果时,需要用到立方体纹理来制作对应效果,而立方体纹理中最重要的就是组成它的6张2D纹理图片
对于之前学过的天空盒来说,6张2D纹理图片可以根据想要的美术表现效果来进行自定义制作,提前把纹理制作好,直接使用即可,这种立方体纹理往往是被提前做好的,是场景中物体们共用的
但如果制作反射、折射等效果还是使用这样的立方体纹理,效果肯定不够理想,因为物体在场景上的位置不同,产生的对应效果也会是不同的,因此为了更好更真实的表现效果,对于场景中不同位置的物体,我们应该为它们在不同位置生成不同的立方体纹理(6张2D纹理贴图)
主要要完成的功能为:
- 自定义编辑器窗口,关联对象(通过对象来指定位置)和cubemap变量(cube 在右键 Create->Legacy 中查找)
- 自定义窗口中有一个生成按钮,点击后使用Camera中的RenderToCubemap自动生成对应的6张2D纹理贴图
注意点:
- 通过动态创建一个空物体为它添加摄像机组件的形式生成立方体纹理贴图,该对象为临时对象,使用完毕后即时删除即可
- cubemap上需要勾选Readable
- 分辨率决定了清晰度
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class RenderToCubeMap : EditorWindow
{
private GameObject obj;
private Cubemap cubeMap;
[MenuItem("立方体纹理动态生成/打开生成窗口")]
static void OpenWindow()
{
Lesson74_RenderToCubeMap window = EditorWindow.GetWindow<Lesson74_RenderToCubeMap>("立方体纹理生成窗口");
window.Show();
}
private void OnGUI()
{
GUILayout.Label("关联对应位置对象");
//用于关联对象的控件
obj = EditorGUILayout.ObjectField(obj, typeof(GameObject), true) as GameObject;
GUILayout.Label("关联对应立方体纹理");
//用于关联立方体纹理的控件
cubeMap = EditorGUILayout.ObjectField(cubeMap, typeof(Cubemap), false) as Cubemap;
//点击按钮后 就去执行生成逻辑
if(GUILayout.Button("生成立方体纹理"))
{
if(obj == null || cubeMap == null)
{
EditorUtility.DisplayDialog("提醒", "请先关联对应对象和立方体贴图", "确认");
return;
}
//动态的生成立方体纹理
GameObject tmpObj = new GameObject("临时对象");
tmpObj.transform.position = obj.transform.position;
Camera camera = tmpObj.AddComponent<Camera>();
//关键方法,可以马上生成6张2D纹理贴图 用于立方体纹理
camera.RenderToCubemap(cubeMap);
DestroyImmediate(tmpObj);
}
}
}
Camera中的RenderToCubemap也可以在运行时实时动态生成立方体纹理,但是要注意对性能的影响
- 在LateUpdate中使用
- 降低立方体纹理贴图的分辨率
- 分帧渲染,RenderToCubemap有重载,可以一个面一个面的渲染
- 降低更新频率,不要每帧执行