4000-520-616
欢迎来到免疫在线!(蚂蚁淘生物旗下平台)  请登录 |  免费注册 |  询价篮
主营:原厂直采,平行进口,授权代理(蚂蚁淘为您服务)
咨询热线电话
4000-520-616
当前位置: 首页 > 新闻动态 >
热卖商品
新闻详情
Shader学习笔记(三):Shader中的光照_长三月的游戏开发..._CSDN博客
来自 : CSDN技术社区 发布时间:2021-03-25

这篇文章讨论shader中用到的光照。

理解光照

Unity中的光照技术包括

实时光照 realtime lighting 烘焙后的光照贴图 baked lightmaps 预计算的实时全局光照 precomputed realtime global illumination 实时光照

Unity最基础的光照方式 能够随光线和物体移动实时变化。但是只能处理直射光 无法处理反射光 所以只是一种局部光照。

烘焙后的光照贴图

Unity可以将静态物体的光照信息 包括直射光和反射光 预先烘焙到一张贴图 lightmap 上 供运行时使用 从而避免动态计算。

lightmap的原理是 预先计算整个光照路径 只除去物体表面到摄像机的一段 。

它的优点是省去了运行时计算的代价 缺点是运行时无法改变。

另外一种烘焙方式叫光照探针 light probe 。与lightmap的不同点在于 lightmap烘焙的是射到物体表面的光 而light probe烘焙的是空间中的传播光 可用于静态物体到动态物体的反射。

Unity将光照数据存储在名为Lighting Data Asset的文件中。它是Unity 5.3新增的文件 替代原来的Snapshot。用于存储GI数据 以及render、lightmap、light probe等的引用。

预计算的实时全局光照

预计算静态物体之间所有可能的反射并编码 在运行时再生成间接光照。运行时可以随光源位置、方向、颜色的改变而改变。Unity 5.0支持的新功能 需要设置开启。

优点是既能随光源动态改变 也能降低运行时消耗 缺点是只能针对静态物体。

各种光照技术比较

三种技术典型的应用场景包括

实时光照 移动的角色。烘焙后的光照贴图 场景中静态的物体。预计算的实时全局光照 一天之内的阳光 随时间变化而角度、强度各不相同。

在移动设备上适合用baked lightmaps 在PC上适合用precomputed realtime GI。

光源类型 名字英文名解释点光源point light从一个点向四面八方发射 类似电灯泡锥形光spot light从一个点以锥形发出 类似手电筒有向光directional light以固定方向平行发出 类似太阳区域光area light光线限制在一个矩形区域内 固定从一侧以任意角度发出环境光ambient light光在场景中无处不在 不从特定物体发出 理解阴影

unity中的阴影分为实时阴影和阴影贴图。

实时阴影 实时光产生的阴影。要使用这种阴影 需要在产生的物体上开启投射 cast 在投影到的物体上开启接收 receive 。阴影贴图 以贴图方式实现的阴影。这种方式可以降低运行时消耗 但是阴影的大小、形状都是固定的。 shader中的光照

光照是如何影响我们的视觉的呢 事实上 我们之所以能看到物体 除去那些能自发光的物体外 如灯泡 都是因为光线射到物体表面再反射到我们眼睛中。一个物体之所以呈现不同颜色 那是因为它对光的不同颜色分量的反射率不一样。例如 红色的物体对于红光几乎全部反射 而对于绿光和蓝光几乎全部吸收。所以 物体最终呈现在我们眼中的颜色 取决于反射光和自发光的叠加。

不同的光照模型对于反射光的处理大不一样。Unity中内置了两种光照模型 Lambert光照是漫反射 光线射过去向四面八方反射 适合于普通较粗糙的材质 BlingPhong光照是镜面反射 适合光滑如镜的材质。这两种光照就可以涵盖绝大多数情况。除此之外 我们也可以根据需求自己定制光照模型。

Unity中可以使用Surface Shader或者Vertex/Fragment Shader来处理光照。对于前者 需要自定义光照处理函数 对于后者 则需要在vert函数中做varying变量的赋值 而在frag函数中处理光照。对于Surface Shader和光照函数在渲染管线中的位置 可以看图 来自知乎
\"这里写图片描述\"

可以看到 surf函数和光照都位于Fragment Shader中 两者是紧挨着的关系。

实例解析

以下均为Unity Manual中的例子。

Surface Shader中的光照 DiffuseTexture 与Lambert光照等效的实现。自定义光照类型SimpleLambert 对应的函数在surf之后执行。计算顶点颜色涉及到的参数 片元的法向量、光入射角度、光的rgba和衰减、片元的Albedo。

\"这里写图片描述\"

 Shader Example/Diffuse Texture { Properties { _MainTex ( Texture , 2D) white {} SubShader { Tags { RenderType Opaque } CGPROGRAM #pragma surface surf SimpleLambert half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) { half NdotL dot (s.Normal, lightDir); half4 c; c.rgb s.Albedo * _LightColor0.rgb * (NdotL * atten); c.a s.Alpha; return c; struct Input { float2 uv_MainTex; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) { o.Albedo tex2D (_MainTex, IN.uv_MainTex).rgb; ENDCG Fallback Diffuse  }
SimpleSpecular 与BlingPhong光照等效的实现。计算顶点颜色涉及到的参数 视角、片元的法向量、光入射角度、光的rgba和衰减、片元的Albedo。

\"这里写图片描述\"

 ...ShaderLab code... CGPROGRAM #pragma surface surf SimpleSpecular half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) { half3 h normalize (lightDir viewDir); half diff max (0, dot (s.Normal, lightDir)); float nh max (0, dot (s.Normal, h)); float spec pow (nh, 48.0); half4 c; c.rgb (s.Albedo * _LightColor0.rgb * diff _LightColor0.rgb * spec) * atten; c.a s.Alpha; return c; struct Input { float2 uv_MainTex; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) { o.Albedo tex2D (_MainTex, IN.uv_MainTex).rgb; ENDCG ...ShaderLab code...
Vertex/Fragment Shader中的光照

要使用光照 首先需要在pass tag中设置LightMode 从而定义各种rendering path。常见的选择有

关键字意义解释ForwardBaseforward rendering使用关键光照信息立即渲染Deferreddeferred shading使用所有光照信息延迟渲染ShadowCastershadow caster投射阴影所必需 通常与ForwardBase或Deferred配合使用 SimpleDiffuse 与Lambert光照等效。需要在vert和frag中做处理。

\"这里写图片描述\"

Shader Lit/Simple Diffuse  Properties [NoScaleOffset] _MainTex ( Texture , 2D) white {} SubShader Pass // indicate that our pass is the base pass in forward // rendering pipeline. It gets ambient and main directional // light data set up; light direction in _WorldSpaceLightPos0 // and color in _LightColor0 Tags { LightMode ForwardBase } CGPROGRAM #pragma vertex vert #pragma fragment frag #include UnityCG.cginc // for UnityObjectToWorldNormal #include UnityLightingCommon.cginc // for _LightColor0 struct v2f float2 uv : TEXCOORD0; fixed4 diff : COLOR0; // diffuse lighting color float4 vertex : SV_POSITION; v2f vert (appdata_base v) v2f o; o.vertex UnityObjectToClipPos(v.vertex); o.uv v.texcoord; // get vertex normal in world space half3 worldNormal UnityObjectToWorldNormal(v.normal); // dot product between normal and light direction for // standard diffuse (Lambert) lighting half nl max(0, dot(worldNormal, _WorldSpaceLightPos0.xyz)); // factor in the light color o.diff nl * _LightColor0; return o; sampler2D _MainTex; fixed4 frag (v2f i) : SV_Target // sample texture fixed4 col tex2D(_MainTex, i.uv); // multiply by lighting col * i.diff; return col; ENDCG}
ShadowCasting 实现阴影投射。定义了两个Pass LightMode分别是ForwardBase和ShadowCaster。

\"这里写图片描述\"

Shader Lit/Shadow Casting  SubShader // very simple lighting pass, that only does non-textured ambient Pass Tags { LightMode ForwardBase } CGPROGRAM #pragma vertex vert #pragma fragment frag #include UnityCG.cginc  struct v2f fixed4 diff : COLOR0; float4 vertex : SV_POSITION; v2f vert (appdata_base v) v2f o; o.vertex UnityObjectToClipPos(v.vertex); half3 worldNormal UnityObjectToWorldNormal(v.normal); // only evaluate ambient o.diff.rgb ShadeSH9(half4(worldNormal,1)); o.diff.a 1; return o; fixed4 frag (v2f i) : SV_Target return i.diff; ENDCG // shadow caster rendering pass, implemented manually // using macros from UnityCG.cginc Pass Tags { LightMode ShadowCaster } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_shadowcaster #include UnityCG.cginc  struct v2f {  V2F_SHADOW_CASTER; v2f vert(appdata_base v) v2f o; TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) return o; float4 frag(v2f i) : SV_Target SHADOW_CASTER_FRAGMENT(i) ENDCG}

本文链接: http://lambertsimp.immuno-online.com/view-777352.html

发布于 : 2021-03-25 阅读(0)
公司介绍
品牌分类
联络我们
服务热线:4000-520-616
(限工作日9:00-18:00)
QQ :1570468124
手机:18915418616
官网:http://