发布时间:2024-01-16 14:02:24 浏览量:168次
关注“indienova”,挖掘独立游戏的更多乐趣
大萌喵现在还只是学生党一枚, 对图形学和渲染技术的理解依然比较肤浅, 如果文章中有不明确甚至出错的地方, 烦请前辈们斧正啦~
OK, 我们进入Warming Up环节。
相交高亮, 是一种附加在Mesh上的着色器特效, 其功能是将所有其他穿过该Mesh表面的截面轮廓绘制出来, 产生一种类似于扫描一样的效果。 多用于科幻类游戏中。
在这里大萌喵要检讨下 ... 这种相交高亮的特效出现的频次真心不低, 我能确切想起来的实际应用游戏便有杀戮地带系列,质量效应系列,泰坦陨落系列和死亡空间系列. 不过大萌喵在youtube上找了好几圈也没有找到一个包含了这个效果的视频 ... 所以说只能贴上这张图啦.。(喵, 下次玩游戏要边玩边截图了哈哈哈哈)
根据摄像机的CameraDepthTexture(深度纹理? 不知道这么翻译对不对)绘制相交区域的高亮颜色。
对着色器的混合模式, 深度测试, 点元着色器和片元着色器有一定了解. 写作过程中我也会贴上一些可供查阅的资料。
我顺带着也打算讲解下一个坐标转换的原理, 如果想要看懂的话需要一定的线性代数基础。
你会知道一种优雅地使用DepthBuffer的方法。
以及, 说好的源代码。
大萌喵.不正常模式.SetStatus(false);
大萌喵.SetFace (Face.严肃脸);
获取当前摄像机渲染的场景的DepthBuffer, 在渲染当前模型的时候判断每一个经过坐标变换的片元的世界坐标Z是否和DepthBuffer的对应点深度足够接近. 如果足够接近, 则将其渲染成另一种颜色.
还是那个熟悉的水壶, 只不过加上了一台优雅的Macbook(不过为毛那个桌面长得有点像OpenSUSE)和一个凌空飞舞放荡不羁的键盘。当然了这不关键, 关键的是后面的那个黄色的正方体。
我们要实现的就是那个正方体的材质. 从图中我们清楚的看到, 水壶, 电脑和键盘在正方体外面的部分是非常正常的, 在正方体内部的部分蒙上了一层黄色。 但是和正方体的相交截面的外轮廓被绘制成了蓝颜色。
到此, 我们能够推断出来的事实有:
Blend Mode为: Blend SrcAlpha OneMinusSrcAlpha 原因很简单, 因为我们能够通过正方体看到其后面的物体, 这说明正方体本身的颜色和原本的ColorBuffer的Alpha值被"平分秋色"后进行了混合。 依然看不懂的童鞋请参见Unity官方文档(http://link.zhihu.com/?target=
https%3A//docs.unity3d.com/Manual/SL-Blend.html).
RenderQueue为Transparent 很明显, 我们当然是希望这个正方体在Geometry后渲染出来, 这样才能透过它看到优先渲染的Opaque Materials. 关于Render Order的详细描述可以看Unity官方文档(http://link.zhihu.com/?target=
https%3A//docs.unity3d.com/462/Documentation/Manual/SL-SubshaderTags.html)。
正因为我们的正方体是被后渲染出来的, 所以我们可以通过当前的ColorBuffer或者是DepthBuffer等资源来以某种方式处理相交截面。
但是不管截面到底是怎么被处理出来的, 我们必须得知道屏幕上某点的世界坐标相对于正方体某个片元的世界坐标的相对关系。
很明显, 我们要做的就是优雅地解决第四个问题。
可以通过DepthBuffer, 摄像机Near Clip Plane, Far Clip Plane, Field of View来计算出屏幕上每一个点的世界坐标, 但是传统的在片元着色器中计算世界坐标的方式是处理后依次乘以世界-视图矩阵的逆, 效率堪忧。 就算利用点元着色器预先计算视椎体射线, 效率有了些许提升, 也远远达不到"优雅"的水准。
(PS: 我会在后面的文章中详细介绍Global Fog后期处理特效, 其中会对在片元着色器中通过DepthBuffer计算世界坐标的方法展开讨论。 )
说了这么多, 我们发现直接求世界坐标这种套路最直接, 最好理解, 但似乎并不太可取. 那么我们就要思考一个问题: 我们真的必须得知道具体的世界坐标嘛?
通过观察上面的那张图, 我们发现为了确定如何渲染并混合颜色, 我们只需要知道相对于摄像机来讲, 正方体的片元和原本场景中对应位置的像素谁离得更远就行了。 也就是说, 我们只需要知道两个三维向量的长度, 也就是两个实数, 而并不需要知道这两个三维向量的xyz都分别是什么。
所以说, 求世界坐标的话有点儿杀鸡用牛刀了。
如果你不知道DepthBuffer, 或者是Unity的CameraDepthTexture, 那么强烈建议你谷歌下, 要不然接下来的东东就都GG了。
我们是如何知道一个片元的投影坐标的呢? 恐怕下面这段代码你都看烂了:
o.pos = mul ( UNITY_MATRIX_MVP, v.vertex );
我甚至不用说出o和v的变量声明以及这段代码出自何处, 你就知道我在说什么了。 (语气颇像 ... 额, 专栏还是要办下去的, 打住)
所以说我们要怎么通过世界坐标来将其xy映射到[0, 1]区间呢? 毕竟只有这样我们才能采样DepthBuffer啊! 不用担心, Unity都替我们做好了: 在UnityCG.cginc中, 有这么个函数:
当然了并不是要调用它, 而是要使用ComputeScreenPos函数:
呐, 带着编译器指令原封不动地搬过来, 大家看起来肯定有点方. 其实大多数情况下, ComputeScreenPos函数可以重写成以下形式:
传入Clip Space坐标pos, 最终输出xy在[0, 1]之间, z值为Camera Space深度的结果。
不过 ... 这个函数什么鬼 ... 拿到了Clip Space坐标先乘个0.5 ... 然后 ... 还要加上w分量的二分之一?
大萌喵接下来打算稍微介绍下这个函数的原理. 如果你之前对坐标转换不是很了解, 大萌喵提供了几个链接, 可供参考:
learnOpenGL(神启蒙教程):
http://link.zhihu.com/?target=http%3A//learnopengl.com/%23%21Getting-started/Coordinate-Systems
scratchapixel.com :
http://link.zhihu.com/?target=http%3A//www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/projection-matrix-GPU-rendering-pipeline-clipping
神书:
http://link.zhihu.com/?target=https%3A//books.google.co.uk/books%3Fid%3DmNw_CQAAQBAJ%26pg%3DPA14%26dq%3Dhomogeneous%2Bcoordinate%2Bin%2Bthe%2Bfixed-function%2Bpipeline%26hl%3Den%26sa%3DX%26ved%3D0ahUKEwiE7-rk8crJAhUDPhQKHSzSCJQQ6AEIIzAA%23v%3Donepage%26q%3Dhomogeneous%2520coordinate%2520in%2520the%2520fixed-function%2520pipeline%26f%3Dfalse
如果你觉得Math = Mental Abuse To Human(对人类的精神侮辱), 那暂时略过也无所谓。 ComputeScreenPos当成黑盒子使用也没什么问题。
首先上一张图:
在Unity中,mul ( UNITY_MATRIX_MVP, v.vertex )和UnityObjectToClipPos(float4 ( v.vertex.xyz, 1.0 ) )干的差不多都是一回事儿, 就是将模型坐标转换到摄像机的Homogeneous Clip Space. 详情参加官方文档(http://link.zhihu.com/?target=
https%3A//docs.unity3d.com/Manual/SL-BuiltinFunctions.html)。
但是, 一般渲染管线不会立刻将Clip后的坐标标准化(也就是除以w分量. 不知道w分量代表什么的童鞋 ... 请先补课), 而是在点元着色函数结束以后将其标准化. 这个地方有点坑.
(原文摘录如下: Once all the vertices are transformed to clip space a final operation called perspective division is performed where we divide the x, y and z components of the position vectors by the vector's homogeneous w component; perspective division is what transforms the 4D clip space coordinates to 3D normalized device coordinates. This step is performed automatically at the end of each vertex shader run.)
所以, 可以认为我们现在得到的是已经经过Clipping, 但是还没有标准化的投影坐标. 我们的目的是要将这个坐标转化为xy在[0, 1]之间, 而z反映深度的屏幕坐标.
既然是[0, 1]之间, 那么我们自然就不用向上图一样乘以ViewPort宽高了. 同时要注意ViewPort坐标原点的问题: Unity中是左下角, 而上图采用的是左上角. 所以具体到我们的情况下y和x的处理方式应该是相同的.
为了将[-1, 1]映射到[0, 1]上, 将原坐标加1然后除2是显而易见的. 但是要注意我们的x和y都比人家多乘着一个w分量. 因为运算到这个时候我们依然在点元着色器函数中, 因此最终的标准化过程还没有执行.
所以, 我们就得到了下面这段代码(其实也是上面那段)
float4 o = pos * 0.5;
o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
如果没想清楚是怎么转过这个弯来的 ... 对比上图倒数第二个框框和上面的文字就OK了.
(如果我不是手贱翻了下ComputeScreenPos的源代码, 也就没这么多麻烦事儿了哈哈哈)
在片元着色器中, 我们只需要提取出对应屏幕位置的深度信息, 然后和点元着色器的输出深度信息作比较, 根据相差结果进行插值即可.
不知道那个插值是怎么回事儿的童鞋, 请动用C语言的思考模式, 写个if出来, 然后想办法消除掉这个if.
虽然话说回来就算这有个if也不算动态分支, 对性能的影响不太大 ... 但还是养成良好的习惯吧.
其实这个特效的原理真心一点也不复杂, 只是用到了DepthTexture来获取屏幕中每个像素的深度信息来进行比对以决定模型最终的颜色. 但是UnityCG.cginc里面的ComputeScreenPos函数那个奇怪的外观引发了我极大的好奇心.
大萌喵是个学生党, 非常热切地希望能和诸位前辈们交流! 如果文章中存在任何疏漏, 不足, 或错误之处, 希望您能批评指正! 谢谢!
Preview: 大萌喵最近对DepthTexture有点着迷呀, 下几次打算讲讲Global Fog, Volumetric Light Scattering和Edge Detection. 不过中间也会夹杂一些小的好玩儿的着色器效果 ~
想了解更多?请点击下方
阅读原文
热门资讯
探讨游戏引擎的文章,介绍了10款游戏引擎及其代表作品,涵盖了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戏设计领域和数字艺术教育的重要性,欢迎点击咨询报名。
2. 手机游戏如何开发(如何制作传奇手游,都需要准备些什么?)
如何制作传奇手游,都需要准备些什么?提到传奇手游相信大家都不陌生,他是许多80、90后的回忆;从起初的端游到现在的手游,说明时代在进步游戏在更新,更趋于方便化移动化。而如果我们想要制作一款传奇手游的
3. B站视频剪辑软件「必剪」:免费、炫酷特效,小白必备工具
B站视频剪辑软件「必剪」,完全免费、一键制作炫酷特效,适合新手小白。快来试试!
游戏中玩家将面临武侠人生的挣扎抉择,战或降?杀或放?每个抉定都将触发更多爱恨纠葛的精彩奇遇。《天命奇御》具有多线剧情多结局,不限主线发展,高自由...
5. Bigtime加密游戏经济体系揭秘,不同玩家角色的经济活动
Bigtime加密游戏经济模型分析,探讨游戏经济特点,帮助玩家更全面了解这款GameFi产品。
6. 3D动画软件你知道几个?3ds Max、Blender、Maya、Houdini大比拼
当提到3D动画软件或动画工具时,指的是数字内容创建工具。它是用于造型、建模以及绘制3D美术动画的软件程序。但是,在3D动画软件中还包含了其他类型的...
7. 3D动漫建模全过程,不是一般人能学的会的,会的多不是人?
步骤01:面部,颈部,身体在一起这次我不准备设计图片,我从雕刻进入。这一次,它将是一种纯粹关注建模而非整体绘画的形式。像往常一样,我从Sphere创建它...
8. 如何自己开发一款游戏(游戏开发入门必看:五大独立游戏开发技巧)
游戏开发入门必看:五大独立游戏开发技巧无论您是刚刚起步开发自己的第一款游戏,还是已经制作了几款游戏,本篇文章中的5大独立游戏开发技巧都可以帮助您更好地设计下一款游戏。无论你对游戏有着什么样的概念,都
三昧动漫对于著名ARPG游戏《巫师》系列,最近CD Projekt 的高层回应并不会推出《巫师4》。因为《巫师》系列在策划的时候一直定位在“三部曲”的故事框架,所以在游戏的出品上不可能出现《巫师4》
想让你的3D打印模型更坚固?不妨尝试一下Cura参数设置和设计技巧,让你轻松掌握!
同学您好!