Unity 制作灯罩 双面材质背面不受光照影响的解决方法

来源:互联网 发布:手机声音增强软件 编辑:程序博客网 时间:2024/04/27 21:57

     最近开发一个Unity项目主要是打算模拟一下灯效果,本以为把一个光源放入我们的灯的模型中就可以完美解决问题,然而当开始操作的时候,真的是困难重重,套在模型里面的点光源根本无法照亮外面的模型!

     

     我们可以发现,这个光源可以在外面照亮这个立方体,而无法从里面照亮立方体。 

     百度了一下之后,也没有发现过多的信息,大多数的做法还是选择高亮表面,然后旁边加几个点光源照亮表面(设定layer,只照亮灯的部分),一开始,我也是这么弄得,但是我的项目就是为了表现灯的,所以不免有对灯的亮度的调节,而且有的灯的模型面太多了根本就没法实现正常的模拟,毕竟在外面找一个类圆形的物体肯定会导致照的不均匀的,而且光源过多的话对系统消耗也有不小的影响。于是,我决定一定要研究一下这个灯的发光效果,目标就是实现光源从里面照亮整个灯罩!

      所以,这样的话,我们的目标就明确了,就是要立方体的背面可以被照亮,但是为什么立方体外面可以被照亮然而内部不可以被照亮呢?

      其实每一个模型都是有一个面的,也就是正面和反面,默认的情况下,我们的图形渲染和光照影响都是只会在正面有效果的,这样做是为了节省资源,毕竟背面的话,我们也看不见何必再消耗资源去渲染它呢?现在网上有很多关于双面材质的解决方案,最简单的做法就是在Shader里面加入一个cull off,也就是关闭剔除渲染(表达的有点不清楚,这个意思就是cull back 的话就是不渲染背面,cull front的话就是不渲染正面),所以你添加了cull off的话就是两面都渲染,也就是实现了双面材质。

    

      以上的效果是当光源照正面的时候,我们发现这个plane的两边都被照亮了,下面我们来看看,照背面会怎么样?

     我们可以发现,当光源照到背面的时候,两面都没有光照的效果。

     Google了一下之后,发现了一片文章解决了我的疑惑,这篇文章讲的真心不错,强烈推荐读一读:http://danielbrauer.com/files/rendering-double-sided-geometry.html。其实,正面之所以被光照影响是因为,当前的模型上面的法线和光照的方向是相反的,所谓法线,大家初中物理就应该接触过吧,就是很据入射光计算反射光的中间的那条线。在Unity3D中,光照效果的漫反射也是根据这个计算的,之所以背面不接受光照,是因为法线方向和光线方向平行当然就计算不出反射光线的方向,也就反射不回来,所以我们也看不到它。那么,这样的话,我们的工作就明确了,只要把法线方向变为和原来的相反,那么模型的背面也就有效果啦~

下面贴一下,Shader的代码(这个Shader是我根据Unity自带的自发光高光Shader改的双面材质背面受光照影响):

Shader "Happy/TwoSideShader" {Properties {_Color ("Main Color", Color) = (1,1,1,1)_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)_Shininess ("Shininess", Range (0.01, 3)) = 1_Parallax ("Height", Range (0.005, 0.08)) = 0.02_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}_Illum ("Illumin (A)", 2D) = "white" {}_BumpMap ("Normalmap", 2D) = "bump" {}_ParallaxMap ("Heightmap (A)", 2D) = "black" {}}SubShader {Tags { "RenderType"="Opaque" }LOD 600cull offCGPROGRAM#pragma surface surf BlinnPhong#pragma target 3.0sampler2D _MainTex;sampler2D _BumpMap;sampler2D _ParallaxMap;sampler2D _Illum;fixed4 _Color;float _Parallax;half _Shininess;struct Input {float2 uv_MainTex;float2 uv_BumpMap;float2 uv_Illum;float3 viewDir;};void surf (Input IN, inout SurfaceOutput o) {half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);IN.uv_MainTex += offset;IN.uv_BumpMap += offset;IN.uv_Illum += offset;fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);fixed4 c = tex * _Color;o.Albedo = c.rgb;o.Gloss = tex.a;o.Emission = c.rgb * tex2D(_Illum, IN.uv_Illum).a;o.Specular = _Shininess;o.Alpha = c.a;o.Normal = -UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));}ENDCG}FallBack "Legacy Shaders/Self-Illumin/Bumped Specular"CustomEditor "LegacyIlluminShaderGUI"}

     其实,单单实现灯罩的话没必要使用双面材质,可以把这个Shader里面的cull off去掉,这次为了做一个这样的效果也是花费不少的时间,最终的解决方法也是如此的简单,看来还事Shader的基础不扎实!有时间还得好好研究一下~

  

    

0 0
原创粉丝点击