I’m working to create a virtual art gallery of my photography. Each “gallery” will show around 30-50 photos, which will be a mix of 2D, “flat” stereographs, and 180-degree stereographs photos. As you can imagine, the textures could be sizable.
Is there a “built-in” mechanism for loading a low-resolution texture and replacing it with a higher-resolution version when the camera is a certain distance away – and ideally, swapping it back out when the camera moves away?
The other only solution I can think of would be to create a collision detection mesh in front of each photograph and use those events to swap out the textures manually.
If your textures are on a mesh like a plan, you can calculate the distance between the camera and the mesh, then change the texture as soon as the agreed distance is passed.
I don’t know of an easier way.
If there’s no auto-hot-swap Texture variant, I guess the question would be whether the “usual” or “recommended” way of handling this (this must be A Thing Other People Do, right?) would be to rely on mesh collision events, or if there’s a performance or other benefit to looping through the photos on each frame render manually and checking signedDistanceTo(scene.activeCamera.position).
Definitely seems like a possibility! Though it would require swapping out the entire mesh rather than just the texture.
Here’s what I came up with – polling on each frame. Seems to work fine. I don’t have a Playground for it, but hopefully this gets the gist across in case someone wanders through looking for an answer.
interface IPhoto {
url: string
urlThumbnail: string
isLowRes: boolean
material: StandardMaterial
textureLow?: Texture
textureMed?: Texture
}
function setPhotoTexture(scene: Scene, photo: IMountedPhoto, isLowRes: boolean): void {
photo.isLowRes = isLowRes
const currentTexture = isLowRes ? photo.textureLow : photo.textureMed
if (currentTexture == undefined) {
const t = new Texture(isLowRes ? photo.urlThumbnail : photo.url, scene, undefined, undefined, undefined, function () {
photo.material.diffuseTexture = t
if (isLowRes) {
photo.textureLow = t
} else {
photo.textureMed = t
}
})
} else {
photo.material.diffuseTexture = currentTexture
}
}
scene.onBeforeCameraRenderObservable.add((camera: Camera) => {
for (const p of mountedPhotos) {
const d = p.mesh.getDistanceToCamera(camera)
const isFarAway = d > 10
if (isFarAway && !p.isLowRes) {
setPhotoTexture(scene, p, true)
} else if (!isFarAway && p.isLowRes) {
setPhotoTexture(scene, p, false)
}
}
})