Lightmap在PC上与android和ios的区别以及解决方法

1、  问题描述 
相信很多人碰到过Lightmap的一些问题: 
烘培好Lightmap之后,在PC上看起来相当给力,而打包成ios或android之后,就傻眼了,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在切换android或ios会自动将Lightmap_PC压缩为LDR格式,这就丢失了精度。

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

解决Lightmap在PC上与ios和Android上表现不同的问题的更多相关文章

  1. 如何让音频跟视频在ios跟android上自动播放

    如何让音频跟视频在ios跟android上自动播放 <audio autoplay ><source src="audio/alarm1.mp3" type=&q ...

  2. 关于Unity程序在IOS和Android上显示内嵌网页的方式

    近期因为有须要在Unity程序执行在ios或android手机上显示内嵌网页.所以遍从网上搜集了一下相关的资料.整理例如以下: UnityWebCore 从搜索中先看到了这个.下载下来了以后发现这个的 ...

  3. cocos打包到ios与android上音频推荐

    首先贴一张官方对于ios与android上音频格式的推荐: 这里只给出了推荐格式,一般我们在实际运用中会使用如下方式: 一.IOS与安卓各一套:音乐:都使用MP3    音效:ios用caf Andr ...

  4. EasyTouch绑定事件在电脑上点击有效Android上无效的解决方法

    最近做一个RPG类的游戏发现使用EasyTouch虚拟摇杆插件在电脑上点击有效Android上无效,查找资料发现是Easy Joystick中的一个属性interaction type要设置成 Dir ...

  5. [原] GLES在iOS和Android上的不同

    本来GLES提供了与native platform的接口 EGL, 然而iOS没有使用EGL接口, 而是自己搞了一套,叫做EAGL的类似东西, 虽然说大同小异,但是在做跨平台的时候还是很恶心. elg ...

  6. input,textarea在ios和Android上阴影和边框的处理方法(在移动端)

    1.去掉ios上阴影的方法只需要在css文件上添加input,textarea{-webkit-appearance: none;}就可以了 2.在移动端上input和textarea边框问题,也是在 ...

  7. PC端利用Xshell连接Android上的Termux

    需要准备的工具 Android端:Termux.RE管理器 PC端:Xshell 开始操作 1. 启动Termux,安装openssh pkg install openssh 2. 安装好后,启动ss ...

  8. 【转】iOS类似Android上toast效果

    原文网址:http://m.blog.csdn.net/article/details?id=50478737 做过Android开发的人都知道toast,它会在界面上显示一排黑色背景的文字,用于提示 ...

  9. 解决Unity5+Vuforia+Network本地联机发布到Android上白屏的问题

    Unity5+Vuforia+Network本地联机,在Android下点击联机,然后识别模型就出现白屏,点击屏幕上相应位置的按钮(已白屏,但点击该看不见的按钮)还是能起作用,如跳转到其他场景正常. ...

随机推荐

  1. RDD之六:Action算子

    本质上在Actions算子中通过SparkContext执行提交作业的runJob操作,触发了RDD DAG的执行. 根据Action算子的输出空间将Action算子进行分类:无输出. HDFS. S ...

  2. java实验四——找鞍点

    package hello; public class 实验四 { public static void main(String[] args) { // TODO Auto-generated me ...

  3. 在HTML标签的事件后面直接写JS代码

    <input type="button" onclick="document.getElementdByTagName('div')[0].innrtHTML='S ...

  4. XStream和Dom4j的区别

    对于搞技术的人来说,xml文件的处理应该并不陌生吧,先总述下,个人感觉XStream在处理XML文件和JavaBean对象互转时比较好,dom4j对常用的xml配置文件操作比较好点:首先,Dom4j ...

  5. [Java基础] Java float保留两位小数或多位小数

    方法1:用Math.round计算,这里返回的数字格式的. float price=89.89; int itemNum=3; float totalPrice=price*itemNum; floa ...

  6. 初次从eclipse转到intellij idea上的一些经验

    如果出现:mvn 请使用 -source 7 或更高版本以启用 diamond 运算符 这种问题 pom.xml里 <build>标签里面 需要加入这么一段 <plugins> ...

  7. [UE4]UE4中的常见类

    一.Actor:可以放在世界中物体 二.Pawn:可以接受Controller输入的Actor 三.Character:是一个可以行走.跑.跳等行为的Pawn 四.Controller:没有物理表现的 ...

  8. application/xml 和 text/xml的区别

    application/xml and text/xml的区别 经常看到有关xml时提到"application/xml" 和 "text/xml"两种类型, ...

  9. SQL的三种连接方式内连接、左连接、外连接

    1.内连接 select * from table_a x inner join table_b y on x.a_id = y.b_id 返回两个表关键字x.a_id = y.b_id的交集数据集 ...

  10. 第3章 文件I/O(6)_高级文件操作:文件锁

    7. 高级文件操作:文件锁 (1)文件锁分类 分类依据 类型 说明 按功能分 共享读锁 文件描述符必须读打开 一个进程上了读锁,共它进程也可以上读锁进行读取 独占写锁 文件描述符必须写打开 一个进程上 ...