2017-02-21 17:37:25 e295166319 阅读数 904
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

上篇给大家解答了:为什么场景烘焙出来的lightmap上有Realitime灯光的颜色?为什么在Unity 5中动态更换lightmap没有作用? 这两个问题。今天,我们继续给大家解答Unity 5 全局光照系统Enlighten中的其他常见问题。

为什么烘焙的point灯光会有一圈圈的色阶变化?

   大家在烘焙lightmap的时候可能会发现类似下图的奇怪效果。


   图中我们使用了一盏Baked的point light,烘焙之后发现光照效果会出现一圈圈的色阶突变。

   原因是我们使用的是压缩版本的lightmap。如下图Lighting窗口中选项所示:


   这个压缩虽然可以帮助我们减少游戏最后的打包体积,但是对场景的光照效果也会产生影响,所以对于要追求最好的光照效果的场景建议不要勾选此选项。

   最后我们来看看去掉此选项后的效果,现在,色阶变化不存在了。


为什么在Realtime灯光下的效果和改为Baked烘焙的效果差别很大?

    这个的问题美术同学会经常遇见。美术同学一般在烘焙场景之前会先把灯光都设为Realtime,来实时查看调整灯光参数后的效果。调整到较满意的效果之后,就把灯光类型改为Baked然后进行烘焙。
   
   在Unity 4中这样做一般可以达到烘焙之后的效果与实时灯光的效果比较接近,但是在Unity 5中可能会发现差别很大。究其原因主要有二点。

   1、在上面我们已经提到,新的灯光参数Bounce Intensity,这个参数的调整会影响最终烘焙效果中间接光分量的比例。
   2、Unity 5中对Gamma和Linear颜色空间的实现做了调整以更符合真实情况,但这也导致实时灯光效果与烘焙效果在两种颜色空间中存在差异。

   所以,建议美工同学在Linear颜色空间中进行Realtime灯光的调整。因为在Linear颜色空间下,实时灯光与烘焙效果最为接近。不过由于目前移动平台并不支持颜色空间切换,我们可以让项目在PC平台下切换为Linear颜色空间。该选项在Player Settings中的Other Settings里,如下图所示:



   另外,为了让Bounce Intensity参数的调整也能反映在Realtime灯光中,建议美术同学在实时调整灯光参数的时候在Lighting窗口中勾选Precomputed Realtime GI,如下图所示:


当然Precomputed Realtime GI也是需要在场景静态物体的位置固定之后烘焙一次的,所以如果怕会忘记烘焙的话也可以勾选Build旁边的Auto选框。

    最后,在调整好灯光效果之后我们把灯光类型改为Baked(或Mixed),取消勾选Precomputed Realtime GI,并勾选Baked GI,然后进行烘焙。
下面展示了两种颜色空间下Realtime灯光与烘焙效果的对比:



    我们可以看到Linear颜色空间下两种光照方式的效果是最为接近的。

    另外还有朋友曾经咨询:项目的场景在手机上的烘焙效果与Editor中看到的实时灯光的差异非常的大,已经远远比上面对比图中的差别要大了。

     如果大家也有这样的问题,那么请注意:不同的屏幕对于同一种颜色的表现都会有或多或少的差别,要对比手机与电脑上看到的颜色差别不能直接进行对比,而应该让两个效果在同一个屏幕中对比。一个简单的办法是在手机中截屏然后传到电脑中进行对比。感兴趣的同学可以尝试,保证你一定会为手机与电脑屏幕的颜色解析差异感到惊讶。

怎么让不同物体占用不同数量的lightmap像素?

   这个问题经常会有开发者遇见。主要目的是为了最大限度缩减lightmap的大小,通过让场景中次要物体的lightmap效果粗糙一点来节省游戏的空间。

   其实做法非常简单,我们可以通过lighting窗口中Object页面里的Scale In Lightmap来设定某个选定的Object在lightmap中占用像素的多少,默认是1对于重要的物体通过提高这个数值来增加此物体使用的lightmap像素,反之我们可以把这个值设为0到1之间来减少此物体所使用的lightmap像素。选项如下图所示:



为大家解答的Unity 5 全局光照系统Enlighten问题就到这里了,如果大家还有其他问题希望和我们的技术工程师直接进行交流,欢迎大家访问中文官方论坛进行提问: http://forum.china.unity3d.com



2016-04-25 19:49:08 hcud024 阅读数 13545
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。




本系列主要参考Unity灯光与渲染技术教程Unity Lighting And Rendering,同时会加上一点个人实践过程和理解。


========================================== 分割线 ==========================================

这篇文章主要讲全局光照,在看教程的时候就有一个点不是很理解,就是作者开启物体的static这个选项。在网上查找一些资料,有的说”static表示物体时静态的,多用于静止不动的物体,此外static有多种,有的用于烘焙,有的用于遮挡剔除“;还有的指出”所谓静态就是静止的,你如果要改变它位置,就不是静态了,静态物体在脚本加载的时候就开始渲染,不随着update 每侦更新,你如果要移动物体,就必然要重新刷新,就是动态了 “
总结来看,就是说unity3d中物体组件上的static选项是包括很多种static含义的,而本文中主要研究的是Lightmap Static。也就是在游戏中如何实现全局光照的方式。
而为什么要选择这种方式主要是由游戏的需求决定的,在游戏运行中,速度是最重要的,所以在跟渲染质量进行比较的时候,就要做出取舍,然而我们仍然在追求着更真实的视觉效果,全局光照即是实现虚拟物体真实性的一个很重要的因素,因为它可以模拟真实世界中各个物体反射光线的相互作用。这种交互是非常消耗性能的,因此选择了游戏中的光线通常会用lightmap这种静态的光照技术来代替动态的光照,从而在保证游戏运行帧数的同时提高渲染效果。
一般而言,在场景中完全静止的物体标记成static是比较好的。这个静止是指在游戏运行过程中没有发生移动或者缩放或者旋转等。因为每当物体进行运动,都需要重新进行模拟运算。这不仅仅是在光照方面,在其他的方向上也可以提高效率,比如静态物体的碰撞检测要更快,同时多个使用同一材质的静态物体在绘制的时候只使用一个drawcall,进而节省了CPU。在光照计算上,static的物体也更快一些。
在进行操作之前还要说明,个人免费版基本上无法实时渲染,大部分情况下只能静态渲染。这篇文章的内容我用免费版的时候开启static就直接挂掉了,换成专业版就没问题,猜想如果要是出现故障,可以考虑是这个原因。



步骤如下:
点击物体Cornell Box-点击static-选择yes,change children,即可实现全局光照的效果。 



这篇文章的步骤很简单,到这里就结束了,然而这只是后续讲解的一个引子,因为现在每移动小球或者改变光照方向都需要重新逐帧烘焙light map,后续将通过多种方式来实现。当然,改变光照的时候,光照贴图自动烘焙的前提是需要开启连续的烘焙选项,在lighting面板系统中默认开启。



遗留问题:

在实现小球的static效果的时候,并没有得到作者那种光滑的光照贴图。设置完全相同结果不同不知道为什么。

我得到的是下图这种很硬的效果,而且小球上似乎反射了一些不平整的阴影。



就在这篇文章快写完的时候去论坛看到一篇关于Unity4和Unity5灯光烘焙差别的文章,其中提到由于版本采用的光照烘焙技术不同,所以有很大的出入。官网介绍在这里

这个面板的区别似乎解决了我最开始的疑惑,因为必须把烘焙的物体设置为静态。


再有就是之前操作的时候没有把灯光的烘焙模式调为Baked,只有在这个设置好,同时自动烘焙关闭才能看到烘焙后的效果。
最后Scale In Lightmap Realtime ResolutionBaked Resolution个参数都试过仍然没有解决我球体为什么上面有奇怪阴影的问题。

2019-06-29 14:59:22 wodownload2 阅读数 76
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

global illumination

gi is a system that models(动态模拟的意思) how light is bounced off of surfaces onto other surfaces (indirect light) rather than being limited to just the light that hits a surface directly from a light source (direct light).

modelling (模拟)indirect lighting allows for effects that make the virtual world seem more realistic and connected(更加逼真,更加连续), since objects affect each other’s appearance. once classic example is ‘color bleeding’ where, for example, sunlight hitting a red sofa will casuse red light to be bounced onto the wall behind it.

another is when sunlight hits the floor at the opening of a cave and bounces around inside so the inner parts of the cave are illuminated too.

global illumination in the scene view. note the subtle effect of indirect lighting.

gi concepts

traditionally, video games and other realtime graphics applications have been limited to direct lighting, while the calculations required for indirect lighting were too slow so they could only be used in non-realtime situations such as CG animated films. a way for games to work around this limitation is to calcualte indirect light only for objects and surfaces that are known ahead of time to not move around (that are static). thay way the slow computation can be done ahead of time, but since the objects do not move, the indirect light that is pre-calcualted this way will still be correct at runtime.

unity supports this technique, called baked gi (also known as baked lightmaps), which is named after “the bake” the process in which the indirect light is precalcualted and stored (baked). in addition to indirect light, bakded gi also takes advantage of the greater computation time avaiable to generate more realistic soft shadows from area lights and indirect light than what can normally be archieved with realtime techniques.

additionally, unity 5.0 adds support for a new technique called precomputed realtime gi. it still requires a precomputation phase similar to the bake mentioned above, and it is still limited to static objects.

however, it does not just precompute how light bounces in the scene at the time it is built, but rather it precomputes all possible light bounces and encodes this information for use at runtime.

so essentially for all static objects it answers the question “if any light hits this surface, where does it bounce to?”

unity then saves this information about which paths light can propagate by later use.

the final lighting is done at runtime by feeding the actual lights present into these previously computed light propagation paths.

this means that the number and type of lights, their position, direction and other propertiers can all be changed and the indirect lighting will update accrodingly. similarly it is also possible to change material properties of obejcts, such as their color, how much light they emit themselves.

limitations of gi

both baked gi and precomputed realtime gi have the only static objects can be included in the bake/precomputation— so moving objects can not bounce light onto other objects and vice versa.反之亦然

however they can still pick up bounce light from static objects using LightProbes. light probes are positions in the scene where the light is measured (probed) during the bake/precompuation, and then at runtime the indirect light that hits non-static objects is approximated using the values from the probes

so for example a red ball that rolls up next to a white wall would not bleed its color onto the wall, but a white ball next to a red wall could pick up a red color bleed from the wall via the light probes.

2016-01-11 11:03:12 meichen8050753 阅读数 7210
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

Unity5 里面, 当场景里的物体保存成Prefab之后,LightMap的信息就会丢失。Fuck。。

所以最后就写了个脚本,把每个Render里的lightmap纪录下来,当prefab实例化之后,重新设置。

上代码。。


相关设置:



注意事项:检查下是否勾选了 Static -> BatchingStatic ,如果勾选了,一定要去除勾选 !!!!!!

using UnityEngine;  
using System.Collections;  
using System.Collections.Generic;
using UnityEngine.Rendering;

public class PrefabLightmapData : MonoBehaviour {

	//LightMap信息
	[System.Serializable]  
	public struct RendererInfo  
	{  
		public Renderer     renderer;  
		public int          lightmapIndex;  
		public Vector4      lightmapOffsetScale;  
	}

	//场景中的Fog信息
	[System.Serializable]  
	public struct FogInfo  
	{  
		public bool         fog;  
		public FogMode      fogMode;  
		public Color        fogColor;
		public float        fogStartDistance;
		public float        fogEndDistance;
		public float 		fogDensity;
	}


	public FogInfo fogInfo;
	public List<RendererInfo> m_RendererInfo; 
	public List<Texture2D> lightmapNear;
	public List<Texture2D> lightmapFar;
	public LightmapData[] lightmapData;
	public LightmapsMode lightmapsMode;

	//地形的LightMap信息
	public Terrain terrain;
	public RendererInfo terrainRendererInfo;

	//设置光照信息
	[ContextMenu("SetUp")]
	public void SetUp(){  
		lightmapData = new LightmapData[lightmapNear.Count > lightmapFar.Count ? lightmapNear.Count : lightmapFar.Count];
		for(int i = 0; i < lightmapData.Length; i ++){
			lightmapData[i]=new LightmapData();
			lightmapData[i].lightmapFar = i < lightmapFar.Count ? lightmapFar[i] : null;
			lightmapData[i].lightmapNear = i < lightmapNear.Count ? lightmapNear[i] : null;
		}
		LightmapSettings.lightmapsMode = lightmapsMode;
		LightmapSettings.lightmaps=lightmapData;
		LoadLightmap();
		RenderSettings.fog = fogInfo.fog;
		RenderSettings.fogMode = fogInfo.fogMode;
		RenderSettings.fogColor = fogInfo.fogColor;
		RenderSettings.fogStartDistance = fogInfo.fogStartDistance;
		RenderSettings.fogEndDistance = fogInfo.fogEndDistance;
		RenderSettings.fogDensity = fogInfo.fogDensity;
	}

	//保存光照信息
	[ContextMenu("SaveData")]
	public void SaveData(){  
		SaveLightmap ();
	}
	
	public void SaveLightmap()
	{  
		fogInfo = new FogInfo ();
		fogInfo.fog = RenderSettings.fog;
		fogInfo.fogMode = RenderSettings.fogMode;
		fogInfo.fogColor = RenderSettings.fogColor;
		fogInfo.fogStartDistance = RenderSettings.fogStartDistance;
		fogInfo.fogEndDistance = RenderSettings.fogEndDistance;

		lightmapNear = new List<Texture2D>();
		lightmapFar = new List<Texture2D>();
		for(int i = 0; i < LightmapSettings.lightmaps.Length; i ++){
			LightmapData data = LightmapSettings.lightmaps[i];
			if(data.lightmapNear != null){
				lightmapNear.Add(data.lightmapNear);
			}

			if(data.lightmapFar != null){
				lightmapFar.Add(data.lightmapFar);
			}
		}
		m_RendererInfo = new List<RendererInfo> ();
		var renderers = GetComponentsInChildren<MeshRenderer>();  
		foreach (MeshRenderer r in renderers) {  
			if (r.lightmapIndex != -1) {  
				RendererInfo info = new RendererInfo();  
				info.renderer = r;  
				info.lightmapOffsetScale = r.lightmapScaleOffset;  
				info.lightmapIndex = r.lightmapIndex;  
				m_RendererInfo.Add(info);  
			}  
		}

		terrain = GetComponentInChildren<Terrain> ();
		if (terrain != null) {
			terrainRendererInfo = new RendererInfo();
			terrainRendererInfo.lightmapOffsetScale = terrain.lightmapScaleOffset;  
			terrainRendererInfo.lightmapIndex = terrain.lightmapIndex;  
		}
		lightmapsMode = LightmapSettings.lightmapsMode;
	}  
	
	public void LoadLightmap()  
	{  
		if (m_RendererInfo.Count <= 0) return;  

		if (terrain != null) {
			terrain.lightmapScaleOffset = terrainRendererInfo.lightmapOffsetScale;
			terrain.lightmapIndex = terrainRendererInfo.lightmapIndex;
		}

		foreach (var item in m_RendererInfo) {  
			item.renderer.lightmapIndex = item.lightmapIndex;  
			item.renderer.lightmapScaleOffset = item.lightmapOffsetScale;  
		}  
	}
}

当场景中LightMap烘培好了之后,在perfab根节点上面挂上这个脚本,右键-》SaveData,之后apply prefab。

在运行时场景初始化完成之后。调用SetUp方法,即可挂载lightMap。


重点!!我遇上个问题,需要保持原来存在的渲染场景,assetbundle才的LightMap能正常。否则就不会有LightMap,希望谁来个提示。

如果把原来渲染lightmap的场景删了,那么在手机上就会加载不到。
我估摸着是因为assetbundle的时候,没有把lightmap的贴图打包进去,只保存了引用的关系。
所以如果场景删了,那么lightmap的贴图也丢了。

如有疑问,请回复哦~~



2017-08-04 11:33:17 jbl20078 阅读数 306
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

原文地址:http://www.360doc.com/content/17/0804/11/46072167_676571882.shtml

Unity 5正式版面世已经一段时间,许多开发者都已经在使用Unity 5进行开发。那么大家在使用Unity 5时都会碰到一些问题。今天我们Unity的官方技术工程师柳振东将在本文中针对Unity 5中全新的Enlighten全局光照系统的一些问题与大家进行一些分享。

        为什么Unity 5的全局光照系统会让大家踩坑呢? 因为Unity 5取缔了Unity 4中使用的Beast全局光照系统,采用了全新的Enlighten全局光照系统。而这两套全局光照系统的算法并不一样,反映到使用上就是各种参数与操作细节的变化。

        对于没有系统学习过计算机图形学的开发者,还是非常建议大家去了解一下全局光照明模型的,因为大家可能对局部光照明模型(就是我们平常所说的实时光照)比较熟悉,有时可能会把局部光照明模型的一些知识用在全局光照明系统上,白白花费时间做了一些无用功。

        下面挑选一些常见问题与大家分享。
        
为什么场景烘焙出来的lightmap上有Realitime灯光的颜色?

        相信不少开发者都为这样的问题头疼过,因为灯光明明是Realtime的,怎么可能会被烘焙到lightmap里面去呢?但是这在Unity 5里并不是一个bug。

        首先我们要知道Unity 5中新增一种全局光照明的使用方式:Precomputed Realtime GI(预计算实时全局光照明),简称:实时GI。而另一种Bake GI就是大家在Unity 4中一直用过来的ligtmap烘焙方式。

        实时GI与Bake GI一样,也需要预先的Bake过程,但是与Bake GI不同,实时GI并不预计算场景中光线的反射信息,而是预计算场景中静态物体表面所有可能的反射光路,然后在游戏运行时结合灯光的位置、方向等信息实时计算出全局光照的结果。

        这个计算机制使得预计算GI具备非常大的优势,在使用预计算GI的灯光,其位置、方向、强度、颜色等各种信息都可以在运行时实时变化。

        举例:使用预计算GI我们就可以在场景中实现非常真实的日光变化效果(别忘了我们其实是在使用全局光照明模型啊,比实时光照效果强多了)。
        但是,问题来了,预计算GI有一点非常容易让人混淆,那就是预计算GI需要灯光类型是Realtime。WTF?Realtime难道不是实时灯光吗?怎么变成全局光照明模型的灯光了?
        Unity 5的灯光属性中增加了一项,叫做Bounce Intensity,如下图所示:




        Bounce Intensity是指全局光照中的间接光强度,要理解这点可以简单地把全局光照理解为直接光照与间接光照两部分。直接光照指直接从光源射到物体上的光,而间接光照指从其他物体表面反射而来的光。那么显而易见,直接光照的部分其实就是局部光照模型,也就是实时光照计算出来的结果。

        回到正题,Bounce Intensity在Unity 5 中默认值是1,意思就是说一盏Realtime灯光默认是使用预计算GI的,并且间接光照的强度不做改变(大于1是强制增大间接光照,这在一些由室外光照射入洞穴这类的场合中可能会用到)。而lighting窗口中的预计算GI选项也是默认开启的,如下图所示:
        



        所以如果你并不更改这些设置,即使看起来你好像只使用了Realtime的灯光,但是真正运行的时候却其实是在使用全局光照系统!

        接下来要说明的一点是,只要一盏灯的Bounce Intensity大于0,Unity就会认为你需要使用全局光照系统。那么即使你在lighting窗口中取消勾选Precomputed Realtime GI,Unity依然会尝试使用全局光照。

        既然已经取消了预计算GI的选项,Unity会去使用另外一种全局光照的方式,Bake GI(只要你还勾选着Bake GI)。而结果就是,烘焙出来的lightmap里也有那盏Bounce Intensity大于0的Realtime灯光的信息。

        总结:Unity 5中灯光有个新属性Bounce Intensity,这个值只要大于0系统就会认为你需要使用预计算GI计算这个灯光,而如果此时Precomputed Realtime GI没有被勾选,而Bake GI勾选了那么Unity会把这个灯光也烘焙到lightmap中去。

为什么在Unity 5中动态更换lightmap没有作用?

        在场景中动态更换lightmap是挺常用的需求。例如:同一个场景需要白天与黑夜两个时间的效果,那么我们就会烘焙两张不同的lightmap,然后用脚本在运行时切换。在Unity 4中可以通过把lightmap资源load到Texture2D中,然后赋值给一个LightmapData结构,最后赋给LightmapSettings.lightmaps来达到更换当前使用lightmap的目的。

        但是在Unity 5中会发现使用这个方法并不凑效。是因为lightmap没有正确更换吗?不是的,其实lightmap已经更换了,问题是在于此时使用lightmap的物体并不知道自己应该使用哪张lightmap,也不知道要从lightmap的哪个地方开始采样,而这其实就是每个Renderer上的两个参数,lightmapIndex与lightmapScaleOffset。

        现在大家肯定会问为什么在Unity 4中没有问题呢?那是因为这些信息在Unity 4中已经被序列化进场景文件中,当场景加载进来的时候这两个值就被赋回到每个Renderer中。而在Unity 5中,lightmapIndex与lightmapScaleOffset因为多场景编辑的逻辑需要,不再被序列化到场景文件中去了,而是存在于一个伴随lightmap烘焙产生的一个新文件,Lighting Data Asset中去了(这个文件在初期的5.x中叫做lightmapSnapShot)。这个文件与lightmap在同层目录中,并且可以在Editor中随时更换当前使用的LightingData文件,如下图所示:



        那么回归正题,既然LightingData文件存储着lightmapIndex与lightmapScaleOffset,那么只要保证LightingData文件能被最终的可执行文件使用不就没有问题了吗?其实这样是没有问题的,如果我们只需要更换灯光条件不同情况下的lightmap,而场景本身并没有更改的话,那么多套lightmap对于场景中的静态物体Renderer而言也只需要同一套lightmapIndex与lightmapScaleOffset信息而已。所以在这种情况下要达到运行时更换lightmap的效果,只要保证lighting窗口的Ligtmaps页面中Light Data Asset里选中了正确的LightingData文件即可(因为很多开发者习惯性删除掉这个文件,因此也就丢失了lightmapIndex与lightmapScaleOffset信息)。

        简单的情况我们简单地使用LightingData文件即可。但是还有一种情况,如果我们需要场景本身也有所改变要怎么办呢?

        举例:我可能需要原始的场景lightmap与一个被炸弹破坏过后的场景lightmap,由于场景中的静态物体有所改变,这个时候两次烘焙会产生两个数据不同LightingData文件,无法简单使用其中一个。然而比较可惜的是现在Unity并不能在运行时切换LightingData文件,其设计之初就仅仅作为Editor使用的资源。
        那么对于这种情况,我们需要自己记录下每个Renderer上的lightmapIndex与lightmapScaleOffset信息,然后在更换lightmap的时候把这个信息还原回去。

        具体做法有很多种,基本原理都是把lightmapIndex与lightmapScaleOffset序列化起来。比如说我们可以给每个静态物体挂一个脚本,在里面定义一个包含Render,lightmapIndex与lightmapScaleOffset的结构,然后一个Save函数用来在每次烘焙lightmap之后把lightmapIndex与lightmapScaleOffset序列化进结构中,一个Load函数用来在切换lightmap时还原每个Renderer的lightmapIndex与lightmapScaleOffset信息。现在这个问题就解决了。

Unity5 全局光照

阅读数 798

没有更多推荐了,返回首页