in packages/core/gsi/src/polaris/utils.ts [25:98]
export function pickResultSorter(a: PickEventResult, b: PickEventResult): number {
const meshA = a.object as RenderableNode
const meshB = b.object as RenderableNode
if (meshA === undefined || meshB === undefined) {
return a.distance - b.distance
}
if (meshA.material !== undefined && meshB.material !== undefined) {
const aTransparent =
meshA.material.alphaMode === 'BLEND' ||
meshA.material.alphaMode === 'BLEND_ADD' ||
meshA.material.alphaMode === 'MASK'
const bTransparent =
meshB.material.alphaMode === 'BLEND' ||
meshB.material.alphaMode === 'BLEND_ADD' ||
meshB.material.alphaMode === 'MASK'
const depthA = meshA.material.extensions?.EXT_matr_advanced?.depthTest
const depthB = meshB.material.extensions?.EXT_matr_advanced?.depthTest
const renderOrderA = meshA.extensions?.EXT_mesh_order?.renderOrder ?? 0
const renderOrderB = meshB.extensions?.EXT_mesh_order?.renderOrder ?? 0
// compare transparent
// transparent object is always rendered after opaque object
if (aTransparent === true && bTransparent === false) {
return -1
} else if (aTransparent === false && bTransparent === true) {
return 1
}
// if both are true, compare renderOrder
else if (aTransparent === true && bTransparent === true) {
return renderOrderB - renderOrderA
}
// both false transparent
// compare depthTest
// if depthTests are true, compare distance
else if (depthA !== undefined && depthB !== undefined) {
if (depthA === depthB) {
// both true
if (depthA === true) {
return a.distance - b.distance
}
// both false, compare transparency, then compare renderOrders
else {
if (aTransparent === true && bTransparent === false) {
return -1
} else if (aTransparent === false && bTransparent === true) {
return 1
} else {
return renderOrderB - renderOrderA
}
}
}
// different depthTest, compare transparency, then compare renderOrders
else {
if (aTransparent === true && bTransparent === false) {
return -1
} else if (aTransparent === false && bTransparent === true) {
return 1
} else {
return renderOrderB - renderOrderA
}
}
}
// compare renderOrder
// lower renderOrder => earlier to render => covered by higher renderOrder
else if (renderOrderA !== renderOrderB) {
return renderOrderB - renderOrderA
}
}
return a.distance - b.distance
}