Skip to content

Instantly share code, notes, and snippets.

@ThomasGorisse
Created September 22, 2022 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThomasGorisse/ddd699525c00f055123d81ee69e86d01 to your computer and use it in GitHub Desktop.
Save ThomasGorisse/ddd699525c00f055123d81ee69e86d01 to your computer and use it in GitHub Desktop.
package io.github.sceneview.environment
import android.content.Context
import com.google.android.filament.Engine
import com.google.android.filament.IndirectLight
import com.google.android.filament.Skybox
import com.google.android.filament.utils.KTX1Loader
import io.github.sceneview.SceneView
import io.github.sceneview.utils.loadFileBuffer
import kotlinx.coroutines.*
/**
* Indirect Based Light
*
* @property indirectLight Filament texture, or null on failure.
* @property sphericalHarmonics Spherical harmonics from the content of a KTX file.
* The resulting array of 9 * 3 floats, or null on failure.
*/
class IBL(val indirectLight: IndirectLight, val sphericalHarmonics: FloatArray?)
/**
* Utility for producing environment resources from precompiled cmgen generated KTX files
*
* Consumes the content of KTX files and produces an [IBL] containing an [IndirectLight] and
* Spherical Harmonics.
*
* You can generate ktx ibl and skybox files using:
*
* `cmgen --deploy ./output --format=ktx --size=256 --extract-blur=0.1 environment.hdr`
*
* Documentation: [Filament - Bake environment map](https://github.com/google/filament/blob/main/web/docs/tutorial_redball.md#bake-environment-map)
*
* @param fileLocation the KTX Image Bases Light (_ibl.ktx) file location
* @param options Loader options
*/
suspend fun KTX1Loader.loadIndirectLight(
engine: Engine,
context: Context,
fileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options()
): IBL? = context.loadFileBuffer(fileLocation)?.let { buffer ->
withContext(Dispatchers.Main) {
IBL(
indirectLight = createIndirectLight(engine, buffer, options),
sphericalHarmonics = getSphericalHarmonics(buffer)
)
}
}
/**
* @see KTX1Loader.loadIndirectLight
*/
fun KTX1Loader.loadIndirectLightAsync(
engine: Engine,
context: Context,
fileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
onResult: (ibl: IBL?) -> Unit
): Job = CoroutineScope(Dispatchers.IO).launch {
loadIndirectLight(engine, context, fileLocation, options).also(onResult)
}
/**
* @see KTX1Loader.loadIndirectLight
*/
suspend fun KTX1Loader.loadIndirectLight(
sceneView: SceneView,
fileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
): IBL? = loadIndirectLight(sceneView.engine, sceneView.context, fileLocation, options)
?.also {
sceneView.indirectLights += it.indirectLight
}
/**
* @see KTX1Loader.loadIndirectLight
*/
fun KTX1Loader.loadIndirectLightAsync(
sceneView: SceneView,
fileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
onResult: (ibl: IBL?) -> Unit
): Job =
loadIndirectLightAsync(sceneView.engine, sceneView.context, fileLocation, options, onResult)
.also {
sceneView.loadingJobs += it
}
/**
* @see KTX1Loader.loadIndirectLight
*/
suspend fun SceneView.loadKtxIndirectLight(
ktxFileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
): IBL? = KTX1Loader.loadIndirectLight(this, ktxFileLocation, options)
?.also {
indirectLight = it.indirectLight
}
/**
* @see KTX1Loader.loadIndirectLight
*/
fun SceneView.loadKtxIndirectLightAsync(
ktxFileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
onResult: ((ibl: IBL?) -> Unit)? = null
): Job = KTX1Loader.loadIndirectLightAsync(this, ktxFileLocation, options) { ibl ->
indirectLight = ibl?.indirectLight
sphericalHarmonics = ibl?.sphericalHarmonics
onResult?.invoke(ibl)
}
/**
* ### Utility for producing environment resources from precompiled cmgen generated KTX files
*
* Consumes the content of KTX files and produces a [Skybox]
*
* You can generate ktx ibl and skybox files using:
*
* `cmgen --deploy ./output --format=ktx --size=256 --extract-blur=0.1 environment.hdr`
*
* Documentation: [Filament - Bake environment map](https://github.com/google/filament/blob/main/web/docs/tutorial_redball.md#bake-environment-map)
*
* @param fileLocation the KTX Skybox (_skybox.ktx) file location
* @param options Loader options
*/
suspend fun KTX1Loader.loadSkybox(
engine: Engine,
context: Context,
fileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options()
): Skybox? = context.loadFileBuffer(fileLocation)?.let { buffer ->
withContext(Dispatchers.Main) {
createSkybox(engine, buffer, options)
}
}
/**
* @see KTX1Loader.loadSkybox
*/
fun KTX1Loader.loadSkyboxAsync(
engine: Engine,
context: Context,
fileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
onResult: (skybox: Skybox?) -> Unit
): Job = CoroutineScope(Dispatchers.IO).launch {
loadSkybox(engine, context, fileLocation, options).also(onResult)
}
/**
* @see KTX1Loader.loadSkybox
*/
suspend fun KTX1Loader.loadSkybox(
sceneView: SceneView,
fileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
): Skybox? = loadSkybox(sceneView.engine, sceneView.context, fileLocation, options)
?.also {
sceneView.skyboxes += it
}
/**
* @see KTX1Loader.loadSkybox
*/
fun KTX1Loader.loadSkyboxAsync(
sceneView: SceneView,
fileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
onResult: (skybox: Skybox?) -> Unit
): Job = loadSkyboxAsync(sceneView.engine, sceneView.context, fileLocation, options, onResult)
.also {
sceneView.loadingJobs += it
}
/**
* @see KTX1Loader.loadSkybox
*/
suspend fun SceneView.loadKtxSkybox(
ktxFileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
) = KTX1Loader.loadSkybox(this, ktxFileLocation, options)
?.also {
skybox = it
}
/**
* @see KTX1Loader.loadSkybox
*/
fun SceneView.loadKtxSkyboxAsync(
ktxFileLocation: String,
options: KTX1Loader.Options = KTX1Loader.Options(),
onResult: ((skybox: Skybox?) -> Unit)? = null
) = KTX1Loader.loadSkyboxAsync(this, ktxFileLocation, options) {
skybox = it
onResult?.invoke(it)
}
// In case of single load needed for both?
//fun KTX1Loader.resolveKtxLocations(ktxFolderLocation: String): Pair<String, String> {
// val folder = ktxFolderLocation.removeSuffix("/")
// val name = folder.substringAfterLast("/")
// return "$folder/${name}_ibl.ktx" to "$folder/${name}_skybox.ktx"
//}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment