feat: add pbr support
|
After Width: | Height: | Size: 3.1 MiB |
@@ -0,0 +1,712 @@
|
|||||||
|
{
|
||||||
|
"asset": {
|
||||||
|
"version": "2.0",
|
||||||
|
"generator": "babylon.js glTF exporter for Maya 2018 v20200228.3 (with minor hand modifications)"
|
||||||
|
},
|
||||||
|
"extensionsUsed": [
|
||||||
|
"KHR_materials_transmission"
|
||||||
|
],
|
||||||
|
"scene": 0,
|
||||||
|
"scenes": [
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"mesh": 0,
|
||||||
|
"name": "Hose_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mesh": 1,
|
||||||
|
"name": "RubberWood_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mesh": 2,
|
||||||
|
"name": "GlassPlastic_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mesh": 3,
|
||||||
|
"name": "MetalParts_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mesh": 4,
|
||||||
|
"name": "LeatherParts_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mesh": 5,
|
||||||
|
"name": "Lenses_low"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes": [
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"POSITION": 1,
|
||||||
|
"TANGENT": 2,
|
||||||
|
"NORMAL": 3,
|
||||||
|
"TEXCOORD_0": 4
|
||||||
|
},
|
||||||
|
"indices": 0,
|
||||||
|
"material": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Hose_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"POSITION": 6,
|
||||||
|
"TANGENT": 7,
|
||||||
|
"NORMAL": 8,
|
||||||
|
"TEXCOORD_0": 9
|
||||||
|
},
|
||||||
|
"indices": 5,
|
||||||
|
"material": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RubberWood_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"POSITION": 11,
|
||||||
|
"TANGENT": 12,
|
||||||
|
"NORMAL": 13,
|
||||||
|
"TEXCOORD_0": 14
|
||||||
|
},
|
||||||
|
"indices": 10,
|
||||||
|
"material": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "GlassPlastic_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"POSITION": 16,
|
||||||
|
"TANGENT": 17,
|
||||||
|
"NORMAL": 18,
|
||||||
|
"TEXCOORD_0": 19
|
||||||
|
},
|
||||||
|
"indices": 15,
|
||||||
|
"material": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "MetalParts_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"POSITION": 21,
|
||||||
|
"TANGENT": 22,
|
||||||
|
"NORMAL": 23,
|
||||||
|
"TEXCOORD_0": 24
|
||||||
|
},
|
||||||
|
"indices": 20,
|
||||||
|
"material": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "LeatherParts_low"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"primitives": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"POSITION": 26,
|
||||||
|
"TANGENT": 27,
|
||||||
|
"NORMAL": 28,
|
||||||
|
"TEXCOORD_0": 29
|
||||||
|
},
|
||||||
|
"indices": 25,
|
||||||
|
"material": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Lenses_low"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors": [
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"componentType": 5123,
|
||||||
|
"count": 59040,
|
||||||
|
"type": "SCALAR",
|
||||||
|
"name": "accessorIndices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 10472,
|
||||||
|
"max": [
|
||||||
|
0.10810829,
|
||||||
|
0.356580257,
|
||||||
|
0.190409869
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.07221258,
|
||||||
|
0.104120225,
|
||||||
|
-0.088394776
|
||||||
|
],
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorPositions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 2,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 10472,
|
||||||
|
"type": "VEC4",
|
||||||
|
"name": "accessorTangents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 125664,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 10472,
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorNormals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 3,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 10472,
|
||||||
|
"type": "VEC2",
|
||||||
|
"name": "accessorUVs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"byteOffset": 118080,
|
||||||
|
"componentType": 5123,
|
||||||
|
"count": 72534,
|
||||||
|
"type": "SCALAR",
|
||||||
|
"name": "accessorIndices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 251328,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 13638,
|
||||||
|
"max": [
|
||||||
|
0.162940636,
|
||||||
|
0.7025226,
|
||||||
|
0.200029165
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.158857465,
|
||||||
|
-2.14242937E-05,
|
||||||
|
-0.171545789
|
||||||
|
],
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorPositions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 2,
|
||||||
|
"byteOffset": 167552,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 13638,
|
||||||
|
"type": "VEC4",
|
||||||
|
"name": "accessorTangents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 414984,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 13638,
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorNormals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 3,
|
||||||
|
"byteOffset": 83776,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 13638,
|
||||||
|
"type": "VEC2",
|
||||||
|
"name": "accessorUVs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"byteOffset": 263148,
|
||||||
|
"componentType": 5123,
|
||||||
|
"count": 24408,
|
||||||
|
"type": "SCALAR",
|
||||||
|
"name": "accessorIndices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 578640,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 4676,
|
||||||
|
"max": [
|
||||||
|
0.140494063,
|
||||||
|
0.61828655,
|
||||||
|
0.147373646
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.140846014,
|
||||||
|
0.440957,
|
||||||
|
-0.107818365
|
||||||
|
],
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorPositions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 2,
|
||||||
|
"byteOffset": 385760,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 4676,
|
||||||
|
"type": "VEC4",
|
||||||
|
"name": "accessorTangents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 634752,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 4676,
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorNormals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 3,
|
||||||
|
"byteOffset": 192880,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 4676,
|
||||||
|
"type": "VEC2",
|
||||||
|
"name": "accessorUVs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"byteOffset": 311964,
|
||||||
|
"componentType": 5123,
|
||||||
|
"count": 60288,
|
||||||
|
"type": "SCALAR",
|
||||||
|
"name": "accessorIndices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 690864,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 13636,
|
||||||
|
"max": [
|
||||||
|
0.132708371,
|
||||||
|
0.6024364,
|
||||||
|
0.199477077
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.203642711,
|
||||||
|
0.02116075,
|
||||||
|
-0.147512689
|
||||||
|
],
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorPositions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 2,
|
||||||
|
"byteOffset": 460576,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 13636,
|
||||||
|
"type": "VEC4",
|
||||||
|
"name": "accessorTangents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 854496,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 13636,
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorNormals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 3,
|
||||||
|
"byteOffset": 230288,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 13636,
|
||||||
|
"type": "VEC2",
|
||||||
|
"name": "accessorUVs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"byteOffset": 432540,
|
||||||
|
"componentType": 5123,
|
||||||
|
"count": 65688,
|
||||||
|
"type": "SCALAR",
|
||||||
|
"name": "accessorIndices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 1018128,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 12534,
|
||||||
|
"max": [
|
||||||
|
0.124933377,
|
||||||
|
0.716000438,
|
||||||
|
0.129168555
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.125863016,
|
||||||
|
0.2958266,
|
||||||
|
-0.1541516
|
||||||
|
],
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorPositions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 2,
|
||||||
|
"byteOffset": 678752,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 12534,
|
||||||
|
"type": "VEC4",
|
||||||
|
"name": "accessorTangents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 1168536,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 12534,
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorNormals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 3,
|
||||||
|
"byteOffset": 339376,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 12534,
|
||||||
|
"type": "VEC2",
|
||||||
|
"name": "accessorUVs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 0,
|
||||||
|
"byteOffset": 563916,
|
||||||
|
"componentType": 5123,
|
||||||
|
"count": 2208,
|
||||||
|
"type": "SCALAR",
|
||||||
|
"name": "accessorIndices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 1318944,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 436,
|
||||||
|
"max": [
|
||||||
|
0.101920746,
|
||||||
|
0.5936986,
|
||||||
|
0.152926728
|
||||||
|
],
|
||||||
|
"min": [
|
||||||
|
-0.101920947,
|
||||||
|
0.5300429,
|
||||||
|
0.090174824
|
||||||
|
],
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorPositions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 2,
|
||||||
|
"byteOffset": 879296,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 436,
|
||||||
|
"type": "VEC4",
|
||||||
|
"name": "accessorTangents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 1,
|
||||||
|
"byteOffset": 1324176,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 436,
|
||||||
|
"type": "VEC3",
|
||||||
|
"name": "accessorNormals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView": 3,
|
||||||
|
"byteOffset": 439648,
|
||||||
|
"componentType": 5126,
|
||||||
|
"count": 436,
|
||||||
|
"type": "VEC2",
|
||||||
|
"name": "accessorUVs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews": [
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteLength": 568332,
|
||||||
|
"name": "bufferViewScalar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 568332,
|
||||||
|
"byteLength": 1329408,
|
||||||
|
"byteStride": 12,
|
||||||
|
"name": "bufferViewFloatVec3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 1897740,
|
||||||
|
"byteLength": 886272,
|
||||||
|
"byteStride": 16,
|
||||||
|
"name": "bufferViewFloatVec4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer": 0,
|
||||||
|
"byteOffset": 2784012,
|
||||||
|
"byteLength": 443136,
|
||||||
|
"byteStride": 8,
|
||||||
|
"name": "bufferViewFloatVec2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers": [
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet.bin",
|
||||||
|
"byteLength": 3227148
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials": [
|
||||||
|
{
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorTexture": {
|
||||||
|
"index": 2
|
||||||
|
},
|
||||||
|
"metallicRoughnessTexture": {
|
||||||
|
"index": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"normalTexture": {
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
"occlusionTexture": {
|
||||||
|
"index": 1
|
||||||
|
},
|
||||||
|
"doubleSided": true,
|
||||||
|
"name": "HoseMat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorTexture": {
|
||||||
|
"index": 2
|
||||||
|
},
|
||||||
|
"metallicRoughnessTexture": {
|
||||||
|
"index": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"normalTexture": {
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
"occlusionTexture": {
|
||||||
|
"index": 1
|
||||||
|
},
|
||||||
|
"name": "RubberWoodMat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorTexture": {
|
||||||
|
"index": 5
|
||||||
|
},
|
||||||
|
"metallicRoughnessTexture": {
|
||||||
|
"index": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"normalTexture": {
|
||||||
|
"index": 3
|
||||||
|
},
|
||||||
|
"occlusionTexture": {
|
||||||
|
"index": 4
|
||||||
|
},
|
||||||
|
"name": "GlassPlasticMat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorTexture": {
|
||||||
|
"index": 8
|
||||||
|
},
|
||||||
|
"metallicRoughnessTexture": {
|
||||||
|
"index": 7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"normalTexture": {
|
||||||
|
"index": 6
|
||||||
|
},
|
||||||
|
"occlusionTexture": {
|
||||||
|
"index": 7
|
||||||
|
},
|
||||||
|
"name": "MetalPartsMat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorTexture": {
|
||||||
|
"index": 11
|
||||||
|
},
|
||||||
|
"metallicRoughnessTexture": {
|
||||||
|
"index": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"normalTexture": {
|
||||||
|
"index": 9
|
||||||
|
},
|
||||||
|
"occlusionTexture": {
|
||||||
|
"index": 10
|
||||||
|
},
|
||||||
|
"name": "LeatherPartsMat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"extensions": {
|
||||||
|
"KHR_materials_transmission": {
|
||||||
|
"transmissionFactor": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pbrMetallicRoughness": {
|
||||||
|
"baseColorTexture": {
|
||||||
|
"index": 14
|
||||||
|
},
|
||||||
|
"metallicRoughnessTexture": {
|
||||||
|
"index": 13
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"normalTexture": {
|
||||||
|
"index": 12
|
||||||
|
},
|
||||||
|
"occlusionTexture": {
|
||||||
|
"index": 13
|
||||||
|
},
|
||||||
|
"name": "LensesMat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 0,
|
||||||
|
"name": "FlightHelmet_Materials_RubberWoodMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 1,
|
||||||
|
"name": "FlightHelmet_Materials_RubberWoodMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 2,
|
||||||
|
"name": "FlightHelmet_Materials_RubberWoodMat_BaseColor.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 3,
|
||||||
|
"name": "FlightHelmet_Materials_GlassPlasticMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 4,
|
||||||
|
"name": "FlightHelmet_Materials_GlassPlasticMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 5,
|
||||||
|
"name": "FlightHelmet_Materials_GlassPlasticMat_BaseColor.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 6,
|
||||||
|
"name": "FlightHelmet_Materials_MetalPartsMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 7,
|
||||||
|
"name": "FlightHelmet_Materials_MetalPartsMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 8,
|
||||||
|
"name": "FlightHelmet_Materials_MetalPartsMat_BaseColor.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 9,
|
||||||
|
"name": "FlightHelmet_Materials_LeatherPartsMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 10,
|
||||||
|
"name": "FlightHelmet_Materials_LeatherPartsMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 11,
|
||||||
|
"name": "FlightHelmet_Materials_LeatherPartsMat_BaseColor.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 12,
|
||||||
|
"name": "FlightHelmet_Materials_LensesMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 13,
|
||||||
|
"name": "FlightHelmet_Materials_LensesMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sampler": 0,
|
||||||
|
"source": 14,
|
||||||
|
"name": "FlightHelmet_Materials_LensesMat_BaseColor.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images": [
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_RubberWoodMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_RubberWoodMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_RubberWoodMat_BaseColor.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_GlassPlasticMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_GlassPlasticMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_GlassPlasticMat_BaseColor.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_MetalPartsMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_MetalPartsMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_MetalPartsMat_BaseColor.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_LeatherPartsMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_LeatherPartsMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_LeatherPartsMat_BaseColor.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_LensesMat_Normal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_LensesMat_OcclusionRoughMetal.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "FlightHelmet_Materials_LensesMat_BaseColor.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers": [
|
||||||
|
{
|
||||||
|
"magFilter": 9729,
|
||||||
|
"minFilter": 9987
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 5.2 MiB |
|
After Width: | Height: | Size: 5.4 MiB |
|
After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 680 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 588 KiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 3.1 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 3.4 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 3.6 MiB |
@@ -83,6 +83,18 @@ vec3 calculateLight(Light light, vec3 fragPos, vec3 n, vec3 v,
|
|||||||
return (diffuse + specular) * light.color * light.intensity * attenuation * NoL * occlusion;
|
return (diffuse + specular) * light.color * light.intensity * attenuation * NoL * occlusion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Analytic approximation of the split sum environment BRDF (Karis, "Physically Based Shading on Mobile").
|
||||||
|
// Used to light the flat ambient term with the same specular response as the lights.
|
||||||
|
vec3 envBRDFApprox(vec3 f0, float roughness, float NoV)
|
||||||
|
{
|
||||||
|
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
|
||||||
|
const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
|
||||||
|
vec4 r = roughness * c0 + c1;
|
||||||
|
float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
|
||||||
|
vec2 ab = vec2(-1.04, 1.04) * a004 + r.zw;
|
||||||
|
return f0 * ab.x + ab.y;
|
||||||
|
}
|
||||||
|
|
||||||
// blue -> green -> red, used to visualise how many lights a tile has
|
// blue -> green -> red, used to visualise how many lights a tile has
|
||||||
vec3 lightHeatmapColor(uint lightCount)
|
vec3 lightHeatmapColor(uint lightCount)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,14 +3,19 @@
|
|||||||
|
|
||||||
#extension GL_EXT_buffer_reference : require
|
#extension GL_EXT_buffer_reference : require
|
||||||
|
|
||||||
|
// Must match MaterialData in Material.h
|
||||||
struct MaterialData {
|
struct MaterialData {
|
||||||
vec4 baseColor;
|
vec4 baseColor;
|
||||||
vec4 metallicRoughnessEmissive;
|
vec4 emissiveColor;
|
||||||
|
vec4 metallicRoughnessNormalOcclusion;
|
||||||
uint textureFilteringMode;
|
uint textureFilteringMode;
|
||||||
uint diffuseTex;
|
uint diffuseTex;
|
||||||
uint normalTex;
|
uint normalTex;
|
||||||
uint metallicRoughnessTex;
|
uint metallicTex;
|
||||||
|
uint roughnessTex;
|
||||||
|
uint occlusionTex;
|
||||||
uint emissiveTex;
|
uint emissiveTex;
|
||||||
|
uint _pad0;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout (buffer_reference, std430) readonly buffer MaterialsBuffer {
|
layout (buffer_reference, std430) readonly buffer MaterialsBuffer {
|
||||||
|
|||||||
@@ -12,14 +12,32 @@ layout (location = 0) in vec3 inPos;
|
|||||||
layout (location = 1) in vec2 inUV;
|
layout (location = 1) in vec2 inUV;
|
||||||
layout (location = 2) in vec3 inNormal;
|
layout (location = 2) in vec3 inNormal;
|
||||||
layout (location = 3) in vec4 inTangent;
|
layout (location = 3) in vec4 inTangent;
|
||||||
layout (location = 4) in mat3 inTBN;
|
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
|
vec3 calculateNormal(MaterialData material, uint samplerID)
|
||||||
|
{
|
||||||
|
vec3 n = normalize(inNormal);
|
||||||
|
|
||||||
|
// Meshes without tangents can't use a normal map
|
||||||
|
if (dot(inTangent.xyz, inTangent.xyz) < 1e-8) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-orthogonalize, the interpolated tangent isn't perpendicular to the normal anymore
|
||||||
|
vec3 t = normalize(inTangent.xyz - n * dot(n, inTangent.xyz));
|
||||||
|
vec3 b = cross(n, t) * inTangent.w;
|
||||||
|
|
||||||
|
vec3 tangentNormal = sampleTexture2D(material.normalTex, samplerID, inUV).rgb * 2.0 - 1.0;
|
||||||
|
tangentNormal.xy *= material.metallicRoughnessNormalOcclusion.z;
|
||||||
|
|
||||||
|
return normalize(mat3(t, b, n) * tangentNormal);
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
MaterialData material = pcs.sceneData.materials.data[pcs.materialID];
|
MaterialData material = pcs.sceneData.materials.data[pcs.materialID];
|
||||||
uint samplerID = pcs.sceneData.materials.data[pcs.materialID].textureFilteringMode;
|
uint samplerID = material.textureFilteringMode;
|
||||||
|
|
||||||
vec4 diffuse = sampleTexture2D(material.diffuseTex, samplerID, inUV) * material.baseColor;
|
vec4 diffuse = sampleTexture2D(material.diffuseTex, samplerID, inUV) * material.baseColor;
|
||||||
vec3 baseColor = diffuse.rgb;
|
vec3 baseColor = diffuse.rgb;
|
||||||
@@ -28,27 +46,18 @@ void main()
|
|||||||
// discard;
|
// discard;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
vec3 normal = normalize(inNormal);
|
vec3 n = calculateNormal(material, samplerID);
|
||||||
// if (inTangent != vec4(0.0)) {
|
|
||||||
// // FIXME: sometimes Blender doesn't export tangents for some objects
|
|
||||||
// // for some reason. When we will start computing tangents manually,
|
|
||||||
// // this check can be removed
|
|
||||||
// normal = sampleTexture2DLinear(material.normalTex, inUV).rgb;
|
|
||||||
// // normal.y = 1 - normal.y; // flip to make OpenGL normal maps work
|
|
||||||
// normal = inTBN * normalize(normal * 2.0 - 1.0);
|
|
||||||
// normal = normalize(normal);
|
|
||||||
// }
|
|
||||||
|
|
||||||
float metallicF = material.metallicRoughnessEmissive.r;
|
float metallicF = material.metallicRoughnessNormalOcclusion.x;
|
||||||
float roughnessF = material.metallicRoughnessEmissive.g;
|
float roughnessF = material.metallicRoughnessNormalOcclusion.y;
|
||||||
|
float occlusionStrength = material.metallicRoughnessNormalOcclusion.w;
|
||||||
|
|
||||||
vec4 metallicRoughness = sampleTexture2DLinear(material.metallicRoughnessTex, inUV);
|
float metallic = metallicF * sampleTexture2D(material.metallicTex, samplerID, inUV).b;
|
||||||
|
float roughness = roughnessF * sampleTexture2D(material.roughnessTex, samplerID, inUV).g;
|
||||||
float roughness = roughnessF * metallicRoughness.g;
|
|
||||||
// roughness *= roughness; // from perceptual to linear
|
|
||||||
roughness = max(roughness, 1e-2); // 0.0 roughness leads to NaNs
|
roughness = max(roughness, 1e-2); // 0.0 roughness leads to NaNs
|
||||||
|
|
||||||
float metallic = metallicF * metallicRoughness.b;
|
float occlusion = sampleTexture2D(material.occlusionTex, samplerID, inUV).r;
|
||||||
|
float ambientOcclusion = mix(1.0, occlusion, occlusionStrength);
|
||||||
|
|
||||||
vec3 dielectricSpecular = vec3(0.04);
|
vec3 dielectricSpecular = vec3(0.04);
|
||||||
vec3 black = vec3(0.0);
|
vec3 black = vec3(0.0);
|
||||||
@@ -57,7 +66,6 @@ void main()
|
|||||||
|
|
||||||
vec3 cameraPos = pcs.sceneData.cameraPos.xyz;
|
vec3 cameraPos = pcs.sceneData.cameraPos.xyz;
|
||||||
vec3 fragPos = inPos.xyz;
|
vec3 fragPos = inPos.xyz;
|
||||||
vec3 n = normal;
|
|
||||||
vec3 v = normalize(cameraPos - fragPos);
|
vec3 v = normalize(cameraPos - fragPos);
|
||||||
|
|
||||||
// forward+: only loop over the lights the culling pass put in this pixel's tile
|
// forward+: only loop over the lights the culling pass put in this pixel's tile
|
||||||
@@ -70,26 +78,28 @@ void main()
|
|||||||
uint lightIndex = pcs.sceneData.tileLightIndices.data[tileOffset + 1 + i];
|
uint lightIndex = pcs.sceneData.tileLightIndices.data[tileOffset + 1 + i];
|
||||||
Light light = pcs.sceneData.lights.data[lightIndex];
|
Light light = pcs.sceneData.lights.data[lightIndex];
|
||||||
|
|
||||||
float occlusion = 1.0;
|
float shadow = 1.0;
|
||||||
if (light.castShadows != 0) {
|
if (light.castShadows != 0) {
|
||||||
occlusion = calculateDirectionalShadow(
|
shadow = calculateDirectionalShadow(
|
||||||
fragPos, n,
|
fragPos, normalize(inNormal),
|
||||||
pcs.sceneData.lightViewProj,
|
pcs.sceneData.lightViewProj,
|
||||||
pcs.sceneData.shadowMapId,
|
pcs.sceneData.shadowMapId,
|
||||||
pcs.sceneData.shadowNormalOffset);
|
pcs.sceneData.shadowNormalOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
fragColor += calculateLight(light, fragPos, n, v,
|
fragColor += calculateLight(light, fragPos, n, v,
|
||||||
diffuseColor, roughness, metallic, f0, occlusion);
|
diffuseColor, roughness, metallic, f0, shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// emissive
|
// emissive
|
||||||
float emissiveF = material.metallicRoughnessEmissive.b;
|
vec3 emissiveColor = material.emissiveColor.rgb * sampleTexture2D(material.emissiveTex, samplerID, inUV).rgb;
|
||||||
vec3 emissiveColor = emissiveF * sampleTexture2DLinear(material.emissiveTex, inUV).rgb;
|
|
||||||
fragColor += emissiveColor;
|
fragColor += emissiveColor;
|
||||||
|
|
||||||
// ambient
|
// ambient, the specular part keeps metals from turning black without lights
|
||||||
fragColor += baseColor * pcs.sceneData.ambientColor * pcs.sceneData.ambientIntensity;
|
float NoV = clamp(dot(n, v), 0.0001, 1.0);
|
||||||
|
vec3 ambientLight = pcs.sceneData.ambientColor * pcs.sceneData.ambientIntensity;
|
||||||
|
vec3 ambientSpecular = envBRDFApprox(f0, roughness, NoV);
|
||||||
|
fragColor += (diffuseColor + ambientSpecular) * ambientLight * ambientOcclusion;
|
||||||
|
|
||||||
if (pcs.sceneData.debugLightHeatmap != 0) {
|
if (pcs.sceneData.debugLightHeatmap != 0) {
|
||||||
fragColor = mix(fragColor, lightHeatmapColor(tileLightCount), 0.5);
|
fragColor = mix(fragColor, lightHeatmapColor(tileLightCount), 0.5);
|
||||||
@@ -104,7 +114,7 @@ void main()
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// NORMAL DEBUG
|
// NORMAL DEBUG
|
||||||
fragColor = normal;
|
fragColor = n;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
outFragColor = vec4(fragColor, diffuse.a);
|
outFragColor = vec4(fragColor, diffuse.a);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ layout (location = 0) out vec3 outPos;
|
|||||||
layout (location = 1) out vec2 outUV;
|
layout (location = 1) out vec2 outUV;
|
||||||
layout (location = 2) out vec3 outNormal;
|
layout (location = 2) out vec3 outNormal;
|
||||||
layout (location = 3) out vec4 outTangent;
|
layout (location = 3) out vec4 outTangent;
|
||||||
layout (location = 4) out mat3 outTBN;
|
|
||||||
|
|
||||||
// The depth pre-pass reuses this shader, positions have to match bit for bit
|
// The depth pre-pass reuses this shader, positions have to match bit for bit
|
||||||
// so the main pass can depth test against it with LESS_OR_EQUAL
|
// so the main pass can depth test against it with LESS_OR_EQUAL
|
||||||
@@ -29,10 +28,6 @@ void main()
|
|||||||
// outNormal = (pcs.transform * vec4(v.normal, 0.0)).xyz;
|
// outNormal = (pcs.transform * vec4(v.normal, 0.0)).xyz;
|
||||||
outNormal = mat3(transpose(inverse(pcs.transform))) * v.normal;
|
outNormal = mat3(transpose(inverse(pcs.transform))) * v.normal;
|
||||||
|
|
||||||
outTangent = v.tangent;
|
// w is the bitangent sign, the fragment shader builds the TBN from the interpolated vectors
|
||||||
|
outTangent = vec4(mat3(pcs.transform) * v.tangent.xyz, v.tangent.w);
|
||||||
vec3 T = normalize(vec3(pcs.transform * v.tangent));
|
|
||||||
vec3 N = normalize(outNormal);
|
|
||||||
vec3 B = cross(N, T) * v.tangent.w;
|
|
||||||
outTBN = mat3(T, B, N);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include <destrum/Util/ModelDoc.h>
|
#include <destrum/Util/ModelDoc.h>
|
||||||
|
|
||||||
namespace ModelFile {
|
namespace ModelFile {
|
||||||
inline constexpr std::uint32_t Version = 1;
|
inline constexpr std::uint32_t Version = 2;
|
||||||
inline constexpr std::string_view Extension = ".dmodel";
|
inline constexpr std::string_view Extension = ".dmodel";
|
||||||
|
|
||||||
inline constexpr ModelDoc::LoadOptions CookOptions{};
|
inline constexpr ModelDoc::LoadOptions CookOptions{};
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ public:
|
|||||||
void updateMaterialGPU(MaterialID id);
|
void updateMaterialGPU(MaterialID id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
[[nodiscard]] MaterialData toMaterialData(const Material& material) const;
|
||||||
|
|
||||||
std::vector<Material> materials;
|
std::vector<Material> materials;
|
||||||
std::vector<std::string> materialKeys;
|
std::vector<std::string> materialKeys;
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,23 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <destrum/Assets/AssetReference.h>
|
#include <destrum/Assets/AssetReference.h>
|
||||||
|
#include <destrum/Graphics/ids.h>
|
||||||
|
|
||||||
|
// Must match MaterialData in materials.glsl
|
||||||
struct alignas(16) MaterialData {
|
struct alignas(16) MaterialData {
|
||||||
alignas(16) glm::vec4 baseColor;
|
alignas(16) glm::vec4 baseColor;
|
||||||
alignas(16) glm::vec4 metalRoughnessEmissive;
|
alignas(16) glm::vec4 emissiveColor;
|
||||||
|
alignas(16) glm::vec4 metallicRoughnessNormalOcclusion;
|
||||||
uint32_t textureFilteringMode;
|
uint32_t textureFilteringMode;
|
||||||
uint32_t diffuseTex;
|
uint32_t diffuseTex;
|
||||||
uint32_t normalTex;
|
uint32_t normalTex;
|
||||||
uint32_t metallicRoughnessTex;
|
uint32_t metallicTex;
|
||||||
|
uint32_t roughnessTex;
|
||||||
|
uint32_t occlusionTex;
|
||||||
uint32_t emissiveTex;
|
uint32_t emissiveTex;
|
||||||
uint32_t _pad0, _pad1, _pad2; // explicit to 64 bytes
|
uint32_t _pad0;
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(MaterialData) == 80);
|
||||||
|
|
||||||
enum class TextureFilteringMode : std::uint32_t {
|
enum class TextureFilteringMode : std::uint32_t {
|
||||||
Nearest,
|
Nearest,
|
||||||
@@ -23,6 +29,9 @@ enum class TextureFilteringMode : std::uint32_t {
|
|||||||
Anisotropic,
|
Anisotropic,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Metallic / roughness workflow, matching glTF:
|
||||||
|
// metallic is read from the blue channel, roughness from green and occlusion from red,
|
||||||
|
// so a packed (occlusion)metallicRoughness texture can be used for all three slots.
|
||||||
struct Material {
|
struct Material {
|
||||||
[[nodiscard]] static Material SimpleColor(
|
[[nodiscard]] static Material SimpleColor(
|
||||||
glm::vec3 color,
|
glm::vec3 color,
|
||||||
@@ -32,22 +41,32 @@ struct Material {
|
|||||||
material.baseColor = color;
|
material.baseColor = color;
|
||||||
material.metallicFactor = 0.0f;
|
material.metallicFactor = 0.0f;
|
||||||
material.roughnessFactor = 1.0f;
|
material.roughnessFactor = 1.0f;
|
||||||
material.emissiveFactor = 0.0f;
|
|
||||||
material.name = std::move(materialName);
|
material.name = std::move(materialName);
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool UsesTexture(ImageID id) const
|
||||||
|
{
|
||||||
|
return id != NULL_IMAGE_ID &&
|
||||||
|
(diffuseTexture == id || normalTexture == id || metallicTexture == id ||
|
||||||
|
roughnessTexture == id || occlusionTexture == id || emissiveTexture == id);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 baseColor{1.f, 1.f, 1.f};
|
glm::vec3 baseColor{1.f, 1.f, 1.f};
|
||||||
float metallicFactor{0.f};
|
float metallicFactor{0.f};
|
||||||
float roughnessFactor{0.7f};
|
float roughnessFactor{0.7f};
|
||||||
float emissiveFactor{0.f};
|
glm::vec3 emissiveColor{0.f};
|
||||||
|
float normalScale{1.f};
|
||||||
|
float occlusionStrength{1.f};
|
||||||
|
|
||||||
TextureFilteringMode textureFilteringMode{TextureFilteringMode::Linear};
|
TextureFilteringMode textureFilteringMode{TextureFilteringMode::Linear};
|
||||||
|
|
||||||
ImageID diffuseTexture{NULL_IMAGE_ID};
|
ImageID diffuseTexture{NULL_IMAGE_ID};
|
||||||
// ImageId normalMapTexture{NULL_IMAGE_ID};
|
ImageID normalTexture{NULL_IMAGE_ID};
|
||||||
// ImageId metallicRoughnessTexture{NULL_IMAGE_ID};
|
ImageID metallicTexture{NULL_IMAGE_ID};
|
||||||
// ImageId emissiveTexture{NULL_IMAGE_ID};
|
ImageID roughnessTexture{NULL_IMAGE_ID};
|
||||||
|
ImageID occlusionTexture{NULL_IMAGE_ID};
|
||||||
|
ImageID emissiveTexture{NULL_IMAGE_ID};
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
AssetReference assetReference;
|
AssetReference assetReference;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace ModelDoc { struct MaterialInfo; }
|
||||||
|
|
||||||
class GfxDevice;
|
class GfxDevice;
|
||||||
|
|
||||||
class RenderResources {
|
class RenderResources {
|
||||||
@@ -40,7 +42,7 @@ public:
|
|||||||
GfxDevice& gfxDevice,
|
GfxDevice& gfxDevice,
|
||||||
const std::filesystem::path& path,
|
const std::filesystem::path& path,
|
||||||
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
|
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
bool mipMap = false,
|
bool mipMap = true,
|
||||||
TextureIntent intent = TextureIntent::ColorSrgb);
|
TextureIntent intent = TextureIntent::ColorSrgb);
|
||||||
|
|
||||||
ImageID addImageToCache(GPUImage image);
|
ImageID addImageToCache(GPUImage image);
|
||||||
@@ -49,6 +51,9 @@ public:
|
|||||||
// References are keyed as "source#subresource" in the resource caches.
|
// References are keyed as "source#subresource" in the resource caches.
|
||||||
void loadModelAsset(GfxDevice& gfxDevice, std::string_view sourceReference);
|
void loadModelAsset(GfxDevice& gfxDevice, std::string_view sourceReference);
|
||||||
|
|
||||||
|
// Creates a PBR material from an imported model material, loading its texture maps.
|
||||||
|
MaterialID addModelMaterial(GfxDevice& gfxDevice, const ModelDoc::MaterialInfo& sourceMaterial);
|
||||||
|
|
||||||
[[nodiscard]] const GPUImage& getImage(ImageID id) const;
|
[[nodiscard]] const GPUImage& getImage(ImageID id) const;
|
||||||
|
|
||||||
[[nodiscard]] ImageID getWhiteTextureID() const { return whiteImageId; }
|
[[nodiscard]] ImageID getWhiteTextureID() const { return whiteImageId; }
|
||||||
|
|||||||
@@ -369,6 +369,9 @@ static MaterialInfo LoadMaterialInfo(const aiScene* scene,
|
|||||||
TextureSemantic::Roughness, out.textures);
|
TextureSemantic::Roughness, out.textures);
|
||||||
AddMaterialTextureSlots(scene, material, modelDir, aiTextureType_AMBIENT_OCCLUSION,
|
AddMaterialTextureSlots(scene, material, modelDir, aiTextureType_AMBIENT_OCCLUSION,
|
||||||
TextureSemantic::AmbientOcclusion, out.textures);
|
TextureSemantic::AmbientOcclusion, out.textures);
|
||||||
|
// glTF occlusion maps are imported as lightmaps
|
||||||
|
AddMaterialTextureSlots(scene, material, modelDir, aiTextureType_LIGHTMAP,
|
||||||
|
TextureSemantic::AmbientOcclusion, out.textures);
|
||||||
AddMaterialTextureSlots(scene, material, modelDir, aiTextureType_EMISSION_COLOR,
|
AddMaterialTextureSlots(scene, material, modelDir, aiTextureType_EMISSION_COLOR,
|
||||||
TextureSemantic::Emissive, out.textures);
|
TextureSemantic::Emissive, out.textures);
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,8 @@ void BindlessSetManager::initDefaultSamplers(VkDevice device, float maxAnisotrop
|
|||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||||
.magFilter = VK_FILTER_NEAREST,
|
.magFilter = VK_FILTER_NEAREST,
|
||||||
.minFilter = VK_FILTER_NEAREST,
|
.minFilter = VK_FILTER_NEAREST,
|
||||||
|
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
|
||||||
|
.maxLod = VK_LOD_CLAMP_NONE,
|
||||||
};
|
};
|
||||||
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo, nullptr, &nearestSampler));
|
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo, nullptr, &nearestSampler));
|
||||||
vkutil::addDebugLabel(device, nearestSampler, "nearest");
|
vkutil::addDebugLabel(device, nearestSampler, "nearest");
|
||||||
@@ -159,6 +161,7 @@ void BindlessSetManager::initDefaultSamplers(VkDevice device, float maxAnisotrop
|
|||||||
.magFilter = VK_FILTER_LINEAR,
|
.magFilter = VK_FILTER_LINEAR,
|
||||||
.minFilter = VK_FILTER_LINEAR,
|
.minFilter = VK_FILTER_LINEAR,
|
||||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||||
|
.maxLod = VK_LOD_CLAMP_NONE,
|
||||||
};
|
};
|
||||||
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo, nullptr, &linearSampler));
|
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo, nullptr, &linearSampler));
|
||||||
vkutil::addDebugLabel(device, linearSampler, "linear");
|
vkutil::addDebugLabel(device, linearSampler, "linear");
|
||||||
@@ -173,6 +176,7 @@ void BindlessSetManager::initDefaultSamplers(VkDevice device, float maxAnisotrop
|
|||||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||||
.anisotropyEnable = VK_TRUE,
|
.anisotropyEnable = VK_TRUE,
|
||||||
.maxAnisotropy = maxAnisotropy,
|
.maxAnisotropy = maxAnisotropy,
|
||||||
|
.maxLod = VK_LOD_CLAMP_NONE,
|
||||||
};
|
};
|
||||||
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo, nullptr, &anisotropicSampler));
|
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo, nullptr, &anisotropicSampler));
|
||||||
vkutil::addDebugLabel(device, anisotropicSampler, "anisotropic");
|
vkutil::addDebugLabel(device, anisotropicSampler, "anisotropic");
|
||||||
|
|||||||
@@ -57,11 +57,6 @@ MaterialID MaterialCache::addMaterial(Material material)
|
|||||||
device->waitIdle();
|
device->waitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto getTextureOrElse = [](ImageID imageId, ImageID placeholder)
|
|
||||||
{
|
|
||||||
return imageId != NULL_IMAGE_ID ? imageId : placeholder;
|
|
||||||
};
|
|
||||||
|
|
||||||
MaterialData* data = static_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
MaterialData* data = static_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
||||||
|
|
||||||
const auto id = getFreeMaterialId();
|
const auto id = getFreeMaterialId();
|
||||||
@@ -72,28 +67,7 @@ MaterialID MaterialCache::addMaterial(Material material)
|
|||||||
throw std::runtime_error("MaterialCache material buffer is not mapped");
|
throw std::runtime_error("MaterialCache material buffer is not mapped");
|
||||||
}
|
}
|
||||||
|
|
||||||
data[id] = MaterialData{
|
data[id] = toMaterialData(material);
|
||||||
.baseColor = glm::vec4(material.baseColor, 1.0f),
|
|
||||||
|
|
||||||
.metalRoughnessEmissive = glm::vec4{
|
|
||||||
material.metallicFactor,
|
|
||||||
material.roughnessFactor,
|
|
||||||
material.emissiveFactor,
|
|
||||||
0.f
|
|
||||||
},
|
|
||||||
|
|
||||||
.textureFilteringMode = static_cast<std::uint32_t>(material.textureFilteringMode),
|
|
||||||
|
|
||||||
.diffuseTex = getTextureOrElse(
|
|
||||||
material.diffuseTexture,
|
|
||||||
defaultTextures.white),
|
|
||||||
|
|
||||||
.normalTex = defaultTextures.normal,
|
|
||||||
|
|
||||||
.metallicRoughnessTex = defaultTextures.metallicRoughness,
|
|
||||||
|
|
||||||
.emissiveTex = defaultTextures.emissive,
|
|
||||||
};
|
|
||||||
device->getMemoryManager().flushAllocation(
|
device->getMemoryManager().flushAllocation(
|
||||||
materialDataBuffer,
|
materialDataBuffer,
|
||||||
static_cast<VkDeviceSize>(id) * sizeof(MaterialData),
|
static_cast<VkDeviceSize>(id) * sizeof(MaterialData),
|
||||||
@@ -190,6 +164,35 @@ std::optional<MaterialID> MaterialCache::findMaterialByName(
|
|||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaterialData MaterialCache::toMaterialData(const Material& material) const
|
||||||
|
{
|
||||||
|
const auto getTextureOrElse = [](ImageID imageId, ImageID placeholder)
|
||||||
|
{
|
||||||
|
return imageId != NULL_IMAGE_ID ? imageId : placeholder;
|
||||||
|
};
|
||||||
|
|
||||||
|
return MaterialData{
|
||||||
|
.baseColor = glm::vec4(material.baseColor, 1.0f),
|
||||||
|
.emissiveColor = glm::vec4(material.emissiveColor, 0.0f),
|
||||||
|
|
||||||
|
.metallicRoughnessNormalOcclusion = glm::vec4{
|
||||||
|
material.metallicFactor,
|
||||||
|
material.roughnessFactor,
|
||||||
|
material.normalScale,
|
||||||
|
material.occlusionStrength
|
||||||
|
},
|
||||||
|
|
||||||
|
.textureFilteringMode = static_cast<std::uint32_t>(material.textureFilteringMode),
|
||||||
|
.diffuseTex = getTextureOrElse(material.diffuseTexture, defaultTextures.white),
|
||||||
|
.normalTex = getTextureOrElse(material.normalTexture, defaultTextures.normal),
|
||||||
|
.metallicTex = getTextureOrElse(material.metallicTexture, defaultTextures.metallicRoughness),
|
||||||
|
.roughnessTex = getTextureOrElse(material.roughnessTexture, defaultTextures.metallicRoughness),
|
||||||
|
.occlusionTex = getTextureOrElse(material.occlusionTexture, defaultTextures.white),
|
||||||
|
.emissiveTex = getTextureOrElse(material.emissiveTexture, defaultTextures.emissive),
|
||||||
|
._pad0 = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
MaterialID MaterialCache::getFreeMaterialId() const
|
MaterialID MaterialCache::getFreeMaterialId() const
|
||||||
{
|
{
|
||||||
return static_cast<MaterialID>(materials.size());
|
return static_cast<MaterialID>(materials.size());
|
||||||
@@ -212,32 +215,10 @@ void MaterialCache::updateMaterialGPU(MaterialID id)
|
|||||||
assert(id < materials.size());
|
assert(id < materials.size());
|
||||||
assert(materialDataBuffer.info.pMappedData && "materialDataBuffer must be mapped");
|
assert(materialDataBuffer.info.pMappedData && "materialDataBuffer must be mapped");
|
||||||
|
|
||||||
const auto getTextureOrElse = [](ImageID imageId, ImageID placeholder)
|
|
||||||
{
|
|
||||||
return imageId != NULL_IMAGE_ID ? imageId : placeholder;
|
|
||||||
};
|
|
||||||
|
|
||||||
Material& material = materials[id];
|
|
||||||
|
|
||||||
MaterialData* data =
|
MaterialData* data =
|
||||||
reinterpret_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
reinterpret_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
||||||
|
|
||||||
data[id] = MaterialData{
|
data[id] = toMaterialData(materials[id]);
|
||||||
.baseColor = glm::vec4(material.baseColor, 1.0f),
|
|
||||||
|
|
||||||
.metalRoughnessEmissive = glm::vec4{
|
|
||||||
material.metallicFactor,
|
|
||||||
material.roughnessFactor,
|
|
||||||
material.emissiveFactor,
|
|
||||||
0.f
|
|
||||||
},
|
|
||||||
|
|
||||||
.textureFilteringMode = static_cast<std::uint32_t>(material.textureFilteringMode),
|
|
||||||
.diffuseTex = getTextureOrElse(material.diffuseTexture, defaultTextures.white),
|
|
||||||
.normalTex = defaultTextures.normal,
|
|
||||||
.metallicRoughnessTex = defaultTextures.metallicRoughness,
|
|
||||||
.emissiveTex = defaultTextures.emissive,
|
|
||||||
};
|
|
||||||
device->getMemoryManager().flushAllocation(
|
device->getMemoryManager().flushAllocation(
|
||||||
materialDataBuffer,
|
materialDataBuffer,
|
||||||
static_cast<VkDeviceSize>(id) * sizeof(MaterialData),
|
static_cast<VkDeviceSize>(id) * sizeof(MaterialData),
|
||||||
|
|||||||
@@ -148,10 +148,11 @@ std::optional<GPUImage> ImageManager::loadImageFromFile(
|
|||||||
VK_FORMAT_FEATURE_BLIT_DST_BIT |
|
VK_FORMAT_FEATURE_BLIT_DST_BIT |
|
||||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
|
||||||
if ((formatProperties.optimalTilingFeatures & requiredFeatures) != requiredFeatures) {
|
if ((formatProperties.optimalTilingFeatures & requiredFeatures) != requiredFeatures) {
|
||||||
spdlog::error(
|
spdlog::warn(
|
||||||
"Format {} does not support linear mip generation",
|
"Format {} does not support linear mip generation, loading '{}' without mips",
|
||||||
static_cast<int>(data.vkFormat));
|
static_cast<int>(data.vkFormat),
|
||||||
return std::nullopt;
|
path.string());
|
||||||
|
mipMap = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,18 +9,18 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <initializer_list>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const ModelDoc::TextureInfo* FindDiffuseTexture(
|
// Returns the first loadable texture, trying the semantics in order
|
||||||
const ModelDoc::MaterialInfo& material)
|
const ModelDoc::TextureInfo* FindTexture(
|
||||||
|
const ModelDoc::MaterialInfo& material,
|
||||||
|
std::initializer_list<ModelDoc::TextureSemantic> semantics)
|
||||||
{
|
{
|
||||||
for (const auto semantic : std::array{
|
for (const auto semantic : semantics) {
|
||||||
ModelDoc::TextureSemantic::BaseColor,
|
|
||||||
ModelDoc::TextureSemantic::Diffuse,
|
|
||||||
}) {
|
|
||||||
for (const auto& texture : material.textures) {
|
for (const auto& texture : material.textures) {
|
||||||
if (texture.semantic == semantic) {
|
if (texture.semantic == semantic && !texture.embedded && !texture.path.empty()) {
|
||||||
return &texture;
|
return &texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,32 +230,56 @@ void RenderResources::loadModelAsset(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Material material = Material::SimpleColor(
|
addModelMaterial(gfxDevice, sourceMaterial);
|
||||||
glm::vec3{sourceMaterial.baseColor},
|
|
||||||
sourceMaterial.name);
|
|
||||||
material.assetReference = sourceMaterial.assetReference;
|
|
||||||
material.metallicFactor = sourceMaterial.metallicFactor;
|
|
||||||
material.roughnessFactor = sourceMaterial.roughnessFactor;
|
|
||||||
material.emissiveFactor = std::max({
|
|
||||||
sourceMaterial.emissiveColor.x,
|
|
||||||
sourceMaterial.emissiveColor.y,
|
|
||||||
sourceMaterial.emissiveColor.z,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (const auto* texture = FindDiffuseTexture(sourceMaterial);
|
|
||||||
texture != nullptr && !texture->embedded && !texture->path.empty()) {
|
|
||||||
material.diffuseTexture = loadImageFromFile(
|
|
||||||
gfxDevice,
|
|
||||||
std::filesystem::path{texture->path},
|
|
||||||
VK_IMAGE_USAGE_SAMPLED_BIT,
|
|
||||||
false,
|
|
||||||
TextureIntent::ColorSrgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
materials().addMaterial(std::move(material));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaterialID RenderResources::addModelMaterial(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
const ModelDoc::MaterialInfo& sourceMaterial)
|
||||||
|
{
|
||||||
|
using Semantic = ModelDoc::TextureSemantic;
|
||||||
|
|
||||||
|
const auto loadTexture = [&](std::initializer_list<Semantic> semantics, TextureIntent intent)
|
||||||
|
{
|
||||||
|
const auto* texture = FindTexture(sourceMaterial, semantics);
|
||||||
|
if (texture == nullptr) {
|
||||||
|
return NULL_IMAGE_ID;
|
||||||
|
}
|
||||||
|
return loadImageFromFile(
|
||||||
|
gfxDevice,
|
||||||
|
std::filesystem::path{texture->path},
|
||||||
|
VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
|
true,
|
||||||
|
intent);
|
||||||
|
};
|
||||||
|
|
||||||
|
Material material = Material::SimpleColor(
|
||||||
|
glm::vec3{sourceMaterial.baseColor},
|
||||||
|
sourceMaterial.name);
|
||||||
|
material.assetReference = sourceMaterial.assetReference;
|
||||||
|
material.metallicFactor = sourceMaterial.metallicFactor;
|
||||||
|
material.roughnessFactor = sourceMaterial.roughnessFactor;
|
||||||
|
material.emissiveColor = sourceMaterial.emissiveColor;
|
||||||
|
|
||||||
|
material.diffuseTexture = loadTexture({Semantic::BaseColor, Semantic::Diffuse}, TextureIntent::ColorSrgb);
|
||||||
|
material.normalTexture = loadTexture({Semantic::Normal}, TextureIntent::DataLinear);
|
||||||
|
material.metallicTexture = loadTexture({Semantic::MetallicRoughness, Semantic::Metallic}, TextureIntent::DataLinear);
|
||||||
|
material.roughnessTexture = loadTexture({Semantic::MetallicRoughness, Semantic::Roughness}, TextureIntent::DataLinear);
|
||||||
|
material.occlusionTexture = loadTexture({Semantic::AmbientOcclusion}, TextureIntent::DataLinear);
|
||||||
|
material.emissiveTexture = loadTexture({Semantic::Emissive}, TextureIntent::ColorSrgb);
|
||||||
|
|
||||||
|
// Formats without PBR factors (FBX, OBJ) leave them at 0, which would hide the map completely
|
||||||
|
if (material.metallicTexture != NULL_IMAGE_ID && material.metallicFactor == 0.0f) {
|
||||||
|
material.metallicFactor = 1.0f;
|
||||||
|
}
|
||||||
|
if (material.emissiveTexture != NULL_IMAGE_ID && material.emissiveColor == glm::vec3{0.0f}) {
|
||||||
|
material.emissiveColor = glm::vec3{1.0f};
|
||||||
|
}
|
||||||
|
|
||||||
|
return materials().addMaterial(std::move(material));
|
||||||
|
}
|
||||||
|
|
||||||
BindlessSetManager& RenderResources::getBindlessSetManager() {
|
BindlessSetManager& RenderResources::getBindlessSetManager() {
|
||||||
return imageCache->bindlessSetManager;
|
return imageCache->bindlessSetManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ void ResourcesInspector::drawImageDetails(ImageID id, const RenderResources& res
|
|||||||
std::vector<std::size_t> users;
|
std::vector<std::size_t> users;
|
||||||
for (std::size_t materialId = 0; materialId < materials.materials.size(); ++materialId)
|
for (std::size_t materialId = 0; materialId < materials.materials.size(); ++materialId)
|
||||||
{
|
{
|
||||||
if (materials.materials[materialId].diffuseTexture == id)
|
if (materials.materials[materialId].UsesTexture(id))
|
||||||
{
|
{
|
||||||
users.push_back(materialId);
|
users.push_back(materialId);
|
||||||
}
|
}
|
||||||
@@ -232,7 +232,7 @@ void ResourcesInspector::drawImageDetails(ImageID id, const RenderResources& res
|
|||||||
if (!users.empty())
|
if (!users.empty())
|
||||||
{
|
{
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("Diffuse texture of %zu material(s):", users.size());
|
ImGui::Text("Used by %zu material(s):", users.size());
|
||||||
|
|
||||||
constexpr std::size_t maxListed = 8;
|
constexpr std::size_t maxListed = 8;
|
||||||
for (std::size_t i = 0; i < std::min(users.size(), maxListed); ++i)
|
for (std::size_t i = 0; i < std::min(users.size(), maxListed); ++i)
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
[Window][Debug##Default]
|
||||||
|
Pos=60,60
|
||||||
|
Size=400,400
|
||||||
|
Collapsed=0
|
||||||
|
LastUsed=20261013
|
||||||
|
|
||||||
|
[Window][Test]
|
||||||
|
Pos=60,60
|
||||||
|
Size=94,54
|
||||||
|
Collapsed=0
|
||||||
|
LastUsed=20261013
|
||||||
|
|
||||||
|
[Window][Debug]
|
||||||
|
Pos=60,60
|
||||||
|
Size=107,48
|
||||||
|
Collapsed=0
|
||||||
|
LastUsed=20261013
|
||||||
|
|
||||||
|
[Window][Physics]
|
||||||
|
Pos=60,60
|
||||||
|
Size=215,201
|
||||||
|
Collapsed=0
|
||||||
|
LastUsed=20261013
|
||||||
|
|
||||||
|
[Window][Inspector]
|
||||||
|
Pos=669,99
|
||||||
|
Size=640,520
|
||||||
|
Collapsed=0
|
||||||
|
LastUsed=20261013
|
||||||
|
|
||||||
@@ -142,6 +142,33 @@ void LightKeeper::customInit()
|
|||||||
floorRb->SetType(RigidbodyType::Static);
|
floorRb->SetType(RigidbodyType::Static);
|
||||||
scene.GetPhysics().RegisterGameObject(*planeObj);
|
scene.GetPhysics().RegisterGameObject(*planeObj);
|
||||||
|
|
||||||
|
const auto helmetObj = scene.CreateGameObject("FlightHelmet");
|
||||||
|
helmetObj->GetTransform().SetWorldPosition(glm::vec3(2.f, -1.f, 0.f));
|
||||||
|
helmetObj->GetTransform().SetWorldScale(glm::vec3(2.f));
|
||||||
|
|
||||||
|
const auto helmetModel = AssetManager::GetInstance().LoadModel(
|
||||||
|
"engine://flight-helmet/FlightHelmet.gltf",
|
||||||
|
staticModelOptions);
|
||||||
|
ModelDocUtils::LogModelDocSummary(helmetModel, "FlightHelmet.gltf");
|
||||||
|
|
||||||
|
std::vector<MaterialID> helmetMaterialIDs;
|
||||||
|
for (const auto& material : helmetModel.materials)
|
||||||
|
{
|
||||||
|
helmetMaterialIDs.push_back(resources.addModelMaterial(gfxDevice, material));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& primitive : helmetModel.primitives)
|
||||||
|
{
|
||||||
|
const auto partObj = scene.CreateGameObject(primitive.nodeName);
|
||||||
|
partObj->GetTransform().SetParent(&helmetObj->GetTransform(), false);
|
||||||
|
|
||||||
|
const auto partMeshComp = partObj->AddComponent<MeshRendererComponent>();
|
||||||
|
partMeshComp->SetMeshID(resources.meshes().addMesh(gfxDevice, primitive.mesh));
|
||||||
|
partMeshComp->SetMaterialID(primitive.materialIndex < helmetMaterialIDs.size()
|
||||||
|
? helmetMaterialIDs[primitive.materialIndex]
|
||||||
|
: resources.materials().getPlaceholderMaterialId());
|
||||||
|
}
|
||||||
|
|
||||||
const auto CharObj = scene.CreateGameObject("Character");
|
const auto CharObj = scene.CreateGameObject("Character");
|
||||||
capybara = CharObj;
|
capybara = CharObj;
|
||||||
|
|
||||||
@@ -504,6 +531,9 @@ void LightKeeper::customInit()
|
|||||||
const auto texPath = AssetFS::GetInstance().GetFullPath("engine://textures/kobe.png");
|
const auto texPath = AssetFS::GetInstance().GetFullPath("engine://textures/kobe.png");
|
||||||
texID = resources.loadImageFromFile(gfxDevice, texPath);
|
texID = resources.loadImageFromFile(gfxDevice, texPath);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightKeeper::customUpdate(float dt)
|
void LightKeeper::customUpdate(float dt)
|
||||||
|
|||||||
@@ -859,7 +859,7 @@ namespace {
|
|||||||
"simple materials must preserve their color");
|
"simple materials must preserve their color");
|
||||||
check(material.metallicFactor == 0.0f &&
|
check(material.metallicFactor == 0.0f &&
|
||||||
material.roughnessFactor == 1.0f &&
|
material.roughnessFactor == 1.0f &&
|
||||||
material.emissiveFactor == 0.0f,
|
material.emissiveColor == glm::vec3{0.0f},
|
||||||
"simple materials must use non-metallic default factors");
|
"simple materials must use non-metallic default factors");
|
||||||
check(material.diffuseTexture == NULL_IMAGE_ID,
|
check(material.diffuseTexture == NULL_IMAGE_ID,
|
||||||
"simple materials must not require a diffuse image");
|
"simple materials must not require a diffuse image");
|
||||||
|
|||||||