计算顶点法线OpenGL

Posted

技术标签:

【中文标题】计算顶点法线OpenGL【英文标题】:Calculating vertex normals OpenGL 【发布时间】:2011-11-28 19:21:44 【问题描述】:

我正在尝试计算波的顶点法线,但我得到的是方格效果而不是所需的平滑阴影。

我不确定我是否将正确的向量传递给calcNormal() 函数,或者是否有其他问题。

这是我的波形代码

Vector3 wave1(Sea::seaGrid[i][j].x, Sea::sinVals[k], Sea::seaGrid[i][j].z);
Vector3 wave2(Sea::seaGrid[i][j+1].x, Sea::sinVals[k], Sea::seaGrid[i][j+1].z);
Vector3 wave3(Sea::seaGrid[i+1][j+1].x, Sea::sinVals[nextK], Sea::seaGrid[i+1][j+1].z);
Vector3 wave4(Sea::seaGrid[i+1][j].x, Sea::sinVals[nextK], Sea::seaGrid[i+1][j].z);

Vector3 waveNorm1 = wave1.calcNormal(wave2);
Vector3 waveNorm2 = wave2.calcNormal(wave3);
Vector3 waveNorm3 = wave3.calcNormal(wave4);
Vector3 waveNorm4 = wave4.calcNormal(wave1);

//rest of wave
glBegin(GL_POLYGON);    
glNormal3f(waveNorm1.x, waveNorm1.y, waveNorm1.z);glTexCoord2f(0.0, 1.0);glVertex3f(Sea::seaGrid[i][j].x, Sea::sinVals[k], Sea::seaGrid[i][j].z);
glNormal3f(waveNorm2.x, waveNorm2.y, waveNorm2.z);glTexCoord2f(0.0, 0.0);glVertex3f(Sea::seaGrid[i][j+1].x, Sea::sinVals[k], Sea::seaGrid[i][j+1].z);
glNormal3f(waveNorm3.x, waveNorm3.y, waveNorm3.z);glTexCoord2f(1.0, 0.0);glVertex3f(Sea::seaGrid[i+1][j+1].x, Sea::sinVals[nextK], Sea::seaGrid[i+1][j+1].z);
glNormal3f(waveNorm4.x, waveNorm4.y, waveNorm4.z);glTexCoord2f(1.0, 1.0);glVertex3f(Sea::seaGrid[i+1][j].x, Sea::sinVals[nextK], Sea::seaGrid[i+1][j].z);
glEnd();

这是calcNormal() 函数

Vector3& Vector3::calcNormal(const Vector3 &other)

Vector3 normal = crossProduct(*this, other);

//normalises vector
float vecLength = sqrt(pow(normal.x,2)+pow(normal.y,2)+pow(normal.z,2));// length();

normal.x = normal.x / vecLength;
normal.y = normal.y / vecLength;
normal.z = normal.z / vecLength;

return normal;

这是crossProduct()函数

Vector3 Vector3::crossProduct( const Vector3 &v1,  const Vector3 &v2 )

Vector3 vCrossProduct;

vCrossProduct.x = v1.y * v2.z - v1.z * v2.y;
vCrossProduct.y = v1.z * v2.x - v1.x * v2.z;
vCrossProduct.z = v1.x * v2.y - v1.y * v2.x;

return vCrossProduct;

有什么想法吗?

【问题讨论】:

当然 i,j 处的法线不仅仅取决于 i,j 和 i+1,j 处的点,在其他波点处类似吗?。 你是说对于 waveNorm1 应该是 wave4.calcNormal(wave2) 吗? 不,点 (i,j) 的法线可能取决于比 (i,j) 和 (i+1,j) 处的点更多的变量和其他变量,并且可能取决于 (i,j) 点以外的其他点i+1,j) 和 (i,j+1) 你也有。由于我可能误读了您的问题的免责声明,我认为您可能想查看en.wikipedia.org/wiki/Finite_difference_method之类的内容 顺便说一句,不要画多边形!只需绘制四边形 (GL_QUADS),甚至更好的三角形 (GL_TRIANGLES)。这样,您甚至可以将整个波浪网格包裹到单个 glBegin/glEnd 块中,并且过渡到顶点数组也容易得多。 【参考方案1】:

那些没有意义:

Vector3 waveNorm1 = wave1.calcNormal(wave2);
Vector3 waveNorm2 = wave2.calcNormal(wave3);
Vector3 waveNorm3 = wave3.calcNormal(wave4);
Vector3 waveNorm4 = wave4.calcNormal(wave1);

您正在计算位置向量的叉积。但你真正想要的是局部差异的叉积,即差异。

即(wave2 - wave1) × (wave3 - wave1)

【讨论】:

那么我是否将所有法线替换为 (wave2 - wave1) × (wave3 - wave1)? 不完全是,因为这会给你面法线,但你肯定想要顶点平滑法线。从技术上讲,您要做的是确定顶点位置处曲面的斜率,即跨越局部近似平面的线性独立向量构成顶点周围的曲面补丁,然后取它们的叉积。在您的情况下还有另一种方式:您正在为波浪使用罪恶。法线是局部偏导数的叉积,你可以写下来(d/dx a sin(b x) = a cos(x) b

以上是关于计算顶点法线OpenGL的主要内容,如果未能解决你的问题,请参考以下文章

从顶点数据中获取像素法线

网格颜色混乱可能是由于顶点法线计算错误

计算 GL_TRIANGLE 的顶点法线

在顶点着色器中定位顶点后如何更新法线?

柏林噪声的每顶点法线?

顶点法线的图形问题