質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Three.js

Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1808閲覧

Three.jsで半径方向に透明度の分布のあるチューブを描画したい

MistletoeNaoko

総合スコア15

Three.js

Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

1クリップ

投稿2019/02/19 06:13

編集2019/02/19 15:36

前提・実現したいこと

three.jsを用いて三次元の可視化システムを作成しており、チューブの内側ほど透明度が低く、外側ほど透明度が高いような、透明度分布のある3Dのチューブを描画したいのですが、高速に描画可能な方法をアドバイスいただけないかと思い、質問させていただきました。

現状の実装・試したこと

現在、半径の異なる半透明なチューブを複数重ねて描画することで、下図のような輪郭のぼやけたチューブを実現することができています。下図の例では32本のチューブを重ねています。
出力結果としては実現できているのですが、200データサンプル程度のデータで描画に3秒程かかってしまっています。32個のTHREE.TubeBufferGeometryを作成するのに時間がかかっているようです。
出力イメージ

該当のソースコード

チューブの描画に関わるコードは以下のようになっております。
全体のソースコード、サンプルデータセットなどはgithubをご覧ください。

javascript

1function createTube(texture) { 2 var tubeSpline = new THREE.CatmullRomCurve3(points); 3 var tubeNum = 32; // 重ねるチューブの数。最低でも16本くらい重ねないと境目が目立ってしまう 4 5 var tubeGeometry; 6 var geometries = []; 7 for (let i = 0; i < tubeNum; i++) { 8 // 半径の異なるチューブを生成 9 const geometryTmp = new THREE.TubeBufferGeometry( 10 tubeSpline, 11 5 * Math.ceil(data[data.length - 1]['JD'] - data[0]['JD']), 12 (1 / tubeNum) * (i + 1), 13 32, 14 false); 15 geometries.push(geometryTmp); 16 } 17 tubeGeometry = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries); 18 // チューブの変形はシェーダで行っています 19 var tubeShaderMaterial = new THREE.ShaderMaterial({ 20 vertexShader: document.getElementById('vertexShaderSimple').textContent, 21 fragmentShader: document.getElementById('fragmentShader').textContent, 22 uniforms: { 23 points: {value: positions}, 24 radiuses: {value: radiuses}, 25 colors: {value: colors}, 26 size: {value: data.length}, 27 texture: {value: texture}, 28 lightPosition: {value: new THREE.Vector3(-20, 40, 60)}, 29 minmaxVJ: {value: new THREE.Vector2(minList['V-J'], maxList['V-J'])}, 30 minmaxFlx: {value: new THREE.Vector2(minList['Flx(V)'], maxList['Flx(V)'])}, 31 viewVector: { value: camera.position } 32 }, 33 side: THREE.DoubleSide, 34 transparent: true, 35 clipping: true, 36 clippingPlanes: [clippingPlane] 37 }); 38 tubeMesh = new THREE.Mesh(tubeGeometry, tubeShaderMaterial); 39 scene.add(tubeMesh); 40}

要件

最終的には数千データサンプルあるデータも扱いたいので、現状の描画速度では使用に耐えないため、何かよりよい方法がないかと思い、質問させていただきました。
200データサンプル程度のデータならば、1秒以下で出力されて欲しいのですが…

お知恵を貸していただければ幸いです。

bochan2👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

視線と面の角度の関数で透明度を決めることでわりと近似できそうな気がしますね。

  1. チューブ表面と視線の角度のうち、チューブの長さ方向の成分は、チューブをどれだけ斜めから見ているかに相当する
  2. それと直交するもう一方の成分は、チューブの中心線からどれだけずれた部分を見ているかに相当する

ここから定式化できそうです。
チューブが視線の途中で曲がる効果は考慮できませんが、それなりの近似にはなるのではないかと。
ただ、曲がるチューブを長さ方向から見るところは別扱いしないと駄目かも。


追記。
面の曲率(視線との角度の勾配)を見ると曲がるチューブを長さ方向から見るところもとれそう。
曲がるチューブを長さ方向から見るところは、カーブの内側で、ポリゴン1枚のところと奥と重なって2枚のところの境目が上手くできないかもしれない。

投稿2019/02/21 00:44

編集2019/02/23 16:30
ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MistletoeNaoko

2019/03/15 17:06

ご回答くださっていたのに、気づいていなくて申し訳ございませんでした。 アイディアをありがとうございます!なるほど…シェーダ―の方でやれそうな気がします… すぐに式思いつかなくて、うまくいったかいっていないかのご報告はできないのですが、ありがとうございました!!試してみます…!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問