2013-10-27 1 views
7

3つのJSを使用して3次元グラフを作成しています。私はグラフの単位をTHREE.SPRITEと表示したいと思います。 SPRITEを作成するには、最初にキャンバス要素を作成し、その要素にテキストを追加しました。それで、以前作成したキャンバス要素を使ってTHREE.Textureを作成しました。テクスチャをマップとしてTHREE.SpriteMaterialを作成し、このスプライトマテリアルを使用してTHREE.SPRITEを作成しました。このスプライトの素材をシーンに追加しました。レンダラーがTHREE.WebGLRendererのインスタンスである場合、テキストのサイズは非常に小さく、レンダラーがTHREE.CanvasRendererのインスタンスである場合、テキストのサイズは非常に大きい。ThreeJS:TextスプライトのWebGLレンダラーとキャンバスレンダラーのフォントサイズの違い

以下は、私が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); 

これはデフォルトの動作ですか、何か間違っていますか? CanvasとWebGLの両方のレンダリングで一貫して機能する修正を提案してください。

ありがとうございます。

+0

残念ながら、 'WebGLRender'と' CanvasRenderer'はスプライトを同じスケールにしません。これは修正すべきものです。 – WestLangley

+0

返事をありがとう。 CanvasRendererとWebGLRendererを使用してサイズを変更したときのサイズの違いが比例/相対であるかどうかを知ることができます。これにより、if-elseブロックを使用して2つのレンダラーに対して異なるロジックを書くことができます。テキストサイズが似ていても(まったく同じではない場合は)十分です。 – Kishor

+0

'WebGLRenderer'では、スケール(1,1,1)を持つスプライトは、同じ位置を持つサイズ(1,1)の' PlaneGeometry'と同じサイズをレンダリングする必要があります。 (three.js r.62) 'CanvasRenderer'では、スケーリングロジックが何であるか分かりません。おそらくあなたはそれを追跡し、改善を提案するかもしれません。 – WestLangley

答えて

6

非常に多くの組み合わせを試した後、次のコードが機能しました。

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

THREE JS(リリース62)リンクを追加し、次のスクリプトを使用します。

これは、同様の問題を抱えている他の人に役立ちます。

更新:上記のコードのjsfiddleは次のとおりです。

+0

スプライト単位はcanvas2dレンダラ(1ピクセル= 1ワールド単位)のピクセルで表示されますが、単位はwebglレンダラのワールド単位です。したがって、上記のようにcanvas2dの高さを2/100に調整する必要がありますが、webglレンダラーを2で調整する必要があります。これは@WestLangleyのような人が、不一致がどこにあるかを知るのに役立ちますか? –

+0

これはWebGLレンダラではうまくいきますが、唯一の問題はテキストがピクセル化されていることです。あなたにこの問題がありましたか? – BuildingJarl

関連する問題