UnityShader学习——立方体纹理及其应用

立方体纹理简介

  • 立方体纹理的形式:包含了6张图像,这些图像对应了一个立方体的6个面,立方体纹理的名称也由此而来。立方体的每个面表示沿着世界空间下的轴向(上、下、左、右、前、后)观察所得的图像。
  • 对立方体纹理采样:需要提供一个三维的纹理坐标,这个三维纹理坐标表示了我们在世界空间下的一个3D方向。这个方向矢量从立方体的中心出发,当它向外部延伸时就会和立方体的6个纹理之一发生相交,而采样得到的结果就是由该交点计算而来的。
  • 优缺点
    • 好处:它的实现简单快速,而且得到的效果也比较好。
    • 缺点:(1)当场景中引入了新的物体、光源,或者物体发生移动时,需要重新生成立方体纹理。(2)立方体纹理也仅可以反射环境,但不能反射使用了该立方体纹理的物体本身。由于这样的原因,我们应该尽量对凸面体使用立方体纹理(因为凹面体会反射自身)。

立方体纹理应用

1.天空盒子

是什么?

天空盒子(Skybox)是游戏中用于模拟背景的一种方法。当我们在场景中使用了天空盒子时,整个场景就被包围在一个立方体内。在Unity中,天空盒子是在所有不透明物体之后渲染的,而其背后使用的网格是一个立方体或一个细分后的球体。

怎么用?

  1. 制作材质:
    • 在Unity中,只需要创建一个Skybox材质,再把它赋给该场景的相关设置即可。
    • 在SkyboxMat的Unity Shader下拉菜单中选择Unity自带的Skybox/6 Sided,该材质需要6张纹理。
    • 注意这6张纹理的正确位置(如posz纹理对应了Front [+Z] 属性)。
    • 我们还需要把这6张纹理的Wrap Mode设置为Clamp,以防止在接缝处出现不匹配的现象。
    • 上面的材质中,除了6张纹理属性外还有3个属性:Tint Color,用于控制该材质的整体颜色;Exposure,用于调整天空盒子的亮度;Rotation,用于调整天空盒子沿+y轴方向的旋转角度。
  2. Window → Lighting菜单中,把SkyboxMat赋给Skybox选项。
  3. 设置摄像机:
    • 为了让摄像机正常显示天空盒子,我们还需要保证渲染场景的摄像机的Camera组件中的ClearFlags被设置为Skybox。
    • 在Window → Lighting → Skybox中设置的天空盒子会应用于该场景中的所有摄像机。如果我们希望某些摄像机可以使用不同的天空盒子,可以通过向该摄像机添加Skybox组件来覆盖掉之前的设置。
2.环境映射

如何创建用于环境映射的立方体纹理?

  1. 直接由一些特殊布局的纹理创建:
    • 我们需要提供一张具有特殊布局的纹理,例如类似立方体展开图的交叉布局、全景布局等。然后,我们只需要把该纹理的Texture Type设置为Cubemap即可,Unity会为我们做好剩下的事情。
    • 在Unity 5中,官方推荐这种方法创建立方体纹理,因为这种方法可以对纹理数据进行压缩,而且可以支持边缘修正、光滑反射(glossy reflection)和HDR等功能。
  2. 手动创建一个Cubemap资源,再把6张图赋给它。 在项目资源中创建一个Cubemap,然后把6张纹理拖曳到它的面板中。
  3. 由脚本生成(理想情况下,我们希望根据物体在场景中位置的不同,生成它们各自不同的立方体纹理)。
    • Camera.RenderToCubemap函数可以把从任意位置观察到的场景图像存储到6张图像中,从而创建出该位置上对应的立方体纹理。
    • 新建一个用于存储的立方体纹理(在Project视图下单击右键,选择Create → Legacy→Cubemap来创建)。为了让脚本可以顺利将图像渲染到该立方体纹理中,我们需要在它的面板中勾选Readable选项。

创建立方体纹理的脚本:

using UnityEngine;
using UnityEditor;
using System.Collections;

public class RenderCubemapWizard : ScriptableWizard {
   
   
   
   public Transform renderFromPosition;
   public Cubemap cubemap;
   
   void OnWizardUpdate () {
   
   
   	helpString = "Select transform to render from and cubemap to render into";
   	isValid = (renderFromPosition != null) && (cubemap != null);
   }
   
   void OnWizardCreate () {
   
   
   	// create temporary camera for rendering
   	GameObject go = new GameObject( "CubemapCamera");
   	go.AddComponent<Camera>();
   	// place it on the object
   	go.transform.position = renderFromPosition.position;
   	// render into cubemap		
   	go.GetComponent<Camera>().RenderToCubemap(cubemap);
   	
   	// destroy temporary camera
   	DestroyImmediate( go );
   }
   
   [MenuItem("GameObject/Render into Cubemap")]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值