分享一种快捷的用于Unity全屏Blit的DrawMesh方法

有时候

我会想简单的全屏输出点什么来看,但是又懒得专门写个Feature去调用底层DrawMesh或者DrawProcedual方法,那么有没有什么懒人包可用么?也许可以张罗一块Quad,然后调整到既能覆盖住摄像机视窗又与某个裁剪面平行。这自然是一种可行的方案,但是弊端也是极大的,比如说我们必须保证摄像机和Quad保持相对静止,再者调整Quad的手动操作也是个吃力的麻烦活。那么到底有没有轻巧快捷的全屏Mesh绘制方案呢?答案是有!下面我分享的就是自己常用的一种方法,虽然猜测有人早已给这种方法取了名字,但是胡Cares?知道怎么用就行。

原料有二,首先是需要准备一块Unity的Quad作为基础Mesh

Quad

除此之外,就只需要再配合一份特制的shader就可以愉快地向全屏输出你的渲染了(确切的说只有VS是特制的shader):

v2f vert (appdata v)
{
    v2f o = (v2f)0;
    //o.vertex = TransformObjectToHClip(v.vertex); //默认方法,可行,但是需要提前布置正确Quad位置 
    o.vertex = float4(v.vertex.xy * 2 * float2(1, -1), 0.1, 1); //偷懒方法,直接设置到NDC空间去  
    o.uv = v.uv;
    return o;
}

在上述VS中,我们舍弃了默认的TransformObjectToHClip操作,该操作将处于Object sapce(对象空间)将Quad转换到了HClip space(齐次裁剪空间)。取而代之的是,我们充分利用了Quad网格顶点的特殊属性,直接构造符合HClip space特征的VS Out

话说什么是Unity默认Quad的顶点特征?请参考下图:

来自Renderdoc的VS Input

矩形Mesh由2个长边重合的三角形黏合而成,Mesh的中心(root)处于4个顶点连线交叉的位置(重心),左下角的模型坐标正好是[-0.5, -0.5],右上角则是[0.5, 0.5]。至于z轴,是一个足以忽略的超级小数,目前将其视为0无妨。

首先回顾一下,一块可以用来进行全屏Blit操作的Mesh,其在经历了MVP矩阵变换后,应该出现在什么位置,是个什么形状呢?以近裁剪面来说,它中心点应该位于原点[0,0,0]点,总体来说是一个正方形,边长为2*NearPlaneDist,左下角的坐标值均为近平面距离的负数[x, y, z] = -NearPlaneDist,因为只有这样,Unity才能在后续的齐次除法里(除以同样值为NearPlaneDistw分量)顺利得将处于HClip space中的矩形顶点变换到NDC space中的4个边界点上去,还是以左下角为例,变换后其具体数值正好是[-1, -1,-1]

上述是走正统变换逻辑,鉴于我们的目的是快速构建能覆盖全屏的Mesh,那么思路自然要跳脱一些,不妨跳过模型+相机+投影的变换,直接参考最终成型的NDC坐标点,将特制的齐次裁剪坐标布置到VS Out(顶点输出)上去!所谓齐次裁剪空间与NDC空间,笼统的说不过是多了一步齐次除法:将vector4的每个分量各自除以vector4.w的过程。于是我们不妨耍个技巧,直接定义w分量为1,这样一来NDC与HClip之间隔着的那层齐次除法就约等于不存在了!我们可以大方的宣布下式是成立的:
NDC Coordination== HClip Coordination
一言以蔽之,就是拿w分量为1的NDC坐标来替代原本要在VS Out阶段输出的HClip坐标!
最后谈起如何构建NDC坐标,请直接参考上图Unity Quad中的顶点,将数值放大一倍* 2即可!

上文解释了为何VS shader中会有v.vertex.xy * 2这样的操作
-> 那是为了得到NDC/HClip空间下的边界点,它们的绝对值都为1

但是为何后面会有~ * float2(1, -1)这项呢?
-> 是因为我们需要将y轴上下对调,从而修正面片三角形的遍历顺序,让其正面朝向摄像机!不妨做个实验,去除~ * float2(1, -1)这部分代码,但是调整Pass的渲染状态:添加上Cull Front或者Cull Off这样的指令(既让模型的背面也显示出来),如此一来,即便不翻转y轴,我们也能得到覆盖全屏的Mesh,只不过顶点顺序不对,会导致uv采样后出现y轴方向颠倒的现象:)

上下颠倒了

提问!三角形的遍历顺序不是写死在Mesh.triangles中的么,3个一组记录有顶点位置的下标。
答:虽然索引的顺序是固定的,但是顶点坐标的上下对调的话,肯定会影响到相邻两向量Cross Product的输出方向,从而会影响到硬件判断三角形的正反面特性。

最后你可能还会注意到,在关键代码段o.vertex = float4(v.vertex.xy * 2 * float2(1, -1), 0.1, 1) 中,第三项z轴是有赋值的,而且这个数值建议> 0。这么做不为别的,只是考虑到不同的底层图像API对NDC的定义略有不同(有的中心点在[0, 0]点,有的中心点在[0.5, 0.5]处),为了确保我们的全屏观察屏幕不被几何阶段最后埋伏着的Clipper无情修剪掉,这里设置个大于0的常数(比方说0.1)会比较百搭。

以下就是最终的VS Out截帧,三角形顶点以CW顺序排列,完美覆盖了NDC的[-1,1]空间,至于uv,使用Quad自带的即可,实践证明在PS里采样一切正常。

来自Renderdoc的VS Output

参考我在延迟渲染的几何阶段,用此方法创建了个Quad,然后直接就能全屏输出一些测试纹理到GBuffer中去了~

在延迟渲染的前向pass中简单运用一下

备注

本文使用的Mesh是Quad,不是Triangle,因此这里有必要提醒一点,如果你打算进行的Blit操作有性能上的要求,那么强烈建议使用三角形网格(DrawTriangle)来实现,因为Quad是由2块三角形拼装起来的,会在屏幕对角线处留下交界线,而基于PixelQuad的影响,这条线在光栅化阶段会带来额外的性能开销。

以上

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

推荐阅读更多精彩内容