unity3d new color5.4怎么添加lightmapcolor

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(7772)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'【Unity 3d】Lightmapping烘焙之两套UV的设置方法',
blogAbstract:'一、首先在3D软件中(在此以Maya为例)设置好两套UV。
一套用作普通的UV分布,另一套用作Lightmapping烘焙使用。
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}Unity3D手机游戏开发_百度百科
声明:百科词条人人可编辑,词条创建和修改均免费,绝不存在官方及代理商付费代编,请勿上当受骗。
Unity3D手机游戏开发
《Unity3D手机游戏开发》是2013年清华大学出版社出版的图书,作者是金玺曾。
Unity3D手机游戏开发内容介绍
unity,也称unity3d,是近几年非常流行的一个3d游戏开发引擎,跨平台能力强,使用它开发的手机游戏数不胜数。
《unity3d手机游戏开发》通过三个部分循序渐进地介绍了unity在游戏开发方面的不同功能。第1~5章,由零开始,引导读者从基本的操作到完成三个完整的游戏实例,使读者对unity游戏开发有一个较全面的认识。第6~7章,重点介绍了unity在网络方面的应用。第8~10章介绍了如何将unity游戏移植到网页、和平台。另外,本书最后附有c#语言的快速教程,帮助缺乏程序开发基础的读者快速入门。
《unity3d手机游戏开发》适合广大游戏开发人员,也面向游戏开发爱好者、软件培训机构,以及的学生等。
Unity3D手机游戏开发作者介绍
金玺曾,资深游戏开发工程师,拥有近10年游戏开发经验,3D塔防游戏《野人大作战》主要开发者。曾在上海盛大网络工作,目前在上海爱客士电脑软件有限公司任开发经理。
Unity3D手机游戏开发作品目录
《unity3d手机游戏开发》  第1章 快速入门 1  1.1 unity简介 1  1.2 运行unity 2  1.2.1 unity的版本 2  1.2.2 安装unity 2  1.2.3 在线激活unity 2  1.2.4 运行示例工程 4  1.2.5 安装visual studio 6  1.3 创建一个“hello world”程序 6  1.4 调试程序 9  1.4.1 显示log 10  1.4.2 设置断点 10  小结 11  第2章 太空射击游戏 12  2.1 浅谈游戏开发 12  2.1.1 开始一个游戏项目 12  2.1.2 阶段性成果 12  2.1.3 策划 13  2.1.4 编写脚本 13  .2.1.5 美术 13  2.1.6 qa测试 14  2.1.7 发布游戏 14  2.2 游戏策划 14  2.2.1 游戏介绍 14  2.2.2 游戏ui 14  2.2.3 主角 14  2.2.4 游戏操作 15  2.2.5 敌人 15  2.3 导入美术资源 15  2.4 创建场景 16  2.4.1 创建火星背景 16  2.4.2 设置摄像机和灯光 20  2.5 创建主角 21  2.5.1 创建脚本 21  2.5.2 控制飞船移动 23  2.5.3 创建子弹 25  2.5.4 创建子弹prefab 26  2.5.5 发射子弹 27  2.6 创建敌人 28  2.7 物理碰撞 30  2.7.1 添加碰撞体 30  2.7.2 触发碰撞 32  2.8 高级敌人 34  2.8.1 创建敌人 34  2.8.2 发射子弹 36  2.9 声音与特效 38  2.10 敌人生成器 41  2.11 游戏管理器 43  2.12 标题界面 48  2.13 发布游戏 49  小结 52  第3章 第一人称射击游戏 53  3.1 策划 53  3.1.1 游戏介绍 53  3.1.2 ui界面 53  3.1.3 主角 53  3.1.4 敌人 53  3.2 游戏场景 53  3.3 主角 54  3.3.1 角色控制器 55  3.3.2 摄像机 57  3.3.3 武器 58  3.4 敌人 59  3.4.1 寻路 59  3.4.2 设置动画 63  3.4.3 行为 64  3.5 ui界面 68  3.6 交互 72  3.6.1 主角的射击 72  3.6.2 敌人的进攻与死亡 75  3.7 出生点 78  3.8 小地图 80  小结 84  第4章 塔防游戏 85  4.1 策划 85  4.1.1 场景 85  4.1.2 摄像机 85  4.1.3 胜负判定 85  4.1.4 敌人 85  4.1.5 防守单位 86  4.1.6 ui界面 86  4.2 游戏场景 86  4.3 摄像机 92  4.4 游戏管理器 95  4.5 路点 97  4.6 敌人 102  4.7 敌人生成器 105  4.7.1 在excel中设置敌人 105  4.7.2 创建敌人生成器 109  4.8 防守单位 115  4.9 生命条 119  4.10 自定义按钮 124  小结 131  第5章 资源创建 132  5.1 光照 132  5.1.1 光源类型 132  5.1.2 环境光与雾 134  5.1.3 lightmapping 135  5.1.4 light probe 137  5.2 terrain 139  5.3 skybox 142  5.4 粒子 144  5.5 物理 148  5.6 自定义shader 150  5.6.1 自定义字体 151  5.6.2 创建shader 152  5.7 贴图 155  5.8 3d模型导出流程 155  5.8.1 3ds max静态模型导出 155  5.8.2 3ds max动画模型导出 157  5.8.3 3ds max动画导出 158  5.8.4 maya模型导出 158  5.9 动画 159  5.10 优化 163  小结 163  第6章 与web服务器的交互 164  6.1 建立服务器 164  6.1.1 安装apache 164  6.1.2 安装mysql 166  6.1.3 安装php 169  6.1.4 显示php信息 171  6.1.5 调试php代码 172  6.2 www基本应用 174  6.2.1 http协议 174  6.2.2 get请求 175  6.2.3 post请求 176  6.2.4 上传下载图片 178  6.2.5 下载声音文件 180  6.3 自定义数据流 180  6.3.1 c#版本的数据流 181  6.3.2 php版本的数据流 188  6.3.3 测试 192  6.4 分数排行榜 195  6.4.1 创建数据库 195  6.4.2 创建php脚本 196  6.4.3 上传下载分数 199  小结 202  第7章 基于tcp/ip协议的聊天实例 203  7.1 tcp/ip开发简介 203  7.2 网络引擎 204  7.2.1 数据流 204  7.2.2 数据包 214  7.2.3 逻辑处理 215  7.2.4 定义消息标识符 217  7.2.5 客户端 217  7.2.6 服务器端 224  7.3 聊天客户端 229  7.4 聊天服务器端 234  7.5 收发结构体 238  7.6 protobuf简介 242  小结 244  第8章 用unity创建网页游戏 245  8.1 网页游戏简介 245  8.2 unity web 游戏 245  8.2.1 streaming关卡 245  8.2.2 上传游戏到kongregate 249  8.2.3 与网页通信 251  8.2.4 在网页上记录积分 253  8.2.5 自定义网页模板 254  8.2.6 自定义启动画面 258  8.3 flash游戏 259  8.3.1 软件安装 260  8.3.2 导出flash游戏 260  8.3.3 调试flash游戏 261  8.3.4 从flash工程读取unity 导出的flash游戏 261  8.3.5 在unity内调用as3代码 267  8.3.6 flash版本的太空射击游戏 271  8.4 assetbundle 274  8.4.1 打包资源 275  8.4.2 下载资源 276  8.4.3 安全策略 279  小结 280  第9章 将unity游戏移植到ios平台 281  9.1 ios简介 281  9.2 软件安装 281  9.3 申请开发权限 281  9.4 设置ios开发环境 282  9.5 测试ios游戏 286  9.6 发布ios游戏 288  9.6.1 申请发布证书 288  9.6.2 创建新应用 288  9.6.3 提交审核 290  9.7 集成game center 291  9.7.1 xcode到unity 291  9.7.2 设置高分榜和成就 297  9.7.3 实现game center功能 299  9.8 集成内消费系统 309  9.8.1 设置内消费 309  9.8.2 实现内消费 310  9.9 本地存储位置 317  小结 317  第10章 将unity游戏移植到android平台 318  10.1 android简介 318  10.2 软件安装 318  10.3 运行android游戏 320  10.3.1 设置android手机 320  10.3.2 安装驱动程序 320  10.3.3 设置android游戏工程 323  10.3.4 测试android游戏 327  10.3.5 发布android游戏 327  10.4 触屏操作 329  10.5 从eclipse到unity 333  10.5.1 创建.jar文件 334  10.5.2 导入.jar到unity 337  10.6 从unity到eclipse 339  10.6.1 导出eclipse工程 339  10.6.2 设置导出的eclipse工程 340  10.6.3 创建用于发布的eclipse工程 341  10.6.4 发布程序 346  10.7 自定义activity 347  小结 350  附录a c#语言 351  a.1 c#基础 351  a.2 面向对象编程 361  a.3 字符串 368  a.4 数组 370  a.5 i/o操作 372  a.6 委托 376  小结 381  附录b 特殊文件夹 382
.豆瓣读书[引用日期]  本文主要介绍Untiy5以后的GI,PBS,以及光源探头,反射探头的用法以及在着色器代码中如何发挥作用,GI是如何影响渲染的,主要分成三个部分,最开始说明PBS需要的材质与相应概念,二是Unity&里相应GI的操作,三是对应着色器代码的理解。如果没有特殊声明,所有操作与代码都是针对Unity5.3.
PBS材质与概念
  简单来说,PBS的优点不同的照明下获得一致的外观,更容易实现,更直观的参数。
PBS材质概念:
  1.albedo&反照率&
  反照率贴图定义漫反射的基本颜色,与原来的漫反射贴图相比,不包含定向光与AO,在这我们应该由环境自己的定向光与AO来影响,Unity里,我们用GI得到相应烘培或是实时的方向光与AO。
  2.Smoothness/Microsurface&表面细节&材料细节&光滑度
  光滑度:描述物体微表面的一个参数,可以用来定义法线分布函数,这样,粗糙的表面呈现宽,淡的镜面反射,光滑呈现集中和明亮的镜面反射。
  3.Metal/reflectivity&金属性/反射&
  金属与绝缘体应该使用不同的反射设置,导体的反射率&60-90%,绝缘体0-20%,高反射光分子不容易到达内部和散射,这样金属的高表现出来比较淡。
  如下全局设置:
  对于固定的材料,反射率趋于稳定,这样一般来说,一个模型的metal相对变化较少,如泥,水,木头这些他们的反射率相关并不大,只有金属与绝缘体会有相对比较大的反差,而模型表面的粗糙度应该用上面的图光滑性来表示,这个相对变化会比较大些,如下,水和泥土有相似的金属性(反射率),但是光滑度相差大,所以相差比较明显。
  上图来自pbr-theory:&
  Unity中事项,Metallic&贴图,金属性质占用R通道,光滑性占用A通道,GB被忽略。  
  物体的本来颜色用albedo表示,光滑性用Smoothness表示,材质特性用Metal表示,其中Unity&二种PBS标准着色,Standard其中金属性越高,本身镜面颜色占比越高,灯光的颜色占比越低,而高光可以设置自己的镜面反射。
  PS: pbr-practice& 
BRDF&光照模型&概念
  1&能量守恒:一个对象不能反射比他接收的光多。
  粗糙的材料有更多比较淡的亮点,而光滑的材料有更集中,更明亮的亮点,也可以这么理解,漫反射越多,镜面反射相对越少,镜面反射越多,漫反射越少。
  2&菲涅尔效应:边缘的反射更亮。
  更具体的可以看:
  3&微表面模型模型:
  普通的着色模型假定着色的区域是一个平滑的表面,表面有一个法线,而微表面则认为,着色区域是一个无数比入射光线覆盖范围更小的微小表面组成的粗糙区域,这个微小表面是光滑的镜面反射。表面细微细节对扩散的影响,表面越粗糙,反射光越发散或模糊。
GI结合BRDF渲染
  GI全局照明指的是全局照明会模拟光线在场景中的多次反射,所有的东西都是一个潜在的光源,任何可见的模型不是辐射光线,就是反射光线,其中GI(渲染间接光源,本身一般也用BRDF渲染)&配合BRDF生成带灯光直射,环境内模型互想影响的逼真场景。 &
  天空盒是GI的组成部分,反射天空盒可以改变场景所有模型接受反射量。
  GI结合PBS,如下,摄像机的镜头是一样的材质,在不同的环境下:
  更详细的可以点进这个链接:&&
  全局光照的特点在于能够捕捉间接光照,所以5以后,除开原来的direct&light的效果,增加indirect&light的效果,简单来说,就是除开光源之后,然后模型本身做为光源,幅射到别的模型上,层层递归后的效果。现不管是预计算实时GI还是烘培GI都只是针对静态模型。预计算Gi的实时光源与烘陪对应的烘培光源里的强度与反射强度都会影响幅射图与方向图的内容。需要注意,预计算Gi针对的是实时方向光,而烘培GI针对的是烘培方向光。
  Skybox&:天空盒,参考材质Skybox/Cubemap,如果全局光源与全局反射探头都选择Skybox模式,则会把Skybox当做一个Cubemap,场景所有模型,静态与非静态的一部分光源从这个Cubemap反射上得到。
  Sun:Skybox选择一个方向光,以这个方向光的方向做方向,这个方向光如颜色与强度不影响全局本身,如果没有设置方向光,选择强度最大的那个方向光源。&
  Ambient&Source:全局光源,如果设置天空盒,但是天空盒本身没有设置,自动选择下面的全局颜色设置,全局反射探头以Ambient&Source当做光源。
  Ambient&Intensity:全局光源强度,越高越亮,为0时,光源不起作用。
  Ambient&GI:当预计算GI与烘培GI二个都选择后,这个可以选择是用实时还是烘培。&
  Reflection&Source:Unity默认放入的全局反射探头,选择Skybox会以Ambient&Source里提供的光源颜色做反射,同时也可以自己提供cubemap当做反射源。
  Resolution:反射探头解析度,应该是对应RTT的cubemap六张纹理的分辨率。
  Compression:是否压缩。
  Reflection&Intensity:Reflection&Source针对所有模型反射强度,值越大,相应的模型面上显示越清晰的Reflection&Source。
  Reflection&Bounces:当设置多个Reflection&Probe时,互相反射对方信息的次数,如二面镜子。
  Precomputed&Realtime&GI
  预计算实时GI,针对实时静态物体之间的幅射光,故相应的幅射图与方向图都是低分辨率下的。动态物体可以使用光照探头来得到相应反射光源信息,注意动态模型与光探头的距离。
  Realtime&Resolution:预计算实时GI,把场景分成许多格,得到每个格的幅射信息。那么这个值越高,计算量将以平方增加,最终值还将和General&GI里的光源参数里的Resolution相乘。
  CPU&Usage:生成相应GI的数据时,在游戏运行时分配多少CPU计算能力。&
  Baked&GI
  烘培GI,因此能得到更精确的模型之间的反射光信息,但是不能运行时更改相应的光源信息,如颜色,方向,预计算实时GI没有这个问题。
  Baked&Resolution:一般来说,是Realtime&Resolution&10+,因为相应的幅射图与方向图精确度要高很多。
  Baked&Padding:网上说是光照贴图中分隔的距离,还需要验证。
  Compressed:是否压缩
  Ambient&Occlusion:值越高,遮挡地区得到的光比差越大。
  Final&Gather:用FG技术来产生烘培数据,这种技术时间会长一些。参考
  Ray&Count:Final&Gather所用的光线追踪光线数目。
  Atlas&Size:图集里贴图的大小,越低实际占用越精确也就是越小,但是贴图产生越多,应该选择一个合适的大小。&  
  General&GI
  预计算实时GI还是烘培如何生成.
  Direction&Mode:幅射图/带方向光/加镜面,具体看Shader分析,其中预计算实时GI与烘培GI在这生成的相应幅射图,方向图等有所不同,后面会提到。
  Indirect&Intensity:间接光的强度。
  Default&Parameters:生成相应贴图所需要的信息。
  其中全局预计算GI,烘培GI,全局反射探头相应的改动需要重新烘培,如果选择自动,相关改动会自动在后台烘培。
  上面这些说实话,写这么操作没啥用,自己对着每项实践一篇,什么都清楚了。&
Light&Probe:&
  对于GI来说,不管是预计算GI与烘培GI,都不会对非静态模型计算间接反射,光探头的加入,可以使非静态模型得到周围静态模型的幅射光,主要技术原理使用一种球谐光照的技术,注意light probe一般不会对静态模型有影响,你看到的影响,只是因为非静态模型的颜色变化大造成的反差。
  相关球谐光照的技术原理可以参见,本人也看不懂,只能说看了后有点印象是怎么回事:
  一种2D傅立叶级数的球形推广,可以把光照函数展开成SH基函数的叠加,类似傅立叶变换能把任何函数展开成正弦波的叠加,对光照图来说一般只用2&bands&=&4&RGB&textures,通过丢失高频细节来压缩存储。  
Reflection&Probe:
  定义一个Cubemap用来影响周围模型的镜面反射,给镜面高光模型使用。
  一般来说,我们想得到一个实时场景的Cubemap,只需要在一个点,用摄像机对着前后,左右,上下,各拍摄一次,形成6个面,组合成Cubemap.
  Type:烘培,用户,自动。其中,烘培就是用户来控制生成一个当前的场景cubemap,用户就是用户自己提供一个cubemap,实时就是不断更新这个cubemap以映射最新的场景。
  当选择实时,Refresh&mode:On&&awake启动时,每桢,用户脚本控制,当每桢时,如下选择。
  Time&slicing:一桢先生成6个面,后面8桢每桢生成一个mipmap,一共9桢。
  Individual&face:6面6桢,加后面8桢每个mipmap,一共14桢。
  No&time&slicing:一桢内把mipmap与cubemap全部生成。
  Importance:当多个反射探头影响一个模型时,这个参数影响这个反射探头的比重。
  Intensity:间接光强度,强度影响镜面反射,镜面反射越亮。
  Box&Projection:从着色代码来看,应该根据当前反射探头的源点与AABB影响是模型原来法线。
  Size:大小,范围内的模型使用这个。
  Probe&Origin:原点。
  Cubemap&capture&sttings:
  Resolution:cubempa材质的大小。
  HDR:高光。
  Shadow&Distance:阴影距离,数值越少,阴影越近。
  下面就是RTT对应摄像机的属性。
GI间接光源算法:辐射度算法
  辐射度算法就是:把场景细分到很细很细的面片(如1个像素那么大的三角形),分别计算它们接受和发出的光能,然后逐次递归,直到每个面片的光能数据不再变化(或者到一定的阀值)为止.因此,计算量很大(要计算很多次),而且难以并行(因为递归),参考
  Unity中GI选择non-direction模式生成的辐射度,使用一张图,储存每个位置收到的间接光照,其中假定都只是扩散,没有镜面反射。&
GI&Directional&LightMap算法:
  把半球面的入射辐射度用某种方法进行采样,保存起来在运行时根据法线图中的法线方向来进行一次合成,由于带方向信息,也可以支持高光计算了,可以参考:
  Unity中GI选择direction模型,会在上面辐射图添加一张图,用来存储接收到的光的方向选择specular,烘培GI与预计算GI使用不同的方式,烘培GI在上面二张图各扩大一倍,原来的保存直接光的影响,新增加的位置用来保存间接光的影响,其中预计算GI新增加一张贴图,三张图分别保存辐射光照,光源方向,法线,需要结合实时方向光源。
  探讨Unity5中全局光照(Enlighten)&
  Unity&5.0新功能教学:
  Unity&5&中的全局光照技术详解&
  Unity5&官网文档GI三种模式具体区别&
Unity&GI&BRDF&Shader
  主要参考对照如下Shader文件:
  UnityStandardCore.cginc:前向渲染base,顶点着色入口vertForwardBase,片断着色入口fragForwardBase,这个是着色器的主要Pass,全局方向光,GI信息合并都在这个pass中。
  UnityStandardBRDF.cginc:BRDF的具体实现.
  UnityGloballllumination.cginc:提取GI信息,包含烘陪GI与预计算GI。
  预计算Gi针对的是实时方向光,而烘培GI针对的是烘培方向光,所以当说预计算GI的light时,指的是实时方向光,而烘培GI的light说的是烘培方向光。
  相应主要代码我都已经加上注释,相信还是比较容易看懂的。
1 ---------UnityStandardCore
2 //顶点着色器入口
3 VertexOutputForwardBase vertForwardBase (VertexInput v)
VertexOutputForwardB
UNITY_INITIALIZE_OUTPUT(VertexOutputForwardBase, o);
//世界坐标下位置
float4 posWorld = mul(_Object2World, v.vertex);
#if UNITY_SPECCUBE_BOX_PROJECTION
o.posWorld = posWorld.
//屏幕空间位置
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.tex = TexCoords(v);
o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
#ifdef _TANGENT_TO_WORLD
float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
o.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
o.tangentToWorldAndParallax[0].xyz = 0;
o.tangentToWorldAndParallax[1].xyz = 0;
o.tangentToWorldAndParallax[2].xyz = normalW
//We need this for shadow receving
TRANSFER_SHADOW(o);
// Static lightmaps
#ifndef LIGHTMAP_OFF
//开启烘培GI后
o.ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.
o.ambientOrLightmapUV.zw = 0;
// Sample light probe for Dynamic objects only (no static or dynamic lightmaps)
//光源探头对动态模型的影响,rgb(颜色)根据SH系数还原光源探头与不重要的点光源上的颜色信息
#elif UNITY_SHOULD_SAMPLE_SH
#if UNITY_SAMPLE_FULL_SH_PER_PIXEL
o.ambientOrLightmapUV.rgb = 0;
#elif (SHADER_TARGET & 30)
o.ambientOrLightmapUV.rgb = ShadeSH9(half4(normalWorld, 1.0));
// Optimization: L2 per-vertex, L0..L1 per-pixel
o.ambientOrLightmapUV.rgb = ShadeSH3Order(half4(normalWorld, 1.0));
// Add approximated illumination from non-important point lights
#ifdef VERTEXLIGHT_ON
o.ambientOrLightmapUV.rgb += Shade4PointLights (
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
unity_4LightAtten0, posWorld, normalWorld);
//开启预计算GI后
#ifdef DYNAMICLIGHTMAP_ON
o.ambientOrLightmapUV.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.
#ifdef _PARALLAXMAP
TANGENT_SPACE_ROTATION;
half3 viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
o.tangentToWorldAndParallax[0].w = viewDirForParallax.x;
o.tangentToWorldAndParallax[1].w = viewDirForParallax.y;
o.tangentToWorldAndParallax[2].w = viewDirForParallax.z;
UNITY_TRANSFER_FOG(o,o.pos);
72 //片断着色器入口
73 half4 fragForwardBase (VertexOutputForwardBase i) : SV_Target
FRAGMENT_SETUP(s)
UnityLight mainLight = MainLight (s.normalWorld);
half atten = SHADOW_ATTENUATION(i);
half occlusion = Occlusion(i.tex.xy);
//提取GI里的信息到UnityGI中。
UnityGI gi = FragmentGI (
s.posWorld, occlusion, i.ambientOrLightmapUV, atten, s.oneMinusRoughness, s.normalWorld, s.eyeVec, mainLight);
// 如果是预计算GI或动态模型,gi.light表示主光源,焙烘取
half4 c = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect);
// GI生成类型是spceular,才会计算
c.rgb += UNITY_BRDF_GI (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, s.normalWorld, -s.eyeVec, occlusion, gi);
c.rgb += Emission(i.tex.xy);
UNITY_APPLY_FOG(i.fogCoord, c.rgb);
return OutputForward (c, s.alpha);
93 //填充UnityGIInput,用来得到UnityGI信息。
94 inline UnityGI FragmentGI (
float3 posWorld,
half occlusion, half4 i_ambientOrLightmapUV, half atten, half oneMinusRoughness, half3 normalWorld, half3 eyeVec,
UnityLight light)
d.worldPos = posW
d.worldViewDir = -eyeV
//如果有GI信息。
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
d.ambient = 0;
d.lightmapUV = i_ambientOrLightmapUV;
//一般来说,非静态模型,得到环境光
d.ambient = i_ambientOrLightmapUV.
d.lightmapUV = 0;
//全局反射探头的AABB
d.boxMax[0] = unity_SpecCube0_BoxM
d.boxMin[0] = unity_SpecCube0_BoxM
d.probePosition[0] = unity_SpecCube0_ProbeP
d.probeHDR[0] = unity_SpecCube0_HDR;
//用户定义的反射探头AABB
d.boxMax[1] = unity_SpecCube1_BoxM
d.boxMin[1] = unity_SpecCube1_BoxM
d.probePosition[1] = unity_SpecCube1_ProbeP
d.probeHDR[1] = unity_SpecCube1_HDR;
return UnityGlobalIllumination (
d, occlusion, oneMinusRoughness, normalWorld);
130 --------UnityGloballllumination.cginc
131 //FragmentGI 跳转到这
132 inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half oneMinusRoughness, half3 normalWorld, bool reflections)
UnityGI o_
UNITY_INITIALIZE_OUTPUT(UnityGI, o_gi);
// Explicitly reset all members of UnityGI
ResetUnityGI(o_gi);
//动态模型使用 SH得到的漫反射信息。
#if UNITY_SHOULD_SAMPLE_SH
#if UNITY_SAMPLE_FULL_SH_PER_PIXEL
half3 sh = ShadeSH9(half4(normalWorld, 1.0));
#elif (SHADER_TARGET &= 30)
half3 sh = data.ambient + ShadeSH12Order(half4(normalWorld, 1.0));
half3 sh = data.
o_gi.indirect.diffuse +=
//如果没有烘培GI,需要当前全局方向光源的信息
#if !defined(LIGHTMAP_ON)
o_gi.light = data.
//atten阴影信息,值越小阴影越重
o_gi.light.color *= data.
// Baked lightmaps
fixed4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
half3 bakedColor = DecodeLightmap(bakedColorTex);
//没有方向贴图
#ifdef DIRLIGHTMAP_OFF
//设置漫反射
o_gi.indirect.diffuse = bakedC
#ifdef SHADOWS_SCREEN
o_gi.indirect.diffuse = MixLightmapWithRealtimeAttenuation (o_gi.indirect.diffuse, data.atten, bakedColorTex);
#endif // SHADOWS_SCREEN
//方向与漫反射
#elif DIRLIGHTMAP_COMBINED
fixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER (unity_LightmapInd, unity_Lightmap, data.lightmapUV.xy);
//更精准的漫反射
调整过后的half Lambert
o_gi.indirect.diffuse = DecodeDirectionalLightmap (bakedColor, bakedDirTex, normalWorld);
#ifdef SHADOWS_SCREEN
o_gi.indirect.diffuse = MixLightmapWithRealtimeAttenuation (o_gi.indirect.diffuse, data.atten, bakedColorTex);
#endif // SHADOWS_SCREEN
//漫反射,方向,高光
#elif DIRLIGHTMAP_SEPARATE
// Left halves of both intensity and direction lightmap right halves - indirect.
// Direct 调整o_gi.light
fixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, data.lightmapUV.xy);
o_gi.indirect.diffuse += DecodeDirectionalSpecularLightmap (bakedColor, bakedDirTex, normalWorld, false, 0, o_gi.light);
// Indirect 漫反射,镜面都是保存在unity_Lightmap中,竖直中间分开
//调整o_gi.light2
half2 uvIndirect = data.lightmapUV.xy + half2(0.5, 0);
bakedColor = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, uvIndirect));
bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, uvIndirect);
o_gi.indirect.diffuse += DecodeDirectionalSpecularLightmap (bakedColor, bakedDirTex, normalWorld, false, 0, o_gi.light2);
//预计算GI
#ifdef DYNAMICLIGHTMAP_ON
// Dynamic lightmaps unity_DynamicLightmap unity_DynamicDirectionality unity_DynamicNormal
fixed4 realtimeColorTex = UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, data.lightmapUV.zw);
//间接漫反射
half3 realtimeColor = DecodeRealtimeLightmap (realtimeColorTex);
#ifdef DIRLIGHTMAP_OFF
o_gi.indirect.diffuse += realtimeC
#elif DIRLIGHTMAP_COMBINED
half4 realtimeDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, data.lightmapUV.zw);
//调整漫反射
o_gi.indirect.diffuse += DecodeDirectionalLightmap (realtimeColor, realtimeDirTex, normalWorld);
#elif DIRLIGHTMAP_SEPARATE
half4 realtimeDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, data.lightmapUV.zw);
half4 realtimeNormalTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicNormal, unity_DynamicLightmap, data.lightmapUV.zw);
//调整o_gi.light3
o_gi.indirect.diffuse += DecodeDirectionalSpecularLightmap (realtimeColor, realtimeDirTex, normalWorld, true, realtimeNormalTex, o_gi.light3);
//gi里的信息全放入indirect的diffuse中
o_gi.indirect.diffuse *=
//有反射探头,设置镜面光源信息。
if (reflections)
half3 worldNormal = reflect(-data.worldViewDir, normalWorld);
#if UNITY_SPECCUBE_BOX_PROJECTION
half3 worldNormal0 = BoxProjectedCubemapDirection (worldNormal, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
half3 worldNormal0 = worldN
half3 env0 = Unity_GlossyEnvironment (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], worldNormal0, 1-oneMinusRoughness);
#if UNITY_SPECCUBE_BLENDING
const float kBlendFactor = 0.99999;
float blendLerp = data.boxMin[0].w;
UNITY_BRANCH
if (blendLerp & kBlendFactor)
#if UNITY_SPECCUBE_BOX_PROJECTION
half3 worldNormal1 = BoxProjectedCubemapDirection (worldNormal, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);
half3 worldNormal1 = worldN
half3 env1 = Unity_GlossyEnvironment (UNITY_PASS_TEXCUBE(unity_SpecCube1), data.probeHDR[1], worldNormal1, 1-oneMinusRoughness);
o_gi.indirect.specular = lerp(env1, env0, blendLerp);
o_gi.indirect.specular = env0;
o_gi.indirect.specular = env0;
//反射探头的信息存入到gi的indirect镜面中
o_gi.indirect.specular *=
262 --------UnityStandardBRDF.cginc
263 // Main Physically Based BRDF
264 // Derived from Disney work and based on Torrance-Sparrow micro-facet model
BRDF = kD / pi + kS * (D * V * F) / 4
I = BRDF * NdotL
269 // * NDF (depending on UNITY_BRDF_GGX):
a) Normalized BlinnPhong
272 // * Smith for Visiblity term
273 // * Schlick approximation for Fresnel
274 half4 BRDF1_Unity_PBS (half3 diffColor, half3 specColor, half oneMinusReflectivity, half oneMinusRoughness,
half3 normal, half3 viewDir,
UnityLight light, UnityIndirect gi)
half roughness = 1-oneMinusR
//nh,能射入眼睛的光线的角度 也叫半线
half3 halfDir = Unity_SafeNormalize (light.dir + viewDir);
half nl = light.
//nh,半线与法线夹角,夹角越少,射入眼睛的光越大
half nh = BlinnTerm (normal, halfDir);
//射线与法线夹角
half nv = DotClamped (normal, viewDir);
//光线与法线夹角
half lv = DotClamped (light.dir, viewDir);
//半线与光线夹角
half lh = DotClamped (light.dir, halfDir);
291 #if UNITY_BRDF_GGX
//遮挡函数
half V = SmithGGXVisibilityTerm (nl, nv, roughness);
//法线分布函数 1/Pi
half D = GGXTerm (nh, roughness);
//遮挡函数
half V = SmithBeckmannVisibilityTerm (nl, nv, roughness);
//法线分布函数 1/Pi
half D = NDFBlinnPhongNormalizedTerm (nh, RoughnessToSpecPower (roughness));
301 #endif
half nlPow5 = Pow5 (1-nl);
half nvPow5 = Pow5 (1-nv);
half Fd90 = 0.5 + 2 * lh * lh *
//disney Diffuse 菲涅尔 边角有更亮的光
half disneyDiffuse = (1 + (Fd90-1) * nlPow5) * (1 + (Fd90-1) * nvPow5);
// HACK: theoretically we should divide by Pi diffuseTerm and not multiply specularTerm!
// BUT 1) that will make shader look significantly darker than Legacy ones
// and 2) on engine side "Non-important" lights have to be divided by Pi to in cases when they are injected into ambient SH
// NOTE: multiplication by Pi is part of single constant together with 1/4 now
//镜面系数
half specularTerm = max(0, (V * D * nl) * unity_LightGammaCorrectionConsts_PIDiv4);// Torrance-Sparrow model, Fresnel is applied later (for optimization reasons)
half diffuseTerm = disneyDiffuse *
//Gi镜面,可以看到oneMinusReflectivity越高,grazingTerm越低,specColor越高(本身镜面颜色)
half grazingTerm = saturate(oneMinusRoughness + (1-oneMinusReflectivity));
//GI non-direction与direction的BRDF如下情况
//light.color
实时方向光直接信息
实时方向光直接信息
//gi.diffuse
直接与间接光源信息
间接光源信息
SH(光源探头)间接光源信息
//gi.specular
half3 color =
diffColor * (gi.diffuse + light.color * diffuseTerm)
+ specularTerm * light.color * FresnelTerm (specColor, lh)
+ gi.specular * FresnelLerp (specColor, grazingTerm, nv);
return half4(color, 1);
  整个代码并不多,但是对于前面所说所有东东,在这都有一个完整的解释,这份代码来告诉我们,那些金属性,光滑度,GI中幅射图,方向图,还有光源探头,反射探头所起的作用。
BRDF&光照模型:
  如下是现有光照模型没有考虑的问题:
  光照现象,漫反射并不是各个方面平均发散. & &----微表面模型(NDF).&&
  菲涅尔定理(Fresnel) & & & & & & & & & & & & & & &&&----光源在边角处有更明亮的反光。
  能量守恒,反射的光不能超过入射的光. & & & & &----遮挡因素,越光滑镜面越集中越亮&
  普通的着色模型假定着色的区域是一个平滑的表面,表面有一个法线,而微表面则认为,着色区域是一个无数比入射光线覆盖范围更小的微小表面组成的粗糙区域,这个微小表面是光滑的镜面反射,因为着色区域并不能一个法向量来表示表面的方向,转面代替用一概率分布函数(NDF)来表示。一般来说,分别用如下字母表示:
  D&用来表示法线分布。
  F&用来菲涅尔影响,光源在边角处有更明亮的反光。
  G/V&用来表示凹凸表面间的遮挡因素(Unity用V来表示)&
  如下是Unity相对应BRDF的处理
  先要说明每个引擎对BRDF处理各不同,在这只介绍Untiy的实现:
  D&采用GGX与BlinnPhong二种法线分布函数,BlinnPhong比较简单,效率高。
  F&采用简化的Disney&Fresnel方式求得菲涅尔影响。
  G/V&采用GGX与Beckmann二种技术,可以看到,光滑度是个关键参数。
  针对Unity5.3简化过的Disney&Fresnel,简单分析下.
  Nl:法线与灯光的夹角,夹角越大,这个值越小。
  Nv:法线与视线的夹角,夹角越大,这个值越小。
  Lh:灯光与视线的半线与法线的夹角,其中灯光与视线的半线就是灯光与视线的平均线,简单来说,这个线与法线重合,这条由灯光发出来的射线才能进入我们的眼镜。
  假定&fd90不变,nl与nl的角度越大,那么nlPow5与nvPow5的值越大,最终结果越大,这也是菲涅尔想表达的,光源在边角处有更明亮的反光。
  在Unity中,可以看到,D与V影响镜面反射,F影响漫反射,特别说明,只有Unity是这样处理。
  其中,可以看到反射率(也就是金属性)影响的是GI的镜面反射,也就是反射探头。
  其余的部分挑的说明下:
  顶点着色器中,填充VertexOutputForwardBase&信息,其中ambientOrLightmapUV(half4)&如果包含烘培GI,xy填充相应烘培GI的UV坐标,如果包含预计算GI,zw填充为预计算GI的UV坐标。如果是非静态模型,不包含GI信息,相应light&probe提供的光源信息放入rgb中。&
  片断着色器中,每个像素要得到对应像素上的Unity&GI信息,相应的,Unity&GI中的属性light并不是表示光源,而是当前像素受如主光源,幅射,镜面对当前像素的影响,每个像素对应的light都有差别,千万不要看到写的是个light,就把它当做光照,这样所有理解都不对了。
  其中如果只有烘培GI,当前像素的Unity&GI中参数light不提供信息,indirect里的漫反射包含烘培光源的光照。而预计算GI中当前像素的light本身就是全局光源,indirect只包含物体之间的漫反射信息,而非静态模型中当前像素只有实时光源等直接光照信息,其周围的静态模型的反射光只有通过光探头得到SH信息。
  FragmentGI里常见结构:
  1 UnityLight:
  包含当前像素中光源颜色,方向,法线与光源方向点积
  2 UnityIndirect:
  包含当前像素中diffuse漫反射,specular镜面信息
  3 UnityGI:特别注意,里面的light是UnityLight类型,并不表示光源,而是用来表示当前像素受光源影响的量。
  Gi.light&如果烘陪GI信息,则使用当前主光源填充UnityLight,如果有烘陪GI信息,则填充为空。
  Gi.light2&当烘培GI启用高光后,才会调用。
  Gi.light3&预计算GI启用高光后,才会调用。
  UnityGI在根据函数UnityGlobalIllumination被填充,我们可以分析得到动态模型,使用SH得到漫反射信息。如果没有烘培GI,我们需要实时全局光源,故gi.light是像素所受全局方向光。烘培GI,GI光照信息保存在gl.light2中,gi漫反射直接取光照图里的diffuse.预计算GI,GI光照信息保存在gl.light3中,gi漫反射添加光照图里的diffuse.而反射探头用来添加反射的信息到GI里的镜面信息中了,其中Occlusion&控制gi的diffuse与specular系数。(n*=occlusion)&   
  其中UNITY_SHOULD_SAMPLE_SH&当前渲染的动态模型,使用SH得到间接的漫反射信息,其中UNITY_SHOULD_SAMPLE_SH如下定义。#define&UNITY_SHOULD_SAMPLE_SH&(&defined&(LIGHTMAP_OFF)&&&&defined(DYNAMICLIGHTMAP_OFF)&)&
  预计算GI与烘培GI
  烘培GI如上代码中分析得到,选择non-direction,只有一张图,保存直接与间接光照所有信息,选择direction后,会保存方向,选择specular后,上面二张图,长度扩大一倍,保存镜面有关信息。
  其中预计算GI,选择non-direction,只有一张图,不保存直接光照,只保存间接光照,选择direction,保存方向,选择specular后,不同于烘培GI,会新增一张纹理保存镜面相关信息(从代码来上看,可能是组织过的法线)&
  反射探头:
  unity_SpecCube0_ 全局反射探头&unity_SpecCube1_当前模型受影响的反射探头。
  FragmnetGI:得到全局反射探头与用户定义的反射探头位置,AABB,IsHDR.
  UnityGlobalIllumination:片断像素中得到反射探头影响镜面值,可以看到,SpecCube0与SpecCube1通过深度影响gi间接光源上的镜面颜色。
  BoxProjectedCubemapDirection:影响worldNormal(反视线进过法线后的反射)
  Unity_GlossyEnvironment:可以看到&,光滑值影响LOD值,越光滑越清晰。 UNITY_SAMPLE_TEXCUBE&从cubemap取值。&
  光源探头:
  vertForwardBase:VertexOutputForwardBase的ambientOrLightmapUV设置颜色,从这可以看到,光源探头实际不影响静态的物体,你如果看到有影响,只是因为周围的非静态模型颜色反差造成给你的影响。
  UnityGlobalIllumination:灯光探头的值赋到gi间接光源上的漫反射上。
  :今天看UE4中的环境反射文档,我去,Unity里的做法完全是参照UE4的,通过上面的着色器代码,我们可以完全理解下面这个链接里所说的。
阅读(...) 评论()}

我要回帖

更多关于 unity3d color 16进制 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信