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. Bootstrap-CSS:网格系统

    ylbtech-Bootstrap-CSS:网格系统 1.返回顶部 1. Bootstrap 网格系统 本章节我们将讲解 Bootstrap 的网格系统(Grid System). Bootstrap ...

  2. [html] 回到页首

    [转]本文来自:最简单最强大的插件框架(Net 2.0+) http://www.cnblogs.com/baihmpgy/p/3305215.html <!doctype html> & ...

  3. Linux 期中架构 Ansible

    ansible  自动化软件   基于Python开发 特点概述: 配置文件不需要过多配置  了解就可以了 ###部署ansble软件 ##受控主机部署 backup   nfs01   web01 ...

  4. Oracle跨库复制表结构

    1.首先建立远程连接 create public database link LINK_SJPSconnect to system identified by manager using '(DESC ...

  5. EL中拼接字符串的方法

    近期在项目中碰到一个需要在JSP页面中比较两String类型的值的问题,于是想当然的写了如下代码: <c:if test="${'p'+longValue=='p1'}"&g ...

  6. Python和Signal

    先简单说一下Signal是啥.(如果想直接使用可以不看) Signal翻译过来中文就是信号- - 当然, 本身他就是Linux系统编程中非常重要的概念, 信号机制是进程之间传递消息的一种机制, 其全称 ...

  7. Linux常用命令的命名来源

    很多人在学习Linux的时候会疑惑:这么多的Linux名,他们都是怎么被定义的?林纳斯是怎么制定如此花样繁多且数量庞大的命令?今天这篇文章可能会帮你解开疑惑. ## 1. 目录缩写 缩写 | 全称 | ...

  8. python之路之函数03

    一 首先我们学到函数的嵌套调用与定义:1 函数嵌套 # def f1(): # print(f1)#我们这里如果输入f1那么输出的则是f1这个变量(函数)所在的地址.如果输入一个字符的话那么就直接输出 ...

  9. Fork-Join分治编程介绍(一)

    一.Fork-Join 框架介绍 1. 什么是 Fork-Join 分治编程框架   Fork/Join框架是Java7提供了的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每 ...

  10. 8.rem适配

    <!DOCTYPE html> <!--lang="en" : 英语 :声明当前页面的语言类型.--> <html lang="en&quo ...