zoukankan      html  css  js  c++  java
  • 解决Cesium1.50对gltf2.0/3dtiles数据读取的问题

    问题说明

    Cesium 1.50(2018/10/01)版本打开3dtiles可能会出现加载不上导致渲染停止的错误。

    错误说明为:RuntimeError: Unsupported glTF Extension: KHR_technique_webgl

    错误截图如下:

     
    输入图片说明

    解决方案

    我发现原因是KHR_technique_webgl扩展新版Cesium已经不支持的缘故,需要升级一下gltf数据,使用KHR_techniques_webgl扩展即可(注意多了一个s)。

    当然如果直接修改3dtiles数据,比较劳心费神。这里提供一个简单的方法,只需要在Cesium.js加载以后,运行以下代码即可正常显示3dtiles数据了。

    var fixGltf = function(gltf) {
        if (!gltf.extensionsUsed) {
            return;
        }
    
        var v = gltf.extensionsUsed.indexOf('KHR_technique_webgl');
        var t = gltf.extensionsRequired.indexOf('KHR_technique_webgl');
        // 中招了。。
        if (v !== -1) {
            gltf.extensionsRequired.splice(t, 1, 'KHR_techniques_webgl');
            gltf.extensionsUsed.splice(v, 1, 'KHR_techniques_webgl');
            gltf.extensions = gltf.extensions || {};
            gltf.extensions['KHR_techniques_webgl'] = {};
            gltf.extensions['KHR_techniques_webgl'].programs = gltf.programs;
            gltf.extensions['KHR_techniques_webgl'].shaders = gltf.shaders;
            gltf.extensions['KHR_techniques_webgl'].techniques = gltf.techniques;
            var techniques = gltf.extensions['KHR_techniques_webgl'].techniques;
    
            gltf.materials.forEach(function (mat, index) {
                gltf.materials[index].extensions['KHR_technique_webgl'].values = gltf.materials[index].values;
                gltf.materials[index].extensions['KHR_techniques_webgl'] = gltf.materials[index].extensions['KHR_technique_webgl'];
    
                var vtxfMaterialExtension = gltf.materials[index].extensions['KHR_techniques_webgl'];
    
                for (var value in vtxfMaterialExtension.values) {
                    var us = techniques[vtxfMaterialExtension.technique].uniforms;
                    for (var key in us) {
                        if (us[key] === value) {
                            vtxfMaterialExtension.values[key] = vtxfMaterialExtension.values[value];
                            delete vtxfMaterialExtension.values[value];
                            break;
                        }
                    }
                };
            });
    
            techniques.forEach(function (t) {
                for (var attribute in t.attributes) {
                    var name = t.attributes[attribute];
                    t.attributes[attribute] = t.parameters[name];
                };
    
                for (var uniform in t.uniforms) {
                    var name = t.uniforms[uniform];
                    t.uniforms[uniform] = t.parameters[name];
                };
            });
        }
    }
    
    Object.defineProperties(Cesium.Model.prototype, {
        _cachedGltf: {
            set: function (value) {
                this._vtxf_cachedGltf = value;
                if (this._vtxf_cachedGltf && this._vtxf_cachedGltf._gltf) {
                    fixGltf(this._vtxf_cachedGltf._gltf);
                }
            },
            get: function () {
                return this._vtxf_cachedGltf;
            }
        }
    });
    

    寻根探底

    KHR_technique_webgl的来源

    这里不得不说下gltf2.0版本曾经存在的奇葩问题:只支持PBR材质,而不支持自定义shader。

    2015年的gltf1.0标准时,本来是天然的支持也仅支持自定义shader的。大家都知道webgl是不支持固定管线的,gltf1.0支持自定义shader,和webgl标准是相当地匹配,但凡按照gltf1.0中的shader来渲染自然是不成问题。

    但没想到gltf升级到2.0以后,居然默认只能使用PBR材质,而且是不再支持自定义shader。这个就很要命了:

    首先各家渲染引擎(three.js/babylon/Cesium)对PBR材质的理解貌似都不一样,结果导致同一个gltf模型在不同的渲染引擎中渲染出来的效果还都有差别。。所以到目前为止也没有统一。从渲染效果上来说,three.js的渲染效果很棒,babylon也还可以,Cesium貌似理解得不太到位,效果差了一大截。。

    其次,另外一个问题对Cesium更严重,Cesium早期本身按照gltf1.0的标准来绘制。到了gltf2.0时代,Cesium的Model类为了能同时支持gltf1.0和gltf2.0,不得不做出调整,将所有gltf1.0的模型都在内部自动升级成gltf2.0,然后再渲染。问题是gltf2.0不支持自定义shader啊,gltf1.0的自定义shader怎么转化成gltf2.0?自定义shader的自由度太大,是不太可能转成PBR材质的。。

    那么Cesium怎么解决gltf1.0升级gltf2.0的问题呢?这里就用到了gltf2.0当时还处于草案阶段的扩展KHR_technique_webgl。通过这个扩展来在gltf2.0中实现自定义shader。

    然而隐患恰恰来自于这个KHR_technique_webgl扩展。。

    因为这个扩展尚未推出,于是出现了一个奇怪的现象。对于某些gltf2.0的模型(使用了KHR_technique_webgl扩展),只有Cesium能打开,连three.js、babylon都爱莫能助。Cesium变得异常强大。。

    然而,好景不长,Cesium在使用这个扩展时,gltf2.0也在逐步进化,居然连KHR_technique_webgl这个扩展的名字都改了,technique后面加了一个s。。所以现在的扩展名叫KHR_techniques_webgl。。

    这下对广大使用Cesium做开发的网友来说,就不太好了。因为之前发布模型时,但凡最终转化成带有KHR_technique_webgl扩展的数据就都会变得不能用。Cesium这次做得也很绝,连兼容性都不做一下。。这就意味着从Ceisum 1.50版本以后,之前使用了该扩展的3dtiles数据就都打不开了。(如果Cesium官方重视的话,或许会推出一个Cesium 1.50.1的补丁版本来解决这个问题吧,呵呵,毕竟也还算好改,就是上文提到的代码就能解决大部分问题了。)

    从KHR_technique_webgl升级到KHR_techniques_webgl

    注意前面是technique,后面是techniques。

    Khronos把KHR_technique_webgl升级到KHR_techniques_webgl,也并非只是改了下名字这样简单。内部也做了一些调整。主要变化有:

    1 把techniques、programs、shaders这三种类型的节点中都放到了扩展中去定义,不像之前直接放在主节点下;

    2 techniques下的technique属性原先会有attributes、parameters、uniforms等几个节点,其中attributes、uniforms节点中定义的shader变量,是要去parameters节点下找到最终的类型和语义(semantic)的。之前看gltf1.0时也是这个地方不太理解为啥要这么折腾下。。现在看来貌似是没有必要了。KHR_techniques_webgl的扩展变得更加精简。直接去掉了parameters节点,并将其中的定义挪至attributes、uniforms中去。

    3 KHR_technique_webgl扩展时,materials节点下的material也需要定义成扩展形式

    4 还有其他的,我还没用到。。

    令人欣喜的Cesium和隐忧

    这一次Cesium貌似又走在了各大引擎的前列,首先支持上了KHR_techniques_webgl扩展。而其他引擎,比如three.js、babylon都还没支持上呢。以下是测试结果:

    three.js视景器

    https://gltf-viewer.donmccurdy.com/

    three.js读取貌似正常,实际上会给出警告,没有使用这个扩展。

     
    输入图片说明
     
    输入图片说明

    babylon视景器

    babylonjs比较直白,直接表示不认得KHR_techniques_webgl。

    http://sandbox.babylonjs.com/

     
    输入图片说明

    国产引擎clay

    clay也是著名的ECharts使用的底层WebGL引擎。

    https://pissang.github.io/clay-viewer/editor/

    居然没有报错。。而且渲染效果也不错!不得不赞叹一下国产引擎的强大。

     
    输入图片说明

    隐忧

    不太好的问题是KHR_techniques_webgl扩展仍然处于草案阶段,也就是说以后还是有可能会修改的。。这就意味着即使现在的3dtiles能渲染,或许以后Cesium版本升级,还会有渲染不出来的问题。。

     
    输入图片说明

    欢迎关注 Cesium实验室 ,QQ群号:595512567

     
    输入图片说明



  • 相关阅读:
    boost::asio在VS2008下的编译错误
    Java集合框架——接口
    ACM POJ 3981 字符串替换(简单题)
    ACM HDU 1042 N!(高精度计算阶乘)
    OneTwoThree (Uva)
    ACM POJ 3979 分数加减法(水题)
    ACM HDU 4004 The Frog's Games(2011ACM大连赛区第四题)
    Hexadecimal View (2011ACM亚洲大连赛区现场赛D题)
    ACM HDU 4002 Find the maximum(2011年大连赛区网络赛第二题)
    ACM HDU 4001 To Miss Our Children Time (2011ACM大连赛区网络赛)
  • 原文地址:https://www.cnblogs.com/cesium1/p/10062861.html
Copyright © 2011-2022 走看看