@@ -737,7 +737,7 @@ function computePartPbrTable(nodeInfo: Tiled3dModelFeature, zMin: number, zMax:
737737// V1 and V2 tiles pack featureColor and partId in opposite halves of the 32-bit
738738// feature value. In V2, meshopt compression forces values below 2^24, so colors
739739// go in the lower 16 bits and part ids in the next nibble up.
740- function buildMeshFeatureArray ( mesh : Mesh , nodeInfo : Tiled3dModelFeature , colorShift : number , idShift : number , doorLightChanged : boolean ) {
740+ function buildMeshFeatureArray ( mesh : Mesh , nodeInfo : Tiled3dModelFeature , colorShift : number , idShift : number , doorLightChanged : boolean , isLodMesh : boolean ) {
741741 if ( ! mesh . featureData ) return ;
742742 const featureArray = mesh . featureArray = new FeatureVertexArray ( ) ;
743743 featureArray . reserveExact ( mesh . featureData . length ) ;
@@ -764,9 +764,14 @@ function buildMeshFeatureArray(mesh: Mesh, nodeInfo: Tiled3dModelFeature, colorS
764764 g = lerp ( g , t [ o + 1 ] , mixA ) ;
765765 b = lerp ( b , t [ o + 2 ] , mixA ) ;
766766 }
767- r *= a ;
768- g *= a ;
769- b *= a ;
767+ // Only LOD meshes (authored by the newer tiler) encode baked ambient occlusion in the
768+ // vertex color alpha channel. The non-LOD mesh may have any alpha value, even 0, so
769+ // applying the AO factor there would incorrectly darken the color, potentially to black.
770+ if ( isLodMesh ) {
771+ r *= a ;
772+ g *= a ;
773+ b *= a ;
774+ }
770775
771776 const a0 = ( r << 8 ) | g ;
772777 const a1 = ( b << 8 ) | t [ o + 4 ] ;
@@ -799,14 +804,14 @@ function updateNodeFeatureVertices(nodeInfo: Tiled3dModelFeature, doorLightChang
799804
800805 for ( let i = 0 ; i < node . meshes . length ; i ++ ) {
801806 if ( ! ( node . lights && node . lightMeshIndex === i ) ) {
802- buildMeshFeatureArray ( node . meshes [ i ] , nodeInfo , colorShift , idShift , doorLightChanged ) ;
807+ buildMeshFeatureArray ( node . meshes [ i ] , nodeInfo , colorShift , idShift , doorLightChanged , false ) ;
803808 }
804809 }
805810
806811 // LOD meshes share the same feature vertex data but have no lights.
807812 if ( node . lodMeshes ) {
808813 for ( const mesh of node . lodMeshes ) {
809- buildMeshFeatureArray ( mesh , nodeInfo , colorShift , idShift , false ) ;
814+ buildMeshFeatureArray ( mesh , nodeInfo , colorShift , idShift , false , true ) ;
810815 }
811816 }
812817}
0 commit comments