【Three.js】海を表示してみる

【Three.js】海を表示してみる

こんにちは。kyamashitaです。

今回は three.js のexampleを修正して海を表示してみました。

Three.js の example

https://threejs.org/examples/

にすばらしい例がたくさんありますので、参考にします。

今回は webglshadersocean2 を参考にしました。

https://threejs.org/examples/webglshadersocean2.html

kyamahsita_20200705_01.gif

すでに海なのですが、カメラの位置等変更してみます。

構成

Three.jsの公式サイトからダウンロードし、以下のような構成にします。

index.html に webglshadersocean2 のコードをコピーし修正していきます。

build/
docs/
editor/
examples/
files/
src/
test/
utils/
index.html

やったこと

FPSの表示と、コントローラーを削除します。

dat.GUI(パラーメータ調整ライブラリ)にカメラの位置を追加します。

※dat.GUIとは・・・パラーメータ調整ライブラリ https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage

カメラや海のパラメータを変えて調整し、お気に入りの設定を初期値とし、dat.GUIを削除(コメント化)します。

ソース

上記実施後は以下のようになります。※dat.GUI部分はコメント化しています。

ほぼexampleのままで不要箇所削除と初期値の設定しました。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>sample</title>
    <style>
        body {
          margin: 0;
          overflow: hidden;
        }
    </style>
</head>
<body>
    <script type="module">
        import * as THREE from '/build/three.module.js';
        // import { GUI } from '/examples/jsm/libs/dat.gui.module.js';
        import { Ocean } from '/examples/jsm/misc/Ocean.js';
        var lastTime = ( new Date() ).getTime();
        var DEMO = {
            ms_Renderer: null,
            ms_Camera: null,
            ms_Scene: null,
            ms_Controls: null,
            ms_Ocean: null,
            Initialize: function () {
                this.ms_Renderer = new THREE.WebGLRenderer({ alpha: true });
                this.ms_Renderer.setPixelRatio( window.devicePixelRatio );
                document.body.appendChild( this.ms_Renderer.domElement );
                this.ms_Scene = new THREE.Scene();
                this.ms_Camera = new THREE.PerspectiveCamera( 55.0, window.innerWidth / window.innerHeight, 0.5, 300000 );
                var gsize = 512;
                var res = 1024;
                var gres = res / 2;
                var origx = - gsize / 2;
                var origz = - gsize / 2;
                this.ms_Ocean = new Ocean( this.ms_Renderer, this.ms_Camera, this.ms_Scene,
                    {
                        USE_HALF_FLOAT: false,
                        INITIAL_SIZE: 256.0,
                        INITIAL_WIND: [ 10.0, 10.0 ],
                        INITIAL_CHOPPINESS: 1.5,
                        CLEAR_COLOR: [ 1.0, 1.0, 1.0, 0.0 ],
                        GEOMETRY_ORIGIN: [ origx, origz ],
                        SUN_DIRECTION: [ - 1.0, 1.0, 1.0 ],
                        OCEAN_COLOR: new THREE.Vector3( 0.004, 0.016, 0.047 ),
                        SKY_COLOR: new THREE.Vector3( 3.2, 9.6, 12.8 ),
                        EXPOSURE: 0.35,
                        GEOMETRY_RESOLUTION: gres,
                        GEOMETRY_SIZE: gsize,
                        RESOLUTION: res
                    } );
                this.ms_Ocean.materialOcean.uniforms[ "u_projectionMatrix" ] = { value: this.ms_Camera.projectionMatrix };
                this.ms_Ocean.materialOcean.uniforms[ "u_viewMatrix" ] = { value: this.ms_Camera.matrixWorldInverse };
                this.ms_Ocean.materialOcean.uniforms[ "u_cameraPosition" ] = { value: this.ms_Camera.position };
                this.ms_Scene.add( this.ms_Ocean.oceanMesh );

                // 調整したパラメータ設定
                this.ms_Camera.position.set(0, 80, 160);
                this.ms_Ocean.size = 100;
                this.ms_Ocean.choppiness = 4;
                this.ms_Ocean.windX = 15;
                this.ms_Ocean.windY = -15;
                this.ms_Ocean.sunDirectionX = -1;
                this.ms_Ocean.sunDirectionY = 1;
                this.ms_Ocean.sunDirectionZ = 1;
                this.ms_Ocean.exposure = 0.5;

                // const that = this;
                // this.controls = new function() {
                //     this.cpX = that.ms_Camera.position.x;
                //     this.cpY = that.ms_Camera.position.y;
                //     this.cpZ = that.ms_Camera.position.z;
                //     this.crX = that.ms_Camera.rotation.x;
                //     this.crY = that.ms_Camera.rotation.y;
                //     this.crZ = that.ms_Camera.rotation.z;
                // }
                // var gui = new GUI();
                // gui.add( this.controls, "cpX", -360, 360 ).onChange( function ( v ) {
                //     that.ms_Camera.position.set(this.object.cpX, this.object.cpY, this.object.cpZ);
                // } );
                // gui.add( this.controls, "cpY", -360, 360 ).onChange( function ( v ) {
                //     that.ms_Camera.position.set(this.object.cpX, this.object.cpY, this.object.cpZ);
                // } );
                // gui.add( this.controls, "cpZ", -360, 360 ).onChange( function ( v ) {
                //     that.ms_Camera.position.set(this.object.cpX, this.object.cpY, this.object.cpZ);
                // } );
                // gui.add( this.ms_Ocean, "size", 100, 5000 ).onChange( function ( v ) {
                //     this.object.size = v;
                //     this.object.changed = true;
                // } );
                // gui.add( this.ms_Ocean, "choppiness", 0.1, 4 ).onChange( function ( v ) {
                //     this.object.choppiness = v;
                //     this.object.changed = true;
                // } );
                // gui.add( this.ms_Ocean, "windX", - 15, 15 ).onChange( function ( v ) {
                //     this.object.windX = v;
                //     this.object.changed = true;
                // } );
                // gui.add( this.ms_Ocean, "windY", - 15, 15 ).onChange( function ( v ) {
                //     this.object.windY = v;
                //     this.object.changed = true;
                // } );
                // gui.add( this.ms_Ocean, "sunDirectionX", - 1.0, 1.0 ).onChange( function ( v ) {
                //     this.object.sunDirectionX = v;
                //     this.object.changed = true;
                // } );
                // gui.add( this.ms_Ocean, "sunDirectionY", - 1.0, 1.0 ).onChange( function ( v ) {
                //     this.object.sunDirectionY = v;
                //     this.object.changed = true;
                // } );
                // gui.add( this.ms_Ocean, "sunDirectionZ", - 1.0, 1.0 ).onChange( function ( v ) {
                //     this.object.sunDirectionZ = v;
                //     this.object.changed = true;
                // } );
                // gui.add( this.ms_Ocean, "exposure", 0.0, 0.5 ).onChange( function ( v ) {
                //     this.object.exposure = v;
                //     this.object.changed = true;
                // } );
            },
            Display: function () {
                this.ms_Renderer.render( this.ms_Scene, this.ms_Camera );
            },
            Update: function () {
                var currentTime = new Date().getTime();
                this.ms_Ocean.deltaTime = ( currentTime - lastTime ) / 1000 || 0.0;
                lastTime = currentTime;
                this.ms_Ocean.render( this.ms_Ocean.deltaTime );
                this.ms_Ocean.overrideMaterial = this.ms_Ocean.materialOcean;
                if ( this.ms_Ocean.changed ) {
                    this.ms_Ocean.materialOcean.uniforms[ "u_size" ].value = this.ms_Ocean.size;
                    this.ms_Ocean.materialOcean.uniforms[ "u_sunDirection" ].value.set( this.ms_Ocean.sunDirectionX, this.ms_Ocean.sunDirectionY, this.ms_Ocean.sunDirectionZ );
                    this.ms_Ocean.materialOcean.uniforms[ "u_exposure" ].value = this.ms_Ocean.exposure;
                    this.ms_Ocean.changed = false;
                }
                this.ms_Ocean.materialOcean.uniforms[ "u_normalMap" ].value = this.ms_Ocean.normalMapFramebuffer.texture;
                this.ms_Ocean.materialOcean.uniforms[ "u_displacementMap" ].value = this.ms_Ocean.displacementMapFramebuffer.texture;
                this.ms_Ocean.materialOcean.uniforms[ "u_projectionMatrix" ].value = this.ms_Camera.projectionMatrix;
                this.ms_Ocean.materialOcean.uniforms[ "u_viewMatrix" ].value = this.ms_Camera.matrixWorldInverse;
                this.ms_Ocean.materialOcean.uniforms[ "u_cameraPosition" ].value = this.ms_Camera.position;
                this.ms_Ocean.materialOcean.depthTest = true;
                this.Display();
            },
            Resize: function ( inWidth, inHeight ) {
                this.ms_Camera.aspect = inWidth / inHeight;
                this.ms_Camera.updateProjectionMatrix();
                this.ms_Renderer.setSize( inWidth, inHeight );
                this.Display();
            }
        };
        DEMO.Initialize();
        window.addEventListener( 'resize', function () {
            DEMO.Resize( window.innerWidth, window.innerHeight );
        } );
        DEMO.Resize( window.innerWidth, window.innerHeight );
        var render = function () {
            requestAnimationFrame( render );
            DEMO.Update();
        };
        render();
    </script>
</body>
</html>

できたもの

ヘッダとか背景に使えないかな~というイメージでした。

kyamahsita_20200705_02.gif

感想

如何でしたでしょうか?

ちょっと難しいところもありますが、3Dは面白いですね。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ