一、基本知识点
  1、Baked Only:不会传入shader,只有烘焙时才有用,也就是_LightColor0等这种变量不会表示一个Baked Only Light(前提是场景有lightmap,如果没有烘培,baked only的参数没有意义);
  (1)烘焙完以后,再将Realtime Only改为Baked Only,还是会传入shader;
  (2)Baked的Light,在烘焙完后,手动改为Realtime Only,还是会传入shader。
  2、Realtime Only:只有实时光照,不参与烘焙过程;
  3、Auto:Unity自己判断你是烘焙的还是实时的。
二、渲染路径相关
  1、VertexLit渲染路径下的光照贴图:
  Vertex Pass和VertexLM* Pass,同时只会执行一种:
  当场景没有lightmap时,会执行Vertex Pass;
  当场景有lightmap时,烘培过的static物体会执行VertexLM* Pass,其它物体执行Vertex Pass。
  注意:Always Pass还是会一直执行。
  Unity默认材质,如果被烘培了,就不再受实时光照影响,也就是说Realtime Only light都直接被忽略。
  可以自己写shader来实现lightmap静态物体,同时有实时光照的效果。
  自发光材质,也能烘焙出光影效果,但需要标记为static,可以按照制定规范自己编写自发光材质。
  2、Forward渲染路径下的光照贴图:
  a.对于Unity bulit-in的shader,物体可以同时接受lightmap和realtime光照效果,
  实时影响烘焙物体的light的属性:pixel、支持RealTime。
  被烘培锅的光源不再对烘焙过的物体产生照明。
  b.自定义shader

  #pragma multi_compile_fwdbase

  #ifndef LIGHTMAP_OFF
  sampler2D unity_LightMap;
  float4 unity_LightMapST;
  #endif   // lightmap的颜色
  #ifndef LIGHTMAP_OFF
  float3 c_lm = DecodeLightmap(tex2D(unity_LightMap, i.uv2));
  c_tex.rgb = c_tex.rgb * c_lm;
  #endif

  3、Deferred渲染路径下的光照贴图:
  双光照贴图默认只在Deferred模式下使用。
  在Forward渲染路径下,可以使用Surface Shader来使用双光照贴图:

#pragma surface surf Lambert dualforward

三、光照贴图模式:
  1、Single Lightmaps
  单光照贴图只生成Far光照图。
  烘焙场景时凹凸信息会丢失。
  2、Dual Lightmaps
  Far光照图:完全的GI光照;
  Near光照图:只包含Indirect照明。
  影响参数:QualitySettings.shadowDistance,物体到相机的距离。
  当距离>shadowDistance时,渐变到Far贴图,没有实时光照;
  当距离<shadowDistance时,渐变到Near贴图,也就是Indirect光照贴图+实时光照。
  应用原理:根据distance在Far和Near两组光照贴图之间混合。
  优点:既可以让我们的场景有GI照明的真实感,又可以拥有动态光源的变化。
  双光照贴图可以很好地支持Specular和凹凸贴图。
  3、Directional Lightmaps
  color光照图:和单光照贴图的完全一样,只包含颜色信息;
  scale光照图:存储灯光的方向信息。
  方向不是指方向光,而是说烘焙出的贴图会保存灯光的方向信息。
四、在shader中使用lightmap的数据:
  1、要使用vs/ps的shader,不使用surface shader
  2、访问lightmap数据的变量:

sampler2D unity_Lightmap;
float4 unity_LightmapST;

  3、unity_LightmapST在规范上来说有一个命名失误,将_ST写成了ST,所以在计算uv的时候不能这样:
  o.uv1 = TRANSFORM_TEX(v.texcoord1.xy, unity_Lightmap);
  因为TRANSFORM_TEX的定义为:
  #define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
  那么对于lightmap需要这样做:
  o.uv1 = i.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
  4、根据DecodeLightmap函数来解析lightmap颜色值,DecodeLightmap的函数定义如下,其内部处理了平台相关的问题:

  // Decodes lightmaps:
  // - doubleLDR encoded on GLES
  // - RGBM encoded with range [0;8] on other platforms using surface shaders
  inline fixed3 DecodeLightmap(fixed4 color) {
    #if defined(SHADER_API_GLES) && defined(SHADER_API_MOBILE)
    return 2.0 * color.rgb;
    #else
    return (8.0 * color.a) * color.rgb;
    #endif
  }

  那么获得Lightmap颜色的代码为:

  half4 lm = tex2D(unity_Lightmap, i.lmuv.xy);
  fixed3 lightmapColor = DecodeLightmap(lm);

 五、shader示例

  VertexLit渲染路径下支持Lightmap:

Shader "James/VP Shader/LightMap-VertexLit"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_addColor ("addColor", Color) = (, , , )
}
SubShader
{
Pass
{
Tags { "LightMode" = "Vertex"}
LOD CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" sampler2D _MainTex;
float4 _MainTex_ST; struct v2f
{
float4 pos: POSITION;
float3 normal: TEXCOORD0;
float2 uv: TEXCOORD1;
float4 lightingColor : TEXCOORD2;
}; v2f vert(appdata_base data)
{
v2f o;
o.lightingColor.rgb = ShadeVertexLights(data.vertex, data.normal);
o.lightingColor.a = ;
o.pos = mul(UNITY_MATRIX_MVP, data.vertex);
o.uv = TRANSFORM_TEX(data.texcoord, _MainTex);
o.normal = data.normal;
return o;
} float4 frag(v2f data) : COLOR
{
fixed4 texColor = tex2D(_MainTex, data.uv);
return texColor * data.lightingColor;
// return float4(0, 1, 0, 1);
}
ENDCG
} Pass
{
Tags { "LightMode" = "VertexLMRGBM"}
LOD CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" float4 _addColor; sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D unity_Lightmap;
float4 unity_LightmapST; struct v2f
{
float4 pos: POSITION;
float3 normal: TEXCOORD0;
float2 uv_tex: TEXCOORD1;
float2 uv_lm: TEXCOORD2;
// 实时光照成分
float3 lightingColor : TEXCOORD3;
}; v2f vert(appdata_full data)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, data.vertex);
o.uv_tex = TRANSFORM_TEX(data.texcoord, _MainTex);
o.uv_lm = data.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
o.normal = data.normal;
o.lightingColor = ShadeVertexLights(data.vertex, data.normal);
return o;
} float4 frag(v2f data) : COLOR
{
// 纹理颜色
fixed4 texColor = tex2D(_MainTex, data.uv_tex);
// 解码的lightmap颜色
fixed4 lm = tex2D(unity_Lightmap, data.uv_lm);
fixed3 lmColor = DecodeLightmap(lm);
// 纹理色 * 光照色
texColor.rgb = texColor.rgb * lmColor;
return texColor * fixed4(data.lightingColor, );
}
ENDCG
}
}
FallBack "Diffuse"
}

  Forward渲染路径下支持Lightmap:

Shader "James/VP Shader/LightMap-ForwardLM"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_Color ("Base Color", Color) = (, , , )
}
SubShader
{
Pass
{
Tags { "LightMode" = "ForwardBase"}
LOD CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "Lighting.cginc" uniform float4 _Color; sampler2D _MainTex;
float4 _MainTex_ST; #ifndef LIGHTMAP_OFF
sampler2D unity_Lightmap;
float4 unity_LightmapST;
#endif struct vertOut
{
float4 pos: POSITION;
float4 color: COLOR;
float3 litDir: TEXCOORD0;
float3 worldN: TEXCOORD1;
float2 uv: TEXCOORD2; #ifndef LIGHTMAP_OFF
float2 uv2: TEXCOORD3;
#endif
}; vertOut vert(appdata_full v)
{
// 世界坐标
float4 worldV = mul(_Object2World, v.vertex);
// 世界法线
// float3 worldN = mul((float3x3)_Object2World, SCALED_NORMAL).xyz;
float3 worldN = mul(_Object2World, float4(SCALED_NORMAL, )).xyz;
float3 c = Shade4PointLights(unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
unity_LightColor[], unity_LightColor[], unity_LightColor[], unity_LightColor[],
unity_4LightAtten0, worldV.xyz, worldN); vertOut o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.litDir = WorldSpaceLightDir(v.vertex);
o.worldN = worldN;
// 4盏点光源的光照
o.color = float4(c, 1.0) * _Color;
o.uv = TRANSFORM_TEX(v.texcoord.xy, _MainTex); #ifndef LIGHTMAP_OFF
o.uv2 = (v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw);
#endif return o;
} float4 frag(vertOut i) : COLOR
{
// 1个主光的光照
float4 c = max(0.0, dot(i.worldN, normalize(i.litDir))) * _LightColor0 * _Color; // 纹理颜色
float4 c_tex = tex2D(_MainTex, i.uv); #ifndef LIGHTMAP_OFF
float3 c_lm = DecodeLightmap(tex2D(unity_Lightmap, i.uv2));
c_tex.rgb *= c_lm;
#endif return c + c_tex + i.color;
}
ENDCG
} Pass
{
Tags { "LightMode" = "ForwardAdd"}
LOD
Blend One One CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc" uniform float4 _Color;
struct vertOut
{
float4 pos : SV_POSITION;
float3 litDir : TEXCOORD0;
float3 worldN : TEXCOORD1;
float atten : TEXCOORD2;
}; vertOut vert(appdata_base v)
{
float3 worldN = mul(_Object2World, float4(SCALED_NORMAL, )).xyz; vertOut o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.litDir = WorldSpaceLightDir(v.vertex);
o.worldN = worldN;
float dist = length(o.litDir);
// 根据_WorldSpaceLightPos0.w来判断是方向光还是点光源
o.atten = / ( + dist * dist * _WorldSpaceLightPos0.w);
return o;
} float4 frag(vertOut i) : COLOR
{
float4 c = _LightColor0 * _Color * max(0.0, dot(i.worldN, normalize(i.litDir))) * i.atten;
return c;
}
ENDCG
}
}
FallBack "Diffuse"
}

Lightmaping的更多相关文章

随机推荐

  1. bzoj 3202: [Sdoi2013]项链

    Description 项链是人体的装饰品之一,是最早出现的首饰.项链除了具有装饰功能之外,有些项 链还具有特殊显示作用,如天主教徒的十字架链和佛教徒的念珠. 从古至今人们为了美化人体本身,也美 化环 ...

  2. StringBuilder(字符串拼接类)

    StringBuilder是在using System.Text命名空间下的一个成员. 在做字符串拼接的时候,因为字符串是引用类型,新的字符串是会再内存中创建的,所以用+号拼接字符串是比较耗效率的. ...

  3. 使用VisualVM分析性能

    性能分析神器VisualVM VisualVM 是一款免费的,集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优.这些功能包括生成和分析海量 ...

  4. Ncut源码编译错误的解决方法

    NCut是一个比较老的开源代码了.所以在新的matlab的环境下老出各种bug. 经过自己的各种折腾,总结为一下几点: 1.保证matlab的mex是有C编译器可以用的,具体可以用 mex -setu ...

  5. ActionMapping

    在Struts中,ActionServlet只是任务的分派者,它依请求分配任务给其它的对象来执行,而分配的依据是请求的URI以及struts-config.xml的<action-mapping ...

  6. android 从服务器获取新闻数据并显示在客户端

    新闻客户端案例 第一次进入新闻客户端需要请求服务器获取新闻数据,做listview的展示, 为了第二次再次打开新闻客户端时能快速显示新闻,需要将数据缓存到数据库中,下次打开可以直接去数据库中获取新闻直 ...

  7. C++ 编写DLL文件给易语言调用

    摸索了两天了,终于解决了所有问题,在此跟大家分享. 需要三个文件,dll_demo.h.dll_demo.cpp.dll_dome.def 直接上代码: 头文件如下: #ifndef _DLL_DEM ...

  8. Struts 2的数据校验

    既然说到了Struts 2的数据校验,我们该怎么去实现呢?又是通过什么来实现呢? 就让我带着大家一起来走进Struts 2的数据校验吧. 首先我们会想到在Stuts 2的登录案例中我们定义了一个Act ...

  9. vim的配置与使用

    经历了一次source insight 一言不合就崩溃之后,决定还是花点时间好好配置和学习以下vim 于是找到大神的配置 https://github.com/humiaozuzu/dot-vimrc ...

  10. canvas初探3:画方画圆

    绘制矩形的方法,strokeRect().fillRect()及clearRect(). 方法 描述 strokeRect(double x,double y,double w,double h) 使 ...