cesium 绘制primitive流程(二)更新primitive

我们从下面图片去观察cesium是怎样触发primitive更新的

1,初始化cesium场景时候会默认执行CesiumWidget类里面的startRenderLoop方法,该方法的作用是

image

调用浏览器requestAnimationFrame方法循环执行widget.render方法进行渲染,我们再看看

image

CesiumWidget里面的rander方法,这个方法调用了scene.initializeFrame()进行初始化一帧,Clock.tick()方法触发时钟更新当前时间,Scene.render方法进行渲染。我们再看看Scene.render方法

image

该方法大致做了以下几件事,更新帧数,预先更新3dtiles数据,预先更新相机飞行的3dtiles数据,调用render方法等

image

我们看看Scene.render方法,该方法内部调用Scene.updateAndExecuteCommands方法

image

Scene.prototype.updateAndExecuteCommands方法根据frameState.mode变量判断是否是3d场景然后执行executeCommandsInViewport方法渲染视口内的图元,

image

调用Scene类里的updateAndRenderPrimitives方法执行primitive更新

image.png

从图中可以看到Scene类里的updateAndRenderPrimitives方法主要做了以下几件事1,更新groundPrimtive贴地primitive.2,更新primitive。3,更新shadowmap 阴影贴图。4,渲染globe椭球体。我们再看看scene._primitives.update(frameState)方法


image.png

PrimitiveCollection类的update方法遍历了集合中的primitive然后调用单个primitive的update方法

image.png

从图中我们可以看到调用了createBatchTable方法,该方法的作用是cesium会根据primitive的参数设置自动生成shader


image.png
image.png

例如根据primitive的填充颜色会生成"czm_batchTable_color"方法,根据primitive是否被选中生成"czm_batchTable_pickColor"方法等。
创建完batchTable之后接着会更新batchTable关联的纹理,将batchTable的属性都写入纹理中,再从片元着色器读取纹理获得属性信息。之后会调用loadAsynchronous或者loadSynchronous方法合并几何实例对象


image.png

然后再根据appearance外观属性和material材质属性是否改变来创建


image.png

image.png

渲染状态,创建着色程序,创建渲染命令,更新帧状态里的绘制命令数组。(这些方法代码太多,不细述)
我们看一下绘制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);
}

你可能感兴趣的:(cesium 绘制primitive流程(二)更新primitive)