【发布时间】:2020-05-30 19:23:56
【问题描述】:
在 Three.js 中,最好将纹理保持为 2 的幂,这实际上是一些旧版 Chrome 浏览器的要求,例如 32x32、64x64 等
因此我需要创建一个二维幂的画布纹理,但我需要让 Sprite 可点击,这意味着它需要以某种方式裁剪。
考虑这个例子:
- 黑色 bg 是 Three.js 渲染器
- 红色 bg 是画布所需的大小(2 次方)
- 白色 bg 是文字的大小
我想将纹理保持为 2 的维度幂,但将其裁剪为仅显示白色区域。例如,用户可以将鼠标悬停在标签上。我不希望他们在红色区域徘徊!
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 400;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var config = {
fontface: 'Arial',
fontsize: 32,
fontweight: 500,
lineheight: 1,
};
var text = 'Hello world!';
function nextPowerOf2(n) {
return Math.pow(2, Math.ceil(Math.log(n) / Math.log(2)));
}
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.font = `${config.fontweight} ${config.fontsize}px/${config.lineheight} ${config.fontface}`;
const textMetrics = ctx.measureText(text);
var textWidth = textMetrics.width;
var textHeight = config.fontsize * config.lineheight;
canvas.width = nextPowerOf2(textWidth);
canvas.height = nextPowerOf2(textHeight);
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, textWidth, textHeight);
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.font = `${config.fontweight} ${config.fontsize}px/${config.lineheight} ${config.fontface}`;
ctx.fillText(text, 0, 0);
console.log('canvas', canvas.width, canvas.height);
console.log('text', textWidth, textHeight);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var spriteMaterial = new THREE.SpriteMaterial({
map: texture
});
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(spriteMaterial.map.image.width, spriteMaterial.map.image.height, 1);
scene.add(sprite);
var animate = function() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();
body { margin: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
这怎么可能?以某种方式裁剪 SpriteMaterial?
【问题讨论】:
-
仅供参考:在旧浏览器上没有也从来没有任何不同。另外,请使用snippet 并为three.js 使用版本化CDN,否则您的示例将在几周内中断并且无用。
-
已更新为使用 cdn 和 sn-p。有不同/旧版本的 Chrome 不支持它 '251[.WebGL-0x86d0ad00]RENDER WARNING:绑定到纹理单元 0 的纹理不可渲染。它可能不是 2 的幂并且具有不兼容的纹理过滤。请参阅以下主题:github.com/mrdoob/three.js/issues/17879
-
我在该线程中没有看到任何内容表明我写的内容不正确。 WebGL 一直对过滤有 2 的幂的要求,今天仍然有。自 9 年前发货以来,这一点一直没有改变。
-
抱歉...我的意思是 Android 7.1 Chrome 会引发 JavaScript 错误,阻止画布渲染,而在更现代的浏览器上只显示纹理调整大小警告。了解这一直是最佳做法!
标签: canvas three.js html5-canvas sprite