fabric 材质定义:着色器实践
贴到沙盒里就可以运行:
随便定义一个浮点数,发现报错:
加上 限定字,报错稍微改了一点:
所以,这个 source 是有规则的。
我改成这样:
报错变化了:
大意是指, 这个函数没有返回值。这很正常,强类型的 GLSL 规定了这个函数的返回值类型是结构体 ,那么再次修改它。
这时,形状有颜色了:
material 这个变量是一个结构体,通过修改其材质因子即可实现材质修改。
修改其漫反射因子:
注意,glsl 中创建结构体 vec3 的默认值是 (0, 0, 0),现在我想要个粉色,rgb色值是:(216 / 255.0, 170 / 255.0, 208 / 255.0),即 (0.8470588235294118, 0.66666666, 0.8156862745098039)
没毛病,颜色出来了:
你可以在很多个地方获取材质、外观的着色器源代码:
Material.prototype.shaderSource:可读可写:当前 material 对象的 source 属性,支持实时修改
Appearance.prototype.vertexShaderSource:只读:当前外观对象的顶点着色器,仅支持构造时传入
Appearance.prototype.fragmentShaderSource:只读:当前外观对象的片元着色器,仅支持构造时传入
Appearance.prototype.getFragmentShaderSource():返回最终完全版片元着色器源代码。
上面在 fabric 对象中的 source 属性指定的 glsl 源代码,与 console.log(m.shaderSource) 出来的是完全一样的,所以此处忽略。
当通过 2.2 节中对漫反射属性的设置后,外观对象的 和 输出结果如下:
观察片元着色器代码中的主函数,其中有一句调用
这一句便是对我们在 fabric 对象中写入的 glsl 代码的调用。
最终,进入 分支(才疏学浅,不知道这个 FLAT 宏是什么),对像素着色,使用 material 结构的漫反射因子 自发光因子 透明度因子进行叠加,生成最终的颜色值。所以,这个时候不妨回到 Material 的 source 中,继续动手脚。
是存在直接修改 Appearance 对象 fragmentShader、vertexShader 的大佬的,后面有机会展开说说。
(我偷偷把高度设为了 30000,不然不太明显)
换个地图和参数:
稍微有那么一点感觉了。
用的是 1. 中的代码,修改 aper 对象的构造参数,直接将 2.3 中的片元着色器代码贴入看看:
没有问题:
所以,基于此模板,只要胆大心细(划掉)只要对 Cesium 内置的着色器足够了解,完全可以自己改顶点和片元着色器。
依旧是上方 1. 的例子,只不过在顶点着色器稍微动动手脚,可达到变形的效果:
很可惜这个 position3DHigh 和 position3DLow 并不是这个 Primitive 的局部相对坐标,所以直接修改 z = 0 是压不平的,但是从图中可略见端倪,猜测这个 z 值是世界坐标,后续使用半透明地形看看。
在 WebGL 中就是恒定值的意思。一般 WebGL 用 关键字指定顶点属性或外来值,用 关键字指定常量,用 关键字指定顶点着色器、片元着色器共享的变量。
在 Cesium fabric 规则中,fabric.uniforms 的所有变量,在 fabric.source 中可以直接使用。
例如,我需要传入一个透明度:
是可以的:
打印 这个 m变量,可以轻松看到 glsl 代码:
并且支持直接对 js 的变量进行修改以重新着色:
uniforms 是 fabric 对象的一个属性,按理说,你可以给这个对象传递任何与 glsl 内置结构、数据类型有对应关系的数据,例如上例的 ,是数字类型,在着色器内部自动解析为
参考官方给出的二十多种预置 Material,如果你有兴趣,可以直接把它们的 source 打印出来观察。
例如,在镜面反射材质中,它的 uniforms 就有这两个:
一个是图片路径,一个是图片用于镜面反射强度的通道(此处是 alpha 通道)。
如果你传递的是对象,例如最常见的纹理材质中:
这个 my_struct,最终会传入一个结构体
当然有的时候不要作死,比如这个情况是转译不了的:
会报错,因为 my_struct 已经超出了 glsl 能理解的类型。
事实上,你在 uniforms 对象中写的任何数据,在 fabric.
从着色器的角度看,一种材质无非就是 函数的返回值罢了。
这里仅仅改的是材质,属于片元着色器阶段发生的事情,在第四节中已经看到了 Material 中写的着色器代码是如何被 Appearance 对象的片元着色器代码调用的。如果你想修改 Primitive 的形状,那就要去修改 Appearance 的顶点着色器。
Primitive 是 Scene 对象下的,在渲染循环中它是最终被宰杀的羔羊(划掉),只要是 Primitive,只要你有能力去修改它的着色器代码,就可以自定义很多东西出来。
将纹理坐标作为漫反射颜色写入,就能看到纹理坐标的样子了:
研究自带材质的着色器以及最终生成的顶点着色器、片元着色器
继续结合源代码,研究各路 Primitive
研究自带 glsl 结构体、函数、常量,灵活运用
理解顶点着色器的坐标含义