diff --git a/src/graphics/rendering/fps-autoscaler.ts b/src/graphics/rendering/fps-autoscaler.ts index 528cadf..739ee50 100644 --- a/src/graphics/rendering/fps-autoscaler.ts +++ b/src/graphics/rendering/fps-autoscaler.ts @@ -1,42 +1,105 @@ -import { Autoscaler as AutoScaler } from '../../helper/autoscaler'; +import { clamp } from '../../helper/clamp'; import { exponentialDecay } from '../../helper/exponential-decay'; -import { settings } from '../settings'; +import { mix } from '../../helper/mix'; +import { Insights } from './insights'; -export class FpsAutoscaler extends AutoScaler { +const settings = { + targetDeltaTimeInMilliseconds: 20, + deltaTimeErrorInMilliseconds: 3, + deltaTimeResponsiveness: 1 / 32, + adjusmentRateInMilliseconds: 1000, + targets: [ + { + distanceRenderScale: 0.1, + finalRenderScale: 0.2, + }, + { + distanceRenderScale: 0.1, + finalRenderScale: 0.6, + }, + { + distanceRenderScale: 0.3, + finalRenderScale: 1.0, + }, + { + distanceRenderScale: 1.0, + finalRenderScale: 1.0, + }, + ], + qualityStepIncrease: 0.01, + qualityStepDecrese: 0.2, +}; + +export class FpsAutoscaler { private timeSinceLastAdjusment = 0; - private exponentialDecayedDeltaTime = 0.0; + private exponentialDecayedDeltaTime = settings.targetDeltaTimeInMilliseconds; - constructor(setters: { [key: string]: (value: number | boolean) => void }) { - super( - setters, - settings.qualityScaling.qualityTargets, - settings.qualityScaling.startingTargetIndex, - settings.qualityScaling.scalingOptions - ); + // can have fractions + private index = 3; + + constructor(private setters: { [key: string]: (value: number | boolean) => void }) { + this.applyScaling(); + } + + public increase() { + this.index += settings.qualityStepIncrease; + this.applyScaling(); + } + + public decrease() { + this.index -= settings.qualityStepDecrese; + this.applyScaling(); + } + + private applyScaling() { + this.index = clamp(this.index, 0, settings.targets.length - 1); + + const floor = Math.floor(this.index); + const fract = this.index - floor; + + const previousTarget: any = settings.targets[floor]; + const nextTarget = + floor + 1 == settings.targets.length ? previousTarget : settings.targets[floor + 1]; + + const result: any = {}; + for (const key in this.setters) { + const previous = previousTarget[key]; + const next = nextTarget[key]; + let current: number | boolean; + if (typeof previous == 'number') { + current = mix(previous, next as number, fract); + } else { + current = next; + } + + result[key] = current; + this.setters[key](current); + } + + Insights.setValue('quality', result); } public autoscale(lastDeltaTime: DOMHighResTimeStamp) { - this.timeSinceLastAdjusment += lastDeltaTime; + this.exponentialDecayedDeltaTime = exponentialDecay( + this.exponentialDecayedDeltaTime, + lastDeltaTime, + settings.deltaTimeResponsiveness + ); + Insights.setValue('FPS', 1000 / this.exponentialDecayedDeltaTime); + if ( - this.timeSinceLastAdjusment >= settings.qualityScaling.adjusmentRateInMilliseconds + (this.timeSinceLastAdjusment += lastDeltaTime) >= + settings.adjusmentRateInMilliseconds ) { this.timeSinceLastAdjusment = 0; - this.exponentialDecayedDeltaTime = exponentialDecay( - this.exponentialDecayedDeltaTime, - lastDeltaTime, - settings.qualityScaling.deltaTimeResponsiveness - ); if ( - this.exponentialDecayedDeltaTime <= - settings.qualityScaling.targetDeltaTimeInMilliseconds - - settings.qualityScaling.deltaTimeError + this.exponentialDecayedDeltaTime + settings.deltaTimeErrorInMilliseconds <= + settings.targetDeltaTimeInMilliseconds ) { this.increase(); } else if ( - this.exponentialDecayedDeltaTime > - settings.qualityScaling.targetDeltaTimeInMilliseconds + - settings.qualityScaling.deltaTimeError + this.exponentialDecayedDeltaTime > settings.targetDeltaTimeInMilliseconds ) { this.decrease(); } diff --git a/src/helper/autoscaler.ts b/src/helper/autoscaler.ts deleted file mode 100644 index 85a613a..0000000 --- a/src/helper/autoscaler.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Insights } from '../graphics/rendering/insights'; -import { clamp } from './clamp'; -import { mix } from './mix'; - -export class Autoscaler { - // can have fractions - private index: number; - - constructor( - private setters: { [key: string]: (value: number | boolean) => void }, - private targets: Array<{ [key: string]: number | boolean }>, - startingIndex: number, - private scalingOptions: { - additiveIncrease: number; - multiplicativeDecrease: number; - } - ) { - this.index = startingIndex; - this.applyScaling(); - } - - public increase() { - this.index += this.scalingOptions.additiveIncrease; - this.applyScaling(); - } - - public decrease() { - this.index /= this.scalingOptions.multiplicativeDecrease; - this.applyScaling(); - } - - private applyScaling() { - this.index = clamp(this.index, 0, this.targets.length - 1); - - const floor = Math.floor(this.index); - const fract = this.index - floor; - - const previousTarget = this.targets[floor]; - const nextTarget = - floor + 1 == this.targets.length ? previousTarget : this.targets[floor + 1]; - - const result: any = {}; - for (const key in this.setters) { - const previous = previousTarget[key]; - const next = nextTarget[key]; - let current: number | boolean; - if (typeof previous == 'number') { - current = mix(previous, next as number, fract); - } else { - current = next; - } - - result[key] = current; - - this.setters[key](current); - } - - Insights.setValue('quality', result); - } -}