最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ThreeJS: Text Sprite's font size difference between WebGL renderer and Canvas renderer - Stack Overflow

programmeradmin2浏览0评论

I am using Three JS to develop a 3d graph. I want to show units of a graph as THREE.SPRITE. For creating SPRITE, I have first created a canvas element and added text to it. Then I have created THREE.Texture with the canvas element that was previously created. Created THREE.SpriteMaterial with the texture as a map and then created THREE.SPRITE using this sprite material. Added this sprite material to scene. When the renderer is an instance of THREE.WebGLRenderer the size of text is very small and when the renderer is an instance of THREE.CanvasRenderer then the size of text is very large.

Following is the code that I have used to create Sprite.

var canvas = document.createElement('canvas'),
    context = canvas.getContext('2d'),
    metrics = null,
    textHeight = 100,
    textWidth = 0,
    actualFontSize = 20;

context.font = "normal " + textHeight + "px Arial";
metrics = context.measureText("Sample Text");
var textWidth = metrics.width;

canvas.width = textWidth;
canvas.height = textHeight;
context.font = "normal " + textHeight + "px Arial"; 
context.textAlign = "center";
context.textBaseline = "middle";
context.fillStyle = "#ff0000";
context.fillText("Sample Text", textWidth / 2, textHeight / 2);

var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;

var material = new THREE.SpriteMaterial({ map: texture, useScreenCoordinates: false, alignment: THREE.SpriteAlignment.center });
material.transparent = true;
//var textObject = new THREE.Sprite(material);
var textObject = new THREE.Object3D();
var sprite = new THREE.Sprite(material);
textObject.textHeight = actualFontSize;
textObject.textWidth = (textWidth / textHeight) * textObject.textHeight;
//sprite.scale.set(textObject.textWidth / textWidth, textObject.textHeight / textHeight, 1);
textObject.add(sprite);

scene.add(textObject);

Is it the default behavior or am I doing anything wrong. I am seeking a fix that works in both Canvas and WebGL renderers consistently.

I am using Three JS to develop a 3d graph. I want to show units of a graph as THREE.SPRITE. For creating SPRITE, I have first created a canvas element and added text to it. Then I have created THREE.Texture with the canvas element that was previously created. Created THREE.SpriteMaterial with the texture as a map and then created THREE.SPRITE using this sprite material. Added this sprite material to scene. When the renderer is an instance of THREE.WebGLRenderer the size of text is very small and when the renderer is an instance of THREE.CanvasRenderer then the size of text is very large.

Following is the code that I have used to create Sprite.

var canvas = document.createElement('canvas'),
    context = canvas.getContext('2d'),
    metrics = null,
    textHeight = 100,
    textWidth = 0,
    actualFontSize = 20;

context.font = "normal " + textHeight + "px Arial";
metrics = context.measureText("Sample Text");
var textWidth = metrics.width;

canvas.width = textWidth;
canvas.height = textHeight;
context.font = "normal " + textHeight + "px Arial"; 
context.textAlign = "center";
context.textBaseline = "middle";
context.fillStyle = "#ff0000";
context.fillText("Sample Text", textWidth / 2, textHeight / 2);

var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;

var material = new THREE.SpriteMaterial({ map: texture, useScreenCoordinates: false, alignment: THREE.SpriteAlignment.center });
material.transparent = true;
//var textObject = new THREE.Sprite(material);
var textObject = new THREE.Object3D();
var sprite = new THREE.Sprite(material);
textObject.textHeight = actualFontSize;
textObject.textWidth = (textWidth / textHeight) * textObject.textHeight;
//sprite.scale.set(textObject.textWidth / textWidth, textObject.textHeight / textHeight, 1);
textObject.add(sprite);

scene.add(textObject);

Is it the default behavior or am I doing anything wrong. I am seeking a fix that works in both Canvas and WebGL renderers consistently.

Share Improve this question edited Nov 24, 2019 at 13:05 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Oct 27, 2013 at 12:56 KishorKishor 2,6774 gold badges18 silver badges34 bronze badges 4
  • Unfortunately, WebGLRender and CanvasRenderer do not scale sprites the same. This is something that should be fixed. – WestLangley Commented Oct 28, 2013 at 2:03
  • Thanks for the reply. Can I know the whether the difference in sizes is proportional/relative when scaled using CanvasRenderer and WebGLRenderer, so that I can use an if-else block and write different logic for two renderers. It is sufficient for me if text sizes are similar (and not exactly the same). – Kishor Commented Oct 28, 2013 at 2:50
  • With WebGLRenderer, a Sprite having scale ( 1, 1, 1 ) should render the same size as a PlaneGeometry of size ( 1, 1 ) having the same location. (three.js r.62) For CanvasRenderer, I am not sure what the scaling logic is. Perhaps you can track it down and suggest an improvement. – WestLangley Commented Oct 28, 2013 at 3:22
  • Okay. Thanks for taking your time to help me. I am working on it now. If I find any fix I will suggest. Thanks. – Kishor Commented Oct 28, 2013 at 3:34
Add a ment  | 

1 Answer 1

Reset to default 6

After trying so many binations, the following code worked.

var SCREEN_WIDTH = 400,
    SCREEN_HEIGHT = 300,
    VIEW_ANGLE = 45,
    ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT,
    NEAR = 0.1,
    FAR = 20000,
    webGLScene = new THREE.Scene(),
    canvasScene = new THREE.Scene(),
    webGLCamera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR),
    canvasCamera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR),
    webGLRenderer = new THREE.WebGLRenderer({ antialias: true }),
    canvasRenderer = new THREE.CanvasRenderer();

webGLScene.add(webGLCamera);
canvasScene.add(canvasCamera);

webGLCamera.position.set(0, 0, 20);
webGLCamera.lookAt(webGLScene.position);

canvasCamera.position.set(0, 0, 20);
canvasCamera.lookAt(canvasScene.position);

webGLRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
canvasRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);

container = document.body;
container.appendChild(webGLRenderer.domElement);
container.appendChild(canvasRenderer.domElement);

makeSprite(webGLScene, "webgl");
makeSprite(canvasScene, "2d");

function makeSprite(scene, rendererType) {
    var canvas = document.createElement('canvas'),
        context = canvas.getContext('2d'),
        metrics = null,
        textHeight = 100,
        textWidth = 0,
        actualFontSize = 2;

    context.font = "normal " + textHeight + "px Arial";
    metrics = context.measureText("Sample Text");
    var textWidth = metrics.width;

    canvas.width = textWidth;
    canvas.height = textHeight;
    context.font = "normal " + textHeight + "px Arial";
    context.textAlign = "center";
    context.textBaseline = "middle";
    context.fillStyle = "#ff0000";
    context.fillText("Sample Text", textWidth / 2, textHeight / 2);

    var texture = new THREE.Texture(canvas);
    texture.needsUpdate = true;

    var material = new THREE.SpriteMaterial({ map: texture, useScreenCoordinates: false, alignment: THREE.SpriteAlignment.center });
    material.transparent = true;
    //var textObject = new THREE.Sprite(material);
    var textObject = new THREE.Object3D();
    var sprite = new THREE.Sprite(material);
    textObject.textHeight = actualFontSize;
    textObject.textWidth = (textWidth / textHeight) * textObject.textHeight;
    if (rendererType == "2d") {
        sprite.scale.set(textObject.textWidth / textWidth, textObject.textHeight / textHeight, 1);
    } else {
        sprite.scale.set(textWidth / textHeight * actualFontSize, actualFontSize, 1);
    }

    textObject.add(sprite);

    scene.add(textObject);
}

canvasRenderer.render(canvasScene, canvasCamera);
webGLRenderer.render(webGLScene, webGLCamera);

Add THREE JS (release 62) link and use the following script.

Hope this helps others with similar problems.

Update: Here is the jsfiddle of the above code.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论