From 184d4fb371499ce86656caefbae17b0499eded25 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Thu, 21 May 2020 17:14:38 +0200 Subject: [PATCH] Improve emissive material support --- orx-dnk3/src/main/kotlin/PBRMaterial.kt | 2 +- orx-dnk3/src/main/kotlin/gltf/Gltf.kt | 40 ++++++++++++---- orx-dnk3/src/main/kotlin/gltf/GltfScene.kt | 56 +++++++++++++++++++++- 3 files changed, 87 insertions(+), 11 deletions(-) diff --git a/orx-dnk3/src/main/kotlin/PBRMaterial.kt b/orx-dnk3/src/main/kotlin/PBRMaterial.kt index 9dcf258a..fdf26472 100644 --- a/orx-dnk3/src/main/kotlin/PBRMaterial.kt +++ b/orx-dnk3/src/main/kotlin/PBRMaterial.kt @@ -310,7 +310,7 @@ class PBRMaterial : Material { TextureTarget.METALNESS -> "m_metalness = tex$index.r;" TextureTarget.ROUGHNESS -> "m_roughness = tex$index.r;" TextureTarget.METALNESS_ROUGHNESS -> "m_metalness = tex$index.r; m_roughness = tex$index.g;" - TextureTarget.EMISSION -> "m_emission += tex$index.rgb;" + TextureTarget.EMISSION -> "m_emission *= tex$index.rgb;" TextureTarget.NORMAL -> "f_worldNormal = normalize((v_modelNormalMatrix * vec4(tex$index.xyz,0.0)).xyz);" TextureTarget.AMBIENT_OCCLUSION -> "m_ambientOcclusion *= tex$index.r;" is TextureTarget.Height -> "" diff --git a/orx-dnk3/src/main/kotlin/gltf/Gltf.kt b/orx-dnk3/src/main/kotlin/gltf/Gltf.kt index 6e3e7cdb..5d4bcb7d 100644 --- a/orx-dnk3/src/main/kotlin/gltf/Gltf.kt +++ b/orx-dnk3/src/main/kotlin/gltf/Gltf.kt @@ -9,6 +9,8 @@ import java.io.RandomAccessFile import java.nio.Buffer import java.nio.ByteBuffer import java.nio.ByteOrder +import java.util.* +import kotlin.collections.LinkedHashMap import kotlin.math.max const val GLTF_FLOAT = 5126 @@ -46,6 +48,7 @@ class GltfPrimitive(val attributes: LinkedHashMap, val indices: Int val bufferView = gltfFile.bufferViews[accessor.bufferView] val buffer = gltfFile.buffers[bufferView.buffer] val contents = buffer.contents(gltfFile) + (contents as Buffer).limit(contents.capacity()) (contents as Buffer).position((bufferView.byteOffset ?: 0) + (accessor.byteOffset)) (contents as Buffer).limit((bufferView.byteOffset ?: 0) + (accessor.byteOffset) + accessor.count * indexType.sizeInBytes) @@ -146,7 +149,7 @@ class GltfPbrMetallicRoughness(val baseColorFactor: DoubleArray?, val metallicFactor: Double?) class GltfMaterialTexture(val index: Int, val scale: Double?, val texCoord: Int?) -class GltfImage(val uri: String) +class GltfImage(val uri: String?, val bufferView: Int?) class GltfSampler(val magFilter: Int, val minFilter: Int, val wrapS: Int, val wrapT: Int) @@ -158,7 +161,15 @@ class GltfMaterial(val name: String, val occlusionTexture: GltfMaterialTexture?, val emissiveTexture: GltfMaterialTexture?, val emissiveFactor: DoubleArray?, - val pbrMetallicRoughness: GltfPbrMetallicRoughness?) + val pbrMetallicRoughness: GltfPbrMetallicRoughness?, + val extensions: GltfMaterialExtensions? + ) + +class GltfMaterialExtensions( + val KHR_materials_pbrSpecularGlossiness: KhrMaterialsPbrSpecularGlossiness? +) + +class KhrMaterialsPbrSpecularGlossiness(val diffuseFactor: DoubleArray?, val diffuseTexture: GltfMaterialTexture?) class GltfBufferView(val buffer: Int, val byteOffset: Int?, @@ -168,13 +179,24 @@ class GltfBufferView(val buffer: Int, class GltfBuffer(val byteLength: Int, val uri: String?) { fun contents(gltfFile: GltfFile): ByteBuffer = if (uri != null) { - val raf = RandomAccessFile(File(gltfFile.file.parentFile, uri), "r") - val buffer = ByteBuffer.allocateDirect(byteLength) - buffer.order(ByteOrder.nativeOrder()) - buffer.rewind() - raf.channel.read(buffer) - buffer.rewind() - buffer + + if (uri.startsWith("data:")) { + val base64 = uri.substring(uri.indexOf(",") + 1) + val decoded = Base64.getDecoder().decode(base64) + val buffer = ByteBuffer.allocateDirect(decoded.size) + buffer.order(ByteOrder.nativeOrder()) + buffer.put(decoded) + buffer.rewind() + buffer + } else { + val raf = RandomAccessFile(File(gltfFile.file.parentFile, uri), "r") + val buffer = ByteBuffer.allocateDirect(byteLength) + buffer.order(ByteOrder.nativeOrder()) + buffer.rewind() + raf.channel.read(buffer) + buffer.rewind() + buffer + } } else { gltfFile.bufferBuffer ?: error("no embedded buffer from glb") } diff --git a/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt b/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt index 3122c724..8c21a5eb 100644 --- a/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt +++ b/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt @@ -14,7 +14,28 @@ fun GltfFile.buildSceneNodes(): List> { val sceneImages = mutableMapOf() fun GltfImage.createSceneImage(): ColorBuffer { - return sceneImages.getOrPut(this) { loadImage(File(file.parent, uri)) } + return sceneImages.getOrPut(this) { + if (uri == null) { + + bufferView?.let { bv -> + val localBufferView = bufferViews[bv] + + val localBuffer = buffers[localBufferView.buffer].contents(this@buildSceneNodes) + require(localBufferView.byteOffset != null) + require(localBufferView.byteLength != null) + localBuffer.position(localBufferView.byteOffset) + localBuffer.limit(localBufferView.byteOffset + localBufferView.byteLength) + ColorBuffer.fromBuffer(localBuffer) + } ?: error("no uri and no bufferview") + + } else { + if (uri.startsWith("data:")) { + loadImage(uri) + } else { + loadImage(File(file.parent, uri)) + } + } + } } val sceneMaterials = mutableMapOf() @@ -58,10 +79,43 @@ fun GltfFile.buildSceneNodes(): List> { cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR) cb.wrapU = WrapMode.REPEAT cb.wrapV = WrapMode.REPEAT + val sceneTexture = Texture(ModelCoordinates(texture = cb, tangentInput = "va_tangent", pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.NORMAL) material.textures.add(sceneTexture) } + emissiveFactor?.let { + material.emission = ColorRGBa(it[0], it[1], it[2]) + } + + emissiveTexture?.let { + val cb = images!![textures!![it.index].source].createSceneImage() + val sceneTexture = Texture(ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.EMISSION) + material.textures.add(sceneTexture) + } + + + extensions?.let { ext -> + + ext.KHR_materials_pbrSpecularGlossiness?.let { sg -> + sg.diffuseFactor?.let { + material.color = ColorRGBa(it[0], it[1], it[2], it[3]) + } + sg.diffuseTexture?.let { + val cb = images!![textures!![it.index].source].createSceneImage() + cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR) + cb.wrapU = WrapMode.REPEAT + cb.wrapV = WrapMode.REPEAT + val sceneTexture = Texture(ModelCoordinates(texture = cb, pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.COLOR) + material.textures.add(sceneTexture) + } + + } + + + } + + emissiveFactor?.let { material.emission = ColorRGBa(it[0], it[1], it[2], 1.0) }