携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
上篇提到了一些属性的shader代码。 但是,如果你是第一次去读,你找起来会很麻烦。
怎么个麻烦法呢? 且看源码。 我们用执果索因之法,先来到物理材质的js文件
除了这个,你发现完全找不到哪里用了shader。
于是,你可能想到,这个应用着色器代码应该是共性,或许在基类Material里面。
好,我们来看
发现还是找不到。
这说明,应用着色器就不归它管,但是不同的材质就是应用了不同的着色器。 我知道有两个材质肯定有用到,那就是自定义材质,
果然,有用到,我猜着色器文件应该都是放在一起的,所以进去那个文件夹。找physical相关文件,其实是不是该直接搜索文件名的。 然后,找到了这个,
但是,你发现,居然一个uniform 变量都对应不上, 仔细看文件名,确实不是,起名还是挺规范的。 不要紧,下面还有一个文件夹。
看这名字,应该是对了。
但是问题才刚刚开始。 #include 关键字 预编译文件? glsl本身不太可能支持,应该是用了什么扩展,后面肯定是打包成一个文件。
搜不到,也不知到这个include 是引入哪里的文件。 不要紧,我们搜索一下uniform float transparent 。搜不到,于是我想了想,搜opacity。 好吧,就在刚才那个文件里。 试着,搜一下 include后面的文件, 我终于发现了, 原来,include 的文件都是这个shaderChunk下面的。
但是读起来,还是很麻烦,跨文件读麻烦,为啥,因为不能直接转到定义了,而且大量的数学计算,和条件处理,这不是我们通常的代码模块化了, 从某种角度来说, 除了函数和变量定义,它只是简单的把代码分裂开来。
获取完整的shader代码
于是,我就想,能不能获取完整的shader代码。 我知道,初始化着色器的时候,传给gl的一定是完整的着色器字符串。 所以,我又去找初始化着色器的代码。 这怎么找,回顾一下初始化流程,搜initShader试试,估计也是这个名字,还是没搜到。 直接搜shadersource,它肯定调用了这个方法,这是原生方法。
果然,找到了。 然后,我只要打个log,把shader打出来,复制粘贴即可。
继续探究
完整代码有了,这样我们探究起来就很方便了。 我们先来直接看最后几行。 最终肯定是要给fragColor赋值,所以我们看它的变化。
对了,glsl预编译和js材质属性的关系,在这个文件里, 虽然,大部分宏的命名和原属性有关,但也有,在我们看起来毫不相关的。 比如tranparent 。 为什么,我如此在意它,因为开始的时候,我就是为了它,但是却找不到。
因为transparent 根本不是直接决定opaque的。
光的来源
好了,我们来逆光分析。
不考虑fog premultipliedAlpha sheen dithering 这些属性的情况,可以看到, 最终光照rgb和alpha是分开的
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
我比较看重 alpha通道的来源,因为我本来就是为了这个才看源码的。
alpha 通道的
gl_FragColor = vec4( outgoingLight, diffuseColor.a )
vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;
//这两个是顺序
#ifdef OPAQUE diffuseColor.a = 1.0;
#endif
#ifdef USE_TRANSMISSION diffuseColor.a *= transmissionAlpha + 0.1;
#endif diffuseColor.a *= transmissionAlpha + 0.1;
// 这两也是顺序 #ifdef USE_ALPHAMAP diffuseColor.a *= texture2D( alphaMap, vUv ).g;
#endif
#ifdef USE_ALPHATEST
if ( diffuseColor.a < alphaTest ) discard;
#endif
看上没有什么问题,但是,实际上 transmissionAlpha 这个很成问题,之前说了,即便开启了transimission , opacity也会影响到alpha。 所以,我们走进这个vec4 transmission,不是我们材质上的属性,js属性到了shader里,换了个变量名 transmissionFactor。
我们可以看到,这个vec transmission 就是由getIBLVolumeRefraction 计算得到。
transmissionAlpha 默认是1 ,然后和 transmission.a按 transmissionFactor混合, 也就是说,假如transmissionFactor是0 ,那么alpha就为1.并不是,不能等于0 ,可以接近,js 0也是false
parameters.transmission ? '#define USE_TRANSMISSION' : ''。
#ifdef USE_TRANSMISSION
float transmissionAlpha = 1.0;
float transmissionFactor = transmission;
float thicknessFactor = thickness;
#ifdef USE_TRANSMISSIONMAP
transmissionFactor *= texture2D( transmissionMap, vUv ).r;
#endif
#ifdef USE_THICKNESSMAP
thicknessFactor *= texture2D( thicknessMap, vUv ).g;
#endif
vec3 pos = vWorldPosition; //世界坐标
vec3 v = normalize( cameraPosition - pos );// 视线
vec3 n = inverseTransformDirection( normal, viewMatrix );//法线
vec4 transmission = getIBLVolumeRefraction(
n, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,
pos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,
attenuationColor, attenuationDistance );
totalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );
transmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );
#endif
看到这里,想必大家也累了(我累了),明天再继续。