当前位置: 首页 > 知识库问答 >
问题:

场景渲染问题分为三个方面。js imgui js项目

卢朝
2023-03-14

我有一个使用Three.jsimgui-js的项目。我正在尝试更新到每个的最新版本,但我遇到了问题(它们最后一次更新是在2020年2月左右)。

要初始化我正在调用的两个库,请执行以下操作:

  await ImGui.default();
  ImGui.CreateContext();
  ImGui_Impl.Init(canvas);
  ImGui.StyleColorsDark();
  
  const clear_color = new ImGui.ImVec4(0.3, 0.3, 0.3, 1.00);
  const renderer = new THREE.WebGLRenderer({ canvas: canvas });
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  renderer.gammaFactor = 2.2;
  renderer.physicallyCorrectLights = true;
  renderer.outputEncoding = THREE.sRGBEncoding;

然后我将一些对象添加到三个场景中:

  const scene = new THREE.Scene();
  
  let floorDim = 1000;
  var grid = new THREE.GridHelper(floorDim, 200, 'orange', 'white');
  grid.name = "grid";
  grid.material.opacity = 1.0;
  grid.material.transparent = true;
  grid.material.color.convertGammaToLinear(2.2);
  grid.position.set(0, 2, 0);
  scene.add(grid);
  
  var subgrid = new THREE.GridHelper(floorDim, 600, 'grey', 'grey');
  subgrid.name = "subgrid";
  subgrid.material.opacity = 1.0;
  subgrid.material.color.convertGammaToLinear(2.2);
  subgrid.material.transparent = true;
  subgrid.position.set(0, 1, 0);
  scene.add(subgrid);
  
  const light = new THREE.DirectionalLight(0xffffff, 0.8);
    light.position.set(0, 100, -50);
    light.lookAt(new THREE.Vector3(0, 0, 0));
    scene.add(light);

    const box_1_mesh = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5), new THREE.MeshLambertMaterial({ color:0x970000 }));
  box_1_mesh.position.set(0, 5, 0);
  scene.add(box_1_mesh);

    const box_2_mesh = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5), new THREE.MeshLambertMaterial({ color:0x333000 }));
  box_2_mesh.position.set(-2, 6, 7);
  scene.add(box_2_mesh);
  
  const camera = new THREE.PerspectiveCamera(50, canvas.width / canvas.height, 2, 10000);
    camera.position.set(0, 10, -25);
  camera.updateProjectionMatrix();
  camera.lookAt(0, 0, 0);
    scene.add(camera);

并调用一个更新循环,如下所示:

  function _loop(time) {
    ImGui_Impl.NewFrame(time);
    ImGui.NewFrame();

    ImGui.SetNextWindowPos(new ImGui.ImVec2(20, 20), ImGui.Cond.FirstUseEver);
    ImGui.SetNextWindowSize(new ImGui.ImVec2(294, 140), ImGui.Cond.FirstUseEver);
    ImGui.Begin("Visblility Toggles:");
    ImGui.Checkbox("box_1 (near)", (value = box_1_mesh.visible) => box_1_mesh.visible = value);
    ImGui.Checkbox("box_2 (distant)", (value = box_2_mesh.visible) => box_2_mesh.visible = value);
    ImGui.Checkbox("grid", (value = grid.visible) => grid.visible = value);
    ImGui.Checkbox("subgrid", (value = subgrid.visible) => subgrid.visible = value);
    
    ImGui.End();
    ImGui.EndFrame();
    ImGui.Render();
    
    renderer.setClearColor(new THREE.Color(clear_color.x, clear_color.y, clear_color.z), clear_color.w);
    renderer.setSize(canvas.width, canvas.height);
    camera.aspect = canvas.width / canvas.height;
    camera.updateProjectionMatrix();
    renderer.render(scene, camera);

    ImGui_Impl.RenderDrawData(ImGui.GetDrawData());
    renderer.state.reset();

    window.requestAnimationFrame(_loop);
  }

更新到这些库的最新版本后,我遇到了场景中的对象没有按预期呈现的问题。

例如,我将2个GridHelpers添加到场景中,但由于某种原因只显示一个。此外,如果在场景中切换不同三个对象的可见性,例如切换其中一个网格的显示关闭/打开,当切换回对象时不会再次显示(有时其他对象会消失)。

出现的另一个问题是,更复杂的网格的材质将具有意外的透明度,但对于我在本例中添加的简单框,该问题似乎没有出现。尽管如此,方框的外观可能会根据ImGui是否执行而改变。调用RenderDrawData。

我发现,如果我注释掉对ImGui_Impl的调用。RenderDrawData(ImGui. GetDrawData()),场景会按预期显示,两个网格助手都显示出来,所以我怀疑现在webGl的两个库用法之间可能会发生一些内部冲突。虽然我肯定有可能设置不正确,或者我错过了一个必需的调用。

为了帮助演示该问题,我创建了一个复制该问题的片段:https://codepen.io/bpeake/pen/KKNNQre.

(async function() {
  await ImGui.default();
  const canvas = document.getElementById("output");
  const devicePixelRatio = window.devicePixelRatio || 1;
  canvas.width = canvas.scrollWidth * devicePixelRatio;
  canvas.height = canvas.scrollHeight * devicePixelRatio;
  window.addEventListener("resize", () => {
    const devicePixelRatio = window.devicePixelRatio || 1;
    canvas.width = canvas.scrollWidth * devicePixelRatio;
    canvas.height = canvas.scrollHeight * devicePixelRatio;
  });

  ImGui.CreateContext();
  ImGui_Impl.Init(canvas);
  ImGui.StyleColorsDark();
  
  const clear_color = new ImGui.ImVec4(0.3, 0.3, 0.3, 1.00);
  const renderer = new THREE.WebGLRenderer({ canvas: canvas });
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  renderer.gammaFactor = 2.2;
  renderer.physicallyCorrectLights = true;
  renderer.outputEncoding = THREE.sRGBEncoding;
  
  const scene = new THREE.Scene();
  
  let floorDim = 1000;
  var grid = new THREE.GridHelper(floorDim, 200, 'orange', 'white');
  grid.name = "grid";
  grid.material.opacity = 1.0;
  grid.material.transparent = true;
  grid.material.color.convertGammaToLinear(2.2);
  grid.position.set(0, 2, 0);
  scene.add(grid);
  
  var subgrid = new THREE.GridHelper(floorDim, 600, 'grey', 'grey');
  subgrid.name = "subgrid";
  subgrid.material.opacity = 1.0;
  subgrid.material.color.convertGammaToLinear(2.2);
  subgrid.material.transparent = true;
  subgrid.position.set(0, 1, 0);
  scene.add(subgrid);
  
  const light = new THREE.DirectionalLight(0xffffff, 0.8);
    light.position.set(0, 100, -50);
    light.lookAt(new THREE.Vector3(0, 0, 0));
    scene.add(light);

    const box_1_mesh = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5), new THREE.MeshLambertMaterial({ color:0x970000 }));
  box_1_mesh.position.set(0, 5, 0);
  scene.add(box_1_mesh);

    const box_2_mesh = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5), new THREE.MeshLambertMaterial({ color:0x333000 }));
  box_2_mesh.position.set(-2, 6, 7);
  scene.add(box_2_mesh);
  
  const camera = new THREE.PerspectiveCamera(50, canvas.width / canvas.height, 2, 10000);
    camera.position.set(0, 10, -25);
  camera.updateProjectionMatrix();
  camera.lookAt(0, 0, 0);
    scene.add(camera);
  
  window.requestAnimationFrame(_loop);
  function _loop(time) {
    ImGui_Impl.NewFrame(time);
    ImGui.NewFrame();

    ImGui.SetNextWindowPos(new ImGui.ImVec2(20, 20), ImGui.Cond.FirstUseEver);
    ImGui.SetNextWindowSize(new ImGui.ImVec2(294, 140), ImGui.Cond.FirstUseEver);
    ImGui.Begin("Visblility Toggles:");
    ImGui.Checkbox("box_1 (near)", (value = box_1_mesh.visible) => box_1_mesh.visible = value);
    ImGui.Checkbox("box_2 (distant)", (value = box_2_mesh.visible) => box_2_mesh.visible = value);
    ImGui.Checkbox("grid", (value = grid.visible) => grid.visible = value);
    ImGui.Checkbox("subgrid", (value = subgrid.visible) => subgrid.visible = value);
    
    ImGui.End();
    ImGui.EndFrame();
    ImGui.Render();
    
    renderer.setClearColor(new THREE.Color(clear_color.x, clear_color.y, clear_color.z), clear_color.w);
    renderer.setSize(canvas.width, canvas.height);
    camera.aspect = canvas.width / canvas.height;
    camera.updateProjectionMatrix();
    renderer.render(scene, camera);

    ImGui_Impl.RenderDrawData(ImGui.GetDrawData());
    renderer.state.reset();

    window.requestAnimationFrame(_loop);
  }

})();
css lang-css prettyprint-override">#output {
  position: absolute;
  top: 0px;
  right: 0px;
  width: 100%;
  height: 100%;
  z-index: 1;
}
<script>
// emu localStorage otherwise ImGUI fails because S.O blocks localStorage
{
  const localStorageStorage = new Map();
  const localStorage = {
    getItem(k) { return localStorageStorage.get(k); },
    setItem(k,v) { return localStorageStorage.set(k, v); },
  };
  Object.defineProperty(window, 'localStorage', {
    get() { return localStorage; }
  });
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r125/three.min.js"></script>
<script src="https://flyover.github.io/imgui-js/dist/imgui.umd.js"></script>
<script src="https://flyover.github.io/imgui-js/dist/imgui_impl.umd.js"></script>
<script src="https://flyover.github.io/nanovg-js/dist/nanovg.umd.js"></script>
<canvas tabindex="0" id="output"></canvas>

我的imgui-jstrie-js的设置有什么问题吗?有什么想法可以让ImGui_Impl。RenderDrawData调用不会影响我的three.js场景的渲染?

共有1个答案

邰伟彦
2023-03-14

问题是imgui js正在破坏属性状态。

您可能需要考虑在覆盖在three.js画布之上的另一个画布中运行imgui-js,每个画布都有自己的WebGL上下文。然后他们不必担心彼此。

快速破解是这个

    const gl = renderer.getContext();
    window.vao = window.vao || gl.createVertexArray();
    const oldVao = gl.getParameter(gl.VERTEX_ARRAY_BINDING);
    gl.bindVertexArray(vao);
    
    ImGui_Impl.RenderDrawData(ImGui.GetDrawData());
    
    gl.bindVertexArray(oldVao);

但是那个黑客只在WebGL2中工作。要完全保存和恢复丢失的状态并不难,但是处理WebGL1和扩展并不难,而WebGL2可能需要50-80行代码

我在这里提交了一个问题和一个PR示例

(async function() {
  await ImGui.default();
  const canvas = document.getElementById("output");
  const devicePixelRatio = window.devicePixelRatio || 1;
  canvas.width = canvas.scrollWidth * devicePixelRatio;
  canvas.height = canvas.scrollHeight * devicePixelRatio;
  window.addEventListener("resize", () => {
    const devicePixelRatio = window.devicePixelRatio || 1;
    canvas.width = canvas.scrollWidth * devicePixelRatio;
    canvas.height = canvas.scrollHeight * devicePixelRatio;
  });

  ImGui.CreateContext();
  ImGui_Impl.Init(canvas);
  ImGui.StyleColorsDark();

  const clear_color = new ImGui.ImVec4(0.3, 0.3, 0.3, 1.00);
  const renderer = new THREE.WebGLRenderer({ canvas: canvas });
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  renderer.gammaFactor = 2.2;
  renderer.physicallyCorrectLights = true;
  renderer.outputEncoding = THREE.sRGBEncoding;
  
  const scene = new THREE.Scene();
  
  let floorDim = 1000;
  var grid = new THREE.GridHelper(floorDim, 200, 'orange', 'white');
  grid.name = "grid";
  grid.material.opacity = 1.0;
  grid.material.transparent = true;
  grid.material.color.convertGammaToLinear(2.2);
  grid.position.set(0, 2, 0);
  scene.add(grid);
  
  var subgrid = new THREE.GridHelper(floorDim, 600, 'grey', 'grey');
  subgrid.name = "subgrid";
  subgrid.material.opacity = 1.0;
  subgrid.material.color.convertGammaToLinear(2.2);
  subgrid.material.transparent = true;
  subgrid.position.set(0, 1, 0);
  scene.add(subgrid);
  
  const light = new THREE.DirectionalLight(0xffffff, 0.8);
    light.position.set(0, 100, -50);
    light.lookAt(new THREE.Vector3(0, 0, 0));
    scene.add(light);

    const box_1_mesh = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5), new THREE.MeshLambertMaterial({ color:0x970000 }));
  box_1_mesh.position.set(0, 5, 0);
  scene.add(box_1_mesh);

    const box_2_mesh = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5), new THREE.MeshLambertMaterial({ color:0x333000 }));
  box_2_mesh.position.set(-2, 6, 7);
  scene.add(box_2_mesh);
  
  const camera = new THREE.PerspectiveCamera(50, canvas.width / canvas.height, 2, 10000);
    camera.position.set(0, 10, -25);
  camera.updateProjectionMatrix();
  camera.lookAt(0, 0, 0);
    scene.add(camera);

  setTimeout(() => {
    grid.visible = false;
  }, 1000);
  setTimeout(() => {
    grid.visible = true;
  }, 2000);
  setTimeout(() => {
    console.log(grid.visible);
  }, 2500);

  window.requestAnimationFrame(_loop);
  function _loop(time) {
    ImGui_Impl.NewFrame(time);
    ImGui.NewFrame();

    ImGui.SetNextWindowPos(new ImGui.ImVec2(20, 20), ImGui.Cond.FirstUseEver);
    ImGui.SetNextWindowSize(new ImGui.ImVec2(294, 140), ImGui.Cond.FirstUseEver);
    ImGui.Begin("Visblility Toggles:");
    ImGui.Checkbox("box_1 (near)", (value = box_1_mesh.visible) => box_1_mesh.visible = value);
    ImGui.Checkbox("box_2 (distant)", (value = box_2_mesh.visible) => box_2_mesh.visible = value);
    ImGui.Checkbox("grid", (value = grid.visible) => grid.visible = value);
    ImGui.Checkbox("subgrid", (value = subgrid.visible) => subgrid.visible = value);
    
    
    ImGui.End();
    ImGui.EndFrame();
    ImGui.Render();

    renderer.setClearColor(new THREE.Color(clear_color.x, clear_color.y, clear_color.z), clear_color.w);
    renderer.setSize(canvas.width, canvas.height);
    camera.aspect = canvas.width / canvas.height;
    camera.updateProjectionMatrix();
    renderer.render(scene, camera);

    const gl = renderer.getContext();
    window.vao = window.vao || gl.createVertexArray();
    const oldVao = gl.getParameter(gl.VERTEX_ARRAY_BINDING);
    gl.bindVertexArray(vao);
    
    ImGui_Impl.RenderDrawData(ImGui.GetDrawData());
    
    gl.bindVertexArray(oldVao);

    renderer.state.reset();

    window.requestAnimationFrame(_loop);
  }

})();
#output {
  position: absolute;
  top: 0px;
  right: 0px;
  width: 100%;
  height: 100%;
  z-index: 1;
}
<script>
// emu localStorage otherwise ImGUI fails because S.O blocks localStorage
{
  const localStorageStorage = new Map();
  const localStorage = {
    getItem(k) { return localStorageStorage.get(k); },
    setItem(k,v) { return localStorageStorage.set(k, v); },
  };
  Object.defineProperty(window, 'localStorage', {
    get() { return localStorage; }
  });
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r125/three.js"></script>
<script src="https://flyover.github.io/imgui-js/dist/imgui.umd.js"></script>
<script src="https://flyover.github.io/imgui-js/dist/imgui_impl.umd.js"></script>
<script src="https://flyover.github.io/nanovg-js/dist/nanovg.umd.js"></script>
<canvas tabindex="0" id="output"></canvas>
 类似资料:
  • 问题内容: 在过去的六个月中,我一直在与Backbone合作。前两个月很混乱,学习并弄清楚我要如何围绕它构建代码。接下来的4个月,该公司推出了适合生产的应用程序。不要误会我的意思,Backbone使我摆脱了以前标准的成千上万行客户端代码的混乱,但是它使我能够在更短的时间内完成更多宏伟的事情,从而带来了一系列全新的问题。对于我在这里提出的所有问题,有一些简单的解决方案,感觉像是骇客或只是 错误 。我

  • 我想在一个扩展场景的类中画一张画布。当我按下场景上的按钮时,这个场景应该显示出来,这个场景是在扩展的类“GUI”中创建的。 为设置图像(我不知道要将ImageView作为子节点添加到哪个节点{类似不起作用}) 试图在画布上画画。(与上面的问题相同。在哪里添加此画布?) 类: 和类: PS:Jeah!我在这个论坛上的第一个问题。你好世界!

  • 我目前正在从事一个项目,该项目涉及将LWJGL游戏场景渲染为视频流而不是窗口。我相信,如果将游戏场景渲染为中间格式(如 ByteBuffer),我就能实现这一目标。我正在尝试扩展LWJGL 演示作为概念证明。 我发现了一个类似的SO问题和一个论坛帖子,但我无法做到这一点。我是OpenGL和LWJGL的初学者,我正在努力寻找关于这方面的可理解文档。 在渲染循环()的开始,调用函数。根据我的理解,它将

  • 我是android studio的新手,安装了一个新版本(1.5.1版)。出于某种原因,我一直收到一条错误消息(每次我使用应用程序主题时),说有渲染问题:缺少样式。我在网上寻找解决方案,但大多数都过时了,或者根本不起作用。 谢谢你的帮助。 清单文件: 构建渐变:

  • 从昨天开始,我已经开始与Android Studio的工作。我的问题是当我做我的布局。我有下一个错误(观看屏幕截图了解更多信息): 渲染问题:此版本的渲染库比您的Android Studio版本更新。请更新Android Studio 如果我检查更新,他会说我已经有了最新版本的Android studio,所以我无法更新。 我也在SDK管理器中安装了一些东西,请看下面的截图。 有人能帮我解决这个问

  • 我添加了一个基于谷歌(https://codelabs.developers.google.com/codelabs/sceneform-intro/index.html?index=../..index#15)Codelabs教程的功能,允许用户拍摄添加到场景中的增强现实对象的照片。代码工作正常,但是,我希望在用户拍摄的照片中隐藏PlaneRenader(当ARCore检测到表面时出现的白点)。