我正在尝试更新THREE.Texture" .image"具有HTML5画布对象的属性。这适用于笔记本电脑上的Chromium(MacOSX)。但是,iPhone Safari和iPhone Chrome都不起作用。可能是根本原因以及如何解决这个问题?
在Safari中使用Web Inspector,我收到以下错误消息:" WebGL:INVALID_VALUE:texImage2D:no canvas "。
我确保在更新之前完全绘制画布,使用以下代码更新材料:
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加载图像,它可以正常工作。但是,我的用例是我必须使用画布对象(画布上的多个图像)。
感谢。
答案 0 :(得分:1)
根据Texture
docs,对于通过TextureLoader.load()
方法创建的图像元素,.image属性更像是一个“获取器”。如果要使用<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²。
同样,您可以按照in this documentation page的说明使用THREE.WebGLRenderer.capabilities.maxTextureSize
以编程方式访问此信息,因此可以使用此数字来防止画布尺寸超出设备的限制。
答案 1 :(得分:0)
此问题很可能是由于对d3-x3d Fix #14 texImage2D: no canvas.的此提交(已关闭)INVALID_VALUE: texImage2D: no canvas的提交而得到的修复。
如果问题仍然存在,则可能与每个浏览器在其支持的最大画布尺寸/区域上的限制有关。
请参考另一篇文章的this答案,以了解每个浏览器的上述限制。
在大多数浏览器中超过最大长度/宽度/面积会使画布无法使用。 (即使在可用区域中,它也会忽略任何绘制命令。)
-Brandon Gano
不幸的是,答案没有给出Safari的具体数字,但是您可以在下面找到它的注释:
iPhone 6 Plus上的iOS 9.3.1 Safari仅限16777216像素(例如4096 x 4096)区域
-matb33
或者查看帖子的其他答案,例如this
因此,任何尺寸变化为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
以此类推。
最大的SQUARE画布为(“ 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
另一个可能的因素是客户端的图形卡。