PBR物理渲染、IBL基於影象

2020-08-09 14:24:47

0 說在開始

PBR總結文章有很多,如 Ubp.a總結文章moriya蘇蛙可總結文章,以及 LearnOpenGLPBR章節部分等等。都是優秀的文章,不在過多重複和贅述,這裏給出需要學習的內容以及我所實現的場景。

整個場景的程式碼: https://github.com/douysu/person-summary如果對您有幫助,還請給一個star,如果大家發現錯誤以及不合理之處,還希望多多指出。

1 執行效果

[執行效果視訊鏈接]
图片

2 所需知識和概念

總結學習過程中涉及到的知識和概念。

  • 微平面模型

  • 輻射度量學(Radiometry)

    • 輻射通量(Radiant flux)
    • 輻射強度(Radiant Intensity)
    • 輻照度(Irradiance)
    • 輻射率 (Radiance)
    • 立體角
  • 渲染方程(Render Equation)

    • BRDF(Bidirectional Reflective Distribution Function)
    • Cook-Torrance 微表面模型
      • 正態分佈函數(Normal Distribution Function)
      • 菲涅爾方程(Fresnel Rquation)
      • 幾何函數(Geometry Function)
    • 常見PBR材質
  • 基於影象的照明(Image Based Lighting, IBL)

    • 通過Environment Map生成漫反射Irradiance貼圖
    • 通過Environment Map生成帶有粗糙度Roughness的鏡面Irradiance貼圖
    • 採樣及積分(蒙特卡洛方法)

總結的只是重點內容,還有HDR、Gamma變換等內容在LearnOpenGL中檢視。

3 踩坑及優化

LearnOpenGL的IBL程式碼比較冗餘,個人在此基礎上進行優化,優化部分如下。

3.1 PBR紋理載入優化

程式碼涉及載入較多紋理,複製貼上很難受,完成優化:

    const int sphereNum = 8; 
    std::string inputPath = "resources/textures/pbr"; 
    std::string twoInputPath[] = { "/gold/", "/slipperystonework/", "/ornate-celtic-gold/", "/bamboo-wood-semigloss/", "/wornpaintedcement/", "/paint-peeling/", "/Titanium-Scuffed/", "/wrinkled-paper/" }; 
    std::string allTextureName[] = { "albedo.png", "normal.png", "metallic.png", "roughness.png", "ao.png" }; 
    unsigned int sphereMap[sphereNum][5]; 
     
    for (int i = 0; i < sphereNum; i++) 
    { 
        std::string tempInputPath = inputPath + twoInputPath[i]; 
        for (int j = 0; j < 5; j++) 
        { 
            std::string lastInputPath = tempInputPath + allTextureName[j]; 
            sphereMap[i][j] = loadTexture(FileSystem::getPath(lastInputPath).c_str()); 
        } 
    } 

3.2 assimp模型數據載入順序

assimp模型載入順序與Shader中數據輸入順序不同,需要修改,否則無法完成載入模型。

        // set the vertex attribute pointers 
        // vertex Positions 
        glEnableVertexAttribArray(0);	 
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); 
        // vertex normals 
        glEnableVertexAttribArray(1);	 
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords)); 
        // vertex texture coords 
        glEnableVertexAttribArray(2);	 
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal)); 
#version 330 core 
layout (location = 0) in vec3 aPos; 
layout (location = 1) in vec2 aTexCoords; 
layout (location = 2) in vec3 aNormal; 

out vec2 TexCoords; 
out vec3 WorldPos; 
out vec3 Normal; 

uniform mat4 projection; 
uniform mat4 view; 
uniform mat4 model; 

void main() 
{ 
TexCoords = aTexCoords; 
WorldPos = vec3(model * vec4(aPos, 1.0)); 
Normal = mat3(model) * aNormal; 

gl_Position =  projection * view * vec4(WorldPos, 1.0); 
} 

3.3 完整專案設定

從零設定了一個PBR VS專案,其中涉及到lib,dll,等檔案匯入,設定好的專案在這裏找到: https://github.com/douysu/person-summary

4 參考

[1] LearnOpenGL

[2] 閆令琪-現代計算機圖學入門-Ray Tracing

[3] 以及其他博主文章