forked from natuka/web.puabadge.com
修改:优化手机端的点云效果
This commit is contained in:
1 parent
5892c47a6b
commit
704f6a30e0
4 files changed
+45
-17
No files matched your search
@@ -313,7 +313,8 @@ function init() {
|
|||||||
onSwitchToSubject: () => {
|
onSwitchToSubject: () => {
|
||||||
const src = props.imageUrl
|
const src = props.imageUrl
|
||||||
const entry = renderer.textures.getSubject(src) || renderer.textures.get(src)
|
const entry = renderer.textures.getSubject(src) || renderer.textures.get(src)
|
||||||
if (entry && entry.subjectCloudBuffer) {
|
// 缓冲无效则不切,避免切到空点云后整页变黑
|
||||||
|
if (entry && entry.subjectCloudBuffer && entry.subjectCloudBuffer.buffer) {
|
||||||
renderer.transitionToCloud({
|
renderer.transitionToCloud({
|
||||||
pointCloudBuffer: entry.subjectCloudBuffer,
|
pointCloudBuffer: entry.subjectCloudBuffer,
|
||||||
aspect: entry.aspect,
|
aspect: entry.aspect,
|
||||||
|
|||||||
@@ -78,8 +78,11 @@ function createStateMachine(hooks) {
|
|||||||
subjectReady = false
|
subjectReady = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let resultReadyAt = 0
|
||||||
|
|
||||||
function setResultPreloadStatus(s) {
|
function setResultPreloadStatus(s) {
|
||||||
resultPreloadStatus = s
|
resultPreloadStatus = s
|
||||||
|
if (s === 'ready' && !resultReadyAt) resultReadyAt = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUniforms() {
|
function getUniforms() {
|
||||||
@@ -104,11 +107,15 @@ function createStateMachine(hooks) {
|
|||||||
|
|
||||||
function tryEnterSubject() {
|
function tryEnterSubject() {
|
||||||
if (subjectEntered || subjectFailed || !subjectReady) return false
|
if (subjectEntered || subjectFailed || !subjectReady) return false
|
||||||
if (phase !== PHASE.IMAGE_COLOR_POINT_CLOUD) return false
|
if (phase !== PHASE.IMAGE_COLOR_POINT_CLOUD && phase !== PHASE.RESULT_PRELOADING) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 等效果图点云采样完成后再进 mask 人物段,避免真机提前切空缓冲黑屏
|
||||||
|
if (resultPreloadStatus !== 'ready') return false
|
||||||
// 原图彩色点云需先完整展示
|
// 原图彩色点云需先完整展示
|
||||||
if (Date.now() - phaseStartedAt < TIMING.IMAGE_COLOR_MS) return false
|
if (Date.now() - phaseStartedAt < TIMING.IMAGE_COLOR_MS && phase === PHASE.IMAGE_COLOR_POINT_CLOUD) {
|
||||||
// 结果已好则优先进结果,跳过人物段
|
return false
|
||||||
if (resultPreloadStatus === 'ready') return false
|
}
|
||||||
subjectEntered = true
|
subjectEntered = true
|
||||||
if (hooks && hooks.onSwitchToSubject) hooks.onSwitchToSubject()
|
if (hooks && hooks.onSwitchToSubject) hooks.onSwitchToSubject()
|
||||||
beginMorph()
|
beginMorph()
|
||||||
@@ -232,16 +239,22 @@ function createStateMachine(hooks) {
|
|||||||
) {
|
) {
|
||||||
// 彩色原图已展示够再标预加载;人物段优先于 RESULT_PRELOADING 文案
|
// 彩色原图已展示够再标预加载;人物段优先于 RESULT_PRELOADING 文案
|
||||||
}
|
}
|
||||||
if (!tryStartResultTransition() && phase === PHASE.IMAGE_COLOR_POINT_CLOUD) {
|
// 效果图点云就绪后再进 mask 人物段;识别失败或超时则直接切效果图点云
|
||||||
tryEnterSubject()
|
if (resultPreloadStatus === 'ready') {
|
||||||
}
|
const entered = tryEnterSubject()
|
||||||
// 人物未就绪且结果仍在加载:原图彩色展示满后再进预加载相位
|
const subjectWaitedOut =
|
||||||
if (
|
|
||||||
!subjectEntered &&
|
|
||||||
!subjectReady &&
|
!subjectReady &&
|
||||||
resultPreloadStatus === 'loading' &&
|
!subjectFailed &&
|
||||||
|
resultReadyAt &&
|
||||||
|
Date.now() - resultReadyAt > 12000
|
||||||
|
if (!entered && (subjectFailed || subjectWaitedOut)) {
|
||||||
|
if (subjectWaitedOut) subjectFailed = true
|
||||||
|
tryStartResultTransition()
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
phase === PHASE.IMAGE_COLOR_POINT_CLOUD &&
|
phase === PHASE.IMAGE_COLOR_POINT_CLOUD &&
|
||||||
Date.now() - phaseStartedAt >= TIMING.IMAGE_COLOR_MS
|
Date.now() - phaseStartedAt >= TIMING.IMAGE_COLOR_MS &&
|
||||||
|
(resultPreloadStatus === 'loading' || resultPreloadStatus === 'idle')
|
||||||
) {
|
) {
|
||||||
enter(PHASE.RESULT_PRELOADING)
|
enter(PHASE.RESULT_PRELOADING)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,16 +201,20 @@ function createRenderer(canvas, cssW, cssH, dpr, scaleCanvas) {
|
|||||||
cloudA = entry.pointCloudBuffer
|
cloudA = entry.pointCloudBuffer
|
||||||
cloudB = entry.pointCloudBuffer
|
cloudB = entry.pointCloudBuffer
|
||||||
contentAspect = entry.aspect || cloudA.aspect || 1
|
contentAspect = entry.aspect || cloudA.aspect || 1
|
||||||
|
// count 是整段缓冲长度。点按从上到下写入,只画 liveCount 会把下半身裁掉
|
||||||
pointCount = cloudA.count || maxPoints
|
pointCount = cloudA.count || maxPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Promote current target to A, set B = new target (particle morph) */
|
/** Promote current target to A, set B = new target (particle morph) */
|
||||||
function transitionToCloud(entry) {
|
function transitionToCloud(entry) {
|
||||||
if (!entry || !entry.pointCloudBuffer) return
|
if (!entry || !entry.pointCloudBuffer || !entry.pointCloudBuffer.buffer) return
|
||||||
cloudA = cloudB
|
cloudA = cloudB
|
||||||
cloudB = entry.pointCloudBuffer
|
cloudB = entry.pointCloudBuffer
|
||||||
contentAspect = entry.aspect || cloudB.aspect || contentAspect
|
contentAspect = entry.aspect || cloudB.aspect || contentAspect
|
||||||
pointCount = Math.max(cloudA.count || 0, cloudB.count || 0, maxPoints)
|
const countA = cloudA.count || 0
|
||||||
|
const countB = cloudB.count || 0
|
||||||
|
// 取两边缓冲容量的较小值,避免越界;不要用有效点数,否则下半身被截掉
|
||||||
|
pointCount = Math.max(1, Math.min(countA || countB, countB || countA))
|
||||||
}
|
}
|
||||||
|
|
||||||
function setResultTexture(entry) {
|
function setResultTexture(entry) {
|
||||||
|
|||||||
@@ -44,7 +44,17 @@ function createTextureManager(gl, canvas, scaleCanvas, viewportW, viewportH) {
|
|||||||
try {
|
try {
|
||||||
const dpr = (typeof window !== 'undefined' && window.devicePixelRatio) || 1
|
const dpr = (typeof window !== 'undefined' && window.devicePixelRatio) || 1
|
||||||
const cores = (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) || 4
|
const cores = (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) || 4
|
||||||
if (dpr >= 2.5 && cores >= 8) {
|
const ua = (typeof navigator !== 'undefined' && navigator.userAgent) || ''
|
||||||
|
const mobile = /Android|iPhone|iPad|iPod|Mobile/i.test(ua)
|
||||||
|
// 真机内存紧,高点数上传容易丢 WebGL 上下文,之后整页黑屏
|
||||||
|
if (mobile) {
|
||||||
|
maxPoints = POINT_CLOUD.LOW
|
||||||
|
sampleSide = POINT_CLOUD.SAMPLE_LOW
|
||||||
|
maxTexSize = VISUAL.LOW_TEX_SIZE
|
||||||
|
maskSide = POINT_CLOUD.MASK_LOW
|
||||||
|
subjectPoints = POINT_CLOUD.SUBJECT_LOW
|
||||||
|
quality = 'low'
|
||||||
|
} else if (dpr >= 2.5 && cores >= 8) {
|
||||||
maxPoints = POINT_CLOUD.HIGH
|
maxPoints = POINT_CLOUD.HIGH
|
||||||
sampleSide = POINT_CLOUD.SAMPLE_HIGH
|
sampleSide = POINT_CLOUD.SAMPLE_HIGH
|
||||||
maxTexSize = VISUAL.MAX_TEX_SIZE
|
maxTexSize = VISUAL.MAX_TEX_SIZE
|
||||||
@@ -475,7 +485,7 @@ function createTextureManager(gl, canvas, scaleCanvas, viewportW, viewportH) {
|
|||||||
const mask = maskProcessor.decodeMaskImage(
|
const mask = maskProcessor.decodeMaskImage(
|
||||||
maskRes.image,
|
maskRes.image,
|
||||||
scaleCtx,
|
scaleCtx,
|
||||||
scaleCanvas,
|
sampleCanvas,
|
||||||
aligned.width,
|
aligned.width,
|
||||||
aligned.height
|
aligned.height
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in new issue
Block a user