Unity Shaders and Effects Cookbook (4-6)震撼的实时反射 动态立方图系统

Posted _Captain

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Shaders and Effects Cookbook (4-6)震撼的实时反射 动态立方图系统相关的知识,希望对你有一定的参考价值。

昨天逛街的时候看到太平鸟里面摆了个金属的米老鼠,于是职业病犯了,一直在想金属的颜色是什么,这个反射该怎么写,想不出来……

今天正好看到动态反射立方图系统这一节,看完觉得很别扭,因为书上介绍的是事先踩点生成Cubemap的方式而不是实时的。于是到官方文档找到实时反射的代码,做了一个比较花俏的场景,运行之后吃了一大惊,实时反射是如此的震撼。。


第四章第一节第二节介绍了创建Cubemap,然后学习了如何使用。

Unity Shaders and Effects Cookbook (4-1)(4-2)静态立方体贴图的创建与使用

我也说过了,是静态的Cubemap,就是说这个Cubemap是采集自一个地方,不会随着位置的移动去动态采集周围环境来产生反射。

这一节学习实时动态立方图。

书上 4.6 这一节讲的是简单的动态立方图系统,意思就是在一个房间内的几个点,进行采集,然后生成好几个Cubemap。

然后判断物体位置,靠近了采集点的时候就选用当前采集点的Cubemap。

我画了个图


1、2、3、4是采集点,在这4个点分别创建 Cubemap1、Cubemap2、Cubemap3、Cubemap4。

中间的是人。

当人走到靠近 采集点3 的位置,就使用 Cubemap3。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

这样是动态的,但并不是实时。

我还是到网上寻找实时的反射,参照Unity 文档实现。

http://docs.unity3d.com/ScriptReference/Camera.RenderToCubemap.html

文档上是 js 的,不过并不影响阅读,因为代码很简单。

我翻译成了 C#的。


先来看看效果图。




和4.1 学习的静态立方图 相比,这一节学习的实时立方图,只是把立方图修改为实时生成了。

还记得立方图生成 是使用了 Camera的API

camera.RenderToCubemap(cubemap);

在每次人物移动后,就调用这个函数更新 Cubemap,就达到了实时的目的。


之前我们在 Assets 中创建了 Cubemap ,是因为 创建 和 使用 不是在一起做的。

这一次因为是实时的,所以不用在 Assets 中创建 Cubemap了,创建后用变量存起来,在 LateUpdate 中更新。



搭建好场景,我这里为了好看点就涂涂抹抹做了一个地形。添加一个 Sphere做反射,材质用第一节 的就可以了,复制一份。然后材质中的 Cubemap 去掉,因为现在我们用实时生成的了。

在 Sphere 上挂上下面的脚本

using UnityEngine;
using System.Collections;

public class RealtimeReflection : MonoBehaviour 

    Camera reflectionCamera;
    RenderTexture cubemap;

	// Use this for initialization
	void Start () 
    
        GameObject go = new GameObject("Reflection Camera", typeof(Camera));

        reflectionCamera = go.camera;

        go.hideFlags = HideFlags.HideAndDontSave;
        go.transform.position = transform.position;
        go.transform.rotation = Quaternion.identity;

        reflectionCamera.farClipPlane = 100;
        reflectionCamera.enabled = false;

        cubemap = new RenderTexture(128, 128, 16);
        cubemap.isCubemap = true;
        cubemap.hideFlags = HideFlags.HideAndDontSave;
        renderer.sharedMaterial.SetTexture("_Cubemap", cubemap);

        reflectionCamera.transform.position = transform.position;
        reflectionCamera.RenderToCubemap(cubemap, 63);
	

    void RenderCubemap()
    

    
	
	// Update is called once per frame
	void Update ()
    

	

    void LateUpdate()
    
        reflectionCamera.transform.position = transform.position;
        reflectionCamera.RenderToCubemap(cubemap, 63);
    



主要的就是 LateUpdate 中的 RenderToCubemap

public bool RenderToCubemap(RenderTexture cubemap, int faceMask = 63); 

faceMask 是指 哪几个面需要渲染。63 就是 111111 ,需要渲染就写1.

官方文档

http://docs.unity3d.com/ScriptReference/Camera.RenderToCubemap.html

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

这 6 个 1的顺序是:右 左 上 下 前 后

官方文档

http://docs.unity3d.com/ScriptReference/CubemapFace.html

主要就是上面脚本,控制移动的脚本如下

using UnityEngine;
using System.Collections;

public class MoveController : MonoBehaviour 


    [SerializeField]
    Transform cameraTrans;

	// Use this for initialization
	void Start () 
	
	


    void OnGUI()
    
        if (GUI.RepeatButton(new Rect(250, 50, 90, 90), "Forward"))
        
            transform.localPosition += new Vector3(0, 0, 10 * Time.deltaTime);
        
        if (GUI.RepeatButton(new Rect(250, 150, 90, 90), "Back"))
        
            transform.localPosition += new Vector3(0, 0, -10 * Time.deltaTime);
        
        if (GUI.RepeatButton(new Rect(150, 150, 90, 90), "Left"))
        
            transform.localPosition += new Vector3(-10 * Time.deltaTime, 0, 0);
            
        
        if (GUI.RepeatButton(new Rect(350, 150, 90, 90), "Right"))
        

            transform.localPosition += new Vector3(10 * Time.deltaTime, 0, 0);
        
        if (GUI.RepeatButton(new Rect(650, 50, 90, 90), "Up"))
        
            transform.localPosition += new Vector3(0, 10 * Time.deltaTime, 0);
        
        if (GUI.RepeatButton(new Rect(650, 150, 90, 90), "Down"))
        
            
            transform.localPosition += new Vector3(0, -10 * Time.deltaTime, 0);
        
    

	// Update is called once per frame
	void Update () 
    

        if (Input.GetKey(KeyCode.W))
        
            transform.localPosition += new Vector3(0, 0, 10 * Time.deltaTime);
        

        if (Input.GetKey(KeyCode.A))
        
            transform.localPosition += new Vector3(-10 * Time.deltaTime,0, 0);
        

        if (Input.GetKey(KeyCode.S))
        
            transform.localPosition += new Vector3(0, 0, -10 * Time.deltaTime);
        

        if (Input.GetKey(KeyCode.D))
        
            transform.localPosition += new Vector3(10 * Time.deltaTime, 0, 0);
        

        if (Input.GetKey(KeyCode.Q))
        
            transform.localPosition += new Vector3(0, -10 * Time.deltaTime, 0);
        

        if (Input.GetKey(KeyCode.E))
        
            transform.localPosition += new Vector3(0, 10 * Time.deltaTime, 0);
        
	

    void LateUpdate()
    
        cameraTrans.localPosition = transform.localPosition + new Vector3(0f, 1.0f, -2f);
    


我也放到手机上 魅蓝 metal 测试了下,非常卡。

手机上的截图



但是效果真的很震撼。


项目打包下载:

http://pan.baidu.com/s/1dFqb7NV


APK下载:

http://pan.baidu.com/s/1gf2iJcv


以上是关于Unity Shaders and Effects Cookbook (4-6)震撼的实时反射 动态立方图系统的主要内容,如果未能解决你的问题,请参考以下文章

Unity Shaders and Effects Cookbook (6-2) 透明裁剪着色器

Unity Shaders and Effects Cookbook (6-1) 使用 alpha 参数的 半透明着色器

Unity Shaders and Effects Cookbook (6-3) 修改渲染队列Queue 来 修改渲染顺序

Unity Shaders and Effects Cookbook (7-3) 在地形中使用顶点颜色做混合

Unity Shaders and Effects Cookbook (D-2) Cull Back背面剔除 -- 模型半边不可见

Unity Shaders and Effects Cookbook (5-1)LitSphere lighting model