threeJS紋理控制偏移+Sprite標籤運用

需要電子檔書籍或者源碼可以Q羣:828202939   希望可以和大家一起學習、一起進步!!

如有錯別字或有理解不到位的地方,可以留言或者加微信15250969798,博主會及時修改!!!!!

本章節主要涉及的知識點是:

1、canvas繪製(繪製線、曲線)

2、threeJS中處理2個捱得極近的物體

3、紋理的控制(紋理的偏移控制)

4、精靈材質+canvas作爲紋理的運用

其他的都是一些基礎的知識

效果錄屏:

代碼:

<html>

<head>
    <title>紋理偏移+Sprite標籤</title>
    <style>
        body {
            background-color: #000;
            margin: 0px;
            overflow: hidden;
        }

        #WebGL {
            width: 100%;
            height: 100%;
            position: absolute;
            left: 0;
            top: 0;
            z-index: 999;
        }
    </style>
</head>

<body>
    <div id="WebGL"></div>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
    <script src="../../../build/three.js"></script>
    <script src="../../../examples/js/controls/OrbitControls.js"></script>
    <script src="./texture.js"></script>
</body>

</html>

        'use strict';
        var container, camera, scene, renderer, geometry, material, controls; //常用變量
        var spotLight, mesh_sphere; //自定義對象變量
        var target = new THREE.Vector3(0, 30, 0);
        var webGLW = $('#WebGL').width();
        var webGLH = $('#WebGL').height();
        var textureLoader = new THREE.TextureLoader(); //紋理加載器
        init();
        animate();

        function init() {
            container = document.getElementById('WebGL');
            rendererScene(); //場景渲染
            sceneBackground();
            camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
            camera.position.set(0, 50, 200);
            camera.lookAt(target);
            plane() //// 地面
            lights(); //燈光:聚光燈
            addMovePlane(scene); //推薦偏移的平面和圓
            loadModel(); //添加模型
            OrbitControls(camera, renderer); //OrbitControls控件模塊
            window.addEventListener('resize', onWindowResize, false); //監聽屏幕變化
        }

        function sceneBackground() {
            scene = new THREE.Scene();
            // scene.background = new THREE.Color(0xcfcfcf);//可以用圖片代替作爲背景
            var path = '../image/sky/';
            var format = '.jpg';
            new THREE.CubeTextureLoader().load([
                path + 'px' + format, path + 'nx' + format, //右左
                path + 'py' + format, path + 'ny' + format, //上下
                path + 'pz' + format, path + 'nz' + format //前後
            ], function (res) {
                scene.background = res;
            });
            // // scene.fog = new THREE.Fog(0xa0a0a0, 200, 1000); //霧
        }


        function plane() {
            texture_plane = textureLoader.load('../image/textureOffset.png');
            texture_plane.wrap = texture_plane.wrapT = THREE.RepeatWrapping; //平鋪重複
            texture_plane.anisotropy = renderer.capabilities.getMaxAnisotropy();
            // 地面
            let geometry = new THREE.PlaneBufferGeometry(200, 200);
            let grid_mesh = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({
                color: 0x999999,
                // depthWrite: false
            }));
            grid_mesh.rotation.x = -Math.PI / 2;
            grid_mesh.receiveShadow = true;
            scene.add(grid_mesh);

            var grid = new THREE.GridHelper(200, 20, 0x000000, 0x000000);
            grid.material.opacity = 0.2;
            grid.material.transparent = true;
            scene.add(grid);

        }

        function lights() { //光影自己改哦

            var ambient = new THREE.AmbientLight(0xffffff);
            scene.add(ambient);
            //聚光燈
            //  SpotLight( color:顏色, intensity:強度, distance:發光距離, angle:角度, penumbra:邊緣範圍, decay:衰減 )
            spotLight = new THREE.SpotLight(0xffffff, 1);
            spotLight.position.set(0, 120, 0);
            spotLight.angle = Math.PI / 6;
            spotLight.penumbra = 0.05; //邊緣範圍,反比
            spotLight.decay = 2; //衰減係數,反比
            spotLight.distance = 400; //發光距離
            spotLight.castShadow = true; //陰影
            spotLight.shadow.mapSize.width = 1024;
            spotLight.shadow.mapSize.height = 1024;
            spotLight.shadow.camera.near = 10; //近截面
            spotLight.shadow.camera.far = 250;
            scene.add(spotLight);
        }

        function lightsHelper(lightsObject) {
            // 聚光燈顯示助手SpotLightHelper( light:燈光, color:顏色 )
            var lightHelper = new THREE.SpotLightHelper(lightsObject, 0xdfdfdf);
            scene.add(lightHelper);
            let mesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(100, 100), new THREE.MeshPhongMaterial({
                color: 0x9cfcf99,
                depthWrite: false
            }));
            mesh.rotation.x = -Math.PI / 2;
            mesh.position.set(0, -20, 0)
            mesh.receiveShadow = true;
            scene.add(mesh);
        }

        var texture_plane;

        function addMovePlane(scene) {
            // 背景平面
            let geometry02 = new THREE.PlaneBufferGeometry(150, 100);
            let plane_back = new THREE.Mesh(geometry02, new THREE.MeshPhongMaterial({
                map: texture_plane,
                transparent: true,
            }));
            plane_back.position.set(0, 50, -100);
            plane_back.name = 'plane';
            let plane_back_make =makeTextSprite(plane_back.name,{
                fontsize: 80,
                borderColor: {r:180, g:125, b:125, a:0.4},/* 邊框顏色 */
                backgroundColor: {r:255, g:255, b:255, a:0.9}/* 背景顏色 */
            })
            plane_back_make.center = new THREE.Vector2(0, 0);
            plane_back_make.name='plane_back_make';
            let plane_back_parameters=plane_back.geometry.parameters ;
            plane_back_make.position.set(-(plane_back_parameters.width/2+15),plane_back.position.y , plane_back.position.z);
            scene.add(plane_back,plane_back_make);

            let circle = new THREE.Mesh(new THREE.CircleGeometry(60, 100, 100), new THREE.MeshPhongMaterial({
                map: texture_plane,
                transparent: true,
                depthTest: false //關閉檢測,讓2個重疊的平面正確顯示
            }));
            circle.rotation.x = -Math.PI / 2;
            circle.name = 'circle';
            scene.add(circle);
        }
        var texture_sphere;

        function loadModel() { //模型
            //圓球
            texture_sphere = textureLoader.load('../image/textureOffset.png');
            texture_sphere.wrap = texture_sphere.wrapT = THREE.RepeatWrapping; //平鋪重複
            mesh_sphere = new THREE.Mesh(
                new THREE.SphereBufferGeometry(20, 20, 20),
                new THREE.MeshBasicMaterial({
                    color: 0xffffff,
                    map: texture_sphere,
                    side: 2,
                    transparent: true,
                    // wireframe: true
                })
            );
            mesh_sphere.position.set(0, 30, 0)
            mesh_sphere.name = 'sphere';
            let mesh_sphere_make =makeTextSprite(mesh_sphere.name,{
                fontsize: 80,
                borderColor: {r:180, g:125, b:125, a:0.4},/* 邊框顏色 */
                backgroundColor: {r:255, g:255, b:255, a:0.9}/* 背景顏色 */
            })
            mesh_sphere_make.center = new THREE.Vector2(0, 0);
            mesh_sphere_make.name='mesh_sphere_make';
            let mesh_sphere_parameters=mesh_sphere.geometry.parameters ;
            mesh_sphere_make.position.set(-(mesh_sphere_parameters.radius+15),mesh_sphere.position.y , mesh_sphere.position.z);
            scene.add(mesh_sphere,mesh_sphere_make);


        }
        /* 創建字體精靈 */
        function makeTextSprite(message, parameters) {

            if (parameters === undefined) parameters = {};
            
            /* 字體 */
            let fontface = parameters.hasOwnProperty("fontface") ?
                parameters["fontface"] : "Arial";

            /* 字體大小 */
            let fontsize = parameters.hasOwnProperty("fontsize") ?
                parameters["fontsize"] : 10;

            /* 邊框厚度 */
            let borderThickness = parameters.hasOwnProperty("borderThickness") ?
                parameters["borderThickness"] : 4;

            /* 邊框顏色 */
            let borderColor = parameters.hasOwnProperty("borderColor") ?
                parameters["borderColor"] : {
                    r: 0,
                    g: 0,
                    b: 0,
                    a: 1.0
                };

            /* 背景顏色 */
            let backgroundColor = parameters.hasOwnProperty("backgroundColor") ?
                parameters["backgroundColor"] : {
                    r: 255,
                    g: 255,
                    b: 255,
                    a: 1.0
                };

            /* 創建畫布 */
            let canvas = document.createElement('canvas');
            let context = canvas.getContext('2d');

            /* 字體加粗 */
            context.font = "Bold " + fontsize + "px " + fontface;

            /* 獲取文字的大小數據,高度取決於文字的大小 */
            let metrics = context.measureText(message);
            console.log('文字metrics::',metrics);
            
            let textWidth = metrics.width;

            /* 背景顏色 */
            context.fillStyle = "rgba(" + backgroundColor.r + "," + backgroundColor.g + "," +
                backgroundColor.b + "," + backgroundColor.a + ")";

            /* 邊框的顏色 */
            context.strokeStyle = "rgba(" + borderColor.r + "," + borderColor.g + "," +
                borderColor.b + "," + borderColor.a + ")";
            context.lineWidth = borderThickness;

            /* 繪製圓角矩形 */
            roundRect(context, borderThickness / 2, borderThickness / 2, textWidth + borderThickness, fontsize * 1.4 +
                borderThickness, 30);

            /* 字體顏色 */
            context.fillStyle = "rgba(0, 0, 0, 1.0)";
            context.fillText(message, borderThickness, fontsize + borderThickness);

            /* 畫布內容用於紋理貼圖 */
            let texture = new THREE.Texture(canvas);
            texture.needsUpdate = true;

            let spriteMaterial = new THREE.SpriteMaterial({
                map: texture
            });
            let sprite = new THREE.Sprite(spriteMaterial);

            console.log(sprite.spriteMaterial);

            /* 縮放比例 */
            sprite.scale.set(10, 5, 1);

            return sprite;

        }

        /**
         * @method 繪製圓角矩形 
         * @param {*} ctx canvas畫布
         * @param {*} x x位置
         * @param {*} y y位置
         * @param {*} w 寬
         * @param {*} h 高
         * @param {*} r 圓角的半徑
         */
        function roundRect(ctx, x, y, w, h, r) {

            ctx.beginPath();
            // 起始點(左上圓角處的直線位置)
            ctx.moveTo(x + r, y);
            // 矩形上寬線條(突出來一點)
            ctx.lineTo(x + w*1.5 - r, y);
            // 繪製左上圓角(二次貝塞爾曲線)
            ctx.quadraticCurveTo(x + w, y, x + w, y + r);
            // 右高線條
            ctx.lineTo(x + w, y + h - r);
            // 右下圓角
            ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
            // 左下線條
            ctx.lineTo(x + r, y + h);
            // 左下圓角
            ctx.quadraticCurveTo(x, y + h, x, y + h - r);
            // 左高線條
            ctx.lineTo(x, y + r);
            // 左上圓角
            ctx.quadraticCurveTo(x, y, x + r, y);
            ctx.closePath();
            ctx.fill();
            ctx.stroke();

        }

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);

        }

        function rendererScene() {
            renderer = new THREE.WebGLRenderer({
                antialias: true
            });
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMap.enabled = true;
            renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            renderer.gammaInput = true;
            renderer.gammaOutput = true;
            container.appendChild(renderer.domElement);
        }

        function OrbitControls(camera, renderer) {
            //OrbitControls控件操作模塊
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.target = target; //控制的target
            // controls.autoRotate = true; //是否自動旋轉
            // controls.autoRotateSpeed = 0.2; //自動旋轉速度,正比
        }
        /* 數據更新 */
        function updata() {
            // 設置紋理偏移
            var time = Date.now() * 0.004;
            // texture_sphere.offset.y = (Math.sin(time)*0.1);//往返偏移
            texture_sphere.offset.x += 0.001; //左右偏移
            if (texture_sphere.offset.x >= 0.5) {
                texture_sphere.offset.x = 0;
            }

            texture_plane.offset.y -= 0.005;
        }

        function animate() {
            requestAnimationFrame(animate);
            if (controls) controls.update();
            updata();
            renderer.render(scene, camera);
        };
    

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章