我想在我的WebGL应用程序中优化重绘.只有当用户修改相机位置或旋转时,才需要重新绘制.其他一切都是静态的.我可以继续用classic 的js游戏循环拨打requestAnimationFrame(),判断相机是否有变化,只有在需要时才会重新绘制.

function animate() {
    requestAnimationFrame(animate);

    if (compare_camera_with_previous_frame()) {
        render();
    }
}

这是有效的,只有当真正需要重新绘制时,GPU才会进行绘制.然而,这仍然将我的Web应用程序标记为动画,每秒调用请求动画帧()60次,除了判断游戏状态的变化外,基本上什么也不做.

另一种 Select 是从animate()循环中移除requestAnimationFrame(animate);,并从touch 事件中调用requestAnimationFrame(animate);.然而,这会导致绘制发生在数百个FPS,因 for each touch 事件都会调用animate().

在使用DesktopGL和SDL2或使用GLFW的C中,我习惯于调用WaitEvents()而不是PollEvents().在启用垂直同步的情况下,这可以完美地解决所有问题.仅当执行输入时才处理逻辑,同时不超过刷新率.我想把这样的行为翻译成Java+WebGL.

我怎么才能解决这个问题?如何在事件发生时只请求绘制帧,而不超过在循环中调用的刷新率设置为requestAnimationFrame();

推荐答案

如果没有要设置动画的内容,请停止运行动画循环:

function animate() {
  // return early if there's nothing to do, halting the animation loop:
  if (!state.stateUpdated) return;

  // soft-lock our state so that values will get written to
  // our "pending state" object instead of the real state, to
  // prevent concurrent modification.
  pendingState = {};

  // then resolve a frame:
  doSomethingThisFrame();

  // and then apply any pending state changes that
  // occurred while we were busy during the frame.
  applyPendingStateChanges();
}

function doSomethingThisFrame() { 
  // ...do all the things...

  // mark the state as handled:
  state.stateUpdated = false;

  // and schedule the next frame:
  requestAnimationFrame(animate);
}

然后,您可以将该标志设置为True,然后调用animate(),作为在输入事件期间更新状态的一部分,这样,只要有需要设置动画的内容,您的代码就会再次开始运行.如果没有,那么早期的返回将使页面再次恢复为静态页面.

当然,您需要确保不会同时更新正在忙于处理帧的状态while,因此需要确保拥有一个既可以充当软锁又可以在实际状态被锁定时写入值的"挂起状态"变量:

const state = { stateUpdated: false };
let pendingState = undefined;

function updateState(name, value) {
  // apply this update either directly, or "for later":
  const target = pendingState ?? state;
  target[name] = value;
  target.stateUpdated = true;
  // and if we applied it directly, call animate.
  if (target === state) animate();
}

function applyPendingStateChanges() {
  if (!pendingState) throw new Error(`apply pending called without pending state`);
  Object.assign(state, pendingState);
  pendingState = undefined;
  if (state.stateUpdated) animate();
}

Javascript相关问答推荐

我可以使用querySelectorAll获取单元格索引吗?

ChartJS:分组堆叠条形图渲染错误

如何将剧作家请求对象转换为字符串,因为它只提供promise ?

创建私有JS出口

为什么使用MAX_SAFE_INTEGER生成随机整数时数字分布不准确?

不渲染具有HTML参数的React元素

react/redux中的formData在expressjs中返回未定义的req.params.id

Angular中计算信号和getter的区别

Angular:动画不启动

MathJax可以导入本地HTML文档使用的JS文件吗?

简单的PayPal按钮集成导致404错误

如何在每次单击按钮时重新加载HighChart/设置HighChart动画?

用JS从平面文件构建树形 struct 的JSON

类构造函数忽略Reaction Native中的可选字段,但在浏览器中按预期工作

查询参数中的JAVASCRIPT/REACT中的括号

使用带有HostBinding的Angular 信号来更新样式?

如何利用CSS中的隐藏元素实现平滑扩展和防止网格行间隙

在表单集中保存更改时删除';禁用';

如何用javascript更改元素的宽度和高度?

处理app.param()中的多个参数