Improve emissive material support

This commit is contained in:
Edwin Jakobs
2020-05-21 17:14:38 +02:00
parent 18b0deb2e0
commit 184d4fb371
3 changed files with 87 additions and 11 deletions

View File

@@ -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 -> ""

View File

@@ -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<String, Int>, 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")
}

View File

@@ -14,7 +14,28 @@ fun GltfFile.buildSceneNodes(): List<List<SceneNode>> {
val sceneImages = mutableMapOf<GltfImage, ColorBuffer>()
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<GltfMaterial, Material>()
@@ -58,10 +79,43 @@ fun GltfFile.buildSceneNodes(): List<List<SceneNode>> {
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)
}