zoukankan      html  css  js  c++  java
  • 解决Lightmap在PC上与ios和Android上表现不同的问题

    LightmapPC上与androidios的区别以及解决方法


    1、  问题描述 
    相信很多人碰到过Lightmap的一些问题: 
    烘培好Lightmap之后,在PC上看起来相当给力,而打包成iosandroid之后,就傻眼了,Lightmap往往就出现了改变,例如灯光曝光度不够、光照颜色偏冷色调、有时候甚至黄色光也能变成绿色光等等。 
    2、造成LightmapPCiosandroid上表现不同的原因 
    u3d里,Lightmap的格式是.exr(openEXR)exr格式的储存方式是使用4*16Bit RGBA来储存数据的,即是说,它使用四个通道分别为RGB和alpha,每个通道占16位储存空间,每个像素占48位储存空间来储存数据。所以EXR格式的图片颜色值域范围就达到了[-65504,65504],远大于8bit(颜色值域[0,255],用浮点数表示就是[0,1])格式所能储存的数值范围。 
    但是EXR格式的Lightmap打包成 android或ios之后,就变成LDR格式(可能是单通道8bit)的了,这就丢失的很多光照信息。例如在PC上烘培出的灯光亮度值是2000,转变成LDR格式后,亮度值就变成了255,这就是为什么打包成android或ios后灯光曝光度不够、光照颜色偏冷色调的原因。 
    3、 解决方法。 
    HDR有几种比较常见的编码格式,这里用的编码格式是LogLuv,就是将RGBA_FP32bit(每个通道32bit或16bit)的数据编码到RGBA32(每个通道8bit)的图片中。LogLuv算法几乎能100%还原unity切换平台后导致Lightmap丢掉的精度信息,算法如下:

       //FP32(RGB) to LogLUV
       fixed4 EncodeLogLuv(fixed3 vRGB)
       {
           fixed3x3 M = fixed3x3(
               0.2209, 0.3390, 0.4184,
               0.1138, 0.6780, 0.7319,
               0.0102, 0.1130, 0.2969 );
     
           fixed4 vResult;
           fixed3 Xp_Y_XYZp = mul(vRGB, 
    M);
           Xp_Y_XYZp = max(Xp_Y_XYZp, 
    fixed3(1e-6, 1e-6, 1e-6));
           vResult.xy = Xp_Y_XYZp.xy / 
    Xp_Y_XYZp.z;
           fixed Le = 2 * 
    log2(Xp_Y_XYZp.y) + 127;
           vResult.w = frac(Le);
           vResult.z = (Le - 
    (floor(vResult.w*255.0f)) / 255.0f) / 255.0f;
           return vResult;


    }

    //LogLuv to FP32(RGB)
       fixed3 DecodeLogLuv(in fixed4 vLogLuv)
       {
           fixed3x3 InverseM = fixed3x3(
              6.0014, -2.7008, -1.7996,
              -1.3320, 3.1029, -5.7721,
              0.3008, -1.0882, 5.6268 );
     
           fixed Le = vLogLuv.z * 255 + 
    vLogLuv.w;
           fixed3 Xp_Y_XYZp;
           Xp_Y_XYZp.y = exp2((Le - 127) 
    / 2);
           Xp_Y_XYZp.z = Xp_Y_XYZp.y / 
    vLogLuv.y;
           Xp_Y_XYZp.x = vLogLuv.x * 
    Xp_Y_XYZp.z;
           fixed3 vRGB = mul(Xp_Y_XYZp, 
    InverseM);


    return max(vRGB, 0); 
    } 
    4、 实现步骤 
    1、 PC平台烘培好光照贴图Lightmap_PC(.exr格式) 
    2、 通过Lightmap_PC生成新的光照贴图Lightmap_LogLuv(.png格式,RGBA32bit,单通道是8bit)。生成过程就用上面提到的LogLuv算法进行编码。这里用GPU来进行生成,有类似GPGPU的思想。如下: 

    //LogLuv算法生成的Lightmap输出到temp上,然后就将temp保存到一张.png格式的图片。

           public bool SaveRenderTextureToPNG(Texture inputTex,Shader outputShader, string contents, string pngName)
    {
                 RenderTexture temp = RenderTexture.GetTemporary(inputTex.width, inputTex.height, 0, RenderTextureFormat.ARGB32);
                 Material mat = new Material(outputShader);
                 Graphics.Blit(inputTex, temp, mat);
                 bool ret = SaveRenderTextureToPNG(temp, contents,pngName);
                 RenderTexture.ReleaseTemporary(temp);
                 return ret;


           } 
            
    //
    RenderTexture保存成一张png图片

             public bool SaveRenderTextureToPNG(RenderTexture rt,string contents, string pngName)
             {
                  RenderTexture prev = RenderTexture.active;
                  RenderTexture.active = rt;
     
                  Texture2D png = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);
                  png.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
                  byte[] bytes = png.EncodeToPNG();
     
                  if (!Directory.Exists(contents))
                       Directory.CreateDirectory(contents);
                  FileStream file = File.Open(contents + "/" + pngName + ".png"FileMode.Create);
     
                  BinaryWriter writer = new BinaryWriter(file);
                  writer.Write(bytes);
                  file.Close();
     
                  Texture2D.DestroyImmediate(png);
                  png = null;
     
                  RenderTexture.active = prev;
     
                  return true;


             } 
    3、 用新生成的光照贴图Lightmap_LogLuv替换原来的光照贴图Lightmap_PC。因为Lightmap_PC在切换androidios会自动将Lightmap_PC压缩为LDR格式,这就丢失了精度。 

    http://www.ceeger.com/forum/read.php?tid=24457&fid=2

  • 相关阅读:
    debian下安装oracle10G
    【海洋女神原创】如何为工程添加一个Installshield不支持的语言艾泽拉斯之海洋女神翻译
    无论程序是否安装,都使setup.exe直接进入安装状态,不出现反安装;以及由此延伸出的同一安装程序允许在同一机器上安装多套软件的探讨
    个人收藏的一些资料(五)Installshield定制行为
    Installshield无人值守安装sqlserver脚本
    个人收藏的一些资料(二)MSI更新和补丁包的制作
    个人收藏的一些资料(三)MSI打包白皮书
    Installshield建立IE快捷方式的方法
    个人收藏的一些资料(一)Installshield制作友好的更新
    MyEclipse的自动提示太让人抓狂了,有没有什么办法改善?
  • 原文地址:https://www.cnblogs.com/jiahuafu/p/7094772.html
Copyright © 2011-2022 走看看