从clipspace.xyz和(INV)投影矩阵计算clipspace.w(Calculate cl

2019-07-18 16:59发布

我使用被写入到深度缓冲器和没有隐式的透视分割的对数深度的算法,这导致someFunc(clipspace.z)。

我所以后来做RTT /后处理在片段着色器我想(存储在深度缓冲值从someFuncInv())重新计算eyespace.xyz,给予ndc.xy(从尾数坐标)和clipspace.z 。

请注意,我没有clipspace.w,和我的存储值不clipspace.z / clipspace.w(如当使用固定功能深度它会) - 这样的线沿线的东西...

float clip_z = ...; /* [-1 .. +1] */
vec2 ndc = vec2(FragCoord.xy / viewport * 2.0 - 1.0);
vec4 clipspace = InvProjMatrix * vec4(ndc, clip_z, 1.0));
clipspace /= clipspace.w;

......不在这里工作了。

那么,有没有一种方法来计算clipspace.w出clipspace.xyz的,给出的投影矩阵或它的逆?

Answer 1:

clipspace.xy = FragCoord.xy / viewport * 2.0 - 1.0;

这是错误的命名方面。 “剪辑空间”是顶点着色器(或任何最后的顶点处理阶段是)输出的空间。 之间夹空间和窗口空间是归一化设备坐标(NDC)空间。 NDC空间是裁剪空间由夹子间隔W划分坐标:

vec3 ndcspace = clipspace.xyz / clipspace.w;

所以第一步就是要把我们的窗口空间坐标,并得到NDC空间坐标。 这是很容易:

vec3 ndcspace = vec3(FragCoord.xy / viewport * 2.0 - 1.0, depth);

现在,我要假设你的depth值是正确的NDC空间深度。 我假设你从深度纹理获取的值,则使用的深度范围的近/远值将其用将其映射到渲染[-1,1]的范围内。 如果你没有,你应该。

所以,现在我们有ndcspace ,我们如何计算clipspace ? 嗯,这是显而易见的:

vec4 clipspace = vec4(ndcspace * clipspace.w, clipspace.w);

显而易见的......没有帮助的,因为我们没有clipspace.w 。 那么,如何才能得到它?

为了得到这一点,我们需要看看如何clipspace被计算在第一时间:

vec4 clipspace = Proj * cameraspace;

这意味着, clipspace.w是通过取计算cameraspace和第四排点产区它Proj

嗯,这不是非常有帮助。 如果我们真正看到的第四行就变得更有益Proj 。 当然,你可以使用任何投影矩阵,如果你不使用通常的投影矩阵,这个计算变得更加困难(可能是不可能的)。

第四行的Proj ,采用通常的投影矩阵,实际上就是这样的:

[0, 0, -1, 0]

这意味着clipspace.w真的只是-cameraspace.z 。 如何帮助我们?

它有助于记住这一点:

ndcspace.z = clipspace.z / clipspace.w;
ndcspace.z = clipspace.z / -cameraspace.z;

嗯,这是很好的,但它只是一个交易未知的另一; 我们仍然有两个未知数(方程式clipspace.zcameraspace.z )。 然而,我们知道别的东西: clipspace.z来自点产区cameraspace我们的投影矩阵的第三行。 传统的投影矩阵的第三行是这样的:

[0, 0, T1, T2]

其中T1和T2是非零数字。 我们会忽略这些数字都是暂时。 因此, clipspace.z真的只是T1 * cameraspace.z + T2 * cameraspace.w 。 如果我们知道cameraspace.w为1.0(因为它通常是这样),那么我们可以将其删除:

ndcspace.z = (T1 * cameraspace.z + T2) / -cameraspace.z;

因此,我们仍然有一个问题。 其实,我们不知道。 为什么? 因为只有一个在这个euqation未知。 请记住: 我们已经知道ndcspace.z 。 因此,我们可以使用ndcspace.z计算cameraspace.z

ndcspace.z = -T1 + (-T2 / cameraspace.z);
ndcspace.z + T1 = -T2 / cameraspace.z;
cameraspace.z = -T2 / (ndcspace.z + T1);

T1T2来的权利,我们的投影矩阵(现场被最初呈现的一个)的。 而且我们已经有ndcspace.z 。 因此,我们可以计算cameraspace.z 。 而我们知道:

clispace.w = -cameraspace.z;

因此,我们可以这样做:

vec4 clipspace = vec4(ndcspace * clipspace.w, clipspace.w);

显然,你需要一个浮子clipspace.w而不是字面的代码,但你明白我的意思。 一旦你有clipspace ,让相机的空间,你乘以逆投影矩阵:

vec4 cameraspace = InvProj * clipspace;


文章来源: Calculate clipspace.w from clipspace.xyz and (inv) projection matrix