烘焙是针对静态物体的
烘焙贴图的精度影响物体的效果
这些物体都是静态的,这些物体使用的材质都是默认的diffuse材质。
第一次设置其分辨率为:
可以看到明显的明暗分界线。
第二次设置为:
明显好一点。
第2,如何采样烘焙贴图的数据
下面是初步的shader:My Lighting.cginc
#include "AutoLight.cginc"struct VertexData
{float4 vertex:POSITION;float2 uv1:TEXCOORD1;
};struct Interpolators
{float4 pos:SV_POSITION;float2 lightmapUV:TEXCOORD1;
};struct FragmentOutput
{float4 color:SV_Target;
};Interpolators MyVertexProgram(VertexData v)
{Interpolators i;i.pos = UnityObjectToClipPos(v.vertex);i.lightmapUV = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw;return i;
}FragmentOutput MyFragmentProgram(Interpolators i)
{FragmentOutput output;output.color = float4(DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.lightmapUV)),1);return output;
}
Shader "Unlit/My First Lighing Shader"
{Properties{}SubShader{Pass{Tags{"LightMode" = "ForwardBase"}CGPROGRAM#pragma vertex MyVertexProgram#pragma fragment MyFragmentProgram#include "UnityCG.cginc"#include "My Lighting.cginc"ENDCG}}
}
针对上面的程序,我简单的做一个小节:
在cginc文件中,我们定义了顶点处理函数,片元处理函数。
使用 i.lightmapUV = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw;方法计算光照贴图纹理坐标。
使用float4(DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.lightmapUV)),1);进行采样光照贴图。
在shader文件中,定义了一个ForwardBase路径,此段shader非常简单,完成了对光照贴图的采样。
增加forwardadd通道
关于这个通道存在的意义,我要详细的说明一下。
1、unity为什么要提供一个add通道呢?
2、什么是像素灯呢?
3、unity里面最多支持多少个像素灯呢?
4、如何改变默认的像素灯的个数呢?
5、每个像素灯在哪里通道渲染呢?
6、多个像素灯,怎么取得灯光的颜色呢?
7、forwardadd通道对于静态物体和动态物体的都有用吗?
下面我们来一个一个解答这些问题。
1、unity为啥要提供一个add通道呢?
首先forwardadd通道是针对向前渲染的,其他的渲染方式如逐顶点渲染或者延迟渲染是没有forwardadd通道的。
其次,要查下unity的官网是如何介绍的:
https://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html
Note that when “OnlyDirectional” pass flag is used in the shader, then the forward base pass only renders main directional light, ambient/lightprobe and lightmaps (SH and vertex lights are not included into pass data).
基础通道
一个平行光且是像素灯还有其他的所有的顶点灯/SH都在这个通道计算。
这个通道还用来计算光照贴图,环境光,以及自发光。
这个通道计算的平行光可以计算阴影。
注意使用光照贴图的物体不接受SH光照,因为直接使用光照贴图。
注意当使用标签"OnlyDirectional"通道标志,那么基础通道则只能渲染主要平行光,环境光/光探针以及光照贴图。(SH和顶点光则不能在这个通道计算)。
**Additional Passes** Additional passes are rendered for each additional per-pixel light that affect this object. Lights in these passes by default do not have shadows (so in result, Forward Rendering supports one directional light with shadows), unless multi_compile_fwdadd_fullshadows variant shortcut is used. 附加通道 附加通道是针对每个额外的像素灯进行渲染计算的通道。这个通道的灯光默认是没有阴影计算的。因此向前渲染只支持一个平行光的阴影计算。除非使用multi_compile_fwdadd_fullshadows 增加shader的特性。ok,到这里还是一头雾水,那么还是要再组织下逻辑。
首先,基础通道只能计算一个最重要的像素灯。还可以进行光照贴图的采样。
然后,其他的像素灯则要放在附加的通道中计算。
这就是最简洁的描述了。
2、什么是像素灯呢?
明白像素灯的前提是明白渲染方式,在https://docs.unity3d.com/Manual/RenderTech-VertexLit.html
提到了逐顶点渲染的方式:
顶点渲染路径通常在一个通道渲染每个物体,按照逐顶点的方式计算所有灯光对其影响结果。它是最快的渲染路径。也因为是按照逐顶点的方式计算,此渲染路径不支持基于像素的效果:比如,阴影,法线映射,灯光cookies,还有镜面反射灯。
所以像素渲染,是顶点经过光栅化之后,对每个像素进行计算渲染结果。所以这个灯到底是否是像素灯,则要看摄像机采样何种渲染路径。
3、unity里面最多支持多少个像素灯呢?
4、如何改变默认的像素灯的个数呢?
这个在QualitySettings中进行设置:
关于这里还要再次说明一下,如果一个灯强制设置为important,那么即使超过了这里设置的数字,这个灯依然会作为像素灯继续处理。
这里的数字,只会对那些全部是auto模式灯才有作用,如果所有的都是auto,那么像素的灯的个数最多为这个默认设置的数字,当然你可以调整为其他数字。
5、每个像素灯在哪里通道渲染呢?
上面已经说过,forwardbase通道只支持一个像素灯的计算,其他的像素灯则安排在forwardadd通道计算。
6、多个像素灯,怎么取得灯光的颜色呢?
举例说明:
如果有4个像素灯,分别为A、B、C、D,而且他们的重要程度依次递减,那么A则在Base中渲染,其余的灯则在Add中渲染。
可以使用FrameDebug工具,查看每个灯的渲染结果。
如何取得颜色,其实很好理解,无论是在Base中还是在Add中,都可以使用_LightColor0来取得ABCD灯的颜色。因为他们是串行执行的渲染,所以当处理A的时候,这个_LightColor0则是A的颜色;在处理B的时候,这个_LightColor0则是B的颜色,以此类推。
那有人会问,最终到底是什么颜色,这要看你是怎么混合的,在forwardadd中,你是使用one zero混合还是其他的混合模式,这个最终影响颜色的结果,但是渲染的每个步骤,都是可以再framedebug中看到其物体颜色的变化。
7、forwardadd通道对于静态物体和动态物体的都有用吗?
forwardadd,并不区分什么是静态物体还是动态物体。它对这个没有概念。首先要明白,这两个完全不是同一个问题,之所以混淆,搞不清楚,是因为不知道如何写自定义的shader去采样烘焙结果。下面详细的讲解下。
首先,静态物体和动态是什么?
静态物体顾名思义,就是场景中不会动的物体,如建筑、花草、树木、高山等,这些都是不会像主角一样,到处乱跑。
那么unity为了实现光影效果,对这些静态物体提供了一个标签,用来标记这些物体是静态。
静态的好处是什么呢?
这样和计算光照搭上了,首先实时光照是计算了光对物体的影子效果,而且物体走到哪里,影子就要跟随到哪里,这就是实时的计算。
那么能不能对静态物体不要实时计算影子呢?不要实时计算灯光对静态物体的影响呢?以及考虑灯光打到一个物体上,这个灯光会再次被反射,然后去影响其他的物体,这个光线跟踪的开销在实时计算中,肯定会很耗,所以unity在实时计算的时候只是计算一次光照对物体的影响,而没有考虑多次反射灯光的效果,这个也就是直接光照的术语了。
而经过其他物体的反射光的影响,实时灯光不计算,那么必然损失了很多的立体感觉。unity是如何解决的呢?答案是通过烘焙,将物体之间的反射光经过预先烘焙到一个贴图上,然后去采样即可实现间接光的效果。
这样最终的效果如果是:直接光+间接光=最终效果,具有很好的立体感、真实感。
所以静态物体,动态物体是针对烘焙来讲的,和渲染路径没有关系。
然后回到这个问题,那么一个物体的渲染,则是需要用到材质,材质就对应了shader,材质和shader的关系,就是一个是产品、一个是加工过程。什么样的算法实现是在shader中写的,最终的效果是shader算出的结果也就是材质。
那么问题来了,如何去渲染一个物体呢?这里有forward渲染方式,所以foward是和渲染相关。
一个物体是静态的,那么依然是可以使用forwardadd路径渲染的,比如说,你烘焙之后,我们并不一定要使用光照贴图,完全可以自己写shader去改变它的颜色,这个完全可以做到。那么计算的时候,你可以给他任意的颜色,可以有多个实时光去影响这个物体,这个和烘焙、静态与否没有半点关系。
唯一要做的是保证正确性,一个物体是静态的,那么其目的是在烘焙中使用,而烘焙之后,会得到光照贴图。得到了光照贴图,你自然会想到如何去使用这个贴图,那么怎么使用呢?哦,光照贴图是在fowardbase中去采样计算。那么forwardadd呢对其是否还有作用,当然可以有也可以没有,什么时候有作用呢,在场景中还有其他的实时的像素灯,超过一个,因为第一个重要的实时灯在forwardbase中计算,这里所说的实时,是灯光的模式为realtime,或者是mixed,而不是baked模式,因为baked模式全部被烘焙到光照贴图了,这个灯就没用了。只有realtime或者是mixed则还可以用于实时计算。那么此时就要用到forwardadd通道。
这里就介绍到这里,关于如何对于透明物体、半透明物体、cutoff物体、以及阴影下一节在详细介绍。