在SSAO着色器中计算切线(learnopengl.com教程)。

huangapple go评论65阅读模式
英文:

Calculating tangent in SSAO shader (learnopengl.com tutorial)

问题

我正在尝试编写一个OpenGL SSAO着色器,并且我正在遵循这个教程:https://learnopengl.com/Advanced-Lighting/SSAO

我对片段着色器中计算切线的部分感到困惑:
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
我了解到这是Gram-Schmidt过程,我理解的是它正在寻找与法线正交的randomVec的分量。

让我困惑的是这些随机向量是在C++中生成的,并作为平铺纹理传递给着色器并进行采样的:

for (unsigned int i = 0; i < 16; i++)
{
    glm::vec3 noise(
        randomFloats(generator) * 2.0 - 1.0, 
        randomFloats(generator) * 2.0 - 1.0, 
        0.0f); 
    ssaoNoise.push_back(noise);
}  

根据解释,“由于采样核心是沿切线空间的正z方向定向的,所以我们将z分量保持在0.0,以便我们绕z轴旋转。”。

这是否意味着随机向量是在切线空间中定义的,而法线是在视图空间中?这不会使将一个投影到另一个上变得毫无意义吗?因为它们位于完全不同的坐标系中?

我的第二个问题是,是否可能使randomVec最终与normal相同,如果是这种情况,那么切线会成为零向量吗?

英文:

I'm trying to write an openGL SSAO shader and I'm following this tutorial https://learnopengl.com/Advanced-Lighting/SSAO

I'm confused by this part of the fragment shader that calculates the tangent:

vec3 tangent   = normalize(randomVec - normal * dot(randomVec, normal));

I learned that this is the Gram Schmidt process, and what I understood is that it's finding the component of randomVec that's orthogonal to normal

What confuses me is that these random vectors are generated as so in C++ and passed to the shader as a tiled texture and sampled:

std::vector&lt;glm::vec3&gt; ssaoNoise;
for (unsigned int i = 0; i &lt; 16; i++)
{
    glm::vec3 noise(
        randomFloats(generator) * 2.0 - 1.0, 
        randomFloats(generator) * 2.0 - 1.0, 
        0.0f); 
    ssaoNoise.push_back(noise);
}  

With the explanation "As the sample kernel is oriented along the positive z direction in tangent space, we leave the z component at 0.0 so we rotate around the z axis.".

So does this mean that the random vectors are defined in tangent space, and the normal is in view space? Doesn't that make it meaningless to project one onto the other as they are in completely different coordinate systems?

And my second question is couldn't it be possible that randomVec ends up the same as normal, in that case making tangent a zero vector?

答案1

得分: 1

我理解的方式是:

  • 首先,切线是一个位于围绕正z轴半球的随机向量(位于世界原点)。

  • 将它与TBN矩阵相乘,将切线旋转,使其成为围绕法线的随机向量(仍然位于原点)。

  • 缩放为radius并添加fragPos,因此切线现在代表距离片段radius的视图空间中的3D点。然后将其转换为屏幕空间,以便更容易测试深度缓冲区中的深度(也在屏幕空间中)。

这是否意味着随机向量是在切线空间中定义的,而法线是在视图空间中定义的?

切线在切线空间中定义,然后移动到视图空间,然后是屏幕空间,以便更容易测试深度缓冲区中的深度。法线仅在创建TBN矩阵的算法中使用。

难道随机向量最终不可能与法线相同,从而使切线成为零向量吗?

理论上是可能的,但更有可能的是,它具有某些浮点值,通过缩放/插值部分朝向法线向量进行缩放。

英文:

The way I understand it is:

  • The tangent is firstly a random vector (at the world origin) in the hemisphere around the positive z axis.

  • Multiply it by TBN matrix which rotates the tangent so that it is a random vector in the hemisphere around the normal (still at the origin).

  • Scale by radius and add fragPos, so the tangent now represents a 3D point in view space at radius from the fragment. Then it is converted to screen-space for the benefit of making it easier to test depths within the depth buffer (also in screen-space).

> So does this mean that the random vectors are defined in tangent space, and the normal is in view space?

The tangent is defined in tangent space and moved into view space then screen space for easier testing against the depth buffer. The normal is only used in the algorithm for the creation of the TBN matrix.

> couldn't it be possible that randomVec ends up the same as normal, in that case making tangent a zero vector?

Theoretically, yes. But more likely it is has some float value that gets scaled toward the normal vector with the scaling/interpolation part.

huangapple
  • 本文由 发表于 2023年6月29日 04:04:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76576383.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定