GameDesign 板


LINE

这篇是 Ray Marching 相关系列的最後一篇, 接着看缘份吧,因为越写越不『超』新手了。 今天我为这篇文章写的 shader 在这: https://youtu.be/P4wCIKMwYlE
没错,有颜色了,这次的主题就是光, 与如何让物件叠加的方法。 (画面里面有『四个』球) 其实要我写『光』的教学文,我感觉超心虚的。 我微积分学的不好,很多东西我只会抄, 一堆相关公式文章wiki根本看不懂在说三只小猫的。 别说我自己写了, 我还希望有哪个大师写给我看勒。Orz 所以... 这篇真的是新手文罗。 [基本知识] 这篇『不会』说到像是用 Game Engine 或是 Blender, 先做几个多边形,然後摆个光源调个强度, 再改一改材质就做会出来的效果。 这篇是新手文,不是大学电脑绘图课。:> 这篇会讲的是体积光 (Volumetric Light)。 体积光是甚麽?体积光也有人叫他 God Light,长这样: https://i.ebayimg.com/images/g/mggAAOSwShpZc31P/s-l500.jpg
早期的电脑绘图,光影效果只出现在实际存在的钢体上。 像是实心的球表面有光暗反射散射等等的效果, 影子也只会出现在实体的地面上, 那些也就是我上面说的大学电脑绘图课会教的东西。 但体积光,就像上面那个天使要降临前的光束, 是在空无一物的空气中出现的。 这种东西就像让光有体积,或是把光当作物体一样看待, 所以就叫体积光。 我们之前二个 shader, 不都有假定世界任何一个点都有密度吗? 只要有密度,就能被光照到, 而且密度不是 1,光就能透过去, 并照到下一个点 (ray marching)。 这概念其实就是体积光。 再换个说法,现实中看的到体积光,是因为空气中有粉尘, 粉尘多寡就代表了该点为中心的某个范围的密度, 所以是很符合物理现实的。 除了体积光,还需要知道一些光的基本常识: 1. 反射 (Reflection) 就国中物理的入射光反射光那些东西, 这篇 shader 没用到,再用 GPU 都要烧起来了。 2 吸收 (Absortion) 光射到一个物体,某些波长会被吸收变成热量之类的, 没被吸收然後反射的部分就是颜色。 3. 透射 (Transmittance) 光可以穿过透明物体,不过会有耗损 (被反射或被吸收了) 所以,Reflection + Absortion + Transmittance = 1.0 透射就是等等程式里的密度, 程式中的光的颜色则是代表了吸收的概念。 大家国中物理一定都学得很好, 所以我们开始看程式吧!(笑) [程式] 程式在这: https://www.shadertoy.com/view/fdycD3 基本逻辑都是继承前二篇的,所以看不懂可以先翻前面的看。 [世界构成] func 跟之前长的一样 void world( vec3 pos, out distance, out density ) 这次世界有四个球,ball_1 ~ ball_4。 虽然前一个范例也有 sky/river 二个物体, 但二者没有任何交集,颜色只是加起来而已。 这是世界的四个球是有重叠的, 这种情况,密度和最短距离要用正确的方法算。 最短距离: 先分别算 pos 对四颗球的最短距离, 然後在四个数字中取最小的。 min( min( min( dis1, dis2 ), dis3 ), dis4 ); 密度: 二种算法, 一种是四个球的密度取最大值。 一种是把四个值加起来。 没有好坏,是叠加处的感觉不同。 我的感觉是透明度越低的,越适合最大值,反之是叠加值。 二种在程式中都有写,可以试试。 [用 ray marching 算颜色] raymarch() 现在不是回传该方向的总密度, 而是直接回传该方向的总颜色了。 vec4 raymarch( in vec3 ro, in vec3 rd ) 要怎麽算某个方向的总颜色呢? 总颜色跟总密度一样, 是 raymarch 的路径上所有的采样点的颜色的总和, 密度高的点颜色占的比例高,密度低的比例低, 比例的高底是放在 color.a 的透明度里面。 计算方法跟总密度的算法几乎一样。 color.a *= 0.4; // 跟范例 (六) 把密度调低在加的意思一样 color.rgb *= color.a; // 照透明度调淡颜色 color_sum += color * (1.0 - color_sum.a); 那要怎麽算出各别的采样点的颜色呢? 假设采样点位置是 pos, 首先,我们有个光源位置: LIGHT_POS = vec3( -2.1, -2.6, 1.2 ), 接着我们可以算出采样点到光源的方向向量。 然後从采样点出发, 往光源方向 ray marching 前进某距离, 再算出 pos 到光源的该距离的总密度 t。 t 代表 Transmittance (透射率), 密度高的路线,光比较不容易射到 pos, 密度低的路线,光比较容易射到 pos, 若 t = 0,光线可以没有任何耗损直接射到 pos。 也就是说, t 越高,光的影响越低, t 越低,光的影响越高。 假设光的颜色是 light_color, 我们就依照透射率比例,加光的颜色加在原本该点的颜色上, 如此就是下面 code 的意思: t = lightmarch( pos, LIGHT_POS ); vec3 light_color = vec3(1.0,0.6,0.3); vec3 ambient_color = vec3(0.91,0.98,1.05); color.rgb = color.rgb * (light_color*(1.0-t) + ambient_color); 那... ambient color 是甚麽? 如果有用 Blender 或任何的游戏引擎做过 3D 游戏都应该用过, 这是 "如果没有任何光源时,物体的基本自体发光"。 你可以把 ambient_color = vec3(0.0), 然後就会发现光照不到的地方都变全黑了。 在做 3D 游戏时, 有 ambient color 其实不太好, 因为不好控制光源效果。 比较好的做法是多放几个光源, 像 direction light 之类的, 但这只是 shader 范例,所以别在意这个了。 [最佳化] 我们一直都没讨论最佳化的问题, 但当你在做光影时,最佳化的问题是避免不了的。 像是我这个范例,在浏览器的 WebGL 跑, 若你拿几千块的手机或是平板, fps 我猜就 10 上下吧。XD 那要怎麽办呢? 首先,我们真的需要对画面上所有的方向做 ray marching 吗? 像前一个例子,做天空时,画面下半部的点可以通通不做 ray march, 做河流时,画面上半部也是一样,马上就可以减少一半的计算。 而以这个四球例子,一般要先算 ro/rd 是否有和任何物体相交, 有相交再做 ray marching。 甚麽? 怎麽知道一条 ro/rd 的光线有没有和四颗球相交? wiki 公式和证明: https://bit.ly/39AgCMz 看不懂在写三只小猫?颗颗,写成 code 是这样: // i remember its from Duke in shadertoy, // but i can't find the origin post, sorry bool inter(v3 ro,v3 rd,v3 pos,f radius,v3 pt) { v3 pos2ro = (ro - pos); float b = dot(pos2ro, rd); float c = dot(pos2ro, pos2ro) - radius*radius; float d = b*b - c; pt = ro + rd*(-b - sqrt(d));//第一个交点 return d >= 0.0; } 不是我写的,给你参考。 还有,光源的 ray marching 采样 可是直接让计算次数以倍数成长的, 到底采样几次,才会达到你预期的效果? 还是只采样最远的那个采样点, 然後照比例算透射率就好? 然後,我们真的需要这麽逼真的表面吗? 不用的话,减少 ray marching 采样次数, 然後调整 noise 参数找到可接受的就好, 像前一个大河的例子, 从 40 次降到 20 次其实也还行。 最後,如果这不是游戏的主要重点, 我们是不是该手动降低 fps, 把资源留给游戏前景呢? 作法只是不用每次都在 main 里叫 ray marching, 加个 timer 减少画面的更新。 [结语] 连写了三篇 ray marching,算是把基本的都讲完了。 靠这三篇的基础,也可以在游戏中做出很炫的东西了。 美丽的夜空、磅礡的大雨、 深海的景象、宇宙、爆炸、通通都做得出来。 但做得出来跟做的漂不漂亮是二回事就是了, 美感是很吃天份的 (我就没有), 请多看看其他神人的作品吧。 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 61.228.104.110 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/GameDesign/M.1655700635.A.0DF.html ※ 编辑: meowyih (61.228.104.110 台湾), 06/20/2022 13:37:10
1F:推 kyushu: 感谢分享,收藏ing 06/20 19:15
2F:推 NciscalA: 推推 06/21 09:36
3F:推 kindamark: 推 06/21 12:46
4F:推 eugenelinrmx: 推分享 06/21 22:59







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP