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);
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容