无头 chrome 中的 Autodesk forge 查看器,CONTEXT_LOST_WEBGL
Posted
技术标签:
【中文标题】无头 chrome 中的 Autodesk forge 查看器,CONTEXT_LOST_WEBGL【英文标题】:Autodesk forge viewer in headless chrome, CONTEXT_LOST_WEBGL 【发布时间】:2018-10-28 03:12:50 【问题描述】:我正在尝试使用无头 Chrome(Win10 上的 v66,使用 C#)从 Forge Autodesk 查看器中的 3D 模型截取一系列屏幕截图。
我面临的问题是,加载模型后,我将相机设置为第一个位置,截取屏幕截图,然后尝试将相机设置为下一个屏幕截图的下一个位置。一旦我尝试过(稍后在初始加载时设置相机位置),webgl 上下文就会丢失。
我对 WebGL / swiftshaders / 等知之甚少,但令我沮丧的是,当我在加载后直接定位相机时,它确实有效。 (IE,解决方法是为每个摄像头视图生成一个单独的无头会话,但由于几何体的加载需要 20 秒或更长时间,这不是首选)
所以,这个:
viewerApp.myCurrentViewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
function ()
_viewer = viewerApp.myCurrentViewer;
SetPerspective();
SetCamera(cams[0].position, cams[0].target);//no probs here
document.getElementById('MyViewerDiv').classList.add("geometry-loaded");
);
有效(相机已定位),但是当我稍后执行 javascript 函数时(使用 driver.ExecuteScript($"SetCamera(JsonConvert.SerializeObject(target.Value.Position),JsonConvert.SerializeObject(target.Value.Target));");
或页面本身超时,它会输出 WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost
。
当我使用较小的模型时,一切正常。因此,我想我理解原因是内存/处理消耗过多,但是为什么它仍然有效呢?
查看资源监视器,我不相信消耗实际上是有问题的,我的笔记本电脑应该能够(i7HQ7700、gtx1050、16gbRam)我尝试摆弄 Chrome 的一些 GPU 和 GL 标志,但无济于事。我怀疑 GPU 没有被使用(我发现一些帖子实际上可以在 headless 中使用......)另外,forge 查看器输出 GPU mem used,但这可能只是日志消息:
Starting ChromeDriver 2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb) on port 62676
Only local connections are allowed.
[0517/203535.902:ERROR:gpu_process_transport_factory.cc(1007)] Lost UI shared context.
DevTools listening on ws://127.0.0.1:12556/devtools/browser/5b66c120-dc64-4211-a207-ac97152ace9a
---some ssl future warnings---
[0517/203540.524:INFO:CONSOLE(2)] "THREE.WebGLRenderer", source: https://developer.api.autodesk.com/modelderivative/v2/viewers/three.min.js (2)
[0517/203543.074:INFO:CONSOLE(0)] "[.Offscreen-For-WebGL-00000237DECBB270]RENDER WARNING: there is no texture bound to the unit 0", source: http://localhost:8881/Content/Screenshot.html
[0517/203543.074:INFO:CONSOLE(0)] "[.Offscreen-For-WebGL-00000237DECBB270]RENDER WARNING: there is no texture bound to the unit 0", source: http://localhost:8881/Content/Screenshot.html
[0517/203552.280:INFO:CONSOLE(2)] "Total geometry size: 8.434013366699219 MB", source: https://developer.api.autodesk.com/modelderivative/v2/viewers/three.min.js (2)
[0517/203552.281:INFO:CONSOLE(2)] "Number of meshes: 2909", source: https://developer.api.autodesk.com/modelderivative/v2/viewers/three.min.js (2)
[0517/203552.281:INFO:CONSOLE(2)] "Num Meshes on GPU: 2908", source: https://developer.api.autodesk.com/modelderivative/v2/viewers/three.min.js (2)
[0517/203552.281:INFO:CONSOLE(2)] "Net GPU geom memory used: 7494392", source: https://developer.api.autodesk.com/modelderivative/v2/viewers/three.min.js (2)
[0517/203558.143:INFO:CONSOLE(0)] "WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost", source: http://localhost:8881/Content/Screenshot.html
完整地说,在没有--headless
标志的情况下运行相同的程序,工作正常,所以我猜代码本身没问题。
有什么办法可以增加允许的资源之类的吗?
(SetCamera 的代码)
function SetCamera(newPos, newTarget)
nav = nav || viewerApp.myCurrentViewer.navigation;
nav.setPosition(newPos);
nav.setTarget(newTarget);
nav.orientCameraUp();
编辑:测试用例(目前在测试网站上,所以我们会在某个时候删除)
EDIT2:运行以下代码的结果
NodeJS:
try
const URN = '';
const Token = '';
(async () =>
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
console.log('browsing');
await page.goto('https://rogerintelligentcloud.azurewebsites.net/test?urn=' + URN + '&token=' + Token);
//replace autodeskURN and token to point to your model
console.log("waiting");
await page.mainFrame().waitForSelector(
'.geometry-loaded',
timeout: 60000
);
await takescreen(page, 'nodetest1');
await takescreen(page, 'nodetest2');
await takescreen(page, 'nodetest3');
await takescreen(page, 'nodetest4');
await takescreen(page, 'nodetest5');
await takescreen(page, 'nodetest6');
await page.evaluate("Test();");
await takescreen(page, 'nodetest11');
await takescreen(page, 'nodetest12');
await takescreen(page, 'nodetest13');
await takescreen(page, 'nodetest14');
await takescreen(page, 'nodetest15');
await takescreen(page, 'nodetest16');
await browser.close();
)();
catch (e)
console.log(e);
async function takescreen(page, name)
await page.screenshot(
path: 'c:\\temp\\'+name+'.png'
);
【问题讨论】:
似乎没有任何官方的 .NET Chrome 无头 API。据我所知,Node.js 只有 Chrome 无头 API,名为 puppeteer。您是否查看过 here 发布的令人敬畏的 puppeteer 演示? 据我了解,puppeteer 通过“Chrome DevTools 协议”以及 selenium webdriver(我使用)处理 Chrome。我可以用 puppeteer 试试,但你真的认为它会有所作为吗? (WebGL 消息来自 Chrome,而不是驱动程序) 我在使用 puppeteer 时没有看到任何错误,我认为这是我们之间唯一的区别。可以试一试吗? @EasonKang,同样的结果:第一个截图没问题,第二个是空的。我现在没有看到错误消息(使用 puppeteer),但结果完全相同。我知道该函数也被调用,因为在我的测试方法中,我还附加了一个 div 元素,它实际上是打印出来的。然而画布是空的。 @EasonKang,您测试的型号“尺寸”是多少?这与我拥有的模型的输出相比吗? 【参考方案1】:我没有看到任何与WebGL
相关的错误消息出现在您的 sn-p 和rme_advanced_sample_project.rvt
模型中,我唯一能看到的是page.delay is not defined
。这是我从您的代码 sn-p 和 Philippe 的 forge-viewer-headless 演示修改的测试代码。如果我错过了什么,请指出。谢谢~
import puppeteer from 'puppeteer'
import 'babel-polyfill'
import path from 'path'
import os from 'os';
try
const URN = 'YOUR_URN';
const Token = 'YOUR_TOKEN';
(async () =>
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(`https://rogerintelligentcloud.azurewebsites.net/test?urn=$ URN &token=$ Token `);
//replace autodeskURN and token to point to your model
await page.mainFrame().waitForSelector(
'.geometry-loaded',
timeout: 60000
);
await delay(3000);
await page.screenshot(
path: path.join( os.tmpdir(), 'nodetest.png' )
)
await page.evaluate("Test();");
await page.evaluate("Test();");
await page.evaluate("Test();");
await page.evaluate("Test();");
await delay(3000);
const targetTxt = await page.evaluate(() => document.querySelector('body > :last-child').innerText );
console.log( targetTxt );
const targetLen = await page.evaluate(() => document.querySelectorAll('body > div:not(.box)').length );
console.log( targetLen );
await page.screenshot(
path: path.join( os.tmpdir(), 'nodetest2.png' )
)
await browser.close();
)();
function delay(timeout)
return new Promise((resolve) =>
setTimeout(resolve, timeout);
);
catch (e)
console.log(e);
我的测试结果截图:
nodetest.png:
nodetest2.png:
编辑 2:
用您的代码测试,它在我的机器上运行良好。
但是有一个更改可以在我的环境中正确运行您的代码。我修改了你的takescreen
函数定义:
function takescreen(page, name)
return page.screenshot(
path: 'c:\\temp\\'+name+'.png'
);
【讨论】:
感谢您的努力,延迟未定义;您是否还复制了我的 nodejs-script 的最后一部分?对于 WEBGL 错误:浏览器需要一些时间来渲染模型,您可以看到这一点,因为在您的示例中创建的屏幕截图没有完全渲染。因此我添加了延迟功能,让浏览器有时间渲染完整的模型。移动相机时也需要这样做。如果您在浏览器中运行站点并使用 F12 工具 Test(),您会看到屏幕应该是什么样子(第一个应该相对于其他) 感谢您的指出,但在添加delay
函数后,我仍然看不到任何 WebGL 错误消息。
嗯,所以,在您的测试中,您最终得到了 2 个渲染模型的屏幕截图,从不同的角度? (准确地说,我实际上并没有在 puppeteer 中看到 webgl 错误。我最终得到了 1 个好的屏幕截图和 1 个空的)
我在测试中得到了两张不错的快照,是的,它们处于不同的视角,相机在调用您的“Test()”后确实会移动它的位置。
我在上面附上了我的快照~:)以上是关于无头 chrome 中的 Autodesk forge 查看器,CONTEXT_LOST_WEBGL的主要内容,如果未能解决你的问题,请参考以下文章
chrome 无头浏览器中的 PDF url 验证失败 - protractor typescript f\w