I try to flatten the model by multiply a small float value to vsOutput.positionMC.y in customShader:
new Cesium.CustomShader({
lightingModel: Cesium.LightingModel.UNLIT,
isTranslucent: true,
vertexShaderText: `
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput)
{
vsOutput.positionMC.y = 0.01 * vsInput.attributes.positionMC.y;
}
`
})
Then I apply this custom shader to the tileset on officical ion, which id is 75343.
const tileset = new Cesium.Cesium3DTileset({
url: Cesium.IonResource.fromAssetId(75343),
customShader,
});
viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset);
But it’s not work as I expected:
I read the custom shader document, and found a notes:
Note : As of this writing, only tilesets that use the 3DTILES_content_gltf
extension will support CustomShaders
. Future releases will add support for other formats such as b3dm.
Is that mean I can not flatten the tile model by modify its vertex position in model coordinate system now?
I also try this vertex shader by using glTF model “SampleData/models/CesiumBalloon/CesiumBalloon.glb”, it work as my expected.
So the y-axis of the tile model from b3dm tileset is not the up direction in the eastNorthUp coordinate system?
Hi @onsummer,
Thank you for your question! It seems like we are getting a lot of questions related to custom shaders recently. @ptrgags has a ton of experience in this area and should be able to help you out
Best,
Sam
Hi @onsummer, right now positionMC
is in the model space of the data. Unfortunately, a lot of old sample tilesets were stored in Cartesian space (up to a matrix translation) so +z points parallel to the earth’s axis. If you want to use positionMC
in a shader and have +z be “up”, the data needs to be in east-north-up (ENU) space.
Just the other day this came up in GitHub, see Possible issue regarding custom shaders and rotation of i3dm/b3dm tilesets · Issue #10146 · CesiumGS/cesium · GitHub for further discussion.
As for the note in the documentation, that’s not relevant, and also I think it’s outdated? As long as you use enableModelExperimental
, b3dm and i3dm models should work. I’ll make a note to update the documentation soon.
@ptrgags @sam.rothstein Thank you for your reply and thanks to the contribution of Cesium team.
Unfortunately, a lot of old sample tilesets were stored in Cartesian space (up to a matrix translation) so +z points parallel to the earth’s axis.
I realize this, because I see that is no transform property in tileset.rootTile
, it means that the vertices in gltf part of b3dm tile are base on ECEF(world coordinate system in cartesian3).
So I will try to use the inverse east-north-up matrix to multiply positionWC
, then get the position on east-north-up space.
eg.
const toEcefMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(interestPoint)
const inverse = Cesium.Matrix4.inverse(toEcefMatrix)
// ...
new Cesium.CustomShader({
uniforms: {
u_toEcefMatrix: {
value: toEcefMatrix,
type: Cesium.UniformType.MAT4
},
u_inverse: {
value: inverse,
type: Cesium.UniformType.MAT4
}
},
vertexShaderText: `
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
vec4 positionENU = u_inverse * vsInput.attributes.positionWC;
// modify positionENU as output here, for example, scale z by 0.1
vec4 modifiedPosition = positionENU * vec4(1.0, 1.0, 0.1, 1.0);
vsOutput.positionMC = u_toEcefMatrix * modifiedPosition;
}
`,
// ...
})
I do not know what will happen, I will test later.