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是幹啥用的?