美文网首页
cesium 绘制primitive流程(二)更新primiti

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

作者: panergongzi | 来源:发表于2021-10-09 20:20 被阅读0次

    我们从下面图片去观察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流程(二)更新primiti

          本文链接:https://www.haomeiwen.com/subject/gzzznltx.html