Skip to content

Commit 5137c75

Browse files
authored
Merge pull request CesiumGS#595 from CesiumGS/add-ignore-khr_materials_unlit-option
Add option to ignore KHR_unlit_material extension in glTF tilesets.
2 parents a92e105 + 008036e commit 5137c75

File tree

7 files changed

+92
-8
lines changed

7 files changed

+92
-8
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Change Log
22

3+
## ? - ?
4+
5+
##### Additions :tada:
6+
7+
- Added option to ignore the `KHR_material_unlit` extension to force default lighting on tilesets.
8+
39
## v1.17.0 - 2025-08-01
410

511
##### Additions :tada:

Editor/Cesium3DTilesetEditor.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class Cesium3DTilesetEditor : Editor
3131
private SerializedProperty _culledScreenSpaceError;
3232

3333
private SerializedProperty _opaqueMaterial;
34+
private SerializedProperty _ignoreKhrMaterialsUnlit;
3435
//private SerializedProperty _useLodTransitions;
3536
//private SerializedProperty _lodTransitionLength;
3637
private SerializedProperty _generateSmoothNormals;
@@ -83,6 +84,7 @@ private void OnEnable()
8384
// this.serializedObject.FindProperty("_lodTransitionLength");
8485
this._generateSmoothNormals =
8586
this.serializedObject.FindProperty("_generateSmoothNormals");
87+
this._ignoreKhrMaterialsUnlit = this.serializedObject.FindProperty("_ignoreKhrMaterialsUnlit");
8688

8789
this._pointCloudShading = this.serializedObject.FindProperty("_pointCloudShading");
8890

@@ -425,6 +427,19 @@ private void DrawRenderProperties()
425427
"normals requires duplicating vertices. This option allows the glTFs to be " +
426428
"rendered with smooth normals instead when the original glTF is missing normals.");
427429
EditorGUILayout.PropertyField(this._generateSmoothNormals, generateSmoothNormalsContent);
430+
431+
var ignoreKhrMaterialsUnlit = new GUIContent(
432+
"Ignore KHR_materials_unlit",
433+
"Whether to ignore the KHR_materials_unlit extension on the glTF tiles in "+
434+
"this tileset, if it exists, and instead render with standard lighting and "+
435+
"shadows. This property will have no effect if the tileset does not have any "+
436+
"tiles that use this extension. "+
437+
"\n\n"+
438+
"The KHR_materials_unlit extension is often applied to photogrammetry "+
439+
"tilesets because lighting and shadows are already baked into their "+
440+
"textures. "
441+
);
442+
EditorGUILayout.PropertyField(this._ignoreKhrMaterialsUnlit, ignoreKhrMaterialsUnlit);
428443
}
429444

430445
private void DrawPointCloudShadingProperties()

Runtime/Cesium3DTileset.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,33 @@ public bool generateSmoothNormals
589589
}
590590
}
591591

592+
[SerializeField]
593+
private bool _ignoreKhrMaterialsUnlit = false;
594+
595+
/// <summary>
596+
/// Whether to ignore the KHR_materials_unlit extension on the glTF tiles in
597+
/// this tileset, if it exists
598+
/// </summary>
599+
/// <remarks>
600+
/// Whether to ignore the KHR_materials_unlit extension on the glTF tiles in
601+
/// this tileset, if it exists, and instead render with standard lighting and
602+
/// shadows. This property will have no effect if the tileset does not have any
603+
/// tiles that use this extension.
604+
///
605+
/// The KHR_materials_unlit extension is often applied to photogrammetry
606+
/// tilesets because lighting and shadows are already baked into their
607+
/// textures.
608+
/// </remarks>
609+
public bool ignoreKhrMaterialsUnlit
610+
{
611+
get => this._ignoreKhrMaterialsUnlit;
612+
set
613+
{
614+
this._ignoreKhrMaterialsUnlit = value;
615+
this.RecreateTileset();
616+
}
617+
}
618+
592619
[SerializeField]
593620
private CesiumPointCloudShading _pointCloudShading;
594621

Runtime/ConfigureReinterop.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ public void ExposeToCPP()
279279
//tileset.useLodTransitions = tileset.useLodTransitions;
280280
//tileset.lodTransitionLength = tileset.lodTransitionLength;
281281
tileset.generateSmoothNormals = tileset.generateSmoothNormals;
282+
tileset.ignoreKhrMaterialsUnlit = tileset.ignoreKhrMaterialsUnlit;
282283
tileset.createPhysicsMeshes = tileset.createPhysicsMeshes;
283284
tileset.suspendUpdate = tileset.suspendUpdate;
284285
tileset.previousSuspendUpdate = tileset.previousSuspendUpdate;
@@ -948,3 +949,4 @@ Cesium3DTilesetLoadFailureDetails tilesetDetails
948949
}
949950
}
950951
}
952+

native~/Runtime/src/Cesium3DTilesetImpl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ void Cesium3DTilesetImpl::DestroyTileset(
566566
void Cesium3DTilesetImpl::LoadTileset(
567567
const DotNet::CesiumForUnity::Cesium3DTileset& tileset) {
568568
TilesetOptions options{};
569+
options.rendererOptions = std::make_any<CreateModelOptions>(tileset);
569570
options.maximumScreenSpaceError = tileset.maximumScreenSpaceError();
570571
options.preloadAncestors = tileset.preloadAncestors();
571572
options.preloadSiblings = tileset.preloadSiblings();

native~/Runtime/src/UnityPrepareRendererResources.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ template <typename TIndex, class TIndexAccessor>
314314
void loadPrimitive(
315315
UnityEngine::MeshData meshData,
316316
CesiumPrimitiveInfo& primitiveInfo,
317+
const CreateModelOptions& options,
317318
const Model& gltf,
318319
const Node& node,
319320
const Mesh& mesh,
@@ -351,7 +352,9 @@ void loadPrimitive(
351352
Model::getSafe(&gltf.materials, primitive.material);
352353

353354
primitiveInfo.isUnlit =
354-
pMaterial && pMaterial->hasExtension<ExtensionKhrMaterialsUnlit>();
355+
options.ignoreKhrMaterialUnlit
356+
? false
357+
: pMaterial && pMaterial->hasExtension<ExtensionKhrMaterialsUnlit>();
355358

356359
bool hasNormals = false;
357360
bool computeFlatNormals = false;
@@ -373,6 +376,7 @@ void loadPrimitive(
373376
loadPrimitive<uint32_t>(
374377
meshData,
375378
primitiveInfo,
379+
options,
376380
gltf,
377381
node,
378382
mesh,
@@ -692,7 +696,8 @@ int32_t countPrimitives(const CesiumGltf::Model& model) {
692696

693697
void populateMeshDataArray(
694698
MeshDataResult& meshDataResult,
695-
TileLoadResult& tileLoadResult) {
699+
TileLoadResult& tileLoadResult,
700+
const CreateModelOptions& options) {
696701
CesiumGltf::Model* pModel =
697702
std::get_if<CesiumGltf::Model>(&tileLoadResult.contentKind);
698703
if (!pModel)
@@ -704,7 +709,7 @@ void populateMeshDataArray(
704709

705710
pModel->forEachPrimitiveInScene(
706711
-1,
707-
[&meshDataResult, &meshDataInstance, pModel](
712+
[&meshDataResult, &meshDataInstance, pModel, &options](
708713
const Model& gltf,
709714
const Node& node,
710715
const Mesh& mesh,
@@ -739,6 +744,7 @@ void populateMeshDataArray(
739744
loadPrimitive<std::uint32_t>(
740745
meshData,
741746
primitiveInfo,
747+
options,
742748
gltf,
743749
node,
744750
mesh,
@@ -751,6 +757,7 @@ void populateMeshDataArray(
751757
loadPrimitive<std::uint16_t>(
752758
meshData,
753759
primitiveInfo,
760+
options,
754761
gltf,
755762
node,
756763
mesh,
@@ -768,6 +775,7 @@ void populateMeshDataArray(
768775
loadPrimitive<std::uint16_t>(
769776
meshData,
770777
primitiveInfo,
778+
options,
771779
gltf,
772780
node,
773781
mesh,
@@ -783,6 +791,7 @@ void populateMeshDataArray(
783791
loadPrimitive<std::uint16_t>(
784792
meshData,
785793
primitiveInfo,
794+
options,
786795
gltf,
787796
node,
788797
mesh,
@@ -798,6 +807,7 @@ void populateMeshDataArray(
798807
loadPrimitive<std::uint16_t>(
799808
meshData,
800809
primitiveInfo,
810+
options,
801811
gltf,
802812
node,
803813
mesh,
@@ -813,6 +823,7 @@ void populateMeshDataArray(
813823
loadPrimitive<std::uint16_t>(
814824
meshData,
815825
primitiveInfo,
826+
options,
816827
gltf,
817828
node,
818829
mesh,
@@ -828,6 +839,7 @@ void populateMeshDataArray(
828839
loadPrimitive<std::uint32_t>(
829840
meshData,
830841
primitiveInfo,
842+
options,
831843
gltf,
832844
node,
833845
mesh,
@@ -881,6 +893,7 @@ UnityPrepareRendererResources::prepareInLoadThread(
881893
TileLoadResult&& tileLoadResult,
882894
const glm::dmat4& transform,
883895
const std::any& rendererOptions) {
896+
884897
CesiumGltf::Model* pModel =
885898
std::get_if<CesiumGltf::Model>(&tileLoadResult.contentKind);
886899
if (!pModel)
@@ -901,15 +914,20 @@ UnityPrepareRendererResources::prepareInLoadThread(
901914
return UnityEngine::Mesh::AllocateWritableMeshData(numberOfPrimitives);
902915
})
903916
.thenInWorkerThread(
904-
[tileLoadResult = std::move(tileLoadResult)](
917+
[tileLoadResult = std::move(tileLoadResult), rendererOptions](
905918
UnityEngine::MeshDataArray&& meshDataArray) mutable {
906919
MeshDataResult meshDataResult{std::move(meshDataArray), {}};
907920
// Free the MeshDataArray if something goes wrong.
908921
ScopeGuard sg([&meshDataResult]() {
909922
meshDataResult.meshDataArray.Dispose();
910923
});
911924

912-
populateMeshDataArray(meshDataResult, tileLoadResult);
925+
const auto* pOptions =
926+
std::any_cast<CreateModelOptions>(&rendererOptions);
927+
if (pOptions)
928+
populateMeshDataArray(meshDataResult, tileLoadResult, *pOptions);
929+
else
930+
populateMeshDataArray(meshDataResult, tileLoadResult, {});
913931

914932
// We're returning the MeshDataArray, so don't free it.
915933
sg.release();
@@ -928,11 +946,10 @@ UnityPrepareRendererResources::prepareInLoadThread(
928946
std::move(workerResult.tileLoadResult),
929947
nullptr});
930948
}
931-
932949
bool shouldCreatePhysicsMeshes = false;
933950
bool shouldShowTilesInHierarchy = false;
934951

935-
DotNet::CesiumForUnity::Cesium3DTileset tilesetComponent =
952+
auto tilesetComponent =
936953
tileset.GetComponent<DotNet::CesiumForUnity::Cesium3DTileset>();
937954
if (tilesetComponent != nullptr) {
938955
shouldCreatePhysicsMeshes =
@@ -1550,7 +1567,6 @@ void* UnityPrepareRendererResources::prepareInMainThread(
15501567
UnityEngine::Object::Instantiate(opaqueMaterial);
15511568
material.hideFlags(UnityEngine::HideFlags::HideAndDontSave);
15521569
meshRenderer.material(material);
1553-
15541570
if (pMaterial) {
15551571
setGltfMaterialParameterValues(
15561572
gltf,

native~/Runtime/src/UnityPrepareRendererResources.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,24 @@
44

55
#include <Cesium3DTilesSelection/IPrepareRendererResources.h>
66

7+
#include <DotNet/CesiumForUnity/Cesium3DTileset.h>
78
#include <DotNet/UnityEngine/GameObject.h>
89

910
namespace CesiumForUnityNative {
1011

12+
struct CreateModelOptions {
13+
/**
14+
* Whether to ignore the KHR_materials_unlit extension in the model. If this
15+
* is true and the extension is present, then flat normals will be generated
16+
* for the model as it loads.
17+
*/
18+
bool ignoreKhrMaterialUnlit = false;
19+
20+
CreateModelOptions() = default;
21+
explicit CreateModelOptions(
22+
const DotNet::CesiumForUnity::Cesium3DTileset& tilesetComponent)
23+
: ignoreKhrMaterialUnlit(tilesetComponent.ignoreKhrMaterialsUnlit()) {}
24+
};
1125
/**
1226
* @brief Information about how a given glTF primitive was converted into
1327
* Unity MeshData.
@@ -28,6 +42,9 @@ struct CesiumPrimitiveInfo {
2842
/**
2943
* @brief Whether or not the primitive material has the KHR_materials_unlit
3044
* extension.
45+
* @remarks This may be overridden if
46+
* DotNet::CesiumForUnity::Cesium3DTileset::ignoreignoreKHRMaterialsUnlit() is
47+
* set.
3148
*/
3249
bool isUnlit = false;
3350

0 commit comments

Comments
 (0)