从shader说Unity阴影的实现理念

这篇文章并不是谈代码里怎么实现,而是阴影效果的实现理念。先有概念上的理解,才有代码的实现。

现实里,阴影是怎么出来的?是光朝某个方向照射,有一部分照在了前面的物体上,造成在后面的物体上亮度出现差别。亮度低的地方就被我们认作是阴影。

可以说没有阴影这回事,只有光,只要物体表面的光是正确的,那么阴影就自然出来了。

在刚开始接触3D世界里的阴影的时候,我在想,光照不是已经算出来来了吗?那么阴影应该自动出现了。可实际上在Unity里计算物体的光照时,我们是认为光能够照到任何地方的。比如漫反射:

fixed3 diffuse = _LightColor0.rgb * saturate(dot(lightDir, i.worldNormal)) * albedo;

这里的_LightColor0是光照,我们并没有做任何的判断,何时_LightColor0有何时没有,拿来就用。

如果要按照现实同样的逻辑来计算阴影,那么就要判断光照何时没有,也就是在当前的基础上做减法。但实际并不是这么做,而是做加法

理念1: 把阴影看做是一种特殊的光,在原来的物体表面覆盖上去。

如果你用电脑画过画就会很容易理解,在画图时给一个部分加阴影的做法是:新开一个图层,放在原色图层的上面,然后设置成正片叠底的模式,在这个图层用灰色画就可以达到阴影的效果。正片叠底其实就是颜色叠加,在一个颜色上面叠加灰色,原颜色性质保持,就是变暗了,跟阴影效果符合。

用代码解释:

color x = (a,b,c);    //rgb分量分别是a b c
color shadow = (0.9, 0.9, 0.9);   //灰色作阴影,每个通道值是在[0,1]
color y = x * shadow = (a * 0.9, b * 0.9 , c * 0.9);  //颜色混合效果就是各通道分量相乘

这样做剩下的问题就是找到那些地方有阴影这种特殊的光,在计算物体颜色的时候,做一个乘法就搞定了。

哪些地方有阴影呢?先看一束光,假设位置A和B在同一束光里,那么谁在后面谁就有阴影。可以想象一下烤串的样子,只有第一个有光,后面的都在阴影里。

所以,如果我可以建立一个数据表,把一个光源所有方向第一个被照到的位置记录下来。那么对于新的位置A,就在这个数据表里找到同一束光第一个位置B,如果A比B近一些,那么A就变成了这束光第一个被照到的地方,且A就没阴影,反之就有A就在阴影里。

对于一个光源来说,我只要维持一个这样的数据表,就可以把阴影的问题搞定了,这个数据表就是阴影映射纹理。纹理这类东西,就是你给一个xy坐标,它返回给你一个特定的值,在这里,这个xy坐标就是用来定位这束光的坐标,而返回的值就是阴影的颜色,如 (0.9, 0.9, 0.9)。

这个逻辑其实跟深度纹理是类似的。

理念2:使用阴影映射纹理

那么问题就转化成了如何定位一束光?
解决方案就是建立一个光源自身的坐标体系(即光源空间),而这个坐标系的xy位置就是用来定位每一束光的。

关于光源空间怎么定义的,下面是我的猜测。

比如对于平行光,平行光没有光源位置概念,只有方向。那么我把光照射方向作为Z轴,与光照射方向垂直的面设为xy轴平面。那么是不是xy值就可以定位一束光的呢?我觉得是的。两个点如果xy值一样,那么他们肯定在同一束光里,因为Z轴方向就是光的方向。

对于点光源,光是球形的发散出去的。光的方向是变化的,那么xy轴该怎么搞?在3D图形空间变换里有一部分,是把顶点从相机空间转变到裁剪空间里去,也就是把照相机的那个有视锥体转变成xyz都是[-1,1]范围的一个立方体。那么光源这里可以同样采用这种变换手段,只是这时是360度的视角。

发散一下,假如光会拐弯,那么xy平面就取垂直于光线的一个平面,这个平面可能是一个凹凸不平的面,把这个不平的面展开成平面就好了,就跟不平的模型表面的纹理坐标一样。这样的截面只需要一个就可以,比如就取包含光源本身的那么面。

对于一个点A,如果不在这个截面里,就可以沿着光线的回流,直到找到同一束光线上的xy截面的点B,这个点B和A具有相同的xy值。

(突然隐约想到流体分析里是不是用了这样的想法。)

理念3:建立光源空间里定位每一束光。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容