redfelix
redfelix

Reputation: 149

Threejs: WebGL 3D text to three.js ocean scene

I'm working with the three.js ocean scene and 3D canvas text. The 3D text is suppose to replace the location of the ball, but the text doesn't appear. When I inspect elements, I only notice the canvas for the background rendering. How can both canvases- the background and 3D text- appear? How can I overlay a canvas on another? What is another way to have 3D text over the water without using canvas or canvasrenderer.js for the 3D text?

Original code for Canvas 3D Text: https://github.com/mrdoob/three.js/blob/master/examples/canvas_geometry_text.html

JavaScript to combine both elements:

var container, stats;
        var camera, scene, renderer;

        var parameters = {
            width: 2000,
            height: 2000,
            widthSegments: 250,
            heightSegments: 250,
            depth: 1500,
            param: 4,
            filterparam: 1
        };
        var waterNormals;
        var group;

        var targetRotation = 0;
        var targetRotationOnMouseDown = 0;

        var loader = new THREE.FontLoader();
        loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {

        } );
        init();
        animate();
        function init( font ) {

            container = document.createElement( 'div' );
            document.body.appendChild( container );



            camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
            camera.position.set( 0, 150, 500 );

            scene = new THREE.Scene();

            // Get text from hash

            var theText = "three.js";

            var hash = document.location.hash.substr( 1 );

            if ( hash.length !== 0 ) {

                theText = hash;

            }

            var geometry0 = new THREE.TextGeometry( theText, {

                font: font,
                size: 80,
                height: 20,
                curveSegments: 2

            });

            geometry.computeBoundingBox();

            var centerOffset = -0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );

            var material0 = new THREE.MultiMaterial( [
                new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } ),
                new THREE.MeshBasicMaterial( { color: 0x000000, overdraw: 0.5 } )
            ] );

            var mesh = new THREE.Mesh( geometry0, material0 );

            mesh.position.x = centerOffset;
            mesh.position.y = 100;
            mesh.position.z = 50;



            group = new THREE.Group();
            group.add( mesh );

            scene.add( group );

            renderer = new THREE.CanvasRenderer();
            renderer.setClearColor( 0xf0f0f0 );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );

            stats = new Stats();
            container.appendChild( stats.dom );

            //

            window.addEventListener( 'resize', onWindowResize, false );

        }
        function onWindowResize() {

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize( window.innerWidth, window.innerHeight );

        }
        function init() {
            container = document.createElement( 'div' );
            document.body.appendChild( container );
            renderer = new THREE.WebGLRenderer();
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
            camera.position.set( 2000, 750, 2000 );
            controls = new THREE.OrbitControls( camera, renderer.domElement );
            controls.enablePan = false;
            controls.minDistance = 1000.0;
            controls.maxDistance = 5000.0;
            controls.maxPolarAngle = Math.PI * 0.495;
            controls.target.set( 0, 500, 0 );
            scene.add( new THREE.AmbientLight( 0x444444 ) );
            var light = new THREE.DirectionalLight( 0xffffbb, 1 );
            light.position.set( - 1, 1, - 1 );
            scene.add( light );
            waterNormals = new THREE.TextureLoader().load( 'textures/waternormals.jpg' );
            waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
            water = new THREE.Water( renderer, camera, scene, {
                textureWidth: 512,
                textureHeight: 512,
                waterNormals: waterNormals,
                alpha:  1.0,
                sunDirection: light.position.clone().normalize(),
                sunColor: 0xffffff,
                waterColor: 0x001e0f,
                distortionScale: 50.0,
            } );
            mirrorMesh = new THREE.Mesh(
                new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
                water.material
            );
            mirrorMesh.add( water );
            mirrorMesh.rotation.x = - Math.PI * 0.5;
            scene.add( mirrorMesh );
            // load skybox
            var cubeMap = new THREE.CubeTexture( [] );
            cubeMap.format = THREE.RGBFormat;
            var loader = new THREE.ImageLoader();
            loader.load( 'textures/skyboxsun25degtest.png', function ( image ) {
                var getSide = function ( x, y ) {
                    var size = 1024;
                    var canvas = document.createElement( 'canvas' );
                    canvas.width = size;
                    canvas.height = size;
                    var context = canvas.getContext( '2d' );
                    context.drawImage( image, - x * size, - y * size );
                    return canvas;
                };
                cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
                cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
                cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
                cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
                cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
                cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
                cubeMap.needsUpdate = true;
            } );
            var cubeShader = THREE.ShaderLib[ 'cube' ];
            cubeShader.uniforms[ 'tCube' ].value = cubeMap;
            var skyBoxMaterial = new THREE.ShaderMaterial( {
                fragmentShader: cubeShader.fragmentShader,
                vertexShader: cubeShader.vertexShader,
                uniforms: cubeShader.uniforms,
                depthWrite: false,
                side: THREE.BackSide
            } );
            var skyBox = new THREE.Mesh(
                new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
                skyBoxMaterial
            );
            scene.add( skyBox );
            var geometry = new THREE.IcosahedronGeometry( 400, 4 );
            for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
                geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
            }
            var material = new THREE.MeshPhongMaterial( {
                vertexColors: THREE.FaceColors,
                shininess: 100,
                envMap: cubeMap
            } );

        }
        //
        function animate() {
            requestAnimationFrame( animate );
            render();
        }
        function render() {


            water.material.uniforms.time.value += 1.0 / 60.0;
            controls.update();
            water.render();
            renderer.render( scene, camera );
        }

Upvotes: 0

Views: 1359

Answers (1)

Nick Briz
Nick Briz

Reputation: 1977

The first thing i notice is that you are calling the init(); animate(); functions before the loader has a chance to load the font ( and because of that you are not passing the font into the init function like the canvas_geometry_text example ).

I've pasted the code from the ocean example below ( with comments for how I modified it to work with the code from the canvas_geometry_text example ). I've tested this and it works

        var container, stats;
        var camera, scene, renderer;
        var sphere;

        var parameters = {
            width: 2000,
            height: 2000,
            widthSegments: 250,
            heightSegments: 250,
            depth: 1500,
            param: 4,
            filterparam: 1
        };

        var waterNormals;

        // 1. 
        // copy+paste this code from the canvas_geometry_text file
        var loader = new THREE.FontLoader();
        loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {

            init( font );
            animate();

        } );

        // 2. 
        // comment out these calls to init() and animate() 
        // these will be called in the loader's callback above instead
        // init();
        // animate();

        // add 'font' parameter to init
        function init( font ) {

            container = document.createElement( 'div' );
            document.body.appendChild( container );

            renderer = new THREE.WebGLRenderer();
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );

            scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
            camera.position.set( 2000, 750, 2000 );

            controls = new THREE.OrbitControls( camera, renderer.domElement );
            controls.enablePan = false;
            controls.minDistance = 1000.0;
            controls.maxDistance = 5000.0;
            controls.maxPolarAngle = Math.PI * 0.495;
            controls.target.set( 0, 500, 0 );

            scene.add( new THREE.AmbientLight( 0x444444 ) );

            var light = new THREE.DirectionalLight( 0xffffbb, 1 );
            light.position.set( - 1, 1, - 1 );
            scene.add( light );


            waterNormals = new THREE.TextureLoader().load( 'textures/waternormals.jpg' );
            waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;

            water = new THREE.Water( renderer, camera, scene, {
                textureWidth: 512,
                textureHeight: 512,
                waterNormals: waterNormals,
                alpha:  1.0,
                sunDirection: light.position.clone().normalize(),
                sunColor: 0xffffff,
                waterColor: 0x001e0f,
                distortionScale: 50.0,
            } );


            mirrorMesh = new THREE.Mesh(
                new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
                water.material
            );

            mirrorMesh.add( water );
            mirrorMesh.rotation.x = - Math.PI * 0.5;
            scene.add( mirrorMesh );


            // load skybox

            var cubeMap = new THREE.CubeTexture( [] );
            cubeMap.format = THREE.RGBFormat;

            var loader = new THREE.ImageLoader();
            loader.load( 'textures/skyboxsun25degtest.png', function ( image ) {

                var getSide = function ( x, y ) {

                    var size = 1024;

                    var canvas = document.createElement( 'canvas' );
                    canvas.width = size;
                    canvas.height = size;

                    var context = canvas.getContext( '2d' );
                    context.drawImage( image, - x * size, - y * size );

                    return canvas;

                };

                cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
                cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
                cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
                cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
                cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
                cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
                cubeMap.needsUpdate = true;

            } );

            var cubeShader = THREE.ShaderLib[ 'cube' ];
            cubeShader.uniforms[ 'tCube' ].value = cubeMap;

            var skyBoxMaterial = new THREE.ShaderMaterial( {
                fragmentShader: cubeShader.fragmentShader,
                vertexShader: cubeShader.vertexShader,
                uniforms: cubeShader.uniforms,
                depthWrite: false,
                side: THREE.BackSide
            } );

            var skyBox = new THREE.Mesh(
                new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
                skyBoxMaterial
            );

            scene.add( skyBox );

            // 3.
            // comment out all the sphere mesh code

            // var geometry = new THREE.IcosahedronGeometry( 400, 4 );

            // for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {

            //  geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );

            // }

            // var material = new THREE.MeshPhongMaterial( {
            //  vertexColors: THREE.FaceColors,
            //  shininess: 100,
            //  envMap: cubeMap
            // } );

            // sphere = new THREE.Mesh( geometry, material );
            // scene.add( sphere );

            // 4.
            // copy+paste the text mesh code from canvas_geometry_text

            var theText = "Hello three.js! :)";

            var hash = document.location.hash.substr( 1 );

            if ( hash.length !== 0 ) {

                theText = hash;

            }

            var geometry = new THREE.TextGeometry( theText, {

                font: font,
                size: 80,
                height: 20,
                curveSegments: 2

            });

            geometry.computeBoundingBox();

            var centerOffset = -0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );

            var material = new THREE.MultiMaterial( [
                new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } ),
                new THREE.MeshBasicMaterial( { color: 0x000000, overdraw: 0.5 } )
            ] );

            var mesh = new THREE.Mesh( geometry, material );

            mesh.position.x = centerOffset;
            mesh.position.y = 100;
            mesh.position.z = 0;

            mesh.rotation.x = 0;
            mesh.rotation.y = Math.PI * 2;

            group = new THREE.Group();
            group.add( mesh );

            scene.add( group );
        }

        //

        function animate() {

            requestAnimationFrame( animate );
            render();

        }

        function render() {

            var time = performance.now() * 0.001;

            // 6.
            // comment out the sphere animation code

            // sphere.position.y = Math.sin( time ) * 500 + 250;
            // sphere.rotation.x = time * 0.5;
            // sphere.rotation.z = time * 0.51;

            // 7.
            // copy+paste the sphere animation code above
            // but replace 'sphere' with 'group'

            group.position.y = Math.sin( time ) * 500 + 250;
            group.rotation.x = time * 0.5;
            group.rotation.z = time * 0.51;

            water.material.uniforms.time.value += 1.0 / 60.0;
            controls.update();
            water.render();
            renderer.render( scene, camera );

        }

Upvotes: 1

Related Questions