最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

【深入淺出】法線貼圖與切線空間(下)

2023-03-23 11:02 作者:獨立游戲人-老雷  | 我要投稿

前言

在課程上半場,我們了解了法線是什么

有時候為了調試方便需要把法線畫出來,那么怎樣把它畫出來?把法線畫出來,其實還有一個目的——鍛煉大家對shader開發(fā)和控制的能力

通過法線的可視化,希望大家能夠更深入的理解法線是什么東西,它的數(shù)值是什么含義?

這都是作為TA同學的基本功

版權聲明

本文為“優(yōu)夢創(chuàng)客”原創(chuàng)文章,您可以自由轉載,但必須加入完整的版權聲明

更多學習資源請私信我獲取(企業(yè)級性能優(yōu)化/熱更新/Shader特效/服務器/商業(yè)項目實戰(zhàn)/每周直播/一對一指導)

點贊、關注、分享可免費獲得配套學習資源

完整視頻請點擊觀看

法線可以做什么?

下面我們來了解一下法線可以做什么

光照計算


首先法線可以用來進行光照計算,為什么法線可以用來進行光照計算呢?

  • 你想一下平時在臺燈下面學習,看到的光線強度是不是跟燈光照射物體表面的角度有關系,所以燈光的照射方向是影響光照強度的第一個因素

  • 第二個因素是物體表面的方向

  • 前面我們講過法線代表物體表面的方向,所以法線跟燈光方向可以用來進行光照強度的計算,進而把物體表面的光照效果表現(xiàn)出來

那么如何計算物體表面的受光強度呢?我們需要用到一點數(shù)學知識,很多同學會覺得學習shader,學習技術美術要掌握很多數(shù)學,其實并沒有大家想的那么復雜

點乘


比如點乘,因為時間關系,沒有辦法講點乘內部的技術實現(xiàn),這又是另外一節(jié)課的知識了,但是我們不理解,或者沒有學過點乘的基本知識,不影響學習shader,為什么呢?因為我們只要了解點乘的用法就可以了

  • 如圖示左上角的小圖,如果燈光的方向跟物體表面的方向是相同的,那這時候我們算出來的點乘值就是1.0,大家記住這個結論

  • 物體表面的方向是朝上的,如果把臺燈橫著照物體表面,那這時光線會比較弱,用點乘代表光線強度算出來,結果值就是0

  • 我們可以推出來,如果A跟B之間的夾角,隨著它逐漸增大,算出來的點層乘值是從1往0跑的


  • 很自然同學們還會想到第三個問題,如果A的方向是朝上的,而B的方向是朝下的,這個時候算出的點乘值是負一,這就表示這兩個方向是完全相反的


  • 同樣的道理,如果A跟B垂直是0,當它們夾角超過90度越接近于180度,剛好相反,那么它就會從零越接近負一

所以此時可以用點乘進行光照計算

光和法線的光學反應


一般來講,我們在unity當中或者在自然界當中會有方向光,方向光是一種平行光,它造成在物體表面

但是為了數(shù)學計算的方便,一般在程序當中,不使用光線的方向向量,而是使用光線方向的反方向向量跟物體表面的某一個點的法線方向(如圖中所畫的是它的法線方向),計算夾角的點乘值,用點乘值表示光照強度系數(shù)

剛才說了夾角越小,它的光照強度越大,越接近于1.0,夾角越大,它的光照強度越接近于負的1.0


那么我們可以看上面這個圖,N表示物體表面的法線,L表示燈光,光照方向相同,點乘值越接近于一

如果法線跟燈光方向垂直,點乘值接近于零

如果法線跟燈光方向方向相反,它的點乘值就是負一

所以就可以用點乘值表示光照強度系數(shù),另外要注意的一點就是光照強度系數(shù)不會是負一,為什么呢?

  • 光照強度最小就是0,這也符合現(xiàn)實當中的直覺,如果燈光方向是朝下的,反方向就是朝上的

  • 燈光方向如果朝下,它照在物體的正面是受光的,只要燈光跟物體的夾角超過90度,也就是在物體的背面(我們用綠色表示背面),它的光照強度值就應該是零,是黑色的(黑色表示沒有受任何光線),不會出現(xiàn)光照強度負一的情況

  • 那么如何表現(xiàn)光照強度不會是負一呢?

  • 可以用shader當中的一個函數(shù)saturate,它的功能是把括號里面的數(shù)值,也就是點乘值夾持到零到一之間,雖然N點乘L的結果可能是負一到正一,但是我們可以把它夾持到最小值是零,最大值是一

具體的saturate的內部數(shù)學運算,大家可以參考小白的TA之路


要實現(xiàn)剛才我們講的光照計算,其實方法也很簡單,代碼一共就幾行

首先把頂點的法線轉換成每一個像素的法線,然后把O(像素的法線)輸入到像素數(shù)據(jù)里面,每個像素的法線跟燈光方向的反方向進行dot,dot就是大家剛才看到的N點乘L的點(點代表點乘),算出來的結果就是介于負一到正一之間的光照強度

然后再用saturate把它變成零到一之間的數(shù)值,因為零到一之間的數(shù)值是單色,并不是彩色,彩色是rgb三個分量,所以最后渲染出來的小球就只有黑白灰的亮度值

Quiz:你發(fā)現(xiàn)問題了嗎?



我們看一下渲染出來的效果,這時我們已經(jīng)可以看到光照出來的黑白灰的效果了,但大家有沒有發(fā)現(xiàn)渲染出來的黑白灰效果不對,為什么不對呢?

  • 現(xiàn)在我調整燈光方向,小球受光是會發(fā)生變化的,因為燈光只能照亮物體的正面

  • 現(xiàn)在旋轉小球,物體表面的受光情況應不應該發(fā)生變化?

  • 在現(xiàn)實生活當中,拿著手電筒對著物體照不同的表面位置,它的光照效果受光情況會變化,但如果手電筒一直放在同一個位置,旋轉我手電筒照小球,那這時光照應不應該變化呢?

  • 不應該發(fā)生變化,所以這個計算結果是錯的

如果不掌握圖形學的知識,那這么簡單的代碼,可能檢查不出來它的問題在哪里,問題在哪里呢?

  • 在這兒計算的時候,使用的法線是物體表面的法線,隨著物體的旋轉,它的表面法線的方向始終是綁定在物體上面的,你可以理解成跟著物體去變的

  • 所以小球一轉,法線方向就變化,這時算出來的光照就會跟著小球旋轉去變,但是這是不對的,我們應該怎么做呢?

  • 不管怎么旋轉,只把小球的法線變換到游戲世界里面,就不會隨著小球去轉了

將法線變換到世界空間


  • 具體該怎么做呢?這個中間牽涉到一些數(shù)學運算,這個運算并不復雜

  • 在這兒寫一個乘法運算,這個乘法運算把法線通過叫做WorldToObject變換到世界空間,這樣就不會隨著模型的旋轉造成小球的受光情況發(fā)生變化,它始終不變


提一個進階的問題,如果你學過一點shader,那么在面試的時候,初級崗位面試經(jīng)常會被問到這么一個問題

  • 第一個,英文單詞WorldToObject就是表示把世界空間的法線變換到物體自身的法線,但是剛才我說的是要把物體自身的法線變換到游戲世界的發(fā)法線

  • 你沒有學過shader,那這個地方你可以忽略,但是如果你學過shader,準備面試,一定要注意一下這個問題,為什么在這兒用的是把世界空間變換到對象空間,燈光位置照射世界空間的燈光位置,它應該跟世界空間的法線進行運算,為什么要變化到對象空間?

  • 第二個,我們正常進行法線的空間變換,應該在mul的左邊寫矩陣,矩陣應該放在逗號的左邊,作為第一個參數(shù),把向量放在逗號的右邊,作為第二個參數(shù)

  • 為什么現(xiàn)在這兩個參數(shù)的位置剛好是反的?反的算出來的結果是不是會有變化?會有什么變化?那為什么這樣反著做?得到的運算結果還是正確的呢?

如果是最近要面試且不太明白,也可以掃一掃左下角的愛麗絲老師進行交流

經(jīng)過處理以后,不管物體怎么旋轉,它的光照始終不會隨著小球的旋轉而變化,那這個結果就是對的


現(xiàn)在已經(jīng)把基本的光照效果利用法線算出來了,但是這還不是想要做的最終目標

按照我們現(xiàn)在的做法,必須要添加16個小球,才能夠把這16個小球的光照利用小球的法線算出來,那么我們怎樣不添加小球,仍然能把小球的光照效果算出來呢?

  • 答案很簡單——就是用法線貼圖,關鍵是法線貼圖該怎么用?

大家看上圖所示是我們要達到的目標,你能不能分出來,左邊是添加了小球的真實光照效果還是右邊是添加了小球的真實光照效果呢,或者說哪個圖像沒有添加小球,只是用法線貼圖算出來,如果你認為左邊可以在討論區(qū)中發(fā)一,右邊請發(fā)二

告訴大家——我也分不出來,因為法線貼圖在這樣的情況里,就是能做到以假亂真的效果,為什么要用法線貼圖而不用真實的小球呢?

  • 在課程開場的時候也講過,如果每個物體為了表現(xiàn)它的真實性,都要把它的模型添加上去,那模型計算的開銷比在一張面片上貼一個法線得到的效果,成本高得多

  • 所以我們要選擇低成本的方法,一定是用法線貼圖


這是我們剛才要渲染的那幅圖像,是使用法線的數(shù)據(jù),左邊和右邊其中有一個是用前面的方法把小球的法線畫出來,另外一個是貼圖轉換成法線數(shù)據(jù)看到的效果,這樣看是沒有差別的,但假的東西就是假,所以我們接下來看看怎么能看出它是假的呢?


如上圖所示,我們就能看出誰是假的了,正確答案是右邊是真的,左邊是假的

  • 法線貼圖只有一種情況能看出來真假,從物體表面的側面,能看出來它是否是假的

如何實現(xiàn)?


那么我們再回到剛才的實際效果,要實現(xiàn)以假亂真的光照,我們該怎樣做呢?

Step1:生成一張法線貼圖


  • 首先第一步,讓項目里面的美工把這些小球模型在建模軟件,比如說3dmax,maya,houdini,blender,任何一個建模軟件里面把3D模型包括小球的模型擺好,擺好以后生成一張圖像,如上圖右邊的圖像

  • 這個圖像就是左邊的模型生成對應的法線圖像,它生成的方法是把法線信息加1乘以0.5,形成一張法線值在0~1之間的圖像

注意:要確保法線貼圖沒有采用sRGB模式


  • 這邊有個小細節(jié),我們要確保法線圖在使用的時候沒有勾選sRGB的選項,為什么呢?

  • 這個地方就牽涉到叫做伽馬顏色空間和線性顏色空間的問題,具體顏色空間問題目前就不細說了


  • 記住一點,如果圖像是一個可見圖像,比如角色身上面的衣服,就把sRGB勾上,如果圖像是肉眼不可見的圖像,比如法線圖,遮地貼圖等等,這時候就不要勾這個選項了,具體的細節(jié)我會在課程里面給大家去解釋

Step2:采樣法線貼圖


  • 剛才我們已經(jīng)生成了一張法線貼圖,接著對法線貼圖進行采樣

  • 因為我把它的法線值從負一到正一變換到了零到一,因此現(xiàn)在要對它進行反向變換,零到一通過乘以2減1,大家課后可以想一下,就可以把它反向變換成法線值介于負一到正一之間的值

  • 然后把貼圖上面的法線值跟燈光方向進行點乘,這樣就能算出來一個非常逼真的,接近真實效果的動態(tài)光照,但實際上我們并沒有使用真實的模型,只是使用了一張法線貼圖,這就是我們實現(xiàn)的效果

但這樣的效果是不是終級效果呢?

  • 不是的,旋轉光照效果沒有任何問題,但是如果旋轉物體,我特意做了兩個對比,是不是很容易區(qū)分出來左邊是假的,右邊是真實的小球


  • 這個真假并不是因為法線貼圖本身的技術限制,法線貼圖從側面看是會有一些瑕疵,但是在這兒并不是因為法線貼圖的技術限制,而是對法線貼圖的使用方式是錯誤的,錯在哪里呢?

  • 就是因為上面這段代碼,在這兒通過tex2D這句話對法線貼圖讀取它的顏色值,然后乘以二加一還原成法線方向向

  • 因為這只是一張圖片,所以當圖片旋轉的時候,從任何角度,只要是采樣這張圖片某一個相同的像素點,它采樣出來的法線值始終是一樣的,也就是它不會根據(jù)物體方向的變化,讓法線進行相應的旋轉

  • 因為法線代表物體表面的方向,而物體方向變了,法線方向應該跟著變,但它沒有跟著變,所以結果就不正確

那么我們要做的就是當物體旋轉的時候,法線貼圖的法線要跟著變,換句話說法線貼圖是處于它自身的坐標空間,叫做切線空間,所以你要做的就是把處于切線空間的法線值變換到世界空間,才能夠正確的跟世界空間的燈光位置進行運算

你可以想象物體在不同空間是不能進行相同運算的,比如米跟厘米能直接運算嗎,斤和公斤,克和千克能直接運算嗎,是不行的,一定要把它換算到相同的單位才能進行運算

同樣道理,比如法線處于切線空間,跟燈光處于世界空間,它們雖然都有數(shù)值,但它數(shù)值代表的含義是不一樣的,就跟剛才講的單位不一樣,要換算一樣,這個也要換算,怎么換算?有兩個辦法

  • 第一個,把燈光換算到切線空間

  • 第二個,把切線空間的法線換算到世界空間

哪種方式更好,我會在vip課程里面教給大家,這是性能優(yōu)化的要點,也是面試時候的必考點

世界空間法線


  • 還有不能用模型自身法線跟燈光進行運算,為什么呢?

  • 可以看左邊跟右邊的圖,它這個點的法線相對于自己物體表面,方向都是(0,1),也就是朝物體表面方向的

  • 但實際上在游戲世界當中,法線相對于整個游戲世界,是在(1,1)的位置,而右邊這個是在(-1,1)的位置,所以我們一定要進行法線的換算,或者進行燈光的換算,必須要換算到同一空間才能進行運算


這個中間其實又牽涉到更多的問題,比如切線空間究竟是什么東西,它是如何構成的,這里面還有很多的技術細節(jié),包括unity也可以幫我們生成物體的切線數(shù)據(jù),中間也有技術實現(xiàn)原理,我都會用中學,甚至是小學數(shù)學的方法教給大家


包括在進行空間轉換運算的時候,中間很多的注意點,都是我們平時照著網(wǎng)上的一頓猛抄,但自己做的時候總是不對的,那你就要學習這些知識點,因為網(wǎng)上抄的只是一個表面,也并沒有抄到他的精髓,更不知道人家具體是怎么樣做的,這些東西我都會在課程里面教給大家


包括法線貼圖的解碼中間還有注意點,unity里面有好幾種解碼方式,比如自己手動寫函數(shù)來解碼,調用unity提供的api接口來進行解碼,這兩者之間有什么區(qū)別,用哪個好,我也會教給大家


回到剛才我們講的問題,要么把法線貼圖里面的法線值轉到世界空間,要么就把世界空間的燈光方向轉到法線空間,如果把法線轉到世界空間,那它運用的公式就應該如圖所示那樣

最后我們可以看到它得到的效果,現(xiàn)在是基本正確了,轉動燈光物體的光照是會跟著動態(tài)變化的,但其實這個效果還是有不正確的地方,假設左邊這個圖是假的,右邊是真的,右邊跟左邊計算的光照剛好是相反的


這中間牽涉到一個問題,法線貼圖在生成的時候有一些細節(jié)是我們要注意的,如果法線貼圖生成的時候沒有那么正確,那么最后算出來的效果就跟上面一樣是反的

最終效果


最終效果就是隨著燈光變化,用法線貼圖渲染的物體,不管怎么旋轉小球或者旋轉燈光,它都是以比較完美的方式呈現(xiàn)它的細節(jié)感,看上去就像物體表面就有一些凸起一樣,但實際上它是沒有的

性能優(yōu)化:轉到切線空間計算光照


還有一些性能優(yōu)化的技巧,究竟應該在切線空間還是在法線空間里面進行細節(jié)運算,我都會教給大家

小結


  • 什么是法線?

  • unity如何生成法線,生成法線的時候如何讓法線的生成方向是正確的

  • 法線要不要單位,根據(jù)實質的效果,從正確性來說要單位化,但是從細節(jié)效果來說又不用單位化

  • 如何將法線可視化<便于調試>

  • 如何利用法線進行光照計算,其中還講到了一些點乘的數(shù)學知識

  • 法線在空間變換上有什么樣的的特殊性

  • 法線貼圖的錯誤用法,就是因為沒有考慮到它處在切線空間要進行空間變換

  • 法線貼圖的色彩空間,色彩空間用不對,結果就是錯的

  • 法線貼圖的編碼和解碼,編碼和解碼有兩種方式,可以自己寫,也可以用unity內置函數(shù),這兩種方式有什么區(qū)別

  • 切線空間是如何構成的

  • unity如何生成切線?

  • 如何運用這個切線空間正確進行法線貼圖計算光照

  • 法線貼圖shader的性能優(yōu)化

都可以關注一下小白的TA之路

進階


當然效果有沒有進階的空間呢?

  • 也是有的,在最早期的年代,要給物體表面凹凸會使用Bump Mapping,這種技術就是把一張黑白圖疊加到物體表面,它的細節(jié)看上去不精細

  • 然后有了今天我們講的法線貼圖,但是法線貼圖還是在物體表面的側面能看出來瑕疵

  • 所以我們又會使用叫做Displacement Mapping,叫做置換貼圖,或者叫做視差貼圖

我們課程里面會教給大家如何使用這種進階的技巧,Displacement Mapping需要用到一種進階的技術,它的算法如果你沒有接觸過,可能需要自己摸索半天,老師會用通俗易懂的方式教給大家


我們如果使用了置換貼圖和視差映射的技術,從物體的側面也能看出來,它的凹凸細節(jié)是比較逼真的


大家知道現(xiàn)在基本上unity新項目都是采用可編程的渲染管線,也就是URP渲染管線定制了,所以我們的vip課程里面也會教給大家如何基于URP來寫shader,包括如何利用URP定制渲染管線解決很多在內置管線下不會遇到的問題

URP性能一定是高的,但是為了實現(xiàn)性能高,它也付出了很多的成本,項目當中大家會碰到很多的問題,老師也會在課程里面教給大家如何解決


這個是unity的開發(fā)者大會上面,里面有個案例,如果使用傳統(tǒng)的渲染管線,在處理透貼的時候是有問題的,如果你使用了可編程的管線對效果進行處理,效果就是正確的

前面的問題主要是由于貼圖的渲染順序造成的,這個問題在過去內置管線里面是比較難以解決的,但是在可編程管線里面解決起來更容易,但是作為開發(fā)者,你需要掌握更多的URP可編程管線的知識

像我們課程里面也有對應的課程案例,包括體積光效果,也是基于URP做了渲染管線定制,幫助大家理解什么是渲染管線定制,如何在項目中真正用好渲染管線定制,大家如果想要了解我們的課程,包括面試要點,作品要點,大家可以添加文末alice老師的聯(lián)系方式

寫在最后

更多學習資源請私信我獲取(企業(yè)級性能優(yōu)化/熱更新/Shader特效/服務器/商業(yè)項目實戰(zhàn)/每周直播/一對一指導)

點贊、關注、分享可免費獲得配套學習資源

完整視頻請點擊觀看



【深入淺出】法線貼圖與切線空間(下)的評論 (共 條)

分享到微博請遵守國家法律
峡江县| 静安区| 临夏市| 盐山县| 体育| 漯河市| 瑞昌市| 宣城市| 汤阴县| 马尔康县| 阜康市| 监利县| 青海省| 浮梁县| 民丰县| 肥乡县| 鸡泽县| 都江堰市| 乌鲁木齐县| 宜州市| 谢通门县| 安图县| 铅山县| 焉耆| 南郑县| 海林市| 赞皇县| 道真| 临泉县| 吴忠市| 桃江县| 南充市| 灌云县| 台安县| 谢通门县| 成都市| 锦州市| 凤城市| 奉节县| 宁夏| 师宗县|