Skip to content

Commit

Permalink
fix flickering
Browse files Browse the repository at this point in the history
  • Loading branch information
bbohlender committed Mar 7, 2025
1 parent 078ecc6 commit 26025f7
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 33 deletions.
20 changes: 7 additions & 13 deletions packages/uikit/src/components/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
setupNode,
} from './utils.js'
import { computedClippingRect } from '../clipping.js'
import { ElementType, WithCameraDistance, computedOrderInfo } from '../order.js'
import { ElementType, WithReversePainterSortStableCache, computedOrderInfo } from '../order.js'
import { Camera, Matrix4, Object3D, Plane, Vector2Tuple, Vector3, WebGLRenderer } from 'three'
import { GlyphGroupManager } from '../text/render/instanced-glyph-group.js'
import { createActivePropertyTransfomers } from '../active.js'
Expand Down Expand Up @@ -112,8 +112,8 @@ export function createRootState<EM extends ThreeEventMap = ThreeEventMap>(
},
)

const ctx: WithCameraDistance & Pick<RootContext, 'requestFrame' | 'requestRender' | 'onFrameSet' | 'pixelSize'> = {
cameraDistance: 0,
const ctx: WithReversePainterSortStableCache &
Pick<RootContext, 'requestFrame' | 'requestRender' | 'onFrameSet' | 'pixelSize'> = {
onFrameSet,
requestRender,
requestFrame,
Expand Down Expand Up @@ -201,16 +201,10 @@ export function setupRoot<EM extends ThreeEventMap = ThreeEventMap>(

setupObjectTransform(state.root, object, state.globalMatrix, abortSignal)

const onCameraDistanceFrame = () => {
state.root.reversePainterSortStableCache = undefined
planeHelper.normal.set(0, 0, 1)
planeHelper.constant = 0
planeHelper.applyMatrix4(object.matrixWorld)
vectorHelper.setFromMatrixPosition(state.getCamera().matrixWorld)
state.root.cameraDistance = planeHelper.distanceToPoint(vectorHelper)
}
state.root.onFrameSet.add(onCameraDistanceFrame)
abortSignal.addEventListener('abort', () => state.root.onFrameSet.delete(onCameraDistanceFrame))
const onFrame = () => void (state.root.reversePainterSortStableCache = undefined)

state.root.onFrameSet.add(onFrame)
abortSignal.addEventListener('abort', () => state.root.onFrameSet.delete(onFrame))

setupInstancedPanel(
state.mergedProperties,
Expand Down
4 changes: 2 additions & 2 deletions packages/uikit/src/context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { signal, Signal } from '@preact/signals-core'
import { Matrix4, Object3D, Vector2Tuple, WebGLRenderer } from 'three'
import { ClippingRect } from './clipping.js'
import { OrderInfo, WithCameraDistance } from './order.js'
import { OrderInfo, WithReversePainterSortStableCache } from './order.js'
import { GlyphGroupManager } from './text/render/instanced-glyph-group.js'
import { PanelGroupManager } from './panel/instanced-panel-group.js'
import { FlexNode } from './flex/index.js'
Expand All @@ -16,7 +16,7 @@ export type ParentContext = Readonly<{
root: RootContext
}>

export type RootContext = WithCameraDistance &
export type RootContext = WithReversePainterSortStableCache &
Readonly<{
requestCalculateLayout: () => void
objectRef: { current?: Object3D | null }
Expand Down
25 changes: 13 additions & 12 deletions packages/uikit/src/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { MergedProperties } from './properties/merged.js'
import { computedInheritableProperty } from './properties/index.js'
import { readReactive } from './utils.js'

export type WithCameraDistance = { cameraDistance: number; reversePainterSortStableCache?: number }
export type WithReversePainterSortStableCache = { reversePainterSortStableCache?: number }

export const cameraDistanceKey = Symbol('camera-distance-key')
export const reversePainterSortStableCacheKey = Symbol('reverse-painter-sort-stable-cache-key')
export const orderInfoKey = Symbol('order-info-key')

export function reversePainterSortStable(a: RenderItem, b: RenderItem) {
Expand All @@ -18,8 +18,12 @@ export function reversePainterSortStable(a: RenderItem, b: RenderItem) {
}
let az = a.z
let bz = b.z
const aDistanceRef = (a.object as any)[cameraDistanceKey] as WithCameraDistance | undefined
const bDistanceRef = (b.object as any)[cameraDistanceKey] as WithCameraDistance | undefined
const aDistanceRef = (a.object as any)[reversePainterSortStableCacheKey] as
| WithReversePainterSortStableCache
| undefined
const bDistanceRef = (b.object as any)[reversePainterSortStableCacheKey] as
| WithReversePainterSortStableCache
| undefined
if (aDistanceRef != null) {
aDistanceRef.reversePainterSortStableCache ??= az
az = aDistanceRef.reversePainterSortStableCache
Expand All @@ -28,14 +32,11 @@ export function reversePainterSortStable(a: RenderItem, b: RenderItem) {
bDistanceRef.reversePainterSortStableCache ??= bz
bz = bDistanceRef.reversePainterSortStableCache
}
if (aDistanceRef == null || bDistanceRef == null) {
//default z comparison
return az !== bz ? bz - az : a.id - b.id
}
if (aDistanceRef === bDistanceRef) {
if (aDistanceRef != null && aDistanceRef === bDistanceRef) {
return compareOrderInfo((a.object as any)[orderInfoKey].value, (b.object as any)[orderInfoKey].value)
}
return bDistanceRef.cameraDistance - aDistanceRef.cameraDistance
//default z comparison
return az !== bz ? bz - az : a.id - b.id
}

//the following order tries to represent the most common element order of the respective element types (e.g. panels are most likely the background element)
Expand Down Expand Up @@ -163,10 +164,10 @@ function shallowEqualRecord(r1: Record<string, any> | undefined, r2: Record<stri

export function setupRenderOrder<T>(
result: T,
rootCameraDistance: WithCameraDistance,
rootCameraDistance: WithReversePainterSortStableCache,
orderInfo: { value: OrderInfo | undefined },
): T {
;(result as any)[cameraDistanceKey] = rootCameraDistance
;(result as any)[reversePainterSortStableCacheKey] = rootCameraDistance
;(result as any)[orderInfoKey] = orderInfo
return result
}
6 changes: 3 additions & 3 deletions packages/uikit/src/panel/instanced-panel-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { MaterialClass, createPanelMaterial } from './panel-material.js'
import { InstancedPanel } from './instanced-panel.js'
import { InstancedPanelMesh } from './instanced-panel-mesh.js'
import { ElementType, OrderInfo, WithCameraDistance, setupRenderOrder } from '../order.js'
import { ElementType, OrderInfo, WithReversePainterSortStableCache, setupRenderOrder } from '../order.js'
import { Signal, computed } from '@preact/signals-core'
import { MergedProperties } from '../properties/merged.js'
import { RootContext } from '../context.js'
Expand Down Expand Up @@ -48,7 +48,7 @@ export class PanelGroupManager {
private map = new Map<MaterialClass, Map<string, InstancedPanelGroup>>()

constructor(
private readonly root: WithCameraDistance &
private readonly root: WithReversePainterSortStableCache &
Pick<RootContext, 'onFrameSet' | 'requestFrame' | 'requestRender' | 'pixelSize'>,
private readonly objectRef: { current?: Object3D | null },
) {}
Expand Down Expand Up @@ -149,7 +149,7 @@ export class InstancedPanelGroup {

constructor(
private readonly object: Object3D,
public readonly root: WithCameraDistance & Pick<RootContext, 'requestFrame' | 'requestRender' | 'pixelSize'>,
public readonly root: WithReversePainterSortStableCache & Pick<RootContext, 'requestFrame' | 'requestRender' | 'pixelSize'>,
private readonly orderInfo: OrderInfo,
private readonly panelGroupProperties: Required<PanelGroupProperties>,
) {
Expand Down
6 changes: 3 additions & 3 deletions packages/uikit/src/text/render/instanced-glyph-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { InstancedGlyph } from './instanced-glyph.js'
import { InstancedGlyphMesh } from './instanced-glyph-mesh.js'
import { InstancedGlyphMaterial } from './instanced-gylph-material.js'
import { Font } from '../font.js'
import { ElementType, OrderInfo, WithCameraDistance, setupRenderOrder } from '../../order.js'
import { ElementType, OrderInfo, WithReversePainterSortStableCache, setupRenderOrder } from '../../order.js'
import { RootContext } from '../../context.js'

export class GlyphGroupManager {
private map = new Map<Font, Map<string, InstancedGlyphGroup>>()
constructor(
private readonly root: WithCameraDistance &
private readonly root: WithReversePainterSortStableCache &
Pick<RootContext, 'requestFrame' | 'requestRender' | 'onFrameSet' | 'pixelSize'>,
private readonly objectRef: { current?: Object3D | null },
) {}
Expand Down Expand Up @@ -78,7 +78,7 @@ export class InstancedGlyphGroup {
constructor(
private objectRef: { current?: Object3D | null },
font: Font,
public readonly root: WithCameraDistance & Pick<RootContext, 'requestFrame' | 'requestRender' | 'pixelSize'>,
public readonly root: WithReversePainterSortStableCache & Pick<RootContext, 'requestFrame' | 'requestRender' | 'pixelSize'>,
private orderInfo: OrderInfo,
depthTest: boolean,
depthWrite: boolean,
Expand Down

0 comments on commit 26025f7

Please sign in to comment.