本系列主要参考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同时会加上一点个人理解或拓展。
这里是本书所有的插图。这里是本书所需的代码和资源(当然你也可以从官网下载)。
========================================== 分割线 ==========================================
我们已经学了很多关于反射的内容,但是我们现在的反射并不能实时反射,即当反射物体移动时它们不能正确反射周围的环境。例如,如果你有一个由很多房间和走廊组成的环境,我们不可能提前渲染所有的Cubemap然后放到一个Cubemap中。这意味着我们不能随着房间的移动而正确反射。我们得到的是一个静态的、令人乏味的反射效果。
有很多方法可以解决这个问题,即一个房间的反射不同于另一个房间的反射。一个最基本的方法就是根据在房间中的位置替换Cubemap。因此,当你从一个房间移动到另一个房间时,Cubemap应该被换成当前房间的Cubemap。第二种方法是当我们角色在环境中移动时,实时更新Cubemap,最终在游戏进行的每一帧得到一个新的Cubemap。尽管第二种方法听起来非常吸引人,但是它比较消耗性能,因此你需要在其他游戏资源之间进行权衡。
这一篇将会讲述第一种方法,并且向你展示如何搭建一个非常简单的系统来基于你在环境中的不同位置去替换两个Cubemaps。更多的关于实时反射系统的内容你可以在本节最后找到,因此如果你对实时反射感兴趣并且想要看看两种技术之间的差别,你可以在那里找到!
[ExecuteInEditMode] public class SwapCubemaps : MonoBehaviour {
public Cubemap cubeA; public Cubemap cubeB; public Transform posA; public Transform posB; private Material curMat; private Cubemap curCube;
void OnDrawGizmos() { Gizmos.color = Color.green; if(posA) { Gizmos.DrawWireSphere(posA.position, 0.5f); } if(posB) { Gizmos.DrawWireSphere(posB.position, 0.5f); } }
private Cubemap CheckProbeDistance() { float distA = Vector3.Distance(transform.position, posA.position); float distB = Vector3.Distance(transform.position, posB.position); if(distA < distB) { return cubeA; } else if(distB < distA) { return cubeB; } else { return cubeA; } }
void Update () { curMat = renderer.sharedMaterial; if(curMat) { curCube = CheckProbeDistance(); curMat.SetTexture("_Cubemap", curCube); } }