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

我們從下面圖片去觀察cesium是怎樣觸發(fā)primitive更新的

1,初始化cesium場景時候會默認(rèn)執(zhí)行CesiumWidget類里面的startRenderLoop方法,該方法的作用是

image

調(diào)用瀏覽器requestAnimationFrame方法循環(huán)執(zhí)行widget.render方法進行渲染,我們再看看

image

CesiumWidget里面的rander方法,這個方法調(diào)用了scene.initializeFrame()進行初始化一幀,Clock.tick()方法觸發(fā)時鐘更新當(dāng)前時間,Scene.render方法進行渲染。我們再看看Scene.render方法

image

該方法大致做了以下幾件事,更新幀數(shù),預(yù)先更新3dtiles數(shù)據(jù),預(yù)先更新相機飛行的3dtiles數(shù)據(jù),調(diào)用render方法等

image

我們看看Scene.render方法,該方法內(nèi)部調(diào)用Scene.updateAndExecuteCommands方法

image

Scene.prototype.updateAndExecuteCommands方法根據(jù)frameState.mode變量判斷是否是3d場景然后執(zhí)行executeCommandsInViewport方法渲染視口內(nèi)的圖元,

image

調(diào)用Scene類里的updateAndRenderPrimitives方法執(zhí)行primitive更新

image.png

從圖中可以看到Scene類里的updateAndRenderPrimitives方法主要做了以下幾件事1,更新groundPrimtive貼地primitive.2,更新primitive。3,更新shadowmap 陰影貼圖。4,渲染globe橢球體。我們再看看scene._primitives.update(frameState)方法


image.png

PrimitiveCollection類的update方法遍歷了集合中的primitive然后調(diào)用單個primitive的update方法

image.png

從圖中我們可以看到調(diào)用了createBatchTable方法,該方法的作用是cesium會根據(jù)primitive的參數(shù)設(shè)置自動生成shader


image.png
image.png

例如根據(jù)primitive的填充顏色會生成"czm_batchTable_color"方法,根據(jù)primitive是否被選中生成"czm_batchTable_pickColor"方法等。
創(chuàng)建完batchTable之后接著會更新batchTable關(guān)聯(lián)的紋理,將batchTable的屬性都寫入紋理中,再從片元著色器讀取紋理獲得屬性信息。之后會調(diào)用loadAsynchronous或者loadSynchronous方法合并幾何實例對象


image.png

然后再根據(jù)appearance外觀屬性和material材質(zhì)屬性是否改變來創(chuàng)建


image.png

image.png

渲染狀態(tài),創(chuàng)建著色程序,創(chuàng)建渲染命令,更新幀狀態(tài)里的繪制命令數(shù)組。(這些方法代碼太多,不細述)
我們看一下繪制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; 
//根據(jù)batchId關(guān)聯(lián)表id和batchTextureStep關(guān)聯(lián)表紋理步長計算紋理坐標(biāo)
vec2 computeSt(float batchId) 
{ 
    float stepX = batchTextureStep.x; 
    float centerX = batchTextureStep.y; 
    float numberOfAttributes = float(2); 
    return vec2(centerX + (batchId * numberOfAttributes * stepX), 0.5); 
} 
//根據(jù)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; 
} 
//根據(jù)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()
{
//計算坐標(biāo),cesium會將一個世界坐標(biāo)拆成整數(shù)部分和小數(shù)部分
vec4 p = czm_computePosition();
//將模型坐標(biāo)系下的頂點坐標(biāo)轉(zhuǎn)到相機坐標(biāo)系
v_positionEC = (czm_modelViewRelativeToEye * p).xyz;
//將法線轉(zhuǎn)到相機坐標(biāo)系
v_normalEC = czm_normal * normal;
//獲取填充顏色
v_color = czm_batchTable_color(batchId);
//使用MVP矩陣將坐標(biāo)轉(zhuǎn)換到標(biāo)準(zhǔn)裁剪坐標(biāo)系
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);
}
//材質(zhì)結(jié)構(gòu)體
struct czm_material
{
vec3 diffuse;
float specular;
float shininess;
vec3 normal;
vec3 emission;
float alpha;
};
//材質(zhì)輸入結(jié)構(gòu)體
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內(nèi)置獲取默認(rèn)材質(zhì)發(fā)方法
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()
{
//相機坐標(biāo)下,片元到相機的連線
vec3 positionToEyeEC = -v_positionEC;
//相機坐標(biāo)下,法向量
vec3 normalEC = normalize(v_normalEC);
//如果開啟了背面翻轉(zhuǎn)屬性
#ifdef FACE_FORWARD
normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
#endif
//獲取伽馬矯正之后的顏色
vec4 color = czm_gammaCorrect(v_color);
//給輸入材質(zhì)結(jié)構(gòu)體賦值
czm_materialInput materialInput;
materialInput.normalEC = normalEC;
materialInput.positionToEyeEC = positionToEyeEC;
czm_material material = czm_getDefaultMaterial(materialInput);
material.diffuse = color.rgb;
material.alpha = color.a;
//在計算光照之后設(shè)置片元顏色
gl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容