zoukankan      html  css  js  c++  java
  • Lightmaping

    一、基本知识点
      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) = (1, 1, 1, 1)
        }
        SubShader 
        {
            Pass
            {    
                Tags { "LightMode" = "Vertex"}
                LOD 200
                
                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 = 1;
                    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 200
                
                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, 1);
                }
                ENDCG
            }
        } 
        FallBack "Diffuse"
    }

      Forward渲染路径下支持Lightmap:

    Shader "James/VP Shader/LightMap-ForwardLM"
    {
        Properties 
        {
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _Color ("Base Color", Color) = (1, 1, 1, 1)
        }
        SubShader
        {
            Pass
            {    
                Tags { "LightMode" = "ForwardBase"}
                LOD 200
                
                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, 0)).xyz;
                    float3 c = Shade4PointLights(unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, 
                                                 unity_LightColor[0], unity_LightColor[1], unity_LightColor[2], unity_LightColor[3],
                                                 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 200
                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, 0)).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 = 1 / (1 + 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"
    }
  • 相关阅读:
    批处理手动设置电脑的ip
    用shell脚本生成日志文件
    编译小米mini openwrt
    Jackson 时间格式化,时间注解 @JsonFormat 用法、时差问题说明
    swagger注释API详细说明
    com.rabbitmq.client.impl.Frame.readFrom(Frame.java:95)
    在Java中如何高效判断数组中是否包含某个元素
    阿里云服务器端口开放对外访问权限
    macos 安装telnet命令
    在 Docker 上配置 Oracle
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/4848689.html
Copyright © 2011-2022 走看看