cesium icon indicating copy to clipboard operation
cesium copied to clipboard

Billboard.scaleByDistance does not scale linearly

Open AndresPozo opened this issue 3 years ago • 1 comments

Using the property Billboard.scaleByDistance I have seen a strange behaviour: the size of the billboard should change linearly with the distance to the camera between the near and far distances, but the size change does not seem to be linear.

This is implemented in the function czm_nearFarScalar at Shaders\Builtin\Functions\nearFarScalar.glsl. In this function the returned value is calculated as proportional to the square of the distance and then a pow(x, 0.2) is applied. I don't understand why this formula is this way.

Since the angular size of an object is proportional to the inverse of the distance, I think the formula should interpolate using the inverse distance instead the squared distance (probably this is why the current implementation needs the pow(x,0.2)).

I propose to use this implementation:

float czm_nearFarScalar(vec4 nearFarScalar, float cameraDistSq)
{
    float valueAtMin = nearFarScalar.y;
    float valueAtMax = nearFarScalar.w;
	
    float nearDistInv = 1.0 / nearFarScalar.x;
    float farDistInv = 1.0 / nearFarScalar.z;
    float cameraDistInv = 1.0 / sqrt(cameraDistSq);

    float t = (cameraDistInv - nearDistInv) / (farDistInv - nearDistInv);
    t = clamp(t, 0.0, 1.0);

    return mix(valueAtMin, valueAtMax, t);
}

I have tested this function in my application and I get much smoother results.

AndresPozo avatar Jul 08 '22 11:07 AndresPozo

For testing the current state you can use this code in Sandcastle:

const viewer = new Cesium.Viewer("cesiumContainer");

viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
  billboard: {
    image: "../images/facility.gif",
    scaleByDistance: new Cesium.NearFarScalar(100, 16.0, 100000, 0.5),
  },
});

The near value is set to 16 at 100m and the far value is set to 0.5 at 100km. I would expect that the size of the billboard would smoothly change from x0.5 to x16 when zooming from a distance of 100km to 100m. However the size change is not linear and it seems to be mostly done in the middle of the distance range. When zooming in, the size change starts very slow, then accelerates and reaches the maximum value before reaching the near distance, and then slows again.

AndresPozo avatar Jul 08 '22 11:07 AndresPozo

Bump

AndresPozo avatar Oct 04 '22 10:10 AndresPozo