2013-05-25 62 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