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"
    }
  • 相关阅读:
    zbb20181207 springboot @ConfigurationProperties使用
    zbb20181206 logback,lombok 默认日志logback配置解析
    Spring Boot (8) 全局异常处理
    Spring Boot (7) JdbcTemplate访问数据库
    Spring Boot (6) Spring Data JPA
    Spring Boot (4) 静态页面和Thymeleaf模板
    Spring Boot (3) 热部署devtools
    Spring Boot (2) Restful风格接口
    Spring Boot (1) 构建第一个Spring Boot工程
    idea使用maven搭建ssm框架实现登陆商品增删改查
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/4848689.html
Copyright © 2011-2022 走看看