如何确定性地检测其2x2像素四边形中的着色器片段位置?

时间:2014-05-10 22:59:15

标签: glsl shader gpu hlsl cg

我一直在尝试使用Eric Penner" Shader Amortization中使用的技术 Pixel Quad Message Passing"来自GPU Pro 2,第VI.2章。基本思想是现代GPU的2x2片段四边形处理片段着色器,你可以使用ddx()和ddy()在所有四个片段中获得some_var的值,只要以下保持:

  1. 您的GPU支持高质量的衍生产品
  2. 您知道自己处理的片段(左上角,右上角,左下角,右下角)
  3. 这为片段着色器优化(例如在2x2像素四边形上分布纹理提取)开辟了很多机会,您需要计算着色器才能击败。

    我的问题是: 我无法确定地检测出我正在处理的片段。理想情况下,每个片段块将从偶数编号的输出像素坐标开始,如(0,0),(2,0),...(1024,1024),...,所以你只需要检查输出像素x和y坐标是偶数还是奇数,以便知道您当前正在处理哪个片段。 Penner在书中使用的方法假设它有效......但它似乎对我来说是错误的。

    不幸的是,我的2x2片段四边形看起来是在不确定的地方开始的:我已经看到它们从(偶数,偶数),(偶数,奇数)和(奇数,偶数)开始。我不记得我是否见过(奇数,奇数),但无论如何,这种安排似乎取决于我无法理解的无数因素,包括输出分辨率和着色器细节。 (我在8800 GTS上进行测试,以防任何人想知道。)

    有谁知道可能导致这种不确定性的原因或有任何文件吗?据我所知,这个领域几乎没有官方标准化,但我对现代桌面级GPU上的实际工作方式更感兴趣,我希望在那里&#39一种让这种技术发挥作用的方法。如果没有人知道如何推理偶数/奇数启动行为,是否有人知道确定当前片段在其2x2四元组中的相对位置的任何其他方式?

    谢谢:)

1 个答案:

答案 0 :(得分:3)

事实证明,我的问题的前提大多是错误的: 只要输出分辨率为偶数,2x2片段四边形DO几乎总是以偶数像素开始...

如果输出分辨率是奇数(我正在使用的基础程序的可能性),由于显而易见的原因,事情会变得更复杂。我不认为驱动程序/ GPU / etc之间存在任何统一性。或者,但是我目前的测试(它们本身可能仍然是错误的)似乎表明2x2像素四边形从奇数分辨率的奇数像素开始,至少当奇数尺寸是水平时。

所有这些奇怪的东西都掩盖了我更大的问题:我用来检测片段在像素四边形中的位置的代码是错误的。我通过将纹理坐标设置为像素四边形(设置为像素四边形中心)来测试......或者我想。但是,我根据全屏四边形计算了屏幕坐标,其中uv映射的+ v轴指向下方。屏幕空间原点从左下角开始,因为它基于笛卡尔坐标的右上象限,我不小心忘了反转用于找到像素四中心的uv偏移的v坐标。我的许多不确定性观察来自于在调试和误解事物时未能检查我的假设,特别是与奇数分辨率相结合。

这是一个令人尴尬的错误,我应该早点抓住它,但我想我会把它作为一个警告,让别人在处理相反的坐标时总是仔细检查垂直轴的方向帧。 ;)

更新: 我遇到了一个情况,即使分辨率为奇数,2x2像素四边形也会在像素数上开始。由于在奇数分辨率下的不确定性,我不得不制定另一种解决方案:

  1. 如果您从全屏四边形的uv坐标中获取屏幕像素数(用于后期处理),从中导出的片段位置仅用于在片段之间排列/放置共享样本等,而不是四像素通信本身。您需要具有相对于屏幕空间原点的屏幕像素数。您可以从顶点位置导出这些,或者您可以在基于uv的像素数上使用ddx()。x和ddy()。y来找出它们的屏幕方向并从那里以适当的方向镜像片段位置。
  2. 根据屏幕像素数(相对于真正的屏幕空间原点)计算片段位置,假设2x2像素四边形在偶数像素上开始。 (如果您使用基于uv的像素数字,现在是时候镜像了。)
  3. 在片段位置执行ddx()。x和ddy()。y,如果它们在任一方向都是负数,则表示像素四边形从该方向的奇数像素数开始...所以镜像在那个方向。
  4. 如果计算两个片段位置,一个基于紫外原点,一个基于屏幕原点,使用基于uv的片段位置来推理基于紫外线的样本放置,并使用基于屏幕的位置实际获得相邻片段的变量值。
  5. 利润。
  6. 一旦我在Github上发布它,我将发布一个链接到我工作的MIT许可代码,以及用法示例(遗憾的是加速不是我的预期,但无论如何;))。我只是等着完成一个更大的着色器,我将随之上传。