Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

场景内添加threejs后切换页面销毁场景,threejs报错 #2343

Open
zuoyifeng opened this issue Mar 13, 2024 · 6 comments
Open

场景内添加threejs后切换页面销毁场景,threejs报错 #2343

zuoyifeng opened this issue Mar 13, 2024 · 6 comments
Assignees

Comments

@zuoyifeng
Copy link

问题描述

用registerRenderService()添加threejs,加载模型,在路由离开后销毁scene.destroy();但是threejs没有被销毁,并且报错,
THREE.WebGLRenderer: Context Lost.

重现链接

No response

重现步骤

No response

预期行为

不要出现THREE.WebGLRenderer: Context Lost.报错,所暂用的内存也应该清除销毁

平台

  • 操作系统: [macOS, Windows, Linux, React Native ...]
  • 网页浏览器: [Google Chrome, Safari, Firefox]

屏幕截图或视频(可选)

image

补充说明(可选)

No response

@lzxue
Copy link
Contributor

lzxue commented Mar 13, 2024

是不是频繁创建,导致实例太多了

@zuoyifeng
Copy link
Author

zuoyifeng commented Mar 13, 2024

是不是频繁创建,导致实例太多了

没有 我就初始化页面后,切换路由离开就出现了,在切换路由离开加的销毁操作 就会有以上提示
但是肯定要有销毁,这个销毁场景方法scene.destroy();之后不需要再threejs销毁模型之类的吗?
threejs是加载了模型组件的
代码如下:

   scene.registerRenderService(ThreeRender)
     const threeJSLayer = new ThreeLayer({
       enableMultiPassRenderer: false,
       zIndex: -1,
       onAddMeshes: (threeScene, layer) => {
         threeSceneNode = threeScene
         // 当前场景的中心
         const center = scene.getCenter()
         // 环境光照
         threeScene.add(new THREE.AmbientLight(0xffffff))
         const sunlight = new THREE.DirectionalLight(0xffffff, 0.25)
         sunlight.position.set(0, 80000000, 100000000)
         sunlight.matrixWorldNeedsUpdate = true
         threeScene.add(sunlight)

         // 使用 Three.js glTFLoader 加载模型
         const loader = new GLTFLoader()
         loader.load('./engine/models/build.glb', (gltf) => {
           const gltfScene = gltf.scene
           setDouble(gltfScene)
           layer.adjustMeshToMap(gltfScene)
           // 设置模型颜色透明度
           gltfScene.children.forEach((modeEl) => {
             // modeEl.material = shadermaterial;
             modeEl.material.transparent = true
             modeEl.material.opacity = 0.5
             modeEl.translateX(-530)
             modeEl.translateZ(163)
           })
           layer.setMeshScale(gltfScene, 18.95, 24, 10)
           
           gltfScene.rotation.y = THREE.MathUtils.degToRad(180)
           layer.setObjectLngLat(gltfScene, [center.lng + 0.05, center.lat], 0)
           // 向场景中添加模型
           threeScene.add(gltfScene)
           // 重绘图层
           // layer.render();
         })
       }
     }).animate(true)

     scene.addLayer(threeJSLayer)

@zhnny
Copy link
Contributor

zhnny commented Mar 13, 2024

这是我的尝试:

import { Scene } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
import * as THREE from 'three';

const scene = new Scene({
  id: 'map',
  map: new GaodeMap({
    center: [111.4453125, 32.84267363195431],
    pitch: 45,
    rotation: 30,
    zoom: 12,
    mapStyle: 'amap://styles/darkblue',
  })
});

scene.on('loaded', () => {
  scene.registerRenderService(ThreeRender);

  const threeJSLayer = new ThreeLayer({
    enableMultiPassRenderer: false,
    onAddMeshes: (threeScene, layer) => {

      // 当前场景的中心
      const center = scene.getCenter();

      // 环境光照
      threeScene.add(new THREE.AmbientLight(0xffffff, 0.2));
      const sunlight = new THREE.DirectionalLight(0xff0000, 0.8);
      layer.setObjectLngLat(sunlight, [center.lng + 0.3, center.lat + 0.08], 1000);
      sunlight.matrixWorldNeedsUpdate = true;
      threeScene.add(sunlight);

      const directionalLightHelper = new THREE.DirectionalLightHelper( sunlight, 5 );
      threeScene.add( directionalLightHelper );

      const box = createBoxGeometry();
      box.scale.set(1000, 1000, 1000);
      box.rotation.set(0, 90, 0)
      layer.setObjectLngLat(box, [center.lng - 0.05, center.lat], 0);
      threeScene.add(box);

     // ....

      // 测试
      setTimeout(()=>{
        console.log(layer.threeRenderService) // 获取Three.js的渲染器,可以对渲染器进行操作,比如销毁
        console.log(layer.scene) // 获取Three.js的Scene,可以对里面的Object进行操作,比如销毁

        layer.threeRenderService.renderer.dispose() // 关闭Three.js的渲染器(避免出现上下文丢失的问题)

        scene.destroy() // 销毁L7的Scene
      }, 4000);

    }
  }).animate(true);
  scene.addLayer(threeJSLayer);
});

经测试呢,不出现THREE.WebGLRenderer: Context Lost报错,但是有概率会出现regl的Context Lost,供参考

#1772

@zuoyifeng
Copy link
Author

这是我的尝试:

import { Scene } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
import * as THREE from 'three';

const scene = new Scene({
  id: 'map',
  map: new GaodeMap({
    center: [111.4453125, 32.84267363195431],
    pitch: 45,
    rotation: 30,
    zoom: 12,
    mapStyle: 'amap://styles/darkblue',
  })
});

scene.on('loaded', () => {
  scene.registerRenderService(ThreeRender);

  const threeJSLayer = new ThreeLayer({
    enableMultiPassRenderer: false,
    onAddMeshes: (threeScene, layer) => {

      // 当前场景的中心
      const center = scene.getCenter();

      // 环境光照
      threeScene.add(new THREE.AmbientLight(0xffffff, 0.2));
      const sunlight = new THREE.DirectionalLight(0xff0000, 0.8);
      layer.setObjectLngLat(sunlight, [center.lng + 0.3, center.lat + 0.08], 1000);
      sunlight.matrixWorldNeedsUpdate = true;
      threeScene.add(sunlight);

      const directionalLightHelper = new THREE.DirectionalLightHelper( sunlight, 5 );
      threeScene.add( directionalLightHelper );

      const box = createBoxGeometry();
      box.scale.set(1000, 1000, 1000);
      box.rotation.set(0, 90, 0)
      layer.setObjectLngLat(box, [center.lng - 0.05, center.lat], 0);
      threeScene.add(box);

     // ....

      // 测试
      setTimeout(()=>{
        console.log(layer.threeRenderService) // 获取Three.js的渲染器,可以对渲染器进行操作,比如销毁
        console.log(layer.scene) // 获取Three.js的Scene,可以对里面的Object进行操作,比如销毁

        layer.threeRenderService.renderer.dispose() // 关闭Three.js的渲染器(避免出现上下文丢失的问题)

        scene.destroy() // 销毁L7的Scene
      }, 4000);

    }
  }).animate(true);
  scene.addLayer(threeJSLayer);
});

经测试呢,不出现THREE.WebGLRenderer: Context Lost报错,但是有概率会出现regl的Context Lost,供参考

#1772

多谢 确实是的 是不是要考虑解决 @lzxue

@lzxue
Copy link
Contributor

lzxue commented Mar 15, 2024

@zuoyifeng codesanbox 提供个在线demo?

@zuoyifeng
Copy link
Author

@zuoyifeng codesanbox 提供个在线demo?

不会弄😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants