ThreeJS使用HTML画布更新纹理在移动设备(iPhone Safari等)上显示“ WebGL:INVALID_VALUE:texImage2D:无画布”

Log*_*og0 9 html javascript webgl ios three.js

我正在尝试THREE.Texture使用HTML5画布对象更新“ .image”属性。这可以在笔记本电脑上的Chromium(MacOSX)上使用。但是,iPhone Safari和iPhone Chrome均不起作用。根本原因是什么?如何解决?

在Safari中使用Web Inspector时,出现以下错误消息:

WebGL:INVALID_VALUE:texImage2D:无画布。

我使用以下代码更新材质,以确保在更新之前完全绘制了画布:

material.map.image = loaded_canvas[curr_id]; // loaded_canvas stores canvas that has been completed loaded already, drawn by Image() objects.
material.map.needsUpdate = true; 
Run Code Online (Sandbox Code Playgroud)

这是材料的使用方式:

var geometry = new THREE.SphereGeometry(100.0, 32, 32);
var material = new THREE.MeshBasicMaterial({
    map: THREE.ImageUtils.loadTexture(image_path),
    side: THREE.BackSide,
});
Run Code Online (Sandbox Code Playgroud)

奇怪的是,如果我THREE.ImageUtils.loadTexture用来加载图像,它可以正常工作。但是,我的用例是必须使用canvas对象(画布上的多个图像)。

谢谢。

Mar*_*zzo 5

根据Texturedocs, .image 属性更像是通过该TextureLoader.load()方法创建的图像元素的“getter”。如果您想使用元素创建纹理<canvas>,可以new THREE.Texture(canvas);使用下面的代码片段演示的方式创建它。纹理创建发生在makeCanvasTexture()函数中:

\n\n

\r\n
\r\n
function makeCanvasTexture() {\r\n    // Create canvas context\r\n    var canvas = document.createElement("canvas");\r\n    var context = canvas.getContext("2d");\r\n    canvas.width = 32;\r\n    canvas.height = 32;\r\n\r\n    // Draw radial gradient\r\n    var grad = context.createRadialGradient(16, 16, 6, 16, 16, 16);\r\n    grad.addColorStop(0, "rgba(255, 150, 0, 1.0");\r\n    grad.addColorStop(0.5, "rgba(255, 0, 150, 1.0");\r\n    grad.addColorStop(1, "rgba(0, 150, 255, 1.0)");\r\n    context.fillStyle = grad;\r\n    context.fillRect(0, 0, 32, 32);\r\n\r\n    // Use canvas to create texture\r\n    var canvasTexture = new THREE.Texture(canvas);\r\n    canvasTexture.needsUpdate = true;\r\n\r\n    return canvasTexture;\r\n}\r\n\r\n// Boilerplate Three.js setup\r\nvar camera, scene, renderer;\r\nrenderer = new THREE.WebGLRenderer({antialias: true});\r\nrenderer.setSize(window.innerWidth, window.innerHeight);\r\ndocument.body.appendChild(renderer.domElement);\r\nscene = new THREE.Scene();\r\nscene.background = new THREE.Color(0xe1e1e1);\r\ncamera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 100);\r\ncamera.position.set(0, 30, -30);\r\ncamera.lookAt(0, 0, 0);\r\n\r\nconst ambient = new THREE.DirectionalLight(0xddeeff, 1);\r\nambient.position.set(0, 1, 1);\r\n\r\n// Using canvas as material map texture:\r\nconst floor = new THREE.Mesh(\r\n    new THREE.BoxBufferGeometry(20, 0.25, 20),\r\n    new THREE.MeshBasicMaterial({map: makeCanvasTexture()})\r\n);\r\n\r\nscene.add(ambient, floor);\r\n\r\nfunction animate(t) {\r\n\t// Animate mesh\r\n    floor.rotation.z += Math.sin(t * 0.001) * 0.1;\r\n\trenderer.render(scene, camera);\r\n\trequestAnimationFrame(animate);\r\n}\r\n\r\nanimate(0);
Run Code Online (Sandbox Code Playgroud)\r\n
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

请记住,WebGL 纹理大小受到限制,具体取决于每个设备的显卡功能,因此如果您尝试创建违反此限制的画布,则会出现错误。您可以访问https://webglreport.com/查看当前设备的限制并查看右侧的“最大纹理大小”读数来我的是8192px\xc2\xb2。

\n\n

在此输入图像描述

\n\n

同样,您可以按照本文档页面中的THREE.WebGLRenderer.capabilities.maxTextureSize说明以编程方式访问此信息编程方式访问此信息,以便您可以使用此数字来防止画布大小超出设备的限制。

\n


Col*_*rus 0

这可能是通过 d3-x3d 上的此提交修复的,修复 #14 texImage2D:没有画布。与此(已关闭)问题相关,INVALID_VALUE: texImage2D: no canvas

如果问题仍然存在,这可能与每个浏览器对其最大支持的画布尺寸/区域的限制有关。

请参阅另一篇文章中答案,以查找每个浏览器的上述限制。

超过大多数浏览器上的最大长度/宽度/面积会导致画布无法使用。(它会忽略任何绘制命令,即使在可用区域也是如此。)
- Brandon Gano

不幸的是,从已投票的答案中没有给出 Safari 的数据,但您可以在其下面查找评论,例如:

iPhone 6 Plus 上的 iOS 9.3.1 Safari 仅限于 16777216 像素的区域(例如 4096 x 4096)
- matb33

或者像这样查看该帖子的其他答案

因此,任何 5242880 (5 x 1024 x 1024) 像素的大小变化都可以在大内存设备上运行,否则为 3145728 像素。

5 兆像素画布示例(宽 x 高):

Any total <= 5242880
--------------------
5 x 1048576 ~= 5MP   (1048576 = 1024 x 1024)
50 x 104857 ~= 5MP
500 x 10485 ~= 5MP
Run Code Online (Sandbox Code Playgroud)

等等..

最大的方形画布是(“MiB”= 1024x1024 字节):

device < 256 MiB   device >= 256 MiB   iPhone 6 [not confirmed]
-----------------  -----------------   ---------------------
<= 3145728 pixels  <= 5242880 pixels   <= 16 x 1024 x 1024 p
1773 x 1773        2289 x 2289         4096 x 4096
Run Code Online (Sandbox Code Playgroud)

- dcbarans

另一个可能的因素是客户端的显卡​​。