要实现的效果如下,让电视机旁的场景(那个cube)接收电视机的光照
原理
unity为我们提供了emission自发光的效果,在一些表面着色器里,比如standard.
我们也可以编写表面着色器调用这些封装好的参数.
emission可以定义发光颜色,也可以根据光照贴图发光.
我们把播放器中当前帧的纹理传给emission作为光照贴图,并且实时渲染就可以达到上面的效果了.
代码
首先先编写一个surfaceShader调用emission
Shader "Custom/Emission" {
Properties{
_Color("MainColor", Color) = (1,1,1,1)//贴图颜色
_ReflectColor("ReflectionColor", Color) = (1,1,1,0.5)//反射颜色
_MainTex("MainText", 2D) = "white" {}//主贴图
_LightMap("Lightmap", 2D) = "lightmap" { LightmapMode }//光照贴图
}
SubShader{
LOD 200
Tags{ "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
sampler2D _LightMap;
fixed4 _Color;
fixed4 _ReflectColor;
struct Input {
float2 uv_MainTex;
float2 uv2_LightMap;
};
void surf(Input IN, inout SurfaceOutput o) {
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);//解析贴图
fixed4 c = tex * _Color;
half4 lm = tex2D(_LightMap,IN.uv2_LightMap);//解析光照贴图
o.Albedo = c.rgb;//计算漫反射颜色
o.Emission = lm.rgb * _ReflectColor.rgb;//计算自发光颜色
o.Alpha = _ReflectColor.a * lm.a;//计算透明度
}
ENDCG
}
FallBack "Standard"
}
随便丢进去一个纹理做光照贴图,可以看到材质球已经很亮了.
设置发光物体和接收光的物体,为lightmapStatic
否则物体不会接收emission的自发光
设置好了之后,你会发现,接收光的物体还是没有被照亮.
我们把当前材质的shader选为standard,开启Emission,并设置为realtime实时烘焙.
之后切换回我们编写的Emissionshader
此时更换lightmap光照贴图,接收光的物体就会受到影响了. 比如这个红色的纹理.
但是当我们运行的时候,更换贴图,并没有影响其照明效果
我们还需要一个C#的小脚本更新纹理的变化,把这个脚本挂载自发光物体上.
public class UpdateGI : MonoBehaviour {
private Renderer mRenderer;
private void Start()
{
mRenderer = gameObject.GetComponent<Renderer>();
}
private void Update()
{
//renderer.material.SetColor("_EmissionColor", color);
//rend.material.SetTexture("_EmissionMap", texture);
mRenderer.UpdateGIMaterials();//更新光照贴图
}
}
此时我们已经获得了想达到的效果.
注意事项
1.如果受光物体模型太大的话,是没办法烘焙的.
2.如果受光物体或者自发光物体一开始是隐藏于场景中的,那么自发光也会失效.
解决方法是.先把这两个物体放在场景中显示.
然后在lightsetting中取消自动烘焙,我们手动烘焙一次,然后隐藏这两个物体即可