我们从下面图片去观察cesium是怎样触发primitive更新的
1,初始化cesium场景时候会默认执行CesiumWidget类里面的startRenderLoop方法,该方法的作用是
调用浏览器requestAnimationFrame方法循环执行widget.render方法进行渲染,我们再看看
CesiumWidget里面的rander方法,这个方法调用了scene.initializeFrame()进行初始化一帧,Clock.tick()方法触发时钟更新当前时间,Scene.render方法进行渲染。我们再看看Scene.render方法
该方法大致做了以下几件事,更新帧数,预先更新3dtiles数据,预先更新相机飞行的3dtiles数据,调用render方法等
我们看看Scene.render方法,该方法内部调用Scene.updateAndExecuteCommands方法
Scene.prototype.updateAndExecuteCommands方法根据frameState.mode变量判断是否是3d场景然后执行executeCommandsInViewport方法渲染视口内的图元,
调用Scene类里的updateAndRenderPrimitives方法执行primitive更新
从图中可以看到Scene类里的updateAndRenderPrimitives方法主要做了以下几件事1,更新groundPrimtive贴地primitive.2,更新primitive。3,更新shadowmap 阴影贴图。4,渲染globe椭球体。我们再看看scene._primitives.update(frameState)方法
PrimitiveCollection类的update方法遍历了集合中的primitive然后调用单个primitive的update方法
从图中我们可以看到调用了createBatchTable方法,该方法的作用是cesium会根据primitive的参数设置自动生成shader
例如根据primitive的填充颜色会生成"czm_batchTable_color"方法,根据primitive是否被选中生成"czm_batchTable_pickColor"方法等。
创建完batchTable之后接着会更新batchTable关联的纹理,将batchTable的属性都写入纹理中,再从片元着色器读取纹理获得属性信息。之后会调用loadAsynchronous或者loadSynchronous方法合并几何实例对象
然后再根据appearance外观属性和material材质属性是否改变来创建
渲染状态,创建着色程序,创建渲染命令,更新帧状态里的绘制命令数组。(这些方法代码太多,不细述)
我们看一下绘制primitive最后生成的着色程序
1,顶点着色器
#define OES_texture_float
uniform vec3 czm_encodedCameraPositionMCLow;
uniform vec3 czm_encodedCameraPositionMCHigh;
float czm_signNotZero(float value)
{
return value >= 0.0 ? 1.0 : -1.0;
}
vec2 czm_signNotZero(vec2 value)
{
return vec2(czm_signNotZero(value.x), czm_signNotZero(value.y));
}
vec3 czm_signNotZero(vec3 value)
{
return vec3(czm_signNotZero(value.x), czm_signNotZero(value.y), czm_signNotZero(value.z));
}
vec4 czm_signNotZero(vec4 value)
{
return vec4(czm_signNotZero(value.x), czm_signNotZero(value.y), czm_signNotZero(value.z), czm_signNotZero(value.w));
}
vec4 czm_columbusViewMorph(vec4 position2D, vec4 position3D, float time)
{
vec3 p = mix(position2D.xyz, position3D.xyz, time);
return vec4(p, 1.0);
}
vec4 czm_translateRelativeToEye(vec3 high, vec3 low)
{
vec3 highDifference = high - czm_encodedCameraPositionMCHigh;
vec3 lowDifference = low - czm_encodedCameraPositionMCLow;
return vec4(highDifference + lowDifference, 1.0);
}
uniform float czm_morphTime;
vec3 czm_octDecode(vec2 encoded, float range)
{
if (encoded.x == 0.0 && encoded.y == 0.0) {
return vec3(0.0, 0.0, 0.0);
}
encoded = encoded / range * 2.0 - 1.0;
vec3 v = vec3(encoded.x, encoded.y, 1.0 - abs(encoded.x) - abs(encoded.y));
if (v.z < 0.0)
{
v.xy = (1.0 - abs(v.yx)) * czm_signNotZero(v.xy);
}
return normalize(v);
}
vec3 czm_octDecode(vec2 encoded)
{
return czm_octDecode(encoded, 255.0);
}
vec3 czm_octDecode(float encoded)
{
float temp = encoded / 256.0;
float x = floor(temp);
float y = (temp - x) * 256.0;
return czm_octDecode(vec2(x, y));
}
void czm_octDecode(vec2 encoded, out vec3 vector1, out vec3 vector2, out vec3 vector3)
{
float temp = encoded.x / 65536.0;
float x = floor(temp);
float encodedFloat1 = (temp - x) * 65536.0;
temp = encoded.y / 65536.0;
float y = floor(temp);
float encodedFloat2 = (temp - y) * 65536.0;
vector1 = czm_octDecode(encodedFloat1);
vector2 = czm_octDecode(encodedFloat2);
vector3 = czm_octDecode(vec2(x, y));
}
uniform mat4 czm_modelViewProjectionRelativeToEye;
uniform mat3 czm_normal;
uniform mat4 czm_modelViewRelativeToEye;
vec4 czm_computePosition();
#line 0
#line 0
attribute vec3 position2DHigh;
attribute vec3 position2DLow;
attribute float compressedAttributes;
vec3 normal;
attribute vec3 position3DHigh;
attribute vec3 position3DLow;
attribute float batchId;
varying vec3 v_positionEC;
varying vec3 v_normalEC;
varying vec4 v_color;
uniform highp sampler2D batchTexture;
uniform vec4 batchTextureStep;
//根据batchId关联表id和batchTextureStep关联表纹理步长计算纹理坐标
vec2 computeSt(float batchId)
{
float stepX = batchTextureStep.x;
float centerX = batchTextureStep.y;
float numberOfAttributes = float(2);
return vec2(centerX + (batchId * numberOfAttributes * stepX), 0.5);
}
//根据batchId从纹理中获取填充颜色
vec4 czm_batchTable_color(float batchId)
{
vec2 st = computeSt(batchId);
st.x += batchTextureStep.x * float(0);
vec4 textureValue = texture2D(batchTexture, st);
vec4 value = textureValue;
return value;
}
//根据batchId从纹理中获取拾取颜色
vec4 czm_batchTable_pickColor(float batchId)
{
vec2 st = computeSt(batchId);
st.x += batchTextureStep.x * float(1);
vec4 textureValue = texture2D(batchTexture, st);
vec4 value = textureValue;
return value;
}
void czm_non_pick_main()
{
//计算坐标,cesium会将一个世界坐标拆成整数部分和小数部分
vec4 p = czm_computePosition();
//将模型坐标系下的顶点坐标转到相机坐标系
v_positionEC = (czm_modelViewRelativeToEye * p).xyz;
//将法线转到相机坐标系
v_normalEC = czm_normal * normal;
//获取填充颜色
v_color = czm_batchTable_color(batchId);
//使用MVP矩阵将坐标转换到标准裁剪坐标系
gl_Position = czm_modelViewProjectionRelativeToEye * p;
}
varying vec4 v_pickColor;
void czm_non_compressed_main()
{
czm_non_pick_main();
v_pickColor = czm_batchTable_pickColor(batchId);
}
void main()
{
normal = czm_octDecode(compressedAttributes);
czm_non_compressed_main();
}
vec4 czm_computePosition()
{
vec4 p;
if (czm_morphTime == 1.0)
{
p = czm_translateRelativeToEye(position3DHigh, position3DLow);
}
else if (czm_morphTime == 0.0)
{
p = czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy);
}
else
{
p = czm_columbusViewMorph(
czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy),
czm_translateRelativeToEye(position3DHigh, position3DLow),
czm_morphTime);
}
return p;
}
2,片元着色器
precision highp float;
#else
precision mediump float;
#define highp mediump
#endif
#define OES_texture_float_linear
#define OES_texture_float
const float czm_epsilon2 = 0.01;
uniform vec3 czm_lightColor;
const float czm_sceneMode3D = 3.0;
uniform float czm_sceneMode;
//计算高光
float czm_getSpecular(vec3 lightDirectionEC, vec3 toEyeEC, vec3 normalEC, float shininess)
{
vec3 toReflectedLight = reflect(-lightDirectionEC, normalEC);
float specular = max(dot(toReflectedLight, toEyeEC), 0.0);
return pow(specular, max(shininess, czm_epsilon2));
}
//计算漫反射
float czm_getLambertDiffuse(vec3 lightDirectionEC, vec3 normalEC)
{
return max(dot(lightDirectionEC, normalEC), 0.0);
}
//材质结构体
struct czm_material
{
vec3 diffuse;
float specular;
float shininess;
vec3 normal;
vec3 emission;
float alpha;
};
//材质输入结构体
struct czm_materialInput
{
float s;
vec2 st;
vec3 str;
vec3 normalEC;
mat3 tangentToEyeMatrix;
vec3 positionToEyeEC;
float height;
float slope;
float aspect;
};
uniform float czm_gamma;
uniform vec3 czm_lightDirectionEC;
float czm_private_getLambertDiffuseOfMaterial(vec3 lightDirectionEC, czm_material material)
{
return czm_getLambertDiffuse(lightDirectionEC, material.normal);
}
float czm_private_getSpecularOfMaterial(vec3 lightDirectionEC, vec3 toEyeEC, czm_material material)
{
return czm_getSpecular(lightDirectionEC, toEyeEC, material.normal, material.shininess);
}
//布灵冯-光照模型
vec4 czm_phong(vec3 toEye, czm_material material, vec3 lightDirectionEC)
{
float diffuse = czm_private_getLambertDiffuseOfMaterial(vec3(0.0, 0.0, 1.0), material);
if (czm_sceneMode == czm_sceneMode3D) {
diffuse += czm_private_getLambertDiffuseOfMaterial(vec3(0.0, 1.0, 0.0), material);
}
float specular = czm_private_getSpecularOfMaterial(lightDirectionEC, toEye, material);
vec3 materialDiffuse = material.diffuse * 0.5;
vec3 ambient = materialDiffuse;
vec3 color = ambient + material.emission;
color += materialDiffuse * diffuse * czm_lightColor;
color += material.specular * specular * czm_lightColor;
return vec4(color, material.alpha);
}
vec4 czm_private_phong(vec3 toEye, czm_material material, vec3 lightDirectionEC)
{
float diffuse = czm_private_getLambertDiffuseOfMaterial(lightDirectionEC, material);
float specular = czm_private_getSpecularOfMaterial(lightDirectionEC, toEye, material);
vec3 ambient = vec3(0.0);
vec3 color = ambient + material.emission;
color += material.diffuse * diffuse * czm_lightColor;
color += material.specular * specular * czm_lightColor;
return vec4(color, material.alpha);
}
//cesium内置获取默认材质发方法
czm_material czm_getDefaultMaterial(czm_materialInput materialInput)
{
czm_material material;
material.diffuse = vec3(0.0);
material.specular = 0.0;
material.shininess = 1.0;
material.normal = materialInput.normalEC;
material.emission = vec3(0.0);
material.alpha = 1.0;
return material;
}
//伽马矫正
vec3 czm_gammaCorrect(vec3 color) {
#ifdef HDR
color = pow(color, vec3(czm_gamma));
#endif
return color;
}
vec4 czm_gammaCorrect(vec4 color) {
#ifdef HDR
color.rgb = pow(color.rgb, vec3(czm_gamma));
#endif
return color;
}
#line 0
#line 0
varying vec4 v_pickColor;
#define FACE_FORWARD
varying vec3 v_positionEC;
varying vec3 v_normalEC;
varying vec4 v_color;
void main()
{
//相机坐标下,片元到相机的连线
vec3 positionToEyeEC = -v_positionEC;
//相机坐标下,法向量
vec3 normalEC = normalize(v_normalEC);
//如果开启了背面翻转属性
#ifdef FACE_FORWARD
normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
#endif
//获取伽马矫正之后的颜色
vec4 color = czm_gammaCorrect(v_color);
//给输入材质结构体赋值
czm_materialInput materialInput;
materialInput.normalEC = normalEC;
materialInput.positionToEyeEC = positionToEyeEC;
czm_material material = czm_getDefaultMaterial(materialInput);
material.diffuse = color.rgb;
material.alpha = color.a;
//在计算光照之后设置片元颜色
gl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);
}