2013-05-25 38 views
1

我目前在GLSL中实现了3D噪声函数,该函数用于替换球体的顶点以提供地形。我目前使用几何着色器来简单地计算每个面的法线(我也有镶嵌细分,因此我在这里做这个而不是顶点着色器)。现在我想计算每个顶点的法线。从3D噪声计算每个顶点法线

现在我已经看到了一些关于从平面网格中移除噪声时计算法线的帖子,但似乎无法让它为自己工作。 以下是我的镶嵌评估着色器的一个片段,它可以计算新顶点的位置。 (这工作正常)。

// Get the position of the newly created vert and push onto sphere's surface. 
tePosition = normalize(point0 + point1 + point2) * Radius; 

// Get the noise val at given location. (Using fractional brownian motion) 
float noiseVal = fBM(tePosition, Octaves); 

// Push out vertex by noise amount, adjust for amplitude desired. 
tePosition = tePosition + normalize(tePosition) * noiseVal * Amplitude; 

tePosition然后进入几何着色器,其中其中三个被用来计算表面法线的三角形。 我将如何去使用它来计算所述顶点的法线?

我试图通过在tePosition的两个小偏移量处重新采样噪声来做“邻居”方法(在将它们移位噪声值之前,我将它们推回到球体上)。然后使用这两个新职位,我从tePosition中获得向量,并使用交叉产品来获得正常。然而,这导致许多区域呈黑色(表明法线向后),并且法线朝外的部分在球体周围似乎非常均匀(光线的相反侧的照明)。 下面是完成上述任务的代码:

// theta used for small offset 
float theta = 0.000001; 
// Calculate two new position on the sphere. 
vec3 tangent = tePosition + vec3(theta, 0.0, 0.0); 
tangent = normalize(tangent) * Radius; 
vec3 bitangent = tePosition + vec3(0.0, theta, 0.0); 
bitangent = normalize(bitangent) * Radius; 

// Displace new positions by noise, then calculate vector from tePosition 
float tanNoise = fBM(tangent, Octaves) * Amplitude; 
tangent += normalize(tangent) * tanNoise; 
tangent = tangent - tePosition; 

float bitanNoise = fBM(bitangent, Octaves) * Amplitude; 
bitangent += normalize(bitangent) * bitanNoise; 
bitangent = bitangent - tePosition; 

vec3 norm = normalize(cross(normalize(tangent), normalize(bitangent))); 

我试图改变theta值,改变这是怎么用来抵消,从而导致不同程度的“不正当”。

有没有人有任何想法,我可以如何正确计算法线?

回答

2

您添加以构造切线的矢量(theta, 0.0, 0.0)(0.0, theta, 0.0)与球体不相切。为了得到一个切线和二重,你应该使用跨产品:

// pos x (1,0,0) could be 0, so add pos x (0,1,0). 
vec3 vecTangent = normalize(cross(tePosition, vec3(1.0, 0.0, 0.0)) 
    + cross(tePosition, vec3(0.0, 1.0, 0.0))); 
// vecTangent is orthonormal to tePosition, compute bitangent 
// (rotate tangent 90° around tePosition) 
vec3 vecBitangent = normalize(cross(vecTangent, tePosition)); 

vec3 ptTangentSample = noisy(tePosition + theta * normalize(vecTangent)); 
vec3 ptBitangentSample = noisy(tePosition + theta * normalize(vecBitangent)); 

vec3 vecNorm = normalize(
    cross(ptTangentSample - tePosition, ptBitangentSample - tePosition)); 

作为一个方面说明,我建议不要使用相同的变量向量(方向+长度,数学(X,Y,Z,0 ))和点(坐标系中的位置,数学(x,y,z,1))。

+0

非常感谢!这种方法很好用!现在只是一些小问题,但这似乎是由于我的噪声功能尚未完善theta的最佳值。 – IdiotCoderCodie