平行光
根据当前摄像机位置和平行光方向向后拉开一定距离并创建一个shadowmap摄像机(CameraPos - LightDir * Length),然后渲染出shadowmap,shadowmap无非就是把shadowmap摄像机看到的物件都简单渲染一遍,将物体的深度信息写到shadowmap里
然后在光照pass的时候,渲染物件每个像素时,需要比较当前像素的深度值和与贴图里记录的深度值大小,如果贴图比较小,表示当前像素在灯光的角度上看被其他物体所覆盖,所以是其他物体的深度,这种情况需要生成阴影。而如果相等或接近的话表示是当前的物体,则不需要阴影。
当需要生成阴影时,用一个阴影系数表示阴影强弱即可,如果是1,表示没有阴影,0表示阴影。最后乘上漫反射的系数就可以了
性能开销:一盏平行光就需要一张Shadowmap,如果是前向渲染的话,需要带了2*N的DC,一个用来渲染shadowmap,一个用来计算光照
点光源
点光源只要光照pass的时候,把点光源的位置、颜色、范围传进shader里即可。这样就可以根据当前像素的位置和光源的位置算出受光的方向,然后将光的方向和normal算出角度,然后进行点乘算出漫反射系数。至于灯光强弱的话,其实只要算出像素实际与灯光的距离,用这个距离除以灯光的范围以后会得到一个用来表示与灯光远近的系数,越近值越小,越远值越大。这个时候只要采样一张ramp贴图(条形渐变色贴图),一张N*1的贴图,从左到右由白到黑。只要采样这张贴图,就能控制越近越亮越远越暗的效果。当然如果是线性的话也可以不采样贴图
而且为了只给点光源范围内的像素上色,还得用模版测试,先根据点光源的模型先设置基础值,再画一遍进行测试,这样只有点光源范围内的像素会有变化,点光源范围外的像素不会有任何变化
当然这个只是我现阶段所知道的点光源的实现,这个并没有解决环境遮蔽的问题。当然不排除环境遮蔽需要通过后期再算。
另外最近听说有种叫体素灯光的点光源,貌似性能很好,不过还没仔细研究
射灯
就是跟手电筒一样的光源,需要结合点光源和平行光所涉及到的知识。首先先制作射灯模型同点光源一样做模版测试,只影响射灯模型内的像素。射灯的模型一般是由5个顶点组成,近处一个点,远处一个矩形面,将点与矩形面上的点连接起来组成射灯模型。需要用到3张贴图,1张shadowmap,1张ramp贴图,1张Mask贴图。因为射灯不像点光源,它有方向所以可以用shadowmap制造阴影效果。shadowmap同平行光一样弄个摄像机渲染就好了,ramp也同点光源一样,可以做近亮远暗的效果。然后Mask贴图的用处主要是因为。这样的话为了实现射灯远处是圆形的效果,就需要将像素坐标转到Mask的uv坐标,判断是否在圆形范围内,来实现裁剪效果
射灯的模型之所以一般不用圆形面,虽然可以省一张贴图,但用多个三角形组成的圆形总归只能近似,所以会有些误差。不用Mask自定义圆形边缘的强弱程度的话,边缘会比较硬,所以这种实装的效果比较差