Skip to content

Commit

Permalink
Decouple voxel coordinate conversion in shader
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeshurun Hembd committed Feb 21, 2024
1 parent 89a21d3 commit d298ab9
Showing 1 changed file with 33 additions and 20 deletions.
53 changes: 33 additions & 20 deletions packages/engine/Source/Shaders/Voxels/convertUvToEllipsoid.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,33 @@ vec2 nearestPointOnEllipse(vec2 pos, vec2 radii) {
return v * sign(pos);
}

/**
* Composition of convertUvToShapeSpace and convertShapeToShapeUvSpace
*/
vec3 convertUvToShapeUvSpace(in vec3 positionUv) {
vec3 convertUvToShapeSpace(in vec3 positionUv) {
// Convert positionUv [0,1] to local space [-1,+1]
vec3 positionLocal = positionUv * 2.0 - 1.0;

// Compute longitude, shifted and scaled to the range [0, 1]
float longitude = (atan(positionLocal.y, positionLocal.x) + czm_pi) / czm_twoPi;
float longitude = atan(positionLocal.y, positionLocal.x);

// Convert position to "normalized" cartesian space [-a,+a] where a = (radii + height) / (max(radii) + height).
// A point on the largest ellipsoid axis would be [-1,+1] and everything else would be smaller.
vec3 posEllipsoid = positionLocal * u_ellipsoidRadiiUv;

// Convert the 3D position to a 2D position relative to the ellipse (radii.x, radii.z)
// (assume radii.y == radii.x) and find the nearest point on the ellipse.
vec2 posEllipse = vec2(length(posEllipsoid.xy), posEllipsoid.z);
vec2 surfacePoint = nearestPointOnEllipse(posEllipse, u_ellipsoidRadiiUv.xz);

vec2 normal = normalize(surfacePoint * u_ellipsoidInverseRadiiSquaredUv.xz);
float latitude = atan(normal.y, normal.x);

float heightSign = length(posEllipse) < length(surfacePoint) ? -1.0 : 1.0;
float height = heightSign * length(posEllipse - surfacePoint);

return vec3(longitude, latitude, height);
}

vec3 convertShapeToShapeUvSpace(in vec3 positionShape) {
// Longitude: shift & scale to [0, 1]
float longitude = (positionShape.x + czm_pi) / czm_twoPi;

// Correct the angle when max < min
// Technically this should compare against min longitude - but it has precision problems so compare against the middle of empty space.
Expand All @@ -76,24 +94,19 @@ vec3 convertUvToShapeUvSpace(in vec3 positionUv) {
longitude = longitude * u_ellipsoidUvToShapeUvLongitude.x + u_ellipsoidUvToShapeUvLongitude.y;
#endif

// Convert position to "normalized" cartesian space [-a,+a] where a = (radii + height) / (max(radii) + height).
// A point on the largest ellipsoid axis would be [-1,+1] and everything else would be smaller.
vec3 posEllipsoid = positionLocal * u_ellipsoidRadiiUv;
// Convert the 3D position to a 2D position relative to the ellipse (radii.x, radii.z)
// (assume radii.y == radii.x) and find the nearest point on the ellipse.
vec2 posEllipse = vec2(length(posEllipsoid.xy), posEllipsoid.z);
vec2 surfacePoint = nearestPointOnEllipse(posEllipse, u_ellipsoidRadiiUv.xz);

// Compute latitude, shifted and scaled to the range [0, 1]
vec2 normal = normalize(surfacePoint * u_ellipsoidInverseRadiiSquaredUv.xz);
float latitude = (atan(normal.y, normal.x) + czm_piOverTwo) / czm_pi;
// Latitude: shift and scale to [0, 1]
float latitude = (positionShape.y + czm_piOverTwo) / czm_pi;
#if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)
latitude = latitude * u_ellipsoidUvToShapeUvLatitude.x + u_ellipsoidUvToShapeUvLatitude.y;
#endif

// Compute height
float heightSign = length(posEllipse) < length(surfacePoint) ? -1.0 : 1.0;
float height = 1.0 + heightSign * length(posEllipse - surfacePoint) * u_ellipsoidInverseHeightDifferenceUv;
// Height: scale to the range [0, 1]
float height = 1.0 + positionShape.z * u_ellipsoidInverseHeightDifferenceUv;

return vec3(longitude, latitude, height);
}

vec3 convertUvToShapeUvSpace(in vec3 positionUv) {
vec3 positionShape = convertUvToShapeSpace(positionUv);
return convertShapeToShapeUvSpace(positionShape);
}

0 comments on commit d298ab9

Please sign in to comment.