Skip to content

Commit 7fbc795

Browse files
authored
Merge pull request #7486 from OmarShehata/gltf-webp
Add support for glTF EXT_texture_webp
2 parents a03edeb + bd8be76 commit 7fbc795

File tree

9 files changed

+332
-6
lines changed

9 files changed

+332
-6
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Change Log
2222
* Added rhumb line support to `PolygonGeometry`, `PolygonOutlineGeometry`, `PolylineGeometry`, `GroundPolylineGeometry`, and `SimplePolylineGeometry`. [#7492](https://github.com/AnalyticalGraphicsInc/cesium/pull/7492)
2323
* When using Cesium in Node.js, we now use the combined and minified version for improved performance unless `NODE_ENV` is specifically set to `development`.
2424
* Improved the performance of `QuantizedMeshTerrainData.interpolateHeight`. [#7508](https://github.com/AnalyticalGraphicsInc/cesium/pull/7508)
25+
* Added support for glTF models with WebP textures using the `EXT_texture_webp` extension. [#7486](https://github.com/AnalyticalGraphicsInc/cesium/pull/7486)
2526

2627
##### Fixes :wrench:
2728
* Fixed 3D Tiles performance regression. [#7482](https://github.com/AnalyticalGraphicsInc/cesium/pull/7482)

Source/Core/FeatureDetection.js

+36-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
define([
22
'./defaultValue',
33
'./defined',
4-
'./Fullscreen'
4+
'./Fullscreen',
5+
'./RuntimeError',
6+
'../ThirdParty/when'
57
], function(
68
defaultValue,
79
defined,
8-
Fullscreen) {
10+
Fullscreen,
11+
RuntimeError,
12+
when) {
913
'use strict';
1014
/*global CanvasPixelArray*/
1115

@@ -199,6 +203,35 @@ define([
199203
return supportsImageRenderingPixelated() ? imageRenderingValueResult : undefined;
200204
}
201205

206+
var supportsWebpPromise;
207+
function supportsWebp() {
208+
// From https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_for_webp
209+
if (defined(supportsWebpPromise)) {
210+
return supportsWebpPromise.promise;
211+
}
212+
213+
supportsWebpPromise = when.defer();
214+
if (isEdge()) {
215+
// Edge's WebP support with WebGL is incomplete.
216+
// See bug report: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/19221241/
217+
supportsWebpPromise.resolve(false);
218+
}
219+
220+
var image = new Image();
221+
image.onload = function () {
222+
var success = (image.width > 0) && (image.height > 0);
223+
supportsWebpPromise.resolve(success);
224+
};
225+
226+
image.onerror = function () {
227+
supportsWebpPromise.resolve(false);
228+
};
229+
230+
image.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';
231+
232+
return supportsWebpPromise.promise;
233+
}
234+
202235
var typedArrayTypes = [];
203236
if (typeof ArrayBuffer !== 'undefined') {
204237
typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array);
@@ -235,6 +268,7 @@ define([
235268
hardwareConcurrency : defaultValue(theNavigator.hardwareConcurrency, 3),
236269
supportsPointerEvents : supportsPointerEvents,
237270
supportsImageRenderingPixelated: supportsImageRenderingPixelated,
271+
supportsWebp: supportsWebp,
238272
imageRenderingValue: imageRenderingValue,
239273
typedArrayTypes: typedArrayTypes
240274
};

Source/Scene/ClassificationModel.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,14 @@ define([
261261
this._rtcCenterEye = undefined; // in eye coordinates
262262
this._rtcCenter3D = undefined; // in world coordinates
263263
this._rtcCenter2D = undefined; // in projected world coordinates
264+
265+
this._supportsWebp = undefined;
266+
267+
var that = this;
268+
FeatureDetection.supportsWebp()
269+
.then(function(result) {
270+
that._supportsWebp = result;
271+
});
264272
}
265273

266274
defineProperties(ClassificationModel.prototype, {
@@ -958,6 +966,10 @@ define([
958966
return;
959967
}
960968

969+
if (!defined(this._supportsWebp)) {
970+
return;
971+
}
972+
961973
if ((this._state === ModelState.NEEDS_LOAD) && defined(this.gltf)) {
962974
this._state = ModelState.LOADING;
963975
if (this._state !== ModelState.FAILED) {
@@ -991,7 +1003,7 @@ define([
9911003
// Transition from LOADING -> LOADED once resources are downloaded and created.
9921004
// Textures may continue to stream in while in the LOADED state.
9931005
if (loadResources.pendingBufferLoads === 0) {
994-
ModelUtility.checkSupportedExtensions(this.extensionsRequired);
1006+
ModelUtility.checkSupportedExtensions(this.extensionsRequired, this._supportsWebp);
9951007

9961008
addBuffersToLoadResources(this);
9971009
parseBufferViews(this);

Source/Scene/Model.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,13 @@ define([
686686
this._useDefaultSpecularMaps = false;
687687

688688
this._shouldRegenerateShaders = false;
689+
this._supportsWebp = undefined;
690+
691+
var that = this;
692+
FeatureDetection.supportsWebp()
693+
.then(function(result) {
694+
that._supportsWebp = result;
695+
});
689696
}
690697

691698
defineProperties(Model.prototype, {
@@ -1652,6 +1659,11 @@ define([
16521659
var uri;
16531660
ForEach.texture(gltf, function(texture, id) {
16541661
var imageId = texture.source;
1662+
1663+
if (defined(texture.extensions) && defined(texture.extensions.EXT_texture_webp) && model._supportsWebp) {
1664+
imageId = texture.extensions.EXT_texture_webp.source;
1665+
}
1666+
16551667
var gltfImage = images[imageId];
16561668
var extras = gltfImage.extras;
16571669

@@ -4296,6 +4308,10 @@ define([
42964308
return;
42974309
}
42984310

4311+
if (!defined(this._supportsWebp)) {
4312+
return;
4313+
}
4314+
42994315
var context = frameState.context;
43004316
this._defaultTexture = context.defaultTexture;
43014317

@@ -4370,7 +4386,7 @@ define([
43704386
if (!loadResources.initialized) {
43714387
frameState.brdfLutGenerator.update(frameState);
43724388

4373-
ModelUtility.checkSupportedExtensions(this.extensionsRequired);
4389+
ModelUtility.checkSupportedExtensions(this.extensionsRequired, this._supportsWebp);
43744390
ModelUtility.updateForwardAxis(this);
43754391

43764392
// glTF pipeline updates, not needed if loading from cache

Source/Scene/ModelUtility.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ define([
1010
'../Core/Matrix3',
1111
'../Core/Matrix4',
1212
'../Core/Quaternion',
13+
'../Core/FeatureDetection',
1314
'../Core/RuntimeError',
1415
'../Core/WebGLConstants',
1516
'../Renderer/ShaderSource',
@@ -30,6 +31,7 @@ define([
3031
Matrix3,
3132
Matrix4,
3233
Quaternion,
34+
FeatureDetection,
3335
RuntimeError,
3436
WebGLConstants,
3537
ShaderSource,
@@ -491,15 +493,20 @@ define([
491493
'KHR_techniques_webgl' : true,
492494
'KHR_materials_unlit' : true,
493495
'KHR_materials_pbrSpecularGlossiness' : true,
494-
'WEB3D_quantized_attributes' : true
496+
'WEB3D_quantized_attributes' : true,
497+
'EXT_texture_webp' : true
495498
};
496499

497-
ModelUtility.checkSupportedExtensions = function(extensionsRequired) {
500+
ModelUtility.checkSupportedExtensions = function(extensionsRequired, browserSupportsWebp) {
498501
for (var extension in extensionsRequired) {
499502
if (extensionsRequired.hasOwnProperty(extension)) {
500503
if (!ModelUtility.supportedExtensions[extension]) {
501504
throw new RuntimeError('Unsupported glTF Extension: ' + extension);
502505
}
506+
507+
if (extension === 'EXT_texture_webp' && browserSupportsWebp === false) {
508+
throw new RuntimeError('Loaded model requires WebP but browser does not support it.');
509+
}
503510
}
504511
}
505512
};

Specs/Core/FeatureDetectionSpec.js

+7
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,11 @@ defineSuite([
115115
expect(FeatureDetection.imageRenderingValue()).not.toBeDefined();
116116
}
117117
});
118+
119+
it('detects WebP support', function() {
120+
return FeatureDetection.supportsWebp()
121+
.then(function(supportsWebp) {
122+
expect(typeof supportsWebp).toEqual('boolean');
123+
});
124+
});
118125
});

0 commit comments

Comments
 (0)