圖形學面試題總結
文章目錄
- 圖形學面試題總結
- Opengl 與 Vulkan
- 1、OpenGL的渲染管線有哪些主要階段?分別做什么?
- 2、OpenGL中的VAO、VBO和EBO分別是什么?為什么需要它們?
- 3、細分著色器與幾何著色器是什么
- 4、Vulkan與Opengl的區別是什么
- 5、OpenGL中的紋理映射(Texture Mapping)是怎么實現的?簡述主要步驟
- 6、在OpenGL中,glViewport和glScissor的區別是什么?
- 7、Vulkan中的Instance、Device、Queue、CommandBuffer分別是什么?
- 8、Vulkan的Pipeline(渲染管線)為什么不可變?
- 9、OpenGL的FBO幀緩沖對象的作用是什么?有哪些常見的應用場景?
- 10、Vulkan中的Fence是用來干什么的?什么時候必須用?
- 11、Vulkan中的Descriptor Set和OpenGL中的Uniform Buffer有什么區別?
- 12、如何在OpenGL/Vulkan中實現LOD(Level of Detail)?
- 13、在OpenGL中,什么是GPU Instancing?
- 14、Vulkan的RenderPass和Subpass的作用
- 15、移動端和PC端的差異,渲染的區別
- 16、在移動端渲染大型場景時,如何優化內存?
- 17、什么是Mesh Shader?
- 18、OpenGL的深度測試(Depth Test)是如何工作的?為什么會出現深度沖突(Z-fighting)?
- 19、在OpenGL中,如果我想要繪制一個半透明的物體,應該怎么做?
- 20、在Vulkan中,為什么要設置多個VkCommandBuffer?而不是一個?
- 21、Vulkan中,為什么我們需要同步機制(Synchronization)?哪些同步機制最常用?
- 圖形學算法
- 1、簡述Blinn-Phong光照模型。Blinn-Phong光照模型與Phong光照模型的區別
- 2、談談Shadow Map
- 3、你知道BSP樹、Octree、KD-Tree嗎?它們在渲染中有什么作用?
- 4、什么是光線追蹤(Ray Tracing)?與光柵化(Rasterization)的最大區別是什么?
- 5、在圖形學中,PBR(Physically Based Rendering)是什么?什么是PBR材質?
- 6、在渲染引擎中,Forward Rendering和Deferred Rendering有什么優缺點?
- 7、什么是BRDF?
- 8、如何實現全局光照?
- 9、投影有正交投影和透視投影,矩陣如何推導?
Opengl 與 Vulkan
1、OpenGL的渲染管線有哪些主要階段?分別做什么?
1、**CPU端處理:**加載模型信息(光照、貼圖),處理用戶輸入(鼠標、鍵盤),更新場景狀態(物體的位置、旋轉,縮放),提交渲染指令(glDrawArrays)
2、**頂點著色器:**GPU上的唯二的可編程階段,處理頂點屬性,主要是位置屬性,通過模型矩陣,視圖矩陣和投影矩陣進行位置的變換。模型矩陣:將模型移動到世界坐標系中。視圖矩陣:將世界空間變換到相機空間,該矩陣由相機的位置,朝向和偏移向三個向量決定。投影矩陣:相機空間是一個四棱臺,投影矩陣將相機空間變換到裁剪空間中。有正交投影和透視投影兩種變換。
3、圖元裝配階段: 將頂點組合成圖元,由opengl的接口決定是裝配成點、線還是三角形。無法直接編程
4、**裁剪階段:**將視錐體外的不可見的部分剔除
5、**光柵化階段:**將三角形,線、點轉化成Fragment
6:**片段著色器:**可編程的階段,計算每個片段的最終顏色。輸入Fragment的數據,比如紋理坐標,法向等輸入。輸入光源信息,比如環境光,鏡面反射,光源坐標等。輸出片段的顏色。
7、**測試與混合階段:**深度測試、模板測試、混合。用于處理遮擋關系與透明渲染的階段
8、寫入幀緩沖區
2、OpenGL中的VAO、VBO和EBO分別是什么?為什么需要它們?
VBO:頂點緩沖對象。將頂點的信息,包括位置、法向、紋理等信息都存入VBO中。可以一次性的將數據從CPU傳入到GPU中
EBO:索引緩沖對象。存放頂點的索引。
VAO:頂點數組對象 。是一個狀態對象,用于記錄 VBO、EBO 以及頂點屬性指針的綁定狀態,避免重復綁定VBO和EBO。
3、細分著色器與幾何著色器是什么
頂點著色器->細分著色器->幾何著色器->光柵化
細分著色器:計算細分頂點
幾何著色器:動態生成額外的幾何體,點、線、三角形。
4、Vulkan與Opengl的區別是什么
特性 | Opengl | Vulkan |
---|---|---|
設計理念 | 固定渲染管線+狀態機 | 完全可控的渲染管線+現實驅動編程 |
顯存管理 | 自動管理,不支持 | 手動管理,支持 |
多線程 | 不支持 | 支持 |
5、OpenGL中的紋理映射(Texture Mapping)是怎么實現的?簡述主要步驟
1、紋理加載:使用stb圖像庫加載紋理
2、紋理綁定:使用glBindTexture(GL_TEXTURE_2D, texture)綁定紋理
3、為頂點指定紋理坐標
4、在頂點著色器中傳遞紋理坐標,在片段著色器中使用紋理坐標
6、在OpenGL中,glViewport和glScissor的區別是什么?
雖然他們都影響渲染結果的可視區域,但是還是有所不同的
功能 | glViewport | glScissor |
---|---|---|
作用 | 設置OpenGL渲染結果映射到窗口中的區域 | 限制像素繪制范圍,只允許特定區域渲染 |
影響范圍 | 影響所有渲染操作的投影區域 | 只影響像素繪制,不影響投影 |
對裁剪的影響 | 不進行任何裁剪 | 強制限定像素寫入范圍 |
修改投影坐標 | 將 NDC 映射到窗口區域 | 不修改任何投影坐標 |
常用場景 | 1、窗口縮放 2、設置視口 | 1、實現小窗口渲染 2、裁剪特定區域 |
7、Vulkan中的Instance、Device、Queue、CommandBuffer分別是什么?
名稱 | 說明 | 功能 |
---|---|---|
Instance | VkInstance是與Vulkan庫進行交互的入口點,表示一個Vulkan應用程序的上下文。它是創建其他Vulkan對象(如VkDevice、VkSurface等)的基礎。 | 1、啟動Vulkan應用程序所必需的基本結構。2、維護Vulkan驅動程序與操作系統之間的接口。3、負責枚舉和查詢支持的擴展、層(Layers)和設備(Device) |
Device | VkDevice表示與Vulkan API進行交互的一個物理GPU或虛擬GPU的抽象。它是應用程序與GPU交互的接口,包含了所有與圖形處理和計算相關的功能。換句話說,Vulkan將一塊任意的GPU抽象成相同的邏輯設備device | 1、VkDevice是創建命令隊列(Queue)、緩沖區(Buffer)、圖像(Image)、著色器模塊(Shader Module)等其他Vulkan對象的基礎。2、管理GPU資源的生命周期。3、用于執行圖形、計算等工作。 |
Queue | VkQueue是GPU執行命令的一個通道,每個設備可能有多個隊列,每個隊列都有不同的優先級和類型。 | 隊列用于提交渲染命令、計算命令等。可以將命令提交到不同類型的隊列(如圖形隊列、計算隊列、傳輸隊列等),每個隊列類型可以執行不同類型的操作。 |
CommandBuffer | VkCommandBuffer是一個用于記錄命令的對象,它包含了一系列GPU將要執行的操作。命令緩沖區實際上并不執行命令,而是將命令記錄到緩沖區中,之后可以將它們提交給隊列執行。 | 1、通過vkBeginCommandBuffer和vkEndCommandBuffer來開始和結束命令的記錄。2、在命令緩沖區中記錄一系列圖形、計算或傳輸命令(如繪制命令、資源綁定、數據傳輸命令等)。3、命令緩沖區可以是一次性的或多次使用的,在執行完成后,命令緩沖區可以被重新使用或重置。 |
8、Vulkan的Pipeline(渲染管線)為什么不可變?
在Vulkan中,渲染管線(Pipeline)是不可變的,意味著一旦創建管線對象后,管線的所有狀態和配置都不能在運行時被修改。這是Vulkan設計的一部分,其主要目的是為了優化性能和簡化狀態管理。
1、減少運行時狀態檢查:由于Vulkan管線不可變,驅動程序不需要在每次渲染時去檢查管線狀態是否已經改變。
- 每次提交渲染命令時,渲染管線的狀態都是一致的,GPU可以直接使用已經創建的管線,而無需重新設置狀態。
- 這減少了CPU和GPU之間的狀態同步和管理工作,從而加快渲染的速度。
2、管線創建時的資源預編譯和優化:Vulkan要求在創建管線時,必須明確指定所有的渲染過程,包括著色器、輸入布局、混合狀態、深度/模板測試等。由于管線不可變,GPU可以在管線創建時執行預編譯和優化,提前為硬件準備好渲染所需的資源。這種設計使得GPU在實際渲染時能直接加載已經優化過的管線,從而提高渲染效率。
9、OpenGL的FBO幀緩沖對象的作用是什么?有哪些常見的應用場景?
FBO(幀緩沖對象)是OpenGL中的一個工具,用來讓渲染結果不直接顯示在屏幕上,而是先存儲在一個紋理或緩沖區中。這種方法常常用于一些復雜的渲染任務,比如:
離屏渲染:你可以將渲染的結果存儲在紋理中,而不是直接顯示在屏幕上。這可以用于后續的處理,比如做特效或者計算陰影。
后處理效果:先渲染一個場景到FBO,然后用這個渲染結果做各種特效(比如模糊、色彩調整等)。比如做陰影貼圖時,先用FBO把場景的深度信息渲染到紋理中,之后計算光源下的陰影。
多渲染目標(MRT):可以把渲染結果同時保存到多個紋理里,做更復雜的效果,比如計算不同的渲染通道(顏色、法線、深度等)。
10、Vulkan中的Fence是用來干什么的?什么時候必須用?
Fence是用于同步不同線程或隊列之間的操作,它通常用于等待命令執行的完成。柵欄主要用于隊列之間的同步,確保一個操作在另一個操作完成后才能繼續執行。
等待操作完成:當你提交命令到一個隊列時,可以使用柵欄來等待命令執行完成。比如,等待GPU完成繪制或計算操作,然后再進行后續操作。
跨隊列同步:當使用多個隊列(例如圖形隊列和計算隊列)時,柵欄可以用來同步這些隊列。你可以等待一個隊列的任務完成,再提交另一個隊列的任務。
避免CPU與GPU的不同步:CPU在提交命令后可以使用柵欄檢查GPU的狀態,確保某些任務完成后才繼續進行后續的CPU操作。
11、Vulkan中的Descriptor Set和OpenGL中的Uniform Buffer有什么區別?
在Vulkan和Opengl中,Descriptor Set和Uniform Buffer都是用于傳遞數據給著色器的方式。
不同的是,Descriptor Set更加靈活,Descriptor Set是Descriptor的集合,每一個Descriptor可以綁定不同類型的資源。當然著色器中也可以有多個Set,兩個set和一個push_constant往著色器中傳入數據:
layout(set = 0, binding = 0) uniform GlobalUbo {mat4 projection;mat4 view;mat4 invView;vec4 ambientLightColor; // w is intensityvec4 color;vec4 direction; } ubo; struct LineShelllet {vec2 point[2];float height[2];float angle[2]; double width; };//讀取從CPU那里發送過來的數據 layout(set=1,binding = 0) readonly buffer Lets { LineShelllet lets[]; }; layout(set=1,binding = 1) readonly buffer Index { uint index[]; }; layout(set=1,binding = 2) readonly buffer Index2 { uint index2[]; }; layout(push_constant) uniform Push {mat4 modelMatrix;mat4 normalMatrix;int modeltype;int letsize; } push;
在Opengl的Uniform Buffer(UBO)是用于存儲常量數據(如模型矩陣、視圖矩陣、光源信息等)并傳遞到著色器中的對象。你可以將多個uniform變量存儲在一個Buffer對象中,然后通過綁定該Buffer將數據傳遞給著色器。每個Uniform Buffer可以存儲的內容是有限的,通常需要按照類型(如mat4、vec3等)組織數據。
12、如何在OpenGL/Vulkan中實現LOD(Level of Detail)?
1、預生成:預先為模型生成多個細節層次的網格(例如,高精度、中精度、低精度的網格)。
2、距離判斷:根據相機到模型的距離來判斷應該使用哪個精度的模型。
3、渲染時選擇:在渲染過程中,選擇最合適的模型進行繪制。
在Vulkan中可以使用MeshShader架構來優化這一過程
13、在OpenGL中,什么是GPU Instancing?
在傳統渲染中,如果需要渲染多個相同的物體(如森林中的樹、群體角色、粒子系統),每個物體都調用一次 glDrawElements() 或 glDrawArrays(),CPU 需要多次發送數據給 GPU,開銷較大。
GPU Instancing 是 OpenGL 提供的一種技術,允許在一次繪制調用(Draw Call)中渲染多個相同的物體,只需提供少量不同的數據(如位置、顏色、旋轉等)。這樣可以大幅減少 CPU 和 GPU 之間的通信開銷,提高渲染效率。
14、Vulkan的RenderPass和Subpass的作用
RenderPass:是一個Vulkan對象,用于表示一組渲染操作的集合。這些操作通常會影響多個顏色附件、深度/模板附件等,并按照特定的順序執行。一個RenderPass通常包括多個Subpass,每個Subpass可以進行不同的渲染操作。
1、優化與重用:Vulkan的RenderPass主要目的是為了提高性能。在RenderPass中,渲染的操作是與幀緩沖區的狀態相結合的,這樣可以讓驅動程序或硬件優化操作。例如,某些操作可能只涉及顏色附件,或者某些操作只會寫入深度緩沖區。通過這些信息,Vulkan可以合理地優化內存訪問和數據依賴,減少不必要的緩存無效化和同步開銷。
2、附件(Attachment)管理:在RenderPass中,定義了多個附件(如顏色附件、深度附件、模板附件等),并描述這些附件的加載、存儲和最終輸出行為。例如,某些附件可以在某個Subpass中進行讀寫,而在其他Subpass中僅進行讀取。
Subpass:是RenderPass中的一個子操作,表示一個渲染過程中的一部分。一個RenderPass可以包含多個Subpass,每個Subpass負責執行某個階段的渲染操作。Subpass允許在同一個RenderPass中進行多次渲染,同時減少對附件的寫入或同步要求。
1、分階段渲染:Subpass表示渲染過程中不同階段的操作,例如第一階段可以是幾何處理和光照計算,第二階段可以是后處理(如全屏后處理效果)。每個Subpass通常會有一個特定的渲染目標(即顏色或深度附件)并與前一個Subpass共享這些目標。
2、附件的共享與依賴:不同Subpass之間可以共享某些附件(如顏色緩沖區或深度緩沖區)。Subpass允許通過共享附件來避免不必要的資源重新加載和同步。通過優化附件的讀取/寫入行為,可以減少內存訪問沖突和性能瓶頸。
3、減少內存訪問和同步:Vulkan中的Subpass可以通過將渲染階段組織成多個Subpass來最小化對附件的寫入和同步。例如,可以在一個Subpass中只寫入顏色數據,而在另一個Subpass中只進行深度測試。通過這種方式,可以避免頻繁的內存無效化操作,提高渲染效率。
15、移動端和PC端的差異,渲染的區別
移動端的內存帶寬較低,計算能力較低
PC 端使用 IMR(即時模式渲染 Immediate Mode Rendering):頂點著色后,直接寫入幀緩沖,可能有大量的 Overdraw(重復繪制相同像素)。
移動端使用 TBDR(基于 Tile 的延遲渲染 Tile-Based Deferred Rendering):先把幾何數據劃分為小塊(Tile),再逐塊渲染,減少 Overdraw。
16、在移動端渲染大型場景時,如何優化內存?
紋理壓縮:使用適合移動設備的紋理壓縮格式(如 ETC1/ETC2、ASTC、PVRTC),這些格式能夠顯著減少紋理的內存占用和帶寬消耗。
Mipmap 生成:生成 Mipmap 紋理,并根據攝像機與物體的距離使用適當的 Mipmap 級別。這可以減少高分辨率紋理的加載和內存占用,提升渲染效率。
簡化網格數據:使用低多邊形數量的模型,或者通過 Level of Detail (LOD) 技術動態調整模型的細節。當攝像機距離較遠時,使用更低細節的網格,減小內存占用和計算量。
GPU 實例化(Instancing):對于重復的物體,使用 GPU Instancing 技術,在內存中存儲一個物體的實例數據,而不是為每個實例單獨存儲數據。這樣可以顯著減少內存的占用。
17、什么是Mesh Shader?
Mesh Shader 是一種在現代圖形API(如Vulkan和DirectX 12)中引入的新型著色器階段,它極大地改進了圖形渲染的效率,特別是在復雜幾何體的處理和剖分上。Mesh Shader 是相對于傳統的頂點著色器(Vertex Shader)和幾何著色器(Geometry Shader)的一種新型替代方案。它允許開發者將網格劃分為更小的單元(Meshlet),并對這些單元進行并行處理。通過這種方式,減少了傳統渲染管線中頂點處理的瓶頸,提高了并行度和性能。
18、OpenGL的深度測試(Depth Test)是如何工作的?為什么會出現深度沖突(Z-fighting)?
深度緩沖區:渲染每個像素時,Opengl會為每個像素存儲一個深度值,通常這個值在0-1范圍內,0代表離相機越近,1代表遠。
深度測試:在渲染一個像素之前,OpenGL首先檢查該像素的深度值(即它相對于攝像機的距離)是否小于當前深度緩沖區中存儲的值。如果是,這意味著該像素比之前的像素更近,因此該像素會被繪制。如果不是,這意味著該像素被遮擋(距離攝像機更遠),因此該像素不會被繪制,深度緩沖區中的值保持不變。
Z-fighting:當兩個面非常近時,就會出現深度競爭。會出現撕裂,閃爍的效果,因為在這些像素中,有一些被判定為需要渲染A面,有一些則被判定為應該渲染B面。
19、在OpenGL中,如果我想要繪制一個半透明的物體,應該怎么做?
- 啟用混合:glEnable(GL_BLEND); 因為一個像素中的顏色是透明物體的顏色和背景顏色混合起來的,因此需要啟用混和,選取混合公式來計算顏色。
- 設置材質的透明度,在顏色的 α \alpha α項,設置一個小于1.0的值
- 禁用深度寫入:因為透明的物體就算擋在了不透明的物體之前,不透明的物體也能被看見,反之則不成立。因此需要禁用深度寫入,而打開深度測試。
20、在Vulkan中,為什么要設置多個VkCommandBuffer?而不是一個?
在 Vulkan 中,生成命令和提交命令是分開的。通過將多個命令緩沖區分開,可以在 CPU 上并行生成多個命令緩沖區,同時將它們提交到 GPU 上進行執行。這樣可以減少 CPU 的等待時間,使 CPU 和 GPU 的工作更加并行。例如,CPU 可以在執行第一個命令緩沖區的同時準備第二個命令緩沖區,減少 CPU 的空閑時間,提高整體渲染效率。
21、Vulkan中,為什么我們需要同步機制(Synchronization)?哪些同步機制最常用?
在 Vulkan 中,GPU 的渲染和計算操作往往是 異步 執行的。GPU上的多個命令、操作可能并行運行,或者可能會依賴于之前的命令的結果,因此同步機制(Synchronization)是非常重要的,因為它們確保在不同操作之間的正確執行順序,防止出現競爭條件和數據沖突。Vulkan是一個低級別、顯式的API,它不為我們自動處理這些同步問題,因此開發者需要手動管理。沒有正確的同步,會導致圖形和計算操作的結果錯誤,甚至崩潰。
名稱 作用 使用場景 工作方式 Fences
柵欄用于在主機(CPU)和設備(GPU)之間同步 通常用于等待 GPU 完成某個操作,特別是在提交命令緩沖區時,確保 GPU 的任務完成后再進行后續操作 當 GPU 完成某個任務時,Vulkan會觸發 fence 信號,主機線程會等待 fence 被觸發 Semaphores
信號量用于在不同的 GPU 操作之間同步,確保操作按正確的順序執行 通常在渲染管線中的多個階段之間進行同步,特別是在多個命令隊列中,確保渲染操作的順序 一個操作完成后會“發出”信號量,等待信號量的操作可以接著進行 Events
事件用于在 GPU 上的多個操作之間或 CPU 和 GPU 之間同步 可以在命令緩沖區內同步某些操作,或者觸發 GPU 內部事件,然后CPU進行響應 事件可以處于兩種狀態:觸發(signaled)或未觸發(unsignaled)。操作可以等待事件被觸發后繼續執行 Pipeline Barriers
(管線屏障)用于在 Vulkan 渲染管線的不同階段之間同步,確保命令之間的正確執行順序 通常在渲染或計算命令之間使用,確保 GPU 正確地執行內存操作或圖像處理操作 可以在進行渲染操作前等待紋理或緩沖區的傳輸操作完成,防止資源被不正確地讀取或寫入
圖形學算法
1、簡述Blinn-Phong光照模型。Blinn-Phong光照模型與Phong光照模型的區別
Blinn-Phong光照模型由三部分組成:環境光,漫反射光和鏡面反射光。其中環境光通常為常數,漫反射光: I d i f f u s e = k d ? ( L ? N ) I_{diffuse} = k_d * (L\cdot N) Idiffuse?=kd??(L?N),其中k是漫反射系數,L是光照方向,N是法向量。也就是說面越垂直與光照方向,那么漫反射越強烈。鏡面反射光則是根據半向量和法向量的點乘進行計算: I s p e c u l a r = k s × m a x ( 0 , ( H ? N ) ) n I_{specular} = k_s \times max(0,(H \cdot N))^n Ispecular?=ks?×max(0,(H?N))n。其中H是半向量,是光源方向+觀察方向的單位向量。
Phong和Blinn的區別在于鏡面反射的計算上,Blinn-Phong的鏡面反射是利用半向量和法向量計算的,而Phong是利用反射向量與觀察方向的點乘來計算的。Phong需要預先根據法向量和光照方向計算反射光照,開銷較大。
2、談談Shadow Map
相當于以光源視角生成了一張深度圖。在渲染某個像素之前,根據這個深度圖,也就是Shadow Map進行判斷,如果它到光源的距離小于深度圖中記載的距離,那么就認為該處不是陰影,否則就是陰影。
優勢:1、高效,適合實時渲染,尤其是在復雜場景中。2、可以適應不同類型的光源,如定向光、點光源等。
不足:陰影可能會出現鋸齒或模糊。可以通過使用PCF(Percentage Closer Filtering)來平滑陰影的邊緣。
3、你知道BSP樹、Octree、KD-Tree嗎?它們在渲染中有什么作用?
BSP樹(Binary Space Partitioning Tree):是一種遞歸地將空間劃分為兩個半空間的空間劃分數據結構。每個節點代表一個平面,通過這個平面將空間分為兩個部分(左側和右側),每個子空間都可以繼續遞歸劃分。
八叉樹 Octree:是一種三維空間劃分數據結構,它將空間分成8個子區域(即八分之一空間),每個子區域可以進一步遞歸劃分成8個子區域。Octree適用于存儲和管理三維空間中的物體,尤其是那些分布不均勻的場景。
KD-Tree(K-Dimensional Tree):是一種空間劃分數據結構,用于組織K維空間的數據(通常是二維或三維)。它通過選擇一個維度(如X、Y或Z軸)將空間劃分為兩部分,然后遞歸地進行空間劃分。每個節點包含一個數據點和一個劃分平面,KD-Tree適合用于高維數據的搜索和查詢。
這些樹可以用于光線追蹤,碰撞檢測,LOD,視錐體剔除等相關算法的加速
4、什么是光線追蹤(Ray Tracing)?與光柵化(Rasterization)的最大區別是什么?
光線追蹤(Ray Tracing)是一種通過模擬光線傳播的物理過程來生成圖像的技術。在光線追蹤中,光線從攝像機(觀察點)出發,向場景中的物體發射,并根據物體的材質屬性(如反射、折射、透光等)計算光線與物體的交互,最終得到顏色和亮度信息。
特性 | 光線追蹤(Ray Tracing) | 光柵化(Rasterization) |
---|---|---|
渲染方向 | 從視點出發,模擬光線與物體的交互 | 從物體出發,投影到屏幕 |
光照計算 | 考慮直接光照和間接光照(反射、折射等) | 主要計算直接光照 |
真實性 | 高,能夠精確模擬光線的傳播,真實感強 | 較低,通常依賴于逼近方法(如光照貼圖) |
計算量 | 高,尤其在需要多次光線反彈時 | 低,實時渲染時效率高 |
應用場景 | 高質量渲染(電影、動畫、光線追蹤游戲) | 實時渲染(視頻游戲、互動應用) |
5、在圖形學中,PBR(Physically Based Rendering)是什么?什么是PBR材質?
PBR(Physically Based Rendering,基于物理的渲染)是一種通過模擬光與物體表面相互作用的物理過程來生成逼真圖像的渲染技術。它基于物理學的真實原理,考慮了光的反射、折射、散射等現象,使得渲染效果能夠在不同的光照環境下保持一致性,能夠生成更加自然和真實的圖像。
PBR材質(Physically Based Rendering Material,基于物理的渲染材質)是一種通過物理屬性來描述物體表面特性、光照與材質相互作用的材質模型。與傳統的材質模型不同,PBR材質遵循物理學的真實規律,旨在使渲染結果更加自然和真實。PBR材質的關鍵在于其通過幾個核心參數(如金屬度、粗糙度等)來描述物體的物理屬性,從而在不同的光照環境下能夠產生一致的效果。
6、在渲染引擎中,Forward Rendering和Deferred Rendering有什么優缺點?
對比項 | Forward Rendering(前向渲染) | Deferred Rendering(延遲渲染) |
---|---|---|
光照計算 | 逐物體計算光照(每個像素計算所有光源) | 屏幕空間光照(僅計算可見像素的光照) |
性能 | 少光源時高效,多光源時性能下降 | 適合大量光源,僅對可見像素計算光照 |
顯存占用 | 低,占用顯存少 | 高,需要存 G-buffer(位置、法線等) |
透明度支持 | 直接支持透明度(Blending) | 不支持,需要額外處理(Forward+) |
后處理效果 | 難以實現 SSAO、HDR、Bloom | 適合高級特效(SSAO、HDR、光照體積) |
陰影處理 | 每個光源單獨計算 Shadow Map,成本高 | 需要額外技術(Deferred Shadowing) |
適用場景 | 簡單 3D 場景、VR/AR、移動端 | PC/主機端、動態光源多的場景(如城市夜景) |
7、什么是BRDF?
它是物體材質的體現,是渲染方程中重要的一項,它定義了表面反射的光強度相對于入射光方向和觀察方向的關系。
具體的: f r ( w i , w o ) = d L o ( w o ) d E i ( w i ) f_r(\mathbf{w_i}, \mathbf{w_o}) = \frac{dL_o(\mathbf{w_o})}{dE_i(\mathbf{w_i})} fr?(wi?,wo?)=dEi?(wi?)dLo?(wo?)?
f r ( w i , w o ) f_r(\mathbf{w_i}, \mathbf{w_o}) fr?(wi?,wo?)是 BRDF 函數,表示表面反射的光強度,依賴于入射光方向( w i \mathbf{w_i} wi?)和觀察方向( w o \mathbf{w_o} wo?)。
d L o ( w o ) dL_o(\mathbf{w_o}) dLo?(wo?) 是單位立體角內從表面反射到觀察者的光強度。
d E i ( w i ) dE_i(\mathbf{w_i}) dEi?(wi?)是單位立體角內從光源照射到表面的入射光強度。
8、如何實現全局光照?
全局光照指光在場景中多次散射,反射和折射,不僅僅考慮直接光照還考慮間接光照。一般用光線追蹤的方式實現。
9、投影有正交投影和透視投影,矩陣如何推導?
正交投影:矩陣需要將三維坐標變換到一個二維平面,并且需要根據近平面(near plane)、遠平面(far plane)、視口的寬度和高度等參數來定義。假設攝像機的視口是一個立方體(或者一個矩形框),其位置在視空域(view space)中,且投影過程中不涉及深度的壓縮。正交投影矩陣的標準形式是:
M o r t h o = ( 2 r ? l 0 0 ? r + l r ? l 0 2 t ? b 0 ? t + b t ? b 0 0 ? 2 f ? n ? f + n f ? n 0 0 0 1 ) M_{ortho} = \begin{pmatrix} \frac{2}{r - l} & 0 & 0 & -\frac{r + l}{r - l} \\ 0 & \frac{2}{t - b} & 0 & -\frac{t + b}{t - b} \\ 0 & 0 & -\frac{2}{f - n} & -\frac{f + n}{f - n} \\ 0 & 0 & 0 & 1 \end{pmatrix} Mortho?= ?r?l2?000?0t?b2?00?00?f?n2?0??r?lr+l??t?bt+b??f?nf+n?1? ?
其中:
- r,l是視體的左、右邊界。
- t,b是視體的下、上邊界。
- n,f 是近平面和遠平面的距離。
透視投影:是模擬現實世界的視覺效果,使得距離遠的物體看起來更小,距離近的物體看起來更大。透視投影會將三維空間中的點通過透視縮放的方式映射到二維平面上。
透視投影的關鍵是根據物體距離視點的遠近調整物體的大小。透視投影矩陣常常根據相機的視野(Field of View,FOV)、長寬比(aspect ratio)、近平面(near plane)和遠平面(far plane)來進行定義。
透視投影矩陣的標準形式如下:
M p e r s p e c t i v e = ( 1 aspect ? tan ? ( F O V 2 ) 0 0 0 0 1 tan ? ( F O V 2 ) 0 0 0 0 f + n n ? f 2 f n n ? f 0 0 ? 1 0 ) M_{perspective} = \begin{pmatrix} \frac{1}{\text{aspect} \cdot \tan(\frac{FOV}{2})} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan(\frac{FOV}{2})} & 0 & 0 \\ 0 & 0 & \frac{f+n}{n-f} & \frac{2fn}{n-f} \\ 0 & 0 & -1 & 0 \end{pmatrix} Mperspective?= ?aspect?tan(2FOV?)1?000?0tan(2FOV?)1?00?00n?ff+n??1?00n?f2fn?0? ?
其中:
- FOV 是視場角(通常是垂直視場角),表示相機的可視范圍。
- aspect 是視口的寬高比,通常是寬度除以高度。
- n和f 近平面和遠平面的距離。