|
全局光照,(Global Illumination,简称 GI),。
或被称为 Indirect Illumination, 间接光照,是指既考虑场景中直接来自光源的光照(Direct Light)又考虑经过场景中其他物体反射后的光照 (Indirect Light)的一种渲染技术。使用全局光照能够有效地增强场景的真实感。
即可以理解为:全局光照 = 直接光照(Direct Light) + 间接光照(Indirect Light)
【05.渲染中光和材质的数学魔法 | GAMES104-现代游戏引擎:从入门到实践】 【精准空降到 31:48】
说白了其实就是计算环境内的所有光照,如果只是单纯计算直接光照,那么看起来就不真实。现实生活中,光会在各种物体间折射和反射,这个计算是十分复杂的,所以也就有了平常常听的光线追踪这类的名词。
对于一般的游戏来说,实时计算GI是件非常耗性能的事情。所以一般来说会先进行预计算,也就是提前将场景的光照烘焙到一张名为LightMap 的贴图中,用来记录光照信息以及一些阴影的信息。
unityt中的GI
烘焙GI
在unity 中,选择 Window -> Rendering -> Lighting
将场景中需要烘焙的物体勾上 static标签,点击Lighting 中的计算,会生成对应场景的光照数据以及光照贴图。
如何使用GI
关闭场景光源,显示烘焙好的阴影
先直接贴代码
Shader "Study/Chapter5/MyGlobalGI"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 引入变体 是否使用光照贴图
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#include "UnityCG.cginc"
#include "AutoLight.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal :NORMAL;
// 当Back GI 或 Realtime GI 开启时则进行定义 (静态或者动态GI的时候)
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
float4 texcoord1 : TEXCOORD1;
#endif
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD0;
half3 worldNormal : TEXCOORD2;
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
float4 lightmapUV : TEXCOORD1;
#endif
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
#if defined(LIGHTMAP_ON)
o.lightmapUV.xy = v.texcoord1 * unity_LightmapST.xy + unity_LightmapST.zw;
#endif
#if defined(DYNAMICLIGHTMAP_ON)
o.lightmapUV.zw = v.texcoord1 * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
#endif
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
SurfaceOutput o;
// UNITY_INITIALIZE_OUTPUT 将类型的参数都初始化为0 (type,name) -> (类型,变量名)
UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)
o.Normal = i.worldNormal;
o.Albedo = 1;
UnityGI gi;
UNITY_INITIALIZE_OUTPUT(UnityGI,gi)
gi.light.color = _LightColor0;
gi.light.dir = _WorldSpaceLightPos0; // 光照方向
gi.indirect.diffuse = 0; //漫反射
gi.indirect.specular = 0; // 高光
UnityGIInput giInput;
UNITY_INITIALIZE_OUTPUT(UnityGIInput,giInput)
giInput.light = gi.light; // 世界光照的颜色
giInput.worldPos = i.worldPos; // 当前世界坐标
giInput.worldViewDir = normalize(_WorldSpaceCameraPos - i.worldPos); //世界坐标到摄像机位置归一向量
giInput.atten = 1; //光照衰减 平行光默认为1
giInput.ambient = 0; // 周围光照(环境光?)
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
giInput.lightmapUV = i.lightmapUV; // lightmapUV 只在烘焙的时候使用
#endif
// GI间接光照计算,数据存储在gi中
gi = UnityGI_Base(giInput,1,o.Normal);
fixed4 c = LightingLambert(o,gi);
return c;
}
ENDCG
}
}
}
一般情况下,unity 内置的 Standard 材质,几乎是满足绝大部分的一些材质需求,当然这个也使得材质十分的臃肿,以及过多的变体。不过,如果需要找具体某些功能,还是能够从里面去拆解自己需要的部分。
如果觉得Standard嵌套太多,还可以看下表面着色器生成的代码。表面着色器生成后的代码虽然冗长,但是还是能从中找到需要的内容。
表面着色器shader
Shader "Standard"{
......
Pass
{
Name "FORWARD"
Tags { "LightMode" = "ForwardBase" }
.......
#pragma vertex vertBase
#pragma fragment fragBase
#include "UnityStandardCoreForward.cginc"
ENDCG
}Standard.shader -> UnityStandardCoreForward.cginc
#include "UnityStandardConfig.cginc"
#if UNITY_STANDARD_SIMPLE
#include "UnityStandardCoreForwardSimple.cginc"
VertexOutputBaseSimple vertBase (VertexInput v) { return vertForwardBaseSimple(v); }
VertexOutputForwardAddSimple vertAdd (VertexInput v) { return vertForwardAddSimple(v); }
half4 fragBase (VertexOutputBaseSimple i) : SV_Target { return fragForwardBaseSimpleInternal(i); }
half4 fragAdd (VertexOutputForwardAddSimple i) : SV_Target { return fragForwardAddSimpleInternal(i); }UnityStandardCoreForward.cginc -> UnityStandardCoreForwardSimple.cginc
half4 fragForwardBaseSimpleInternal (VertexOutputBaseSimple i)
{
......
UnityGI gi = FragmentGI (s, occlusion, i.ambientOrLightmapUV, atten, mainLight);
}UnityStandardCoreForwardSimple.cginc -> UnityStandardCore.cginc
inline UnityGI FragmentGI(......)
{
.......
return UnityGlobalIllumination
}UnityStandardCore.cginc -> UnityGlobalIllumination.cginc
inline UnityGI UnityGlobalIllumination(......)
{
UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld);
}一顿操作,终于翻到最后需要的内容 UnityGI_Base。具体再解析需要的结构数据,一步步传入,最后返回获取的GI数据。
环境光遮蔽 Ambient Occlusion
环境光遮蔽(Ambient Occlusion,简称 AO)是全局光照明的一种近似替代品,可以产生重要 的视觉明暗效果,通过描绘物体之间由于遮挡而产生的阴影, 能够更好地捕捉到场景中的细 节,可以解决漏光,阴影漂浮等问题,改善场景中角落、锯齿、裂缝等细小物体阴影不清晰 等问题,增强场景的深度和立体感。
可以说,环境光遮蔽在直观上给玩家的主要感觉体现在画面的明暗程度上,未开启环境光遮 蔽特效的画面光照稍亮一些;而开启环境光遮蔽特效之后, 局部的细节画面尤其是暗部阴影会更加明显一些。
而且大部分游戏实际会将阴影直接画在贴图上,或者是额外的贴图做阴影高光等特殊的处理。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|