2013-03-02 52 views
2

我正在從高度圖上烘焙片段着色器上的法線貼圖。高度圖看起來很好,看起來很平滑。但是,當我生成法線貼圖時,會得到很奇怪的結果。來自高度圖神器的法線圖

下面是顯示問題的兩個渲染圖像,其中一個包含所有照明計算,第二個包含應用在網格頂部的法線貼圖。 Normap map

enter image description here

的方式予烘烤法線圖是通過對片段着色器採樣相鄰像素。

網格爲32x32,法線貼圖和高度貼圖爲64x64。下面是樣本的相鄰像素的片段着色器代碼:

float NORMAL_OFF = (1.0/64.0); 
vec3 off = vec3(-NORMAL_OFF, 0, NORMAL_OFF); 

// s11 = Current 
float s11 = texture2D(uSampler, texturePos).x; 

// s01 = Left 
float s01 = texture2D(uSampler, vec2(texturePos.xy + off.xy)).x; 

// s21 = Right 
float s21 = texture2D(uSampler, vec2(texturePos.xy + off.zy)).x; 

// s10 = Below 
float s10 = texture2D(uSampler, vec2(texturePos.xy + off.yx)).x; 

// s12 = Above 
float s12 = texture2D(uSampler, vec2(texturePos.xy + off.yz)).x; 

vec3 va = normalize(vec3(off.z, 0.0, s21 - s11)); 
vec3 vb = normalize(vec3(0.0, off.z, s12 - s11)); 

vec3 normal = normalize(cross(va, vb)); 

texturePos上頂點着色器作爲vertexPosition.x/128計算(128,因爲頂點之間的距離爲4個像素,從而32×4 = 128)。

爲什麼我的結果很奇怪?

回答

3

您的高度圖採樣深度分辨率太少,導致這些難度較大的步驟。可能你的身高地圖是8位,給你最高256級的高度。現在,如果您的高度圖的平面分辨率高於256,則橫向分辨率不足以表示平滑的高度場。

解決方案:爲您的高度圖使用更高的採樣分辨率。 16位是流行的選擇。

雖然着色器和烘焙代碼沒有問題,但它們只是沒有足夠的分辨率來處理輸入數據。

+0

謝謝!當我將高度貼圖渲染到我的framebuffer時,我使用gl.UNSIGNED_BYTE而不是gl.FLOAT。這似乎解決了它:-) – raRaRa 2013-03-02 21:16:40

+1

@raRaRa:您可能也想使用GL_R16作爲內部格式(OpenGL-3及更高版本)。根據您的GPU /驅動程序組合,它可能會產生比GL_FLOAT更好或更差的性能。只有知道它的方法纔是基準。 – datenwolf 2013-03-02 21:53:58

+0

哦,沒錯。謝謝!對於這裏感興趣的人來說,現場演示:http://rarara.minecraft.is/ – raRaRa 2013-03-02 22:05:08