Is the shader specified by the source attribute in Cesium fabric the equivalent of the frgamentShader in glsl? If so, what attribute do I need to specify the vertexShader with, I can't find it in the cesium wiki.
What is the relationship between material.fabric.source and vertexShaderSource ,fragmentShaderSource in the following code? What is the order of execution?
let aper = new Cesium.MaterialAppearance({
material: new Cesium.Material({
fabric: {
uniforms: {
iTime: 0,
},
source: `
vec3 rgb2hsv(vec3 c){
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
float rand(vec2 n) {
return fract(sin(cos(dot(n, vec2(12.9898,12.1414)))) * 83758.5453);
}
float noise(vec2 n) {
const vec2 d = vec2(0.0, 1.0);
vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n));
return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y);
}
float fbm(vec2 n) {
float total = 0.0, amplitude = 1.0;
for (int i = 0; i <5; i++) {
total += noise(n) * amplitude;
n += n*1.7;
amplitude *= 0.47;
}
return total;
}
vec4 czm_getMaterial(vec2 vUv) {
vec2 uv = vUv;
const vec3 c1 = vec3(0.5, 0.0, 0.1);
const vec3 c2 = vec3(0.9, 0.1, 0.0);
const vec3 c3 = vec3(0.2, 0.1, 0.7);
const vec3 c4 = vec3(1.0, 0.9, 0.1);
const vec3 c5 = vec3(0.1);
const vec3 c6 = vec3(0.9);
vec2 speed = vec2(1.2, 0.1);
float shift = 1.327+sin(iTime*2.0)/2.4;
float alpha = 1.0;
//change the constant term for all kinds of cool distance versions,
//make plus/minus to switch between
//ground fire and fire rain!
float dist = 3.5-sin(iTime*0.4)/1.89;
vec2 p = uv * dist;
p.x -= iTime/1.1;
float q = fbm(p - iTime * 0.01+1.0*sin(iTime)/10.0);
float qb = fbm(p - iTime * 0.002+0.1*cos(iTime)/5.0);
float q2 = fbm(p - iTime * 0.44 - 5.0*cos(iTime)/7.0) - 6.0;
float q3 = fbm(p - iTime * 0.9 - 10.0*cos(iTime)/30.0)-4.0;
float q4 = fbm(p - iTime * 2.0 - 20.0*sin(iTime)/20.0)+2.0;
q = (q + qb - .4 * q2 -2.0*q3 + .6*q4)/3.8;
vec2 r = vec2(fbm(p + q /2.0 + iTime * speed.x - p.x - p.y), fbm(p + q - iTime * speed.y));
vec3 c = mix(c1, c2, fbm(p + r)) + mix(c3, c4, r.x) - mix(c5, c6, r.y);
vec3 color = vec3(c * cos(shift * uv.y));
color += .05;
color.r *= .8;
vec3 hsv = rgb2hsv(color);
hsv.y *= hsv.z * 1.1;
hsv.z *= hsv.y * 1.13;
hsv.y = (2.2-hsv.z*.9)*1.20;
color = hsv2rgb(hsv);
// fragColor = vec4(color.x, color.y, color.z, alpha);
return vec4(color.x, color.y, color.z, 1);
//return vec4(uv, 0, 1);
}
`,
}
}),
translucent: true,
vertexShaderSource: `
attribute vec3 position3DHigh;
attribute vec3 position3DLow;
attribute float batchId;
attribute vec2 st;
attribute vec3 normal;
varying vec2 v_st;
varying vec3 v_positionEC;
varying vec3 v_normalEC;
void main() {
v_st = st;
vec4 p = czm_computePosition();
v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates
v_normalEC = czm_normal * normal; // normal in eye coordinates
gl_Position = czm_modelViewProjectionRelativeToEye * p;
}
`,
fragmentShaderSource: `
varying vec2 v_st;
varying vec3 v_positionEC;
varying vec3 v_normalEC;
void main() {
vec3 positionToEyeEC = -v_positionEC;
vec3 normalEC = normalize(v_normalEC);
czm_materialInput materialInput;
materialInput.normalEC = normalEC;
materialInput.positionToEyeEC = positionToEyeEC;
materialInput.st = v_st;
vec4 color = czm_getMaterial(v_st);
gl_FragColor = color;
}
`,
});
The Cesium "Fabric" system hasn't seen many updates in a long while, but it's still available. There's a live demo of it here:
https://sandcastle.cesium.com/?src=Materials.html
The important concept to understand is that a Cesium "Fabric" is not a complete shader, it's just a snippet. Specifically, it's an attempt to isolate the "material" part of a GLSL shader from the rest of lighting and rendering-related concerns.
Note for example part of the above demo looks like this:
primitive.appearance.material = new Cesium.Material({
fabric: {
uniforms: {
image: "../images/earthspec1k.jpg",
heightField: "../images/earthbump1k.jpg",
},
materials: {
bumpMap: {
type: "BumpMap",
uniforms: {
image: "../images/earthbump1k.jpg",
},
},
},
source: `
czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
vec4 color;
float heightValue = texture(heightField, materialInput.st).r;
color.rgb = mix(vec3(0.2, 0.6, 0.2), vec3(1.0, 0.5, 0.2), heightValue);
color.a = (1.0 - texture(image, materialInput.st).r) * 0.7;
color = czm_gammaCorrect(color);
material.diffuse = color.rgb;
material.alpha = color.a;
material.normal = bumpMap.normal;
material.specular = step(0.1, heightValue); // Specular mountain tops
material.shininess = 8.0; // Sharpen highlight
return material;
}
`,
},
In the above code, some custom GLSL declares a function called czm_getMaterial
that returns a struct of czm_material
. This struct holds information about the material that Cesium is intended to display, and isolates that information from the rest of the usual shader concerns with lighting and blend modes and such.
So, there's no way for a "Fabric" to take over the vertex shader or move vertex locations around, it's just intended to control the look of the material.