我正在尝试使用PerspectiveCamera在三维场景中使用恒定大小的文本精灵(无论相机距离如何)。为了使非精灵具有恒定的大小,我使它们成为一个特殊的"缩放"对象的子对象,该对象会随着相机到原点的距离的变化而调整其缩放(请参阅下面的代码)。这可以很好地保持普通对象大致相同的视觉大小,但当我将精灵添加到缩放对象中时,精灵似乎会忽略其父对象的缩放(因此,随着放大和缩小,它会越来越小)。
有趣的是,当我们切换到正交摄影机时(取消注释下面相应的行),这个特殊缩放的对象似乎不再影响儿童(即,儿童不会保持不变的大小)。但是,由于我们有一个正交摄影机,精灵不再随着摄影机距离的变化而缩放(因此它们保持不变的大小),但这与缩放对象无关。
我注意到其他一些类似的问题和答案,包括调整精灵本身的比例(将所有精灵添加到一个缩放对象似乎要容易得多),使用正交相机覆盖来绘制精灵(另请参见此)(但我希望我的精灵在3d透视场景中)。
所以,我的问题是:为什么精灵在使用PerspectiveCamera时不根据其父对象的比例使用比例?此外,为什么缩放对象不能与正交摄影机一起使用?这些是摄像头的缺陷还是功能?
谢谢!
http://jsfiddle.net/LLbcs/8/
var camera, scene, renderer, geometry, material, mesh, text, controls;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000); var scenescale=1;
//camera = new THREE.OrthographicCamera( -7,7,7,-7, 1, 20 );
camera.position.z = 10;
scene.add(camera);
scaled=new THREE.Object3D();
scene.add(scaled);
var textmaterial = new THREE.SpriteMaterial( {color: 'red', useScreenCoordinates: true, map: texttexture("hi")});
text = new THREE.Sprite( textmaterial );
text.position.set( 1, 1, 0);
scaled.add(text);
var geometry = new THREE.BoxGeometry( 1, 1,1 );
var material = new THREE.MeshLambertMaterial( { color: 0xffffff } );
mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0,3,0);
scaled.add(mesh);
var light = new THREE.PointLight('green');
light.position.set(10,15,10);
camera.add(light);
light = new THREE.PointLight(0x333333);
light.position.set(-10,-15,-8);
camera.add(light);
renderer = new THREE.WebGLRenderer();
controls = new THREE.OrbitControls( camera, renderer.domElement );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
var scale = camera.position.length()/10;
scaled.scale.set(scale,scale,scale);
render();
}
function render() {
renderer.render(scene, camera);
}
function texttexture(string) {
var fontFace = "Arial"
var size = "50";
var color = "white"
var squareTexture = true;
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.height = size;
var font = "Normal " + size + "px " + fontFace;
context.font = font;
var metrics = context.measureText(string);
var textWidth = metrics.width;
canvas.width = textWidth;
if (squareTexture) {
canvas.height = canvas.width;
}
var aspect = canvas.width / canvas.height;
context.textAlign = "center";
context.textBaseline = "middle";
context.fillStyle = color;
// Must set the font again for the fillText call
context.font = font;
context.fillText(string, canvas.width / 2, canvas.height / 2);
var t = new THREE.Texture(canvas);
t.needsUpdate = true;
return t;
}
如果您希望文本显示在3D场景上,而不关心它是否是静态的,为什么不尝试在场景上分层呢?
这将允许您节省图形带宽和内存,提高场景的性能,并使您在显示内容方面具有更好的灵活性。它也更容易做和维护。