見出し画像

🎡Three.js上でdivタグを動かすCSS2DObjectとフォンシェーディング(鏡面光沢)


前回字を描くためにSVG使ったが一部文字が欠けてしまったので、別のサンプルを見つけた。DIVタグを3D上で動かすものがあった。

地球と月はSphereBufferGeometryで形を作る。

画像2
glTFのチートシートでは黄色くしてあるところ辺がジオメトリ
				const earthGeometry = new THREE.SphereBufferGeometry( EARTH_RADIUS, 16, 16 );
				const earthMaterial = new THREE.MeshPhongMaterial( {
					specular: 0x333333,
					shininess: 5,
					map: textureLoader.load( 'https://threejs.org/examples/textures/planets/earth_atmos_2048.jpg' ),
					specularMap: textureLoader.load( 'https://threejs.org/examples/textures/planets/earth_specular_2048.jpg' ),
					normalMap: textureLoader.load( 'https://threejs.org/examples/textures/planets/earth_normal_2048.jpg' ),
					normalScale: new THREE.Vector2( 0.85, 0.85 )
				} );
				const earth = new THREE.Mesh( earthGeometry, earthMaterial );

MeshPhongMaterialで鏡面効果

MeshPhongMaterial:このマテリアルは、反射率を計算するために物理的ではないBlinn-Phongモデルを使用しています。MeshLambertMaterialで使用されているLambertianモデルとは異なり、鏡面ハイライトを持つ光沢のあるサーフェス(ニスを塗った木材など)をシミュレートすることができます。

フォンシェーディング(英: Phong shading)は、3次元コンピュータグラフィックスにおける陰影計算の補間技法である。フォン補間と呼ばれることもある。ラスタライズされたポリゴン群をまたいだ法線ベクトルの補間によってピクセルの色を推測する技法であり、「ピクセル単位照明」(per-pixel lighting) を実現するための補間技法として利用される。グーローシェーディングやフラットシェーディングなどの他の補間技法との対比で、これを「フォンシェーディング」と呼ぶ。

画像3
右側がホンさんが考えたシェーディング方法で、まるこくて輝いてみえる。

DIVを3D空間に

				const earthDiv = document.createElement( 'div' );
				earthDiv.className = 'label';
				earthDiv.textContent = 'Earth';
				earthDiv.style.marginTop = '-1em';
				const earthLabel = new CSS2DObject( earthDiv );
				earthLabel.position.set( 0, EARTH_RADIUS, 0 );
				earth.add( earthLabel );

CSS2DObjectするとメッシュにDIVタグを足せるようになる。

CSS2DRendererは、CSS3DRendererの簡易版です。サポートされているのは変換のみです。このレンダラーは、HTML ベースのラベルと 3D オブジェクトを組み合わせたい場合に非常に便利です。ここでも、それぞれの DOM 要素は CSS2DObject のインスタンスにラップされ、シーングラフに追加されます。

画像4
Div要素をinitの外に出して宣言して、animateでレンダリングする前に現在時刻をとってみたが普通に更新した。これは便利だ。


				renderer = new THREE.WebGLRenderer();
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				document.body.appendChild( renderer.domElement );
				labelRenderer = new CSS2DRenderer();
				labelRenderer.setSize( window.innerWidth, window.innerHeight );
				labelRenderer.domElement.style.position = 'absolute';
				labelRenderer.domElement.style.top = '0px';
				document.body.appendChild( labelRenderer.domElement );

残りのポイントはレンダラーが二つあって


				renderer.render( scene, camera );
				labelRenderer.render( scene, camera );

レンダリングも二度するということ。

おまけ、照明処理

DirectionalLight:特定の方向に放射される光。この光は、あたかも太陽が無限に遠くにあり、そこから発せられる光線はすべて平行であるかのように振る舞います。太陽は、その位置が無限であると考えられるほど遠くにあり、そこからの光線はすべて平行です。この光は影を落とすことができます - 詳細は DirectionalLightShadow のページを参照してください。


お願い致します