Opengl 打包法向量和切向量

Opengl 打包法向量和切向量,opengl,glsl,shader,Opengl,Glsl,Shader,在我正在使用的延迟着色引擎中,我当前使用内部格式GL\u RGBA16F将法向量存储在缓冲区中。 我一直意识到这不是最好的解决办法,但我没有时间去处理它 最近我读了一篇文章,这篇文章启发我使用八面体法向量(ONV),并将缓冲区更改为GL\u RG16\u snrom: 对法向量进行编码(vec3至vec2): //返回+/-1 vec2信号不为零(vec2 v) { 返回向量2((v.x>=0.0)?+1.0:-1.0,(v.y>=0.0)?+1.0:-1.0); } //假设标准化输入。每个组

在我正在使用的延迟着色引擎中,我当前使用内部格式
GL\u RGBA16F
将法向量存储在缓冲区中。 我一直意识到这不是最好的解决办法,但我没有时间去处理它

最近我读了一篇文章,这篇文章启发我使用八面体法向量(ONV),并将缓冲区更改为
GL\u RG16\u snrom

对法向量进行编码(
vec3
vec2
):

//返回+/-1
vec2信号不为零(vec2 v)
{
返回向量2((v.x>=0.0)?+1.0:-1.0,(v.y>=0.0)?+1.0:-1.0);
}
//假设标准化输入。每个组件的输出均为on[-1,1]。
vec2浮动32x3_至_oct(在vec3 v中)
{
//将球体投影到八面体上,然后投影到xy平面上
vec2p=v.xy*(1.0/(abs(v.x)+abs(v.y)+abs(v.z));
//在对角线上反射下半球的褶皱

返回(v.z以下考虑纯粹是数学上的,我对它们的实用性没有经验。然而,我认为特别是选项2可能是一个可行的备选方案

以下两个选项都有共同的问题描述方式:给定法线(可以使用ONV重建),如何用单个数字对切线进行编码

选择1 第一个选项非常接近Meowgoethedog的建议。定义一个任意参考向量(例如
(0,0,1)
)。然后将切线编码为需要围绕法线旋转此向量以匹配切线方向的角度(标准化为
[-1,1]
范围)(当然,在切线平面上投影后)。您将需要两个不同的参考向量(甚至三个)然后根据法线选择正确的一个。你不希望参考向量平行于法线。我假设这在计算上比第二个选项更昂贵,但需要测量。但是你会得到一个均匀的误差分布作为回报

选择2

让我们考虑切线正交的平面。这个平面可以由切线定义,也可以由平面中的两个向量来定义。我们知道一个向量:曲面法线。如果我们知道第二个向量<代码> V< /代码>,我们可以计算正切为<代码> t=正规化(交叉(正常,V))。

。要对这个向量进行编码,我们可以指定两个分量,并对剩余的分量进行求解。例如,让我们的向量为
(1,1,x)
。然后,要对向量进行编码,我们需要找到
x
,这样
交叉((1,1,x),法线)
与切线平行。这可以通过一些简单的算法来完成。同样,您需要一些不同的向量模板来考虑所有情况。最后,您有一个方案,其编码器更复杂,但其解码器无法更简单。错误分布将不像选项1中那样均匀,但应该适合于向量模板的合理选择。

这个想法可能有效:将法线存储为球形极坐标格式(2个浮点数),以及一个附加的浮点值,用于指定切线的方位角。由于切线被约束到一个平面,因此仅一个值就足以指定它,除非法线位于X-Y平面中。在这种情况下,我们必须更改附加角度的含义(例如,与Z轴的角度。这需要在预处理期间加以考虑)