threejs - src - material和shader是如何對應的?

grassofsky發表於2022-01-26

threejs - src - material和shader是如何對應的?

在上一篇文章中threejs - src - WebGLProgram是如何組建Shader的? - grassofsky - 部落格園 (cnblogs.com),我們介紹了WebGLProgram中如何組建Shader,如何獲取對應的unifrom的,以及簡單的介紹了下WebGLProgram關聯的uniform值是如何設定的。

文字重點針對的問題是:

  • 不同的材質如何對應到不同的Shader?
  • 材質中的屬性和Shader中的屬性之間是如何進行關聯的?

不同材質如何對應不同的Shader?

在上一篇文章中,我們知道ShaderLib中提供了內建的Shader型別,示例如下(通過物件的形式儲存):

// ShaderLib.js
const ShaderLib = {
    basic: {...},
    lambert: {...},
    phong: {...},
    ...
}

那麼必然在程式碼的某處,我們會使用上面的key,來關聯具體的shader,在程式碼中檢索命名比較特殊的key,此處選擇為distanceRGBA,搜尋結果如下:

很快就能夠發現,ShaderLib的key被重新對映了,具體如下:

const shaderIDs = {
    MeshDepthMaterial: 'depth',
    MeshDistanceMaterial: 'distanceRGBA',
    ...
};

此處重新對映後,key的值,就是具體的Material對應的類名,這樣兩者的關係就建立起來了。使用的時候直接通過Material的type屬性(該屬性對應的是Material具體的類名),去獲取具體的shader字串。具體程式碼見WebGLPrograms的getParameters函式,

WebGLRenderer渲染流程

在介紹屬性和shader uniform之間的關聯之前,先過一下WebGLRenderer的渲染流程。渲染流程的入口函式為:renderer.render(scene, camera);這個時候已經構建好場景以及相機,示意圖可能是這樣的:

那麼渲染器是怎麼執行渲染的呢?大致的流程如下圖所示(圖中綠線為函式開始執行的地方,紅線表示函式返回的地方):

此處Material和uniform相關的邏輯位於setProgram中。

材質中的屬性和Shader中的屬性之間是如何進行關聯的?

正如上一節所述,相關的主要邏輯位於WebGLRenderer.setProgram函式中,讓我們來看下這個函式重點幹了啥?為了簡化流程,我們先假設,_clippingEnabled = false; object.isSkinnedMesh = false;materialProperties.__version還沒有賦值,不考慮morph,不考慮陰影,並不是spriteMaterial,不考慮texture,那麼基本流程如下:

圖中紅色的框getProgram函式,實現了material和shader的關聯,綠色的框實現了引數往實際shader中的傳遞。關於WebGLProgram可以參見:threejs - src - WebGLProgram是如何組建Shader的? - grassofsky - 部落格園 (cnblogs.com)

待辦項 TODO List

  • 渲染狀態是怎麼管理的?
  • renderlist是怎麼管理的?
  • projectObject是幹啥用的?

相關文章