three.js 自定义sprite

//功能介绍:自定义sprite  

//1、可以自定义锚点,使sprite的各个顶点与模型进行对齐,例如 左对齐、右对齐、上对齐、下对齐

//2、可以设定图片的九宫格,部分拉伸效果处理

//3、可以设定是否根据距离自动衰减标签大小

//4、可以设定统一颜色或者顶点颜色

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - FBX loader</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #000;
                color: #fff;
                margin: 0px;
                overflow: hidden;
            }
            #info {
                color: #fff;
                position: absolute;
                top: 10px;
                width: 100%;
                text-align: center;
                z-index: 100;
                display:block;
            }
            #info a {
                color: #046;
                font-weight: bold;
            }
        </style>
    </head>

    <body>
        <div id="info">
            <a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - FBXLoader<br />
            Character and animation from <a href="https://www.mixamo.com/" target="_blank" rel="noopener">Mixamo</a>
        </div>

        <script src="../build/three.js"></script>
        <script src="js/libs/inflate.min.js"></script>
        <script src="js/loaders/FBXLoader.js"></script>
        <script src="js/loaders/TGALoader.js"></script>
        <script src="js/controls/OrbitControls.js"></script>
        <script src="js/WebGL.js"></script>
        <script src="js/libs/stats.min.js"></script>
        <script>
        
        
        /*function CustomSprite(){
            Object3D.call(this);
            
            //this.type = 'CustomSprite'
        }
        
        CustomSprite.prototype = Object.assign( Object.create(Object3D.prototype), {
            
            constructor: CustomSprite,
            isCustomSprite: true,
            
            onBeforeRender: 
        } );
        
        Object.potoType*/

            var container, stats, controls;
            var camera, scene, renderer, light;
            var clock = new THREE.Clock();

            var mesh;
            
            var mesh_cube;
        

            if ( WEBGL.isWebGLAvailable() === false ) {
                document.body.appendChild( WEBGL.getWebGLErrorMessage() );
            }

            init();
            animate();

            function init() {

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

                camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 200000 );
                camera.position.set( 100, 200, 300 );

                controls = new THREE.OrbitControls( camera );
                controls.update();

                scene = new THREE.Scene();

                light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
                light.position.set( 0, 200, 0 );
                scene.add( light );

                light = new THREE.DirectionalLight( 0xffffff );
                light.position.set( 0, 200, 100 );
                light.castShadow = true;
                light.shadow.camera.top = 180;
                light.shadow.camera.bottom = - 100;
                light.shadow.camera.left = - 120;
                light.shadow.camera.right = 120;
                scene.add( light );
                
                createSprite();

                var geometry_cube = new THREE.BufferGeometry();
                var vertices_cube = new Float32Array( [
                    -1.0, -1.0,  0.0,
                     1.0, -1.0,  0.0,
                     1.0,  1.0,  0.0,
                     1.0,  1.0,  0.0,
                    -1.0,  1.0,  0.0,
                    -1.0, -1.0,  0.0
                ] );

                geometry_cube.addAttribute( 'position', new THREE.BufferAttribute( vertices_cube, 3 ) );
                var material_cube = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
                mesh_cube = new THREE.Mesh( geometry_cube, material_cube );
                mesh_cube.scale.set(0.2, 0.2, 0.2);
                scene.add( mesh_cube );
                mesh_cube.add(mesh);
                //mesh_cube.translateX(100);
                
                renderer = new THREE.WebGLRenderer( { antialias: true } );
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                renderer.shadowMap.enabled = true;
                container.appendChild( renderer.domElement );

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

                // stats
                stats = new Stats();
                container.appendChild( stats.dom );
            }
            
            function createSprite(){
                var textureLoader = new THREE.TextureLoader();
                
                //九宫格的顶点坐标
                let widthX = [0, 160, 1000, 1200];
                let heightY = [0, 20, 80, 100];
                let vv = []; 
                for(let i = 0; i < 4; i++){
                    for(let j = 0; j < 4; j++){
                        vv.push({x:widthX[i], y: heightY[j], z:0});
                    }
                }
                
                let vertices_data = [];
                for(let m = 0; m < 3; m++){
                    for(let n = 0; n < 3; n++){
                        vertices_data.push(vv[4 * m + n].x,             vv[4 * m + n].y,             vv[4 * m + n].z);
                        vertices_data.push(vv[4 * (m + 1) + n + 1].x,     vv[4 * (m + 1) + n + 1].y,     vv[4 * (m + 1) + n + 1].z);
                        vertices_data.push(vv[4 * m + n + 1].x,         vv[4 * m + n + 1].y,         vv[4 * m + n + 1].z);
                        
                        vertices_data.push(vv[4 * m + n].x,                vv[4 * m + n].y,             vv[4 * m + n].z);
                        vertices_data.push(vv[4 * (m + 1) + n].x,         vv[4 * (m + 1) + n].y,         vv[4 * (m + 1) + n].z);
                        vertices_data.push(vv[4 * (m + 1) + n + 1].x,     vv[4 * (m + 1) + n + 1].y,     vv[4 * (m + 1) + n + 1].z);
                    }
                }
                
                //九宫格的uv坐标
                let u = [0, 0.25, 0.75, 1.0];
                let v = [0, 0.25, 0.75, 1.0];
                let uv = []; 
                for(let i = 0; i < 4; i++){
                    for(let j = 0; j < 4; j++){
                        uv.push({u: u[i], v: v[j]});
                    }
                }
                let uvs_data = [];
                for(let m = 0; m < 3; m++){
                    for(let n = 0; n < 3; n++){
                        uvs_data.push(uv[4 * m + n].u,                            uv[4 * m + n].v);
                        uvs_data.push(uv[4 * (m + 1) + n + 1].u,                 uv[4 * (m + 1) + n + 1].v);
                        uvs_data.push(uv[4 * m + n + 1].u,                         uv[4 * m + n + 1].v);
                        
                        uvs_data.push(uv[4 * m + n].u,                             uv[4 *m + n].v);
                        uvs_data.push(uv[4 * (m + 1) + n].u,                     uv[4 * (m + 1) + n].v);
                        uvs_data.push(uv[4 * (m + 1) + n + 1].u,                 uv[4 * (m + 1) + n + 1].v);
                    }
                }
                
                var geometry = new THREE.BufferGeometry();
                var uvs = new Float32Array( uvs_data );
                var vertices = new Float32Array( vertices_data );
                
                geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
                geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );

                mesh = new THREE.Mesh( geometry, new THREE.ShaderMaterial( {
                            uniforms: {
                                        uPos: {value: new THREE.Vector3(0)},
                                        uSize: {value: new THREE.Vector2(window.innerWidth, window.innerHeight)},
                                        uSizeAttenuation: {value: 0},                        //根据距离衰减
                                        uColor: {value: new THREE.Vector4(0.2,0.8,0.2,1)},
                                        uMap: { value: textureLoader.load( 'erpanqushuibengfang/test.png' )}, 
                                        },
                                        vertexShader: `    
                                            uniform vec3 uPos;
                                            uniform vec2 uSize;
                                            uniform int  uSizeAttenuation;
                                            varying vec2 vUv;
                                            void main() {
                                                vUv = uv;
                                                vec4 mvPosition = modelViewMatrix * vec4( uPos, 1.0 );
                                                vec4 screenpos = projectionMatrix * mvPosition;
                                                if(uSizeAttenuation == 1){

                                                    vec3 v = vec3(position.x,  position.y, 0);
                                                    screenpos += vec4(v, 0);
                                                } else {

                                                     vec3 v = vec3(position.x / uSize.x,  position.y / uSize.y, 0);
                                                    screenpos += vec4(v * screenpos.w, 0);
                                                }
                                                
                                                gl_Position = screenpos;
                                            }`,
                                fragmentShader: ` 
                                uniform vec4 uColor;
                                uniform sampler2D uMap;
                                varying vec2 vUv;
                                void main() {
                                    vec2 uv = vec2(vUv.x, vUv.y);
                                    gl_FragColor = texture2D( uMap, uv) * uColor;
                                    //gl_FragColor = vec4(1.0);
                                }`//,
                                //wireframe:true
                    }) );
                    
                mesh.onBeforeRender = function ( renderer) {
                    var size = renderer.getDrawingBufferSize( new THREE.Vector2() );
                    this.material.uniforms.uSize.value = size;
                };
                mesh.receiveShadow = false;
                mesh.castShadow = false;
            }
            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize( window.innerWidth, window.innerHeight );
            }
            function animate() {
                requestAnimationFrame( animate );
                var delta = clock.getDelta();
                //mesh_cube.translateX(delta);
                renderer.render( scene, camera );
                stats.update();
            }
        </script>
    </body>
</html>

 

原图:

效果:

具体应用:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值