精华内容
下载资源
问答
  • 我们知道全局光照是图形学中一项比较难实现的技术,因为真正要得到全局光照是需要一个点跟所有点的关系计算的,而这个...屏幕空间的全局光照也叫SSGI,是一个相对来说比较快速得到间接光的一种全局光照技术,是基于屏幕

    我们知道全局光照是图形学中一项比较难实现的技术,因为真正要得到全局光照是需要一个点跟所有点的关系计算的,而这个计算如果用在计算机那是不太可能实现的。而现代技术利用了一些比如有向距离场,体素,辐照度等方式实现全局光照,还有就是越来越火的光纤追踪技术实现全局光照。但是这些技术的消耗都很大,包括内存,cpu,gpu的运算量。那么自然会有一种ss系列的方式来实现全局光照,这种方式会比前面几种都容易实现并且运算量相对小。

    屏幕空间的全局光照也叫SSGI,是一个相对来说比较快速得到间接光的一种全局光照技术,是基于屏幕空间大小来实现的,也就是说不会得到屏幕外的颜色或者光照。他也不是基于光源的,而是基于当前的颜色来做扰动采样整合得到的光照信息,最后需要做一些抗锯齿的操作来让他噪点比较合理。这种方式更合理的使用在密闭空间内,这样的效果会比较理想。

    SSGI一般会有几个步骤:

    1.采样不同lod的深度图信息并得到其中最大的深度值。(要执行多少次寻找就看你设置多少次pass)

    2.用光线步进的方式,并用噪音图采样以圆的周长来找周围的像素点的颜色,这个颜色是根据当前场景颜色做的(所以ssgi一般放到最后处理)。采样的点存储到rt上

    3.这时的rt是带有比较明显的锯齿的rt,需要用taa方式过滤一次

    4.最后在横向和纵向做两次模糊处理。

    5.这样就得到了ssgi的漫反射方向的间接光照了,最后只需要把场景图和这个间接光rtcombina一下就好了。

     

    大体实现:

    1.获取深度图信息的核心代码是

    float2 uv = i.uv.xy;
    		
        half4 minDepth = half4(
            _SSGi_HierarchicalDepth_RT.SampleLevel( sampler_SSGi_HierarchicalDepth_RT, uv, _SSGi_HiZ_PrevDepthLevel, int2(-1.0,-1.0) ).r,
            _SSGi_HierarchicalDepth_RT.SampleLevel( sampler_SSGi_HierarchicalDepth_RT, uv, _SSGi_HiZ_PrevDepthLevel, int2(-1.0, 1.0) ).r,
            _SSGi_HierarchicalDepth_RT.SampleLevel( sampler_SSGi_HierarchicalDepth_RT, uv, _SSGi_HiZ_PrevDepthLevel, int2(1.0, -1.0) ).r,
            _SSGi_HierarchicalDepth_RT.SampleLevel( sampler_SSGi_HierarchicalDepth_RT, uv, _SSGi_HiZ_PrevDepthLevel, int2(1.0, 1.0) ).r
        );
    
    	return max( max(minDepth.r, minDepth.g), max(minDepth.b, minDepth.a) );

    采样上下左右四个方向的深度获取最深的。

    2.光线步进采样周围像素点的核心代码(有注释):

    float2 UV = i.uv.xy;
    
    	//当前像素深度
    	float SceneDepth = tex2Dlod(_CameraDepthTexture, float4(UV, 0, 0)).r;
    	//转成摄像机方向的线性深度
    	float EyeDepth = LinearEyeDepth(SceneDepth);
    	//float LinearDepth = Linear01Depth(SceneDepth);
    
    	half Roughness = clamp(1 - tex2D(_CameraGBufferTexture1, UV).a, 0.02, 1);
    	float3 WorldNormal = tex2D(_CameraGBufferTexture2, UV) * 2 - 1;
    	float3 ViewNormal = mul((float3x3)(_SSGi_WorldToCameraMatrix), WorldNormal);
    
    	//摄像机位置,z轴表示深度
    	float3 ScreenPos = GetScreenSpacePos(UV, SceneDepth);
    	//通过摄像机的逆矩阵转换到世界坐标
    	float3 WorldPos = GetWorldSpacePos(ScreenPos, _SSGi_InverseViewProjectionMatrix);
    	//通过投影矩阵的逆矩阵转换到摄像机空间
    	float3 ViewPos = GetViewSpacePos(ScreenPos, _SSGi_InverseProjectionMatrix);
    	//摄像机空间方向
    	float3 ViewDir = GetViewDir(WorldPos, ViewPos);
    
    	//基于世界法线建立切线空间
    	float3x3 TangentBasis = GetTangentBasis( WorldNormal );
    	//uint3 p1 = Rand3DPCG16( uint3( (float)0xffba * abs(WorldPos) ) );
    	//uint2 p = (uint2(UV * 3) ^ 0xa3c75a5cu) ^ (p1.xy);
    
    	half Out_Mask = 0;
    	half3 Out_Color = 0;
    	
    	[loop]
    	for (uint i = 0; i < (uint)_SSGi_NumRays; i++)
    	{
    		//uint3 Random = Rand3DPCG16( int3( p, ReverseBits32(i) ) );
    		//half2 Hash = float2(Random.xy ^ Random.z) / 0xffffu;     
    		//根据扰动图片采样来获取周边的像素和深度
    		half2 Hash = tex2Dlod(_SSGi_Noise, half4((UV + sin( i + _SSGi_Jitter.zw )) * _SSGi_RayCastSize.xy / _SSGi_NoiseSize.xy, 0, 0)).xy;
    
    		float3 L;
    		//基于圆偏移的点
    		L.xy = UniformSampleDiskConcentric( Hash );
    		L.z = sqrt( 1 - dot( L.xy, L.xy ) );
    		//世界空间
    		float3 World_L = mul( L, TangentBasis );
    		//转摄像机空间
    		float3 View_L = mul((float3x3)(_SSGi_WorldToCameraMatrix),  World_L);
    
    		float3 rayStart = float3(UV, ScreenPos.z);
    		//对方向最一些偏移,也是基于圆做偏移
    		float4 rayProj = mul ( _SSGi_ProjectionMatrix, float4(ViewPos + View_L, 1.0) );
    		float3 rayDir = normalize( (rayProj.xyz / rayProj.w) - ScreenPos);
    		rayDir.xy *= 0.5;
    		//找偏移附近的uv
    		float4 RayHitData = Hierarchical_Z_Trace(_SSGi_HiZ_MaxLevel, _SSGi_HiZ_StartLevel, _SSGi_HiZ_StopLevel, _SSGi_NumSteps_HiZ, _SSGi_Thickness, 1 / _SSGi_RayCastSize.xy, rayStart, rayDir, _SSGi_HierarchicalDepth_RT, sampler_SSGi_HierarchicalDepth_RT);
    
    		//根据偏移采样场景颜色
    		float3 SampleColor = tex2Dlod(_SSGi_SceneColor_RT, half4(RayHitData.xy, 0, 0));
    		float4 SampleNormal = tex2Dlod(_CameraGBufferTexture2, half4(RayHitData.xy, 0, 0)) * 2 - 1;
    		float Occlusion = 1 - saturate( dot(World_L, SampleNormal) ); 
    
    		SampleColor *= Occlusion;
    		SampleColor *= rcp( 1 + Luminance(SampleColor) );
    
    		Out_Color += SampleColor;
    		//对场景大小的遮罩决定显示范围
    		Out_Mask += Square( RayHitData.a * GetScreenFadeBord(RayHitData.xy, _SSGi_ScreenFade) );
    	}
    	Out_Color /= _SSGi_NumRays;
    	Out_Color *= rcp( 1 - Luminance(Out_Color) );
    	Out_Mask /= _SSGi_NumRays;
    
    	//颜色用附近采样的颜色,透明度用深度决定
    	[branch]
    	if(_SSGi_MaskRay == 1) {
    		return half4( Out_Color * saturate(Out_Mask * 2), EyeDepth );
    	} else {
    		return half4( Out_Color, EyeDepth );
    	}

    3.做一次TAA,主要是获取aabb的裁剪盒子,然后得到最小颜色,最大颜色,然后clamp进行过渡,再融合上一帧的颜色和当前帧的颜色。

    half2 UV = i.uv.xy;
    	half3 WorldNormal = tex2D(_CameraGBufferTexture2, UV).rgb * 2 - 1;
    	half2 Velocity = tex2D(_CameraMotionVectorsTexture, UV);
    
    	/Get AABB ClipBox
    	half SS_Indirect_Variance = 0;
    	half4 SS_Indirect_CurrColor = 0;
    	half4 SS_Indirect_MinColor, SS_Indirect_MaxColor;
    	ResolverAABB(_SSGi_RayCastRT, 0, 10, _SSGi_TemporalScale, UV, _SSGi_ScreenSize.xy, SS_Indirect_Variance, SS_Indirect_MinColor, SS_Indirect_MaxColor, SS_Indirect_CurrColor);
    
    	/Clamp TemporalColor
    	half4 SS_Indirect_PrevColor = tex2D(_SSGi_TemporalPrev_RT, UV - Velocity);
    	SS_Indirect_PrevColor = clamp(SS_Indirect_PrevColor, SS_Indirect_MinColor, SS_Indirect_MaxColor);
    
    	/Combine TemporalColor
    	half Temporal_BlendWeight = saturate(_SSGi_TemporalWeight * (1 - length(Velocity) * 2));
    	half4 SS_IndirectColor = lerp(SS_Indirect_CurrColor, SS_Indirect_PrevColor, Temporal_BlendWeight);
    
    	return SS_IndirectColor;

    4.做横向和纵向两次模糊(blur里面会对颜色和深度都做模糊处理,颜色直接用相加然后除于相加的数量得到,深度需要用2的n次幂来得到一条曲线,下面的CrossBilateralWeight就是深度的过滤方式):

    float4 Bilateralfilter_X(PixelInput i) : SV_Target
    {
    	half2 UV = i.uv.xy;
    	const float Radius = 12.0;
    	return BilateralBlur( Radius, UV, half2(1.0 / _SSGi_ScreenSize.x, 0), _SSGi_TemporalPrev_RT );
    }
    
    float4 Bilateralfilter_Y(PixelInput i) : SV_Target
    {
    	half2 UV = i.uv.xy;
    	const float Radius = 12.0;
    	return BilateralBlur( Radius, UV, half2(0, 1.0 / _SSGi_ScreenSize.y), _SSGi_TemporalPrev_RT );
    }
    
    float CrossBilateralWeight(float BLUR_RADIUS, float r, float Depth, float originDepth) 
    {
    	const float BlurSigma = BLUR_RADIUS * 0.5;
    	const float BlurFalloff = 1.0 / (2.0 * BlurSigma * BlurSigma);
    
        float dz = (originDepth - Depth) * _ProjectionParams.z * 0.25;
    	return exp2(-r * r * BlurFalloff - dz * dz);
    }

    5.合并就简单了,就是用当前场景颜色和上面算出来的间接光照相加。

    half2 UV = i.uv.xy;
    
    	half3 BaseColor = tex2D(_CameraGBufferTexture0, UV);
    	half3 SceneColor = tex2D(_SSGi_SceneColor_RT, UV);
    	half3 IndirectIrradiance = tex2D(_SSGi_Bilateral_RT, UV) * _SSGi_GiIntensity;
    
    	return (IndirectIrradiance * BaseColor) + SceneColor ;

    总结:ssgi的diffuse方式实现简单,得到的结果也不错,但是他并不是正确的,是一个模拟周围颜色的过程,当你要得到更好的结果时需要扩大获取深度和颜色扰动的范围,同样gpu的压力也会增大。但他确是一种实时的全局光照方式。当然如果我们只需要一些静态或可控的动态区域做全局光照,那么用烘焙和球谐光照就可以了。

     

     

     

    展开全文
  • 动态场景的全局光照实时绘制,一篇浙大的硕士论文,里面对于光照技术有很详细的讲解。
  • 做了这么久可是我们的管线依然没有全局光照,这是一个很尴尬的事情,因此,我们决定给管线加上这个功能。那么我们首先要考虑的是技术的选型与管线的适配,之前文章中已经讲过,我们采用了Cluster Based Lighting,...

    b7a15daae4d083f876b6ca329781fd94.png

    做了这么久可是我们的管线依然没有全局光照,这是一个很尴尬的事情,因此,我们决定给管线加上这个功能。

    那么我们首先要考虑的是技术的选型与管线的适配,之前文章中已经讲过,我们采用了Cluster Based Lighting,配合Shadowcache,使得性能在光影数量较多的情况下还能保证比较好的效果,Shadowcache可以使得静态的灯光在一帧内烘焙好一个深度,并在接下来几帧后更新,除非动态物体经过,否则是不需要更新的,,这也使得动态光影的性能限制被大大放宽,是一种成本较低收益较高的空间换时间的实现。

    在我们面前摆着Unity提供的Subtractive, Shadowmask, Bake Indirect这三种,第一种通过将Irradiance和Light Color同时烘焙到光照贴图里,实现纯静态的光照,第二种将阴影的Mask和间接光烘焙到贴图中,只有直接光实时运算,第三种只会烘焙Indirect光照,也就是一张普通的自发光贴图。首先我们毙掉第二种,因为我们使用的CBDR如果费力的组织Mask bit,不仅十分麻烦,而且这还需要延迟渲染专门提供一个GBuffer,在PC或主机上,带宽往往是一个很容易产生短板的地方,这样突然多4个通道的操作也是很亏的。Subtractive直接强行烘死所有的灯光,这当然没问题,配合Directional Irradiance效果也足够好,然而对于动态物体的支持却很不怎么样,刚刚已经说过,我们的实时灯光计算效率本来就很高,完全没必要用静态灯光,所以最终选择了只烘焙间接光,同时配合实时光影的运算。

    首先打开正常的Unity内置管线和Standard Shader并开始烘焙(为了省时间就暂时用Enlighten凑活一下):

    451e884811d01a6dcdfcccdd367946b1.png

    烘焙完毕后我们就可以选择存储一波光照贴图的数据,在之前的文章中我们短暂的介绍了一下Virtual Texture及其流式加载的方法:

    MaxwellGeng:基于Unity3D的大地形研究(2):资源序列化与材质加载zhuanlan.zhihu.com
    7715e8970716140a9bfbbf3294159b50.png

    Virtual Texture在这里的用法实际上可以理解成是使用一张Texarray或Atlas实现一个Object Pool,或者说Texture Pool,用到的贴图塞进去,用不到的贴图将其标记为删除,这样下次存入时直接去覆盖上一张贴图。使用这样的方法有诸多好处,最大的好处就是贴图的读取过程十分自由,在开放世界的开发时,每块地皮常需要数张贴图的纹理同时显示并混合,如果使用古典的Unity Terrain或者UE Landscape那种一层一层Pass叠上去的办法,绘制的时间复杂度是O(n),即使有Instance之类的也最多是个O(logN),而使用Virtual Texture可以把实时的,每帧都要做的合并过程转移到贴图空间一次性完成,使其变为O(1)复杂度。这样的方法用途甚广,无论是实时生成Detail Map,还是地形流程化生成,都非常适合,我们这里的光照贴图也不例外。

    与之前的实现一样,我们在每个场景中专门储存了所有用到的GUID,GUID的唯一性使得每张贴图不会被重复加载,同时可以直接使用GUID进行二进制文件的储存和读取,存储方法如下:

    2c01a782327a72b8692a8f4653e1dd10.png

    每个存储位置存储着GUID和贴图的大小,因为Unity的Atlas设置的是最大值,所以有可能会有不同大小的贴图,这一点确实非常尴尬,只能强行把2048的贴图扩到4096的VT中,但是这一点其实完全可以避免!因为GPU driven pipeline对于模型如何分配十分不敏感,反正都是要统一合并的也不会产生多余DC,因此只要与美术达成共识,让美术在制作模型时尽可能拆的散一些,尽量少出现巨型的Mesh,这样在烘焙时就不会出现超出模型的三角形覆盖面积超出Atlas总面积的问题了,也就是说我们可以把Atlas的大小调整为2048,使所有光照贴图均使用2048分辨率的光照贴图,在缩小分辨率后只需要把VT的容量扩大几倍即可,就避免了VT浪费空间的问题。

    合并完成后关掉内置管线,启动SRP,运行并加载场景,因为场景是异步线程中加载的,必须手动触发,所以在Editor Mode并看不到效果:

    300851d1c2679a80a51bd5b7eff6e6d8.png

    依旧因为偷懒原因,太阳光的运算并没有采用流明亮度,而是和内置管线一样直接怼的Lighting Scale,这也使得太阳亮度不需要额外调整即可直接进入我们自己的管线运行,除了有了Color Grading后解决了过曝问题并使画面整体变灰,渲染上依旧给人一种晦暗感,这是为什么呢?其实我们换一个角度并把雾的浓度调高三倍来看就不难发现问题所在:

    7ecd352ea9026573ad0947e3b0efa9b2.png

    雾浓度提高以后被灯光照到的红圈的地方已经亮的夸张了,而被绿圈圈出的暗处则越来越黑,有了几分恐怖片的感觉,这是因为光照贴图实际只能解决模型的光照问题,却无论如何也解决不了3D空间的渲染,如体素渲染或动态物体,而之前在看 @MoonChildInSky 大神的文章时,看到他制作的场景Demo非常巧妙的利用了空间的辐照度进行体素雾渲染:

    d25ddc62e69c7ca5363af9013a5791bb.png

    抛开作者美术造诣不谈,单说这个间接光对雾效的影响也着实令画面效果增色不少,因此我也决定在管线中加入Irradiance Volume实现对体素雾的着色。光照的辐射度计算关键来自于计算球谐,也就是Sphere Harmonics,Wikipedia上关于Sphere Harmonics的解释是这样的:

    eedcd018958e39afa45c82645ea261aa.png

    至于该公式的推导过程,这是物理光学的研究,并不在我们的研究范围内,我们只需要拿过来用就可以了。根据公式,某个点的权重是由该点到球心(或球心到该点)的向量来决定的,在光栅化中将表现为点的法线,决定的公式如下:

    f53efdd9e4c3f94923d709d2c753820c.png

    如果将其可视化:

    fcb6aa014343de599771f98d4394648b.png

    那么我们如何实现这个公式呢。首先我们在上下左右前后6个面分别获取6张同等大小的透视投影,合成得到一张Cubemap,由于GPU Driven Pipeline高效的剔除和绘制,使的这个过程非常迅速,即使绘制几百万个采样点,也仅仅需要寥寥数秒,而且这个过程是可以在离线状态下完成的,除非有必要的实时GI需求。因此在这里我们将直接把Cubemap烘焙出来。

    烘焙后就需要套入公式,先来看公式:

    0bbcd265c21b8dfcc437f2ab408ea521.png

    在光栅化中累计积分着实是一个令人头大的问题,如何积分,如何高效累计都是摆在面前的赤裸裸的大问题。而这里我的解决方案是直接使用Compute Shader的原子操作进行累计。首先,在宏定义中套公式,根据法线计算权重:

    865ca4248034d0ad544dcfa2f95e780d.png

    把当前像素的色彩累加到一个固定的Buffer中:

    e6b55b942eb688d9d6f17ab1516278d2.png

    累计完毕后将整数 / 256获得浮点数,并把这串Buffer写入到体素贴图里,我们总共采用了9个常量作为Coefficient,也就是27个浮点数,所以这里使用了7个ARGBHalf格式的体素贴图存储,并依靠硬件自带的Quadlinear完成线性插值。那么为什么要使用贴图而不是直接把结果存到StructuredBuffer中并手动降维+采样插值呢?其实直接插值9个数的消耗,并采样4 * 9个数,消耗是远高于使用贴图的,因为硬件提供的QuadLinear有许多硬件层的优化,包括Pipelining, Caching等,效率要远高于我们直接在Shader中,而且也绝对是更节省带宽访问的消耗的。

    获取到这7张贴图,我们就可以在目标Shader(如动态物体的Shader,Froxel采样Shader等)中通过色彩和权重完成积分,获取最终色彩:

    e18f985a8fe4b8f08417b3bbb94bbe33.png

    来看一下最终的效果,从图中可以看到,即使在光线没有照到的地方,雾也不再是一片死黑,已经有了一定的亮度:

    1ef280f88975aa1f5b64df6e225337b0.png

    进行到了这一步,可以说在全局间接光照的渲染上已经达到了一个入门的水准,已经有了高效的光照贴图加载,支持动态物体和雾效的Irradiance Volume,在下一章中我们将会开始给管线加入反射球的支持,使全局光更加完整。

    展开全文
  • 这篇文章主要讲全局光照,在看教程的时候就有一个点不是很理解,就是作者开启物体的static这个选项。在网上查找一些资料,有的说”static表示物体时静态的,多用于静止不动的物体,此外static有多种,有的用于烘焙,...



    本系列主要参考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个参数都试过仍然没有解决我球体为什么上面有奇怪阴影的问题。

    展开全文
  • Unity Shader 学习笔记(33) 全局光照(GI)、反射探针、线性空间和伽马空间、高动态范围(HDR) 参考书籍:《Unity Shader 入门精要》 【《Real-Time Rendering 3rd》 提炼总结】(八) 第九章 · 全局光照:光线...

    Unity Shader 学习笔记(33) 全局光照(GI)、反射探针、线性空间和伽马空间、高动态范围(HDR)

    参考书籍:《Unity Shader 入门精要》
    【《Real-Time Rendering 3rd》 提炼总结】(八) 第九章 · 全局光照:光线追踪、路径追踪与GI技术进化编年史
    官方:ReflectionProbes
    官方:Global Illumination
    官方:High Dynamic Range Rendering
    官方:Linear rendering overview


    全局光照(Global illumination, GI)

    场景的物体的光线投射到物体会反弹(Bounce)光线到别的物体,产生间接光照。

    通过设置Bounces值来控制间接光的强度。
    在这里插入图片描述

    预计算实时全局光照(Precomputed Realtime GI)

    动态为场景实时更新复杂的光照结果。
    实现原理:先计算静态物体间和光源位置的关系,对动态移动的物体,使用光照探针模拟光照环境。


    反射探针(Reflection Probes)

    在特定位置对场景采样。在有反射效果的物体在探针附近时,会把探针的结果给物体。多个探针时,做插值。
    在这里插入图片描述

    下图白色带微笑的圆圈就是反射探针。
    在这里插入图片描述

    反射探针还可以实现物体互相反射的效果。(如下反射值为2,第一次反射会是全黑色的。)
    在这里插入图片描述


    线性空间(Linear)和 伽马空间(Gamma)

    • 线性空间:采集到亮度为0.5,像素就是0.5。符合计算规则(PBS必须在线性空间计算)。
    • 伽马空间:采集到亮度为0.22,像素是0.5(0.45的编码伽马γ)。根据人眼光灵敏度,调整像素值,充分利用图像的存储空间。

    伽马校正:伽马空间转换到线性空间。Lout = Linγ

    sRGB颜色空间标准下,0.45的编码伽马,配合2.2的显示伽马来相互抵消(2.2 × 0.45 ≈ 1)。线性空间下,输入纹理设置为sRGB模式,对纹理采样时就会转换到线性空间。
    在这里插入图片描述

    在这里插入图片描述


    高动态范围(High Dynamic Range, HDR)

    动态范围:最高和最低的亮度值之间的比值。

    HDR使用高于8位的精度来记录亮度信息,可表示超过0~1的亮度值,更精确反映真实光照。尽管最后要把信息转回显示设备的LDR,但中间的计算可以得到更真实的效果,即如果亮度超过1,可以使用**色调映射(tonemapping)**来最大限度保留需要的亮度细节。

    缺点:需要更大显存空间,渲染会变慢,一些硬件并不支持HDR。使用HDR就无法开启硬件的抗锯齿功能(可以用屏幕后处理弥补)。

    展开全文
  • ce引擎部分技术paper

    2018-08-01 15:00:47
    ce引擎部分技术paper,包含动态全局光照技术lpv,实时阴影,延迟渲染等相关技术
  • 在unity5新版本中,是完全新的光照系统,由以下三部分组成:Enlighten + Probes + Screen Space Reflection Enlighten Enlighten是全局的基础光照,由于它不能...除了静态的光照实现,动态全局光照实现则由Probes
  • 烘焙技术可以将场景中静态物体烘焙出真实的光影...原理:在场景 中先放置一些灯光效果的采样点,收集指定区域的明暗信息,利用内部的差值运算,将详细作用到的动态的游戏模型上,这样也不会全局实时光照那样消耗性能...
  • 今天还是跟大家聊一聊最近很火的虚拟引擎,Epic Game公司的虚幻引擎5惊艳了全球游戏业,其Nanite虚拟微多边形几何技术和Lumen动态全局光照技术带来了产业界的飞跃。Nanite虚拟几何技术的出现意味着由数以亿计的...
  • 和Epic Game公司的虚幻引擎5惊艳了全球游戏业,其Nanite虚拟微多边形几何技术和Lumen动态全局光照技术带来了产业界的飞跃。Nanite虚拟几何技术的出现意味着由数以亿计的多边形组成的影视级艺术作品可以被直接导入...
  • 文中的描述是,介绍了一种用于计算散射光传递的新技术,并演示如何用它来计算运动场景中的全局光照。主要是一种用GPU加速环境光遮蔽计算的技术,并将此算法变成了实时的解决方案。 【核心要点】 ...
  • Unity全局照明.md

    2021-01-25 15:18:36
    把光源对静态物体的光照效果提前烘培到一张lightmap,然后把lightmap采样到物体表面以产生全局光照效果。 ###LightMap 静态物体使用 bake lightmap Light Probes 光照探针是为了让动态物品也可以受bake GI的影响。 ...
  • 首先,使用哪一款游戏引擎去制作一款游戏,并不是根据使用者的喜好来制定的。开发者们的喜好千奇百怪,但最终能...其Nanite虚拟微多边形几何技术和Lumen动态全局光照技术,几乎可以算得上是一次渲染界的产业革命了。...
  • 光照贴图(Lightmap)是一种效果明显的模拟光照的方法,这种光照贴图需要提前渲染,因此可以应用在静态效果图中,属于全局照明技术。但是这种方法一般只适用于静态物体。当然unity做了很多工作,可以让我们混合使用...
  • 其它关于Unity5的光照系统神马的,网上很多资源,这几个文章良大本人觉得是很有价值的:Unity 5 中的全局光照技术详解http://www.gameres.com/forum.php?mod=viewthread&tid=446301详解Unity 5 全局光照系统...
  • HDR 高动态范围光照渲染,简单的说就是对亮度进行处理,使得亮的地方更亮,暗的地方更暗 ...Global illumination 全局光照,随着GPU速度越来越快,现在已经可以进行更多的计算,从而使得模拟全局光照变得可行
  • Maxwell核心新技术VXGI,MFAA测试

    千次阅读 2015-10-26 11:55:43
    刚更新了344.75驱动,试试GTX 980 麦克斯韦尔核心的黑科技吧,970/980同时发布的DSR(动态...这次主要是测试VXGI(立体像素全局光照)和MFAA(多帧采样抗锯齿)技术。 显卡用的是公版GTX 980,满载165W功耗还是相
  • 游戏中间件--Autodesk Beast

    千次阅读 2013-10-20 12:50:04
    核心提示: 使用 Beast 预先计算光照地图、阴影地图和点云的光照,烘焙闭塞贴图或正常贴图,或者为角色和对象的动态二次光照生成光场。...Beast 为游戏制作者提供毫不费劲地增强游戏外观的先进的全局光照技术。使
  •  其全新的立体像素全局光照(VXGI)技术首次让游戏GPU能够提供实时的动态全局光照效果。由于光线能够在游戏环境中逼真地互动,因此场景的逼真度大幅提升,可为游戏玩家带来更强烈的临场感。  基于Maxwell架
  • 重要资料集合

    2011-04-25 15:21:00
    动态全局光照、延迟光照、自然光照与动态软阴影、体积化视野范围雾化、动态模糊与景深等等技术的应用让游戏宛如真实世界 http://www.hxsd.com/news/cg-game/20100805/28908_8.html 2:什么是渲染器...
  • 5.2 动态图形的绘制 5.2.1 彗星状轨迹图 5.2.2 色图的变幻 5.3 绘制动画的方式 5.3.1 以擦除方式绘制动画 5.3.2 以电影播放方式绘制动画 5.4 MATLAB的视频 5.4.1 MATLAB对视频的支持 5.4.2 从静止图像向AVI视频文件...
  • 5.2.1 全局设定 5.2.2 局部设定 5.3 着色器实例 5.3.1 环境映射和铬映射效果——玻璃、金属和铬 5.3.2 移动发光告示牌 5.3.3 简单栅栏效果 5.3.4 高级栅栏效果 5.3.5 监视器效果 5.4 实时硬件渲染 5.4.1 顶点编程 ...
  • 5.2.1 全局设定 5.2.2 局部设定 5.3 着色器实例 5.3.1 环境映射和铬映射效果——玻璃、金属和铬 5.3.2 移动发光告示牌 5.3.3 简单栅栏效果 5.3.4 高级栅栏效果 5.3.5 监视器效果 5.4 实时硬件渲染 5.4.1 顶点编程 ...
  • 之所以作为id下一代技术主打题目,大概因为id的lighting/shadow/shader方案统一以后,下一步movie化所用的rendering 技术硬件跟不上,类似全局光照涉及的一些范畴(全局光,软阴影,光能传递等),motion blur, dep
  • About ID TECH 5

    千次阅读 2007-07-26 23:21:00
    之所以作为id下一代技术主打题目,大概因为id的lighting/shadow/shader方案统一以后,下一步movie化所用的rendering 技术硬件跟不上,类似全局光照涉及的一些范畴(全局光,软阴影,光能传递等),motion blur,

空空如也

空空如也

1 2 3
收藏数 42
精华内容 16
关键字:

动态全局光照技术