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