在移动设备(如iPhone Safari等)上,使用HTML画布更新纹理时,ThreeJS会出现"WebGL: INVALID_VALUE: texImage2D: no canvas"的错误。

10

我正在尝试使用HTML5画布对象更新THREE.Texture的“.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; 

这是材料使用的方法:

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

奇怪的是,如果我使用THREE.ImageUtils.loadTexture加载图片,它能正常工作。但是,我的使用情况是必须使用一个画布对象(在画布上有多个图像)。

谢谢。


我遇到了类似的问题,你有任何结果吗? - Wayne Wang
1
刚刚遇到了同样的错误。找到解决方案了吗? - droidballoon
1
@voondo 这个问题已经4年了。您还遇到问题吗?您是否使用最新版本的three.js(目前是r109)?当前版本支持CanvasTexture - TheJim01
这是一篇文章,链接在此:https://threejsfundamentals.org/threejs/lessons/threejs-canvas-textures.html。如果不想看整篇文章,也可以查看代码片段,链接在此:https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/。你的画布大小是多少?我记得 iPhone 浏览器只支持最大 4096x4096。 - gman
2个回答

5
根据Texture文档,.image属性更像是通过TextureLoader.load()方法创建的图像元素的“获取器”。如果您想使用<canvas>元素创建纹理,可以使用以下代码片段中展示的new THREE.Texture(canvas);创建。纹理创建在makeCanvasTexture()函数中进行:

function makeCanvasTexture() {
    // Create canvas context
    var canvas = document.createElement("canvas");
    var context = canvas.getContext("2d");
    canvas.width = 32;
    canvas.height = 32;

    // Draw radial gradient
    var grad = context.createRadialGradient(16, 16, 6, 16, 16, 16);
    grad.addColorStop(0, "rgba(255, 150, 0, 1.0");
    grad.addColorStop(0.5, "rgba(255, 0, 150, 1.0");
    grad.addColorStop(1, "rgba(0, 150, 255, 1.0)");
    context.fillStyle = grad;
    context.fillRect(0, 0, 32, 32);

    // Use canvas to create texture
    var canvasTexture = new THREE.Texture(canvas);
    canvasTexture.needsUpdate = true;

    return canvasTexture;
}

// Boilerplate Three.js setup
var camera, scene, renderer;
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xe1e1e1);
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(0, 30, -30);
camera.lookAt(0, 0, 0);

const ambient = new THREE.DirectionalLight(0xddeeff, 1);
ambient.position.set(0, 1, 1);

// Using canvas as material map texture:
const floor = new THREE.Mesh(
    new THREE.BoxBufferGeometry(20, 0.25, 20),
    new THREE.MeshBasicMaterial({map: makeCanvasTexture()})
);

scene.add(ambient, floor);

function animate(t) {
 // Animate mesh
    floor.rotation.z += Math.sin(t * 0.001) * 0.1;
 renderer.render(scene, camera);
 requestAnimationFrame(animate);
}

animate(0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>

请记住,WebGL纹理大小受每个设备的图形卡能力限制,因此如果您尝试创建超过此限制的画布,则会出现错误。您可以通过访问https://webglreport.com/并查看右侧的“最大纹理大小”读数来查看当前设备的限制。我的是8192px²。

enter image description here

同样地,您可以通过编程方式访问此信息,方法是使用THREE.WebGLRenderer.capabilities.maxTextureSize,如文档页面所述,因此您可以使用此数字防止画布大小超出设备限制。

1
在我的端上工作中。 - Alex Pappas

0

这可能是由于 d3-x3d 上的此提交 Fix #14 texImage2D: no canvas. 修复了,该问题与此(已关闭)问题 INVALID_VALUE: texImage2D: no canvas 相关。

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

请参考另一篇帖子中的 this 答案,查找每个浏览器的所述限制。

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

很遗憾,从得到的赞同答案中没有给出Safari的数据,但您可以查看其中的评论,例如:

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

或者查看帖子中的其他答案,例如this

Therefore, any size variation of 5242880 (5 x 1024 x 1024) pixels will work on large memory devices, otherwise it's 3145728 pixels.

Example for 5 megapixel canvas (width x height):

Any total <= 5242880
--------------------
5 x 1048576 ~= 5MP   (1048576 = 1024 x 1024)
50 x 104857 ~= 5MP
500 x 10485 ~= 5MP

and so on..

The largest SQUARE canvases are ("MiB" = 1024x1024 Bytes):

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

-dcbarans

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接