2013-10-27 8 views
7

Sto usando Three JS per sviluppare un grafico 3d. Voglio mostrare le unità di un grafico come THREE.SPRITE. Per creare SPRITE, ho prima creato un elemento canvas e aggiunto del testo. Quindi ho creato THREE.Texture con l'elemento canvas che era stato precedentemente creato. Creato THREE.SpriteMaterial con la trama come mappa e quindi creato THREE.SPRITE utilizzando questo materiale sprite. Aggiunto questo materiale sprite alla scena. Quando il renderer è un'istanza di THREE.WebGLRenderer, la dimensione del testo è molto piccola e quando il renderer è un'istanza di THREE.CanvasRenderer, la dimensione del testo è molto grande.ThreeJS: La differenza di dimensione del font di testo Sprite tra il renderer WebGL e il renderer Canvas

Di seguito è riportato il codice che ho utilizzato per creare 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); 

È il comportamento predefinito o sto facendo qualcosa di sbagliato. Si prega di suggerire qualsiasi correzione che funzioni in modo coerente con i renderer Canvas e WebGL.

Grazie in anticipo.

+0

Sfortunatamente, 'WebGLRender' e' CanvasRenderer' non ridimensionano gli sprite allo stesso modo. Questo è qualcosa che dovrebbe essere risolto. – WestLangley

+0

Grazie per la risposta. Posso sapere se la differenza di dimensioni è proporzionale/relativa quando viene ridimensionata usando CanvasRenderer e WebGLRenderer, in modo da poter usare un blocco if-else e scrivere una logica diversa per due renderer. Per me è sufficiente che le dimensioni del testo siano simili (e non esattamente le stesse). – Kishor

+0

Con 'WebGLRenderer', uno' Sprite' con scala (1, 1, 1) dovrebbe restituire la stessa dimensione di una dimensione di PlaneGeometry (1, 1) con la stessa posizione. (tre.js r.62) Per 'CanvasRenderer', non sono sicuro di quale sia la logica di ridimensionamento. Forse puoi rintracciarlo e suggerire un miglioramento. – WestLangley

risposta

6

Dopo aver provato così tante combinazioni, ha funzionato il seguente codice.

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); 

Aggiungere il collegamento THREE JS (versione 62) e utilizzare il seguente script.

Spero che questo aiuti gli altri con problemi simili.

Aggiornamento: Ecco lo jsfiddle del codice precedente.

+0

Sembra che le unità sprite siano in pixel per il renderer canvas2d (1 pixel = 1 unità mondo), ma le unità sono unità mondo per il renderer webgl. Quindi, sopra, devi ridimensionare l'altezza di canvas2d di 2/100, ma il renderer webgl di 2. Forse questo aiuta qualcuno come @WestLangley a vedere dove è l'inconsistenza? –

+0

Questo funziona abbastanza bene per il renderer WebGL, l'unico problema è che il testo è pixelato. Hai avuto questo problema? – BuildingJarl

Problemi correlati