Improve emissive material support
This commit is contained in:
@@ -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 -> ""
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user