Search code examples
backgroundcompressiontexturesscenekit

Is there a way to use compressed textures with SceneKit background CubeMaps?


SceneKit uses a specific SCNMaterial for the 3D background of a scene.

We have to use scnScene.background.diffuse.contents = one of:

  • A vertical strip (single image with height = 6x width)
  • An horizontal strip (single image with 6x height = width)
  • A spherical projection ( single image with 2xheight = width)
  • An array of 6 square images

My background images are currently in JPG or PNG format, but they are slow to decompress, and I would like to use compressed textures (PVRTC or ASTC formats).

I cannot use compressed textures using the vertical, horizontal strips and spherical projections as they are not square images, and PVRTC/ASTC require square textures under iOS. I tried to PVRTC compress the array of 6 square images, but background.diffuse.contents requires an array of 6 UIImages, and although there is no error in the log, I don't see any 3D background when I assign an array of 6 SKTexture to background.diffuse.contents.

My question is the following:

  • Is there a way to use PVRTC or ASTC textures as a 3D SceneKit background (CubeMap, Spherical projection...) ?

Solution

  • I found the solution. For anyone interested:

    You can assign a Model IO texture to scnScene.background.contents You can load a cube map Model IO texture using the function textureCubeWithImagesNamed:(Array of paths to 6 PVRTC compressed textures)

    NSURL* posx = [artworkUrl URLByAppendingPathComponent:@"posx.pvr"]; 
    NSURL* negx = [artworkUrl URLByAppendingPathComponent:@"negx.pvr"];
    NSURL* posy = [artworkUrl URLByAppendingPathComponent:@"posy.pvr"];
    NSURL* negy = [artworkUrl URLByAppendingPathComponent:@"negy.pvr"];
    NSURL* posz = [artworkUrl URLByAppendingPathComponent:@"posz.pvr"];
    NSURL* negz = [artworkUrl URLByAppendingPathComponent:@"negz.pvr"];
    
    MDLTexture* cubeTexture = [MDLTexture textureCubeWithImagesNamed:@[posx.path,negx.path,posy.path,negy.path,posz.path,negz.path] ]; 
    scnScene.background.contents = cubeTexture;