博客專欄

EEPW首頁(yè) > 博客 > Chai 3D之燈光與陰影

Chai 3D之燈光與陰影

發(fā)布人:ygtu 時(shí)間:2023-03-14 來源:工程師 發(fā)布文章

推薦:將 NSDT場(chǎng)景編輯器 加入你的3D開發(fā)工具鏈

介紹

??光是人類可以視覺感知的任何事物的視覺表示背后的最重要的思想。光感知的概念在于,你所看到的不是基于你正在觀看的物體,而是基于光源投射并從這些物體反射的光線。重要的是要注意,你的眼睛不會(huì)直接看到物體,因?yàn)槟愕难劬瓦@些物體之間沒有物理相關(guān)性。

??當(dāng)然,所有這些都是理論上的。我們使用術(shù)語光線只是抽象出更復(fù)雜的機(jī)制。

??光線通常來自能量來源,例如太陽(yáng)或房間內(nèi)的燈。重要的是要注意,從理論上講,光線沿直線傳播,當(dāng)您在視覺上感知物體時(shí),您的眼睛吸收的是該物體反射或散射的光線。

光的抽象類型

??以下術(shù)語描述了在對(duì)需要光源的 3D 應(yīng)用程序進(jìn)行編程時(shí)必須了解的不同類型的光。了解每種類型的光在渲染的 3D 對(duì)象表面上產(chǎn)生的效果非常重要。創(chuàng)建這些術(shù)語是因?yàn)樾枰枋龉鈱?duì)物體產(chǎn)生的某些效果,以便提煉出光的復(fù)雜數(shù)學(xué)計(jì)算。然而,這并不意味著這些確切類型的光實(shí)際上存在于自然界中,我們只是將它們視為光投射在不同材料上時(shí)可能產(chǎn)生的效果的抽象。計(jì)算光的真實(shí)機(jī)制及其在自然界中的工作方式將非常耗時(shí),因此,OpenGL 通常采用這組常見的光類型:環(huán)境光、漫射光和鏡面光。****光與其他光不同,是物體發(fā)出的光的類型,而其他三種類型的光通常用于描述光源。讓我們?cè)敿?xì)看看這些類型的光:

將環(huán)境、漫反射和鏡面反射分量組合在一起

環(huán)境光

??被環(huán)境光照亮的 3D 球體看起來只有 2D。環(huán)境光是由照明區(qū)域周圍(或位于照明區(qū)域內(nèi)部)的所有光源****光而產(chǎn)生的平均光量。當(dāng)陽(yáng)光穿過房間的窗戶時(shí),它們會(huì)打到墻壁上,反射并散射到各個(gè)不同的方向,平均照亮整個(gè)房間。這種視覺質(zhì)量由環(huán)境光描述。僅環(huán)境光無法傳達(dá)在 3D 空間中設(shè)置的對(duì)象的完整表示,因?yàn)樗许旤c(diǎn)都由相同的顏色均勻照明,并且對(duì)象看起來像是二維的,如上圖所示。盡管顯示的對(duì)象實(shí)際上是一個(gè) 3D 球體,但當(dāng)僅由環(huán)境光照亮?xí)r,它在屏幕上看起來是平坦的。

漫反射光

??紅色的漫射光投射到定義其 3D 形狀的黑色物體上。

??漫射光表示光源投射的定向光。漫射光可以描述為在空間中具有位置并且來自單個(gè)方向的光。手電筒稍微高于它所照亮的物體,可以被認(rèn)為是****漫射光。在上圖中,投射紅色漫射光的光源位于物體的左側(cè)。當(dāng)漫射光接觸物體表面時(shí),它會(huì)在該表面上均勻地散射和反射。

??為了演示環(huán)境光和漫射光如何協(xié)同工作以創(chuàng)建看起來更逼真的對(duì)象,請(qǐng)想象一個(gè) 3D 球體,其上散布著深紅色的環(huán)境光:

??現(xiàn)在,通過將漫射光源放置在球體的右側(cè),我們得到以下結(jié)果:

??請(qǐng)注意球體現(xiàn)在看起來是 3D 的。

鏡面光

??除了環(huán)境光層和漫反射層外,此處還顯示鏡面反射(或鏡面反射高光)。您可以觀察到鏡面反射光源屬性如何大大增強(qiáng)對(duì)象的 3D 表示。 就像漫射光一樣,鏡面反射光是一種定向光。它來自一個(gè)特定的方向。

??兩者之間的區(qū)別在于鏡面光以銳利而均勻的方式從表面反射。鏡面反射光的渲染取決于觀察者和光源之間的角度。從觀察者的角度來看,鏡面反射光會(huì)在被觀察對(duì)象的表面上創(chuàng)建一個(gè)突出顯示的區(qū)域,稱為鏡面反射或鏡面反射。鏡面反射的強(qiáng)度取決于構(gòu)成物體的材料以及包含鏡面反射光分量的光源的強(qiáng)度。

****光

??自發(fā)光與之前解釋的任何其他光分量略有不同。自發(fā)光光組件負(fù)責(zé)物體材質(zhì)反射或吸收光的屬性。當(dāng)應(yīng)用于對(duì)象的材質(zhì)時(shí),自發(fā)光光的作用是模擬從物體反射的光。

??由于周圍沒有其他光源,僅應(yīng)用自發(fā)光光分量的物體顏色與僅應(yīng)用環(huán)境光的對(duì)象具有相同的視覺質(zhì)量。然而,任何額外的漫射光或鏡面光如何與僅施加自發(fā)光光的同一物體的表面反應(yīng)的機(jī)制是不同的。讓我們考慮一個(gè)平均發(fā)出綠色的物體。在下圖中,自發(fā)光分量應(yīng)用于球體。如您所見,結(jié)果類似于在上面示例中將環(huán)境光應(yīng)用于同一球體所創(chuàng)建的效果。

??反射綠色自發(fā)光光的 3D 球體。在將其他光源引入場(chǎng)景之前,該效果類似于環(huán)境光。

??如您所知,光源可以分配所有三個(gè)組件,即環(huán)境光、漫反射光和鏡面反射光組件。讓我們看看當(dāng)我們?cè)谏厦娴膱?chǎng)景中應(yīng)用光源時(shí)會(huì)發(fā)生什么。我們應(yīng)用的光源具有以下屬性:紅色環(huán)境光、紅色漫射光和白色鏡面光。

??如果上面的球體沒有發(fā)出綠色的光,它就會(huì)呈現(xiàn)紅色。但是,自發(fā)光的綠色分量被施加到它上面。當(dāng)光源的“光線”照射到球體表面時(shí),“光源”和“目標(biāo)”顏色融合在一起,產(chǎn)生淡黃色的表面。光源的鏡面反射光分量為白色。鏡面反射的中心中心是白色的,但是當(dāng)它擴(kuò)散時(shí),它與綠色和紅色融合,在黃色(即綠紅色)上增加。同樣,請(qǐng)注意,如果沒有將自發(fā)光光應(yīng)用于球體,它看起來就像上面鏡面反射部分下顯示的球體一樣,全部為紅色,帶有白色鏡面反射。

??本教程的以下部分將介紹 OpenGL 著色多邊形以模擬光線的方式,以及如何將光源屬性分配給光源和材質(zhì)。

光源

??為了計(jì)算 3D 物體的陰影,CHAI3D 需要知道落在其上的光線的強(qiáng)度、方向和顏色。這些屬性由世界中的光對(duì)象提供。所有光源的基色和強(qiáng)度設(shè)置相同,但方向取決于您使用的光源類型。此外,光線可能會(huì)隨著與光源的距離而減弱。下面介紹了 CHAI3D 中可用的三種類型的光源。

CHAI3D 光源

位置燈

??位置光位于空間中的某個(gè)點(diǎn),并平等地向各個(gè)方向發(fā)出光。光線照射表面的方向是從接觸點(diǎn)回到光對(duì)象中心的線。強(qiáng)度隨著與光的距離而減小,在指定范圍內(nèi)達(dá)到零。點(diǎn)光源可用于模擬場(chǎng)景中的燈和其他局部光源。

using namespace chai3d;
// create a light source
light = new cPositionalLight(world);
// attach light to camera
world->addChild(light);
// enable light source
light->setEnabled(true);
// position the light source
light->setLocalPos(1.0, 1.0, 0.5);

方向燈

??定向光源沒有任何可識(shí)別的光源位置,因此光源對(duì)象可以放置在世界任何地方。世界上所有的物體都被照亮,就好像光線總是來自同一個(gè)方向一樣。光與目標(biāo)物體的距離未定義,因此光不會(huì)減弱。

??定向光源表示來自活動(dòng)工作區(qū)范圍之外的位置的大而遠(yuǎn)的光源。在逼真的場(chǎng)景中,它們可以用來模擬太陽(yáng)或月亮。在抽象的模擬世界中,它們可以成為一種有用的方法,可以為對(duì)象添加令人信服的陰影,而無需準(zhǔn)確指定光線的來源。在場(chǎng)景視圖中檢查對(duì)象時(shí)(例如,查看其網(wǎng)格、著色器和材質(zhì)的外觀),定向光通常是了解其著色顯示方式的最快方法。對(duì)于這樣的測(cè)試,您通常對(duì)光線來自哪里不感興趣,而只是想看到物體看起來“固體”并尋找模型中的毛刺。

using namespace chai3d;
// create a directional light source
light = new cDirectionalLight(world);
// insert light source inside world
world->addChild(light);
// enable light source
light->setEnabled(true);
// define direction of light beam
light->setDir(-1.0, 0.0, 0.0);

聚光燈

??與位置光源一樣,聚光燈具有光源落落的指定位置和范圍。但是,聚光燈被限制在一個(gè)角度,導(dǎo)致錐形照明區(qū)域。圓錐體的中心指向光源對(duì)象的向后 (X) 方向。

??聚光燈通常用于人造光源,例如可以連接到觸覺工具(例如模擬內(nèi)窺鏡)的手電筒。

using namespace chai3d;
// create a light source
light = new cSpotLight(world);
// attach light to camera
world->addChild(light);
// enable light source
light->setEnabled(true);
// position the light source
light->setLocalPos(0.6, 0.6, 0.5);
// define the direction of the light beam
light->setDir(-0.5,-0.5,-0.5);

陰影

燈光與陰影

??陰影映射或投影陰影是將陰影添加到 3D 計(jì)算機(jī)圖形的過程。陰影是通過測(cè)試像素從光源中是否可見來創(chuàng)建的,方法是將其與以紋理形式存儲(chǔ)的光源視圖的 z 緩沖區(qū)或深度圖像進(jìn)行比較。

從光源生成的陰影貼圖

??如果你從光源向外看,你能看到的所有物體都會(huì)出現(xiàn)在光線中。然而,這些物體后面的任何東西都會(huì)在陰影中。這是用于創(chuàng)建陰影貼圖的基本原則。渲染光源的視圖,存儲(chǔ)它看到的每個(gè)表面的深度(陰影貼圖)。接下來,渲染常規(guī)場(chǎng)景,將繪制的每個(gè)點(diǎn)的深度(好像它被光而不是眼睛看到)與此深度圖進(jìn)行比較。

示例

??在 CHAI3D 中,聚光燈支持陰影貼圖。在下面的示例中,我們說明了如何設(shè)置陰影貼圖。

using namespace chai3d;
// create a light source
light = new cSpotLight(world);
// attach light to camera
world->addChild(light);
// enable light source
light->setEnabled(true);
// position the light source
light->setLocalPos(0.6, 0.6, 0.5);
// define the direction of the light beam
light->setDir(-0.5,-0.5,-0.5);
// set light cone half angle
light->setCutOffAngleDeg(30);
// enable this light source to generate shadows
light->setShadowMapEnabled(true);

??為了最大限度地提高陰影的質(zhì)量,重要的是 de 分配盡可能小的截止角度。此外,可以通過提高陰影貼圖的分辨率來調(diào)整陰影貼圖的質(zhì)量。較大的陰影貼圖顯然需要更長(zhǎng)的時(shí)間來渲染,并且在低性能圖形卡上可能不受支持。

using namespace chai3d;
// (1) set the resolution of the shadow map - low quality
light->m_shadowMap->setQualityLow();
// (2) set the resolution of the shadow map - medium quality
light->m_shadowMap->setQualityMedium();
// (3) set the resolution of the shadow map - high quality
light->m_shadowMap->setQualityHigh();

??渲染攝像機(jī)場(chǎng)景時(shí),首先更新所有陰影貼圖非常重要。如果使用多個(gè)攝像機(jī)和多個(gè)幀緩沖區(qū)(窗口顯示)渲染場(chǎng)景,則只需計(jì)算一次陰影貼圖。

using namespace chai3d;
// update shadow maps
world->updateShadowMaps(false, mirroredDisplay);
// render scene
camera->renderView(windowW, windowH);

3D建模學(xué)習(xí)工作室翻譯整理,轉(zhuǎn)載請(qǐng)標(biāo)明出處!


*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。




相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉