Improve emissive material support
This commit is contained in:
@@ -310,7 +310,7 @@ class PBRMaterial : Material {
|
|||||||
TextureTarget.METALNESS -> "m_metalness = tex$index.r;"
|
TextureTarget.METALNESS -> "m_metalness = tex$index.r;"
|
||||||
TextureTarget.ROUGHNESS -> "m_roughness = tex$index.r;"
|
TextureTarget.ROUGHNESS -> "m_roughness = tex$index.r;"
|
||||||
TextureTarget.METALNESS_ROUGHNESS -> "m_metalness = tex$index.r; m_roughness = tex$index.g;"
|
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.NORMAL -> "f_worldNormal = normalize((v_modelNormalMatrix * vec4(tex$index.xyz,0.0)).xyz);"
|
||||||
TextureTarget.AMBIENT_OCCLUSION -> "m_ambientOcclusion *= tex$index.r;"
|
TextureTarget.AMBIENT_OCCLUSION -> "m_ambientOcclusion *= tex$index.r;"
|
||||||
is TextureTarget.Height -> ""
|
is TextureTarget.Height -> ""
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import java.io.RandomAccessFile
|
|||||||
import java.nio.Buffer
|
import java.nio.Buffer
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.nio.ByteOrder
|
import java.nio.ByteOrder
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.LinkedHashMap
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
const val GLTF_FLOAT = 5126
|
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 bufferView = gltfFile.bufferViews[accessor.bufferView]
|
||||||
val buffer = gltfFile.buffers[bufferView.buffer]
|
val buffer = gltfFile.buffers[bufferView.buffer]
|
||||||
val contents = buffer.contents(gltfFile)
|
val contents = buffer.contents(gltfFile)
|
||||||
|
(contents as Buffer).limit(contents.capacity())
|
||||||
(contents as Buffer).position((bufferView.byteOffset ?: 0) + (accessor.byteOffset))
|
(contents as Buffer).position((bufferView.byteOffset ?: 0) + (accessor.byteOffset))
|
||||||
(contents as Buffer).limit((bufferView.byteOffset ?: 0) + (accessor.byteOffset)
|
(contents as Buffer).limit((bufferView.byteOffset ?: 0) + (accessor.byteOffset)
|
||||||
+ accessor.count * indexType.sizeInBytes)
|
+ accessor.count * indexType.sizeInBytes)
|
||||||
@@ -146,7 +149,7 @@ class GltfPbrMetallicRoughness(val baseColorFactor: DoubleArray?,
|
|||||||
val metallicFactor: Double?)
|
val metallicFactor: Double?)
|
||||||
class GltfMaterialTexture(val index: Int, val scale: Double?, val texCoord: Int?)
|
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)
|
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 occlusionTexture: GltfMaterialTexture?,
|
||||||
val emissiveTexture: GltfMaterialTexture?,
|
val emissiveTexture: GltfMaterialTexture?,
|
||||||
val emissiveFactor: DoubleArray?,
|
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,
|
class GltfBufferView(val buffer: Int,
|
||||||
val byteOffset: Int?,
|
val byteOffset: Int?,
|
||||||
@@ -168,13 +179,24 @@ class GltfBufferView(val buffer: Int,
|
|||||||
|
|
||||||
class GltfBuffer(val byteLength: Int, val uri: String?) {
|
class GltfBuffer(val byteLength: Int, val uri: String?) {
|
||||||
fun contents(gltfFile: GltfFile): ByteBuffer = if (uri != null) {
|
fun contents(gltfFile: GltfFile): ByteBuffer = if (uri != null) {
|
||||||
val raf = RandomAccessFile(File(gltfFile.file.parentFile, uri), "r")
|
|
||||||
val buffer = ByteBuffer.allocateDirect(byteLength)
|
if (uri.startsWith("data:")) {
|
||||||
buffer.order(ByteOrder.nativeOrder())
|
val base64 = uri.substring(uri.indexOf(",") + 1)
|
||||||
buffer.rewind()
|
val decoded = Base64.getDecoder().decode(base64)
|
||||||
raf.channel.read(buffer)
|
val buffer = ByteBuffer.allocateDirect(decoded.size)
|
||||||
buffer.rewind()
|
buffer.order(ByteOrder.nativeOrder())
|
||||||
buffer
|
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 {
|
} else {
|
||||||
gltfFile.bufferBuffer ?: error("no embedded buffer from glb")
|
gltfFile.bufferBuffer ?: error("no embedded buffer from glb")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,28 @@ fun GltfFile.buildSceneNodes(): List<List<SceneNode>> {
|
|||||||
|
|
||||||
val sceneImages = mutableMapOf<GltfImage, ColorBuffer>()
|
val sceneImages = mutableMapOf<GltfImage, ColorBuffer>()
|
||||||
fun GltfImage.createSceneImage(): 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>()
|
val sceneMaterials = mutableMapOf<GltfMaterial, Material>()
|
||||||
@@ -58,10 +79,43 @@ fun GltfFile.buildSceneNodes(): List<List<SceneNode>> {
|
|||||||
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR)
|
||||||
cb.wrapU = WrapMode.REPEAT
|
cb.wrapU = WrapMode.REPEAT
|
||||||
cb.wrapV = 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)
|
val sceneTexture = Texture(ModelCoordinates(texture = cb, tangentInput = "va_tangent", pre = "x_texCoord.y = 1.0-x_texCoord.y;"), TextureTarget.NORMAL)
|
||||||
material.textures.add(sceneTexture)
|
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 {
|
emissiveFactor?.let {
|
||||||
material.emission = ColorRGBa(it[0], it[1], it[2], 1.0)
|
material.emission = ColorRGBa(it[0], it[1], it[2], 1.0)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user