码迷,mamicode.com
首页 > 编程语言 > 详细

unity3d 实时动态反射周围世界

时间:2014-12-15 08:59:54      阅读:506      评论:0      收藏:0      [点我收藏+]

标签:游戏开发   cg语言   shader   unity3d   屏幕特效   

先截出一个效果图:

bubuko.com,布布扣


要反射出周围世界
我们只需要一个周围世界的cubemap


先来看反射的shader

首先声明变量:
_Cubemap                  需要反射的cubemap
_ReflAmount              反射的强度


	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_MainTint ("Diffuse Color", Color) = (1, 1, 1, 1)
		_Cubemap ("CubeMap", CUBE) = ""{}
		_ReflAmount ("Reflection Amount", Range(0.01, 1)) = 0.5
	}

还需要为input结构体增加一个参数

float3 worldRefl
worldRef 即为世界空间的反射向量
内置的worldRefl 来做立方图反射


		struct Input {
			float2 uv_MainTex;
			float3 worldRefl;////worldRefl:即为世界空间的反射向量///内置的worldRefl 来做立方图反射(cubemap         reflection)//为了计算反射
		};

在surf函数中给Emission(像素的发散颜色)赋值
texCUBE函数,获得立方图纹理的信息
再乘上我们之前定义的_ReflAmount反射强度
o.Emission = texCUBE(_Cubemap, IN.worldRefl).rgb * _ReflAmount;

然后就ok了,
我们获得了一个可以反射周围世界的shader


		void surf (Input IN, inout SurfaceOutput o) {
			half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
			o.Emission = texCUBE(_Cubemap, IN.worldRefl).rgb * _ReflAmount;
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}


接下来要解决的问题就是实时
如果我们能实时更新这个cubemap,就可以实时反射了。




接下来我们建立一个c#脚本

全部变量:

要更新的cubemap
public Cubemap cubmap;


这里需要注意:我们要新建立一个camera放在要反射的物体的位置上,成为要反射的物体的子物体
不是main camera
public Camera cam;


这里的材质就是上面shader的材质
private Material curMat;


    public Cubemap cubmap;
    public Camera cam;
    private Material curMat;


初始化curMat,
就是获取我们要反射物体的材质
curMat = renderer.sharedMaterial;


在start函数中建立一个定时器
InvokeRepeating("UpdateChange", 1, 0.1f);
1秒后调用UpdateChange () 函数,之后每0.1秒调用一次
    void Start()
    {
        InvokeRepeating("UpdateChange", 1, 0.1f);
        curMat = renderer.sharedMaterial;
    }

再建立这个 UpdateChange () 函数
保证相机的角度不变
 cam.transform.rotation = Quaternion.identity;
这个是我们的核心函数,
RenderToCubemap渲染到立方图,烘焙场景的静态立方贴图,赋给参数
cam.camera.RenderToCubemap(cubmap);


再把这个cubemap传给上面shader的_Cubemap变量中,就做到了实时更新
curMat.SetTexture("_Cubemap", cubmap);


    void UpdateChange()
    {
        cam.transform.rotation = Quaternion.identity;
        cam.camera.RenderToCubemap(cubmap);

        curMat.SetTexture("_Cubemap", cubmap);
    }


ok,

先来看看效果


bubuko.com,布布扣


从波动的水体就能看出来确实实时反射了周围的环境


再让我们分析一下效果与效率问题,
不可否认的是,这种方法虽然能做到实时反射,但是确实很“浪费”,而且清晰度高了会很卡


看看cubemap的FaceSize值对效果的影响


32:


bubuko.com,布布扣


很明显,32相当模糊,相当“锯齿”


64:


bubuko.com,布布扣


64也是很模糊,但是比32的要好一些,已经有一些凹凸感了



128:


bubuko.com,布布扣


128的效果感觉还可以,但是不是特别清晰



256:



bubuko.com,布布扣

到256的时候可以说实在这么简单的场景里面刚好不卡,

在512时就有一点点卡了,

其实256在游戏当中也不实用,

建议在128一下


512:


bubuko.com,布布扣



512已经很清晰了,有一点点卡。


1024:


bubuko.com,布布扣

截这张1024时,我的unity几乎卡的不动了,帧率不到10fps吧,= =;有点清晰的过头了


看1024卡的那么嚣张就没敢试2048的估计也和1024差不多,


以上就结束了,

本片不需要什么图片资源大家可以试试



以下全部代码:

c#;


using UnityEngine;
using System.Collections;

public class d_cubMap : MonoBehaviour
{
    public Cubemap cubmap;
    public Camera cam;
    private Material curMat;
    // Use this for initialization
    void Start()
    {
        InvokeRepeating("UpdateChange", 1, 0.1f);
        curMat = renderer.sharedMaterial;
    }
    void UpdateChange()
    {
        cam.transform.rotation = Quaternion.identity;
        cam.camera.RenderToCubemap(cubmap);

        curMat.SetTexture("_Cubemap", cubmap);
    }

}



shader;



Shader "Custom/cubmap" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_MainTint ("Diffuse Color", Color) = (1, 1, 1, 1)
		_Cubemap ("CubeMap", CUBE) = ""{}
		_ReflAmount ("Reflection Amount", Range(0.01, 1)) = 0.5
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200

			CGPROGRAM
#pragma surface surf Lambert

			sampler2D _MainTex;
		samplerCUBE _Cubemap;
		float4 _MainTint;
		float _ReflAmount;

		struct Input {
			float2 uv_MainTex;
			float3 worldRefl;////worldRefl:即为世界空间的反射向量///内置的worldRefl 来做立方图反射(cubemap         reflection)//为了计算反射
		};

		void surf (Input IN, inout SurfaceOutput o) {
			half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
			o.Emission = texCUBE(_Cubemap, IN.worldRefl).rgb * _ReflAmount;
			//	o.Albedo = texCUBE(_Cubemap, IN.worldRefl).rgb * _ReflAmount;//c.rgb;
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}


                                                                                                 ---------by   wolf96














unity3d 实时动态反射周围世界

标签:游戏开发   cg语言   shader   unity3d   屏幕特效   

原文地址:http://blog.csdn.net/wolf96/article/details/41939325

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!