HTML礼物圣诞树

发布于:2024-12-08 ⋅ 阅读:(140) ⋅ 点赞:(0)

系列文章

序号 目录
1 HTML满屏跳动的爱心(可写字)
2 HTML五彩缤纷的爱心
3 HTML满屏漂浮爱心
4 HTML情人节快乐
5 HTML蓝色爱心射线
6 HTML跳动的爱心(简易版)
7 HTML粒子爱心
8 HTML蓝色动态爱心
9 HTML跳动的爱心(双心版)
10 HTML橙色动态粒子爱心
11 HTML旋转爱心
12 HTML爱情树
13 HTML3D相册
14 HTML旋转相册
15 HTML基础烟花秀
16 HTML炫酷烟花秀
17 HTML粉色烟花秀
18 HTML新春烟花
19 HTML龙年大吉
20 HTML音乐圣诞树
21 HTML大雪纷飞
22 HTML想见你
23 HTML元素周期表
24 HTML飞舞的花瓣
25 HTML星空特效
26 HTML黑客帝国字母雨
27 HTML哆啦A梦
28 HTML流星雨
29 HTML沙漏爱心
30 HTML爱心字母雨
31 HTML爱心流星雨
32 HTML生日蛋糕
33 HTML3D旋转相册
34 HTML流光爱心
35 HTML满屏飘字
36 HTML飞舞爱心
37 HTML雪花圣诞树

写在前面

HTML语言实现礼物圣诞树的完整代码。

HTML语言

HTML语言(Hypertext Markup Language)是一种用于创建网页的标记语言。它使用标记来描述网页的结构和内容,并定义了网页中的各种元素和布局。

HTML语言由一系列标签组成,每个标签都用尖括号包围,例如:`<tag>content</tag>`。标签用于定义网页中的各种元素,如标题、段落、列表、链接等。

HTML语言的标签主要分为两类:块级元素和内联元素。块级元素占据一整行,例如段落标签`<p>`、标题标签`<h1>`等,它们可以包含其他块级元素或内联元素。内联元素只占据一定的空间,例如加粗标签`<b>`、链接标签`<a>`等,它们不能包含块级元素。

除了标签,HTML语言还有属性。属性用于为标签提供附加信息,如链接的目标网址、图片的地址、元素的样式等。属性通常在标签的开始标签中进行定义,例如:`<tag attribute="value">content</tag>`。

HTML语言的结构主要由`<!DOCTYPE>`声明、`<html>`元素、`<head>`元素和`<body>`元素组成。`<!DOCTYPE>`声明用于指定HTML版本,`<html>`元素是HTML文档的根元素,`<head>`元素用于定义文档的元信息,如标题、样式和脚本等,`<body>`元素包含网页的实际内容。

在HTML语言中,可以通过嵌套标签、引用外部样式表和脚本、使用CSS语言定义样式、使用JavaScript语言添加交互功能等来实现丰富的网页效果和功能。

HTML语言是一种简单易学的标记语言,几乎所有的网页都是使用HTML语言来创建的。它被广泛应用于互联网和Web开发领域,是构建网页和浏览器显示内容的基础。随着技术的进步,HTML语言不断更新和发展,目前最新的版本是HTML5,它提供了更多的新特性和改进,如多媒体支持、本地存储、Canvas绘图等。

总的来说,HTML语言是一种用于创建网页的标记语言,通过标签和属性来描述网页的结构和内容。它是构建网页和Web应用的基础,广泛应用于互联网和Web开发领域,是学习Web开发的重要基础知识。

完整代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />

    <title>圣诞快乐</title>

    <style>
    <script>
     THREE.EffectComposer = function ( renderer, renderTarget ) {
     
       this.renderer = renderer;
     
       if ( renderTarget === undefined ) {
     
         var parameters = {
           minFilter: THREE.LinearFilter,
           magFilter: THREE.LinearFilter,
           format: THREE.RGBAFormat,
           stencilBuffer: false
         };
     
         var size = renderer.getSize( new THREE.Vector2() );
         this._pixelRatio = renderer.getPixelRatio();
         this._width = size.width;
         this._height = size.height;
     
         renderTarget = new THREE.WebGLRenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, parameters );
         renderTarget.texture.name = 'EffectComposer.rt1';
     
       } else {
     
         this._pixelRatio = 1;
         this._width = renderTarget.width;
         this._height = renderTarget.height;
     
       }
     
       this.renderTarget1 = renderTarget;
       this.renderTarget2 = renderTarget.clone();
       this.renderTarget2.texture.name = 'EffectComposer.rt2';
     
       this.writeBuffer = this.renderTarget1;
       this.readBuffer = this.renderTarget2;
     
       this.renderToScreen = true;
     
       this.passes = [];
     
       // dependencies
     
       if ( THREE.CopyShader === undefined ) {
     
         console.error( 'THREE.EffectComposer relies on THREE.CopyShader' );
     
       }
     
       if ( THREE.ShaderPass === undefined ) {
     
         console.error( 'THREE.EffectComposer relies on THREE.ShaderPass' );
     
       }
     
       this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
     
       this.clock = new THREE.Clock();
     
     };
     
     Object.assign( THREE.EffectComposer.prototype, {
     
       swapBuffers: function () {
     
         var tmp = this.readBuffer;
         this.readBuffer = this.writeBuffer;
         this.writeBuffer = tmp;
     
       },
     
       addPass: function ( pass ) {
     
         this.passes.push( pass );
         pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );
     
       },
     
       insertPass: function ( pass, index ) {
     
         this.passes.splice( index, 0, pass );
     
       },
     
       isLastEnabledPass: function ( passIndex ) {
     
         for ( var i = passIndex + 1; i < this.passes.length; i ++ ) {
     
           if ( this.passes[ i ].enabled ) {
     
             return false;
     
           }
     
         }
     
         return true;
     
       },
     
       render: function ( deltaTime ) {
     
         // deltaTime value is in seconds
     
         if ( deltaTime === undefined ) {
     
           deltaTime = this.clock.getDelta();
     
         }
     
         var currentRenderTarget = this.renderer.getRenderTarget();
     
         var maskActive = false;
     
         var pass, i, il = this.passes.length;
     
         for ( i = 0; i < il; i ++ ) {
     
           pass = this.passes[ i ];
     
           if ( pass.enabled === false ) continue;
     
           pass.renderToScreen = ( this.renderToScreen && this.isLastEnabledPass( i ) );
           pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive );
     
           if ( pass.needsSwap ) {
     
             if ( maskActive ) {
     
               var context = this.renderer.getContext();
               var stencil = this.renderer.state.buffers.stencil;
     
               //context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
               stencil.setFunc( context.NOTEQUAL, 1, 0xffffffff );
     
               this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime );
     
               //context.stencilFunc( context.EQUAL, 1, 0xffffffff );
               stencil.setFunc( context.EQUAL, 1, 0xffffffff );
     
             }
     
             this.swapBuffers();
     
           }
     
           if ( THREE.MaskPass !== undefined ) {
     
             if ( pass instanceof THREE.MaskPass ) {
     
               maskActive = true;
     
             } else if ( pass instanceof THREE.ClearMaskPass ) {
     
               maskActive = false;
     
             }
     
           }
     
         }
     
         this.renderer.setRenderTarget( currentRenderTarget );
     
       },
     
       reset: function ( renderTarget ) {
     
         if ( renderTarget === undefined ) {
     
           var size = this.renderer.getSize( new THREE.Vector2() );
           this._pixelRatio = this.renderer.getPixelRatio();
           this._width = size.width;
           this._height = size.height;
     
           renderTarget = this.renderTarget1.clone();
           renderTarget.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );
     
         }
     
         this.renderTarget1.dispose();
         this.renderTarget2.dispose();
         this.renderTarget1 = renderTarget;
         this.renderTarget2 = renderTarget.clone();
     
         this.writeBuffer = this.renderTarget1;
         this.readBuffer = this.renderTarget2;
     
       },
     
       setSize: function ( width, height ) {
     
         this._width = width;
         this._height = height;
     
         var effectiveWidth = this._width * this._pixelRatio;
         var effectiveHeight = this._height * this._pixelRatio;
     
         this.renderTarget1.setSize( effectiveWidth, effectiveHeight );
         this.renderTarget2.setSize( effectiveWidth, effectiveHeight );
     
         for ( var i = 0; i < this.passes.length; i ++ ) {
     
           this.passes[ i ].setSize( effectiveWidth, effectiveHeight );
     
         }
     
       },
     
       setPixelRatio: function ( pixelRatio ) {
     
         this._pixelRatio = pixelRatio;
     
         this.setSize( this._width, this._height );
     
       }
     
     } );
     
     
     THREE.Pass = function () {
     
       // if set to true, the pass is processed by the composer
       this.enabled = true;
     
       // if set to true, the pass indicates to swap read and write buffer after rendering
       this.needsSwap = true;
     
       // if set to true, the pass clears its buffer before rendering
       this.clear = false;
     
       // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer.
       this.renderToScreen = false;
     
     };
     
     Object.assign( THREE.Pass.prototype, {
     
       setSize: function ( /* width, height */ ) {},
     
       render: function ( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) {
     
         console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );
     
       }
     
     } );
     
     // Helper for passes that need to fill the viewport with a single quad.
     THREE.Pass.FullScreenQuad = ( function () {
     
       var camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
       var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
     
       var FullScreenQuad = function ( material ) {
     
         this._mesh = new THREE.Mesh( geometry, material );
     
       };
     
       Object.defineProperty( FullScreenQuad.prototype, 'material', {
     
         get: function () {
     
           return this._mesh.material;
     
         },
     
         set: function ( value ) {
     
           this._mesh.material = value;
     
         }
     
       } );
     
       Object.assign( FullScreenQuad.prototype, {
     
         dispose: function () {
     
           this._mesh.geometry.dispose();
     
         },
     
         render: function ( renderer ) {
     
           renderer.render( this._mesh, camera );
     
         }
     
       } );
     
       return FullScreenQuad;
     
     } )();
     </script>
    <script>
  
     THREE.RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) {
     
       THREE.Pass.call( this );
     
       this.scene = scene;
       this.camera = camera;
     
       this.overrideMaterial = overrideMaterial;
     
       this.clearColor = clearColor;
       this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
     
       this.clear = true;
       this.clearDepth = false;
       this.needsSwap = false;
     
     };
     
     THREE.RenderPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
     
       constructor: THREE.RenderPass,
     
       render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {
     
         var oldAutoClear = renderer.autoClear;
         renderer.autoClear = false;
     
         var oldClearColor, oldClearAlpha, oldOverrideMaterial;
     
         if ( this.overrideMaterial !== undefined ) {
     
           oldOverrideMaterial = this.scene.overrideMaterial;
     
           this.scene.overrideMaterial = this.overrideMaterial;
     
         }
     
         if ( this.clearColor ) {
     
           oldClearColor = renderer.getClearColor().getHex();
           oldClearAlpha = renderer.getClearAlpha();
     
           renderer.setClearColor( this.clearColor, this.clearAlpha );
     
         }
     
         if ( this.clearDepth ) {
     
           renderer.clearDepth();
     
         }
     
         renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
     
         // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
         if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
         renderer.render( this.scene, this.camera );
     
         if ( this.clearColor ) {
     
           renderer.setClearColor( oldClearColor, oldClearAlpha );
     
         }
     
         if ( this.overrideMaterial !== undefined ) {
     
           this.scene.overrideMaterial = oldOverrideMaterial;
     
         }
     
         renderer.autoClear = oldAutoClear;
     
       }
     
     } );
     </script>
    <script>/**
      * @author alteredq / http://alteredqualia.com/
      */
     
     THREE.ShaderPass = function ( shader, textureID ) {
     
       THREE.Pass.call( this );
     
       this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse";
     
       if ( shader instanceof THREE.ShaderMaterial ) {
     
         this.uniforms = shader.uniforms;
     
         this.material = shader;
     
       } else if ( shader ) {
     
         this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
     
         this.material = new THREE.ShaderMaterial( {
     
           defines: Object.assign( {}, shader.defines ),
           uniforms: this.uniforms,
           vertexShader: shader.vertexShader,
           fragmentShader: shader.fragmentShader
     
         } );
     
       }
     
       this.fsQuad = new THREE.Pass.FullScreenQuad( this.material );
     
     };
     
     THREE.ShaderPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
     
       constructor: THREE.ShaderPass,
     
       render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {
     
         if ( this.uniforms[ this.textureID ] ) {
     
           this.uniforms[ this.textureID ].value = readBuffer.texture;
     
         }
     
         this.fsQuad.material = this.material;
     
         if ( this.renderToScreen ) {
     
           renderer.setRenderTarget( null );
           this.fsQuad.render( renderer );
     
         } else {
     
           renderer.setRenderTarget( writeBuffer );
           // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
           if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
           this.fsQuad.render( renderer );
     
         }
     
       }
     
     } );
     </script>
    <script>/**
      * @author alteredq / http://alteredqualia.com/
      *
      * Full-screen textured quad shader
      */
     
     THREE.CopyShader = {
     
       uniforms: {
     
         "tDiffuse": { value: null },
         "opacity": { value: 1.0 }
     
       },
     
       vertexShader: [
     
         "varying vec2 vUv;",
     
         "void main() {",
     
         "	vUv = uv;",
         "	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
     
         "}"
     
       ].join( "\n" ),
     
       fragmentShader: [
     
         "uniform float opacity;",
     
         "uniform sampler2D tDiffuse;",
     
         "varying vec2 vUv;",
     
         "void main() {",
     
         "	vec4 texel = texture2D( tDiffuse, vUv );",
         "	gl_FragColor = opacity * texel;",
     
         "}"
     
       ].join( "\n" )
     
     };
     </script>
    <script>
     
     THREE.LuminosityHighPassShader = {
     
       shaderID: "luminosityHighPass",
     
       uniforms: {
     
         "tDiffuse": { value: null },
         "luminosityThreshold": { value: 1.0 },
         "smoothWidth": { value: 1.0 },
         "defaultColor": { value: new THREE.Color( 0x000000 ) },
         "defaultOpacity": { value: 0.0 }
     
       },
     
       vertexShader: [
     
         "varying vec2 vUv;",
     
         "void main() {",
     
         "	vUv = uv;",
     
         "	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
     
         "}"
     
       ].join( "\n" ),
     
       fragmentShader: [
     
         "uniform sampler2D tDiffuse;",
         "uniform vec3 defaultColor;",
         "uniform float defaultOpacity;",
         "uniform float luminosityThreshold;",
         "uniform float smoothWidth;",
     
         "varying vec2 vUv;",
     
         "void main() {",
     
         "	vec4 texel = texture2D( tDiffuse, vUv );",
     
         "	vec3 luma = vec3( 0.299, 0.587, 0.114 );",
     
         "	float v = dot( texel.xyz, luma );",
     
         "	vec4 outputColor = vec4( defaultColor.rgb, defaultOpacity );",
     
         "	float alpha = smoothstep( luminosityThreshold, luminosityThreshold + smoothWidth, v );",
     
         "	gl_FragColor = mix( outputColor, texel, alpha );",
     
         "}"
     
       ].join( "\n" )
     
     };
     </script>
    <script>
     /**
      * UnrealBloomPass is inspired by the bloom pass of Unreal Engine. It creates a
      * mip map chain of bloom textures and blurs them with different radii. Because
      * of the weighted combination of mips, and because larger blurs are done on
      * higher mips, this effect provides good quality and performance.
      *
      * Reference:
      * - https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/
      */
     THREE.UnrealBloomPass = function ( resolution, strength, radius, threshold ) {
     
       THREE.Pass.call( this );
     
       this.strength = ( strength !== undefined ) ? strength : 1;
       this.radius = radius;
       this.threshold = threshold;
       this.resolution = ( resolution !== undefined ) ? new THREE.Vector2( resolution.x, resolution.y ) : new THREE.Vector2( 256, 256 );
     
       // create color only once here, reuse it later inside the render function
       this.clearColor = new THREE.Color( 0, 0, 0 );
     
       // render targets
       var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
       this.renderTargetsHorizontal = [];
       this.renderTargetsVertical = [];
       this.nMips = 5;
       var resx = Math.round( this.resolution.x / 2 );
       var resy = Math.round( this.resolution.y / 2 );
     
       this.renderTargetBright = new THREE.WebGLRenderTarget( resx, resy, pars );
       this.renderTargetBright.texture.name = "UnrealBloomPass.bright";
       this.renderTargetBright.texture.generateMipmaps = false;
     
       for ( var i = 0; i < this.nMips; i ++ ) {
     
         var renderTargetHorizonal = new THREE.WebGLRenderTarget( resx, resy, pars );
     
         renderTargetHorizonal.texture.name = "UnrealBloomPass.h" + i;
         renderTargetHorizonal.texture.generateMipmaps = false;
     
         this.renderTargetsHorizontal.push( renderTargetHorizonal );
     
         var renderTargetVertical = new THREE.WebGLRenderTarget( resx, resy, pars );
     
         renderTargetVertical.texture.name = "UnrealBloomPass.v" + i;
         renderTargetVertical.texture.generateMipmaps = false;
     
         this.renderTargetsVertical.push( renderTargetVertical );
     
         resx = Math.round( resx / 2 );
     
         resy = Math.round( resy / 2 );
     
       }
     
       // luminosity high pass material
     
       if ( THREE.LuminosityHighPassShader === undefined )
         console.error( "THREE.UnrealBloomPass relies on THREE.LuminosityHighPassShader" );
     
       var highPassShader = THREE.LuminosityHighPassShader;
       this.highPassUniforms = THREE.UniformsUtils.clone( highPassShader.uniforms );
     
       this.highPassUniforms[ "luminosityThreshold" ].value = threshold;
       this.highPassUniforms[ "smoothWidth" ].value = 0.01;
     
       this.materialHighPassFilter = new THREE.ShaderMaterial( {
         uniforms: this.highPassUniforms,
         vertexShader: highPassShader.vertexShader,
         fragmentShader: highPassShader.fragmentShader,
         defines: {}
       } );
     
       // Gaussian Blur Materials
       this.separableBlurMaterials = [];
       var kernelSizeArray = [ 3, 5, 7, 9, 11 ];
       var resx = Math.round( this.resolution.x / 2 );
       var resy = Math.round( this.resolution.y / 2 );
     
       for ( var i = 0; i < this.nMips; i ++ ) {
     
         this.separableBlurMaterials.push( this.getSeperableBlurMaterial( kernelSizeArray[ i ] ) );
     
         this.separableBlurMaterials[ i ].uniforms[ "texSize" ].value = new THREE.Vector2( resx, resy );
     
         resx = Math.round( resx / 2 );
     
         resy = Math.round( resy / 2 );
     
       }
     
       // Composite material
       this.compositeMaterial = this.getCompositeMaterial( this.nMips );
       this.compositeMaterial.uniforms[ "blurTexture1" ].value = this.renderTargetsVertical[ 0 ].texture;
       this.compositeMaterial.uniforms[ "blurTexture2" ].value = this.renderTargetsVertical[ 1 ].texture;
       this.compositeMaterial.uniforms[ "blurTexture3" ].value = this.renderTargetsVertical[ 2 ].texture;
       this.compositeMaterial.uniforms[ "blurTexture4" ].value = this.renderTargetsVertical[ 3 ].texture;
       this.compositeMaterial.uniforms[ "blurTexture5" ].value = this.renderTargetsVertical[ 4 ].texture;
       this.compositeMaterial.uniforms[ "bloomStrength" ].value = strength;
       this.compositeMaterial.uniforms[ "bloomRadius" ].value = 0.1;
       this.compositeMaterial.needsUpdate = true;
     
       var bloomFactors = [ 1.0, 0.8, 0.6, 0.4, 0.2 ];
       this.compositeMaterial.uniforms[ "bloomFactors" ].value = bloomFactors;
       this.bloomTintColors = [ new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 1, 1, 1 ),
                    new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 1, 1, 1 ) ];
       this.compositeMaterial.uniforms[ "bloomTintColors" ].value = this.bloomTintColors;
     
       // copy material
       if ( THREE.CopyShader === undefined ) {
     
         console.error( "THREE.UnrealBloomPass relies on THREE.CopyShader" );
     
       }
     
       var copyShader = THREE.CopyShader;
     
       this.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
       this.copyUniforms[ "opacity" ].value = 1.0;
     
       this.materialCopy = new THREE.ShaderMaterial( {
         uniforms: this.copyUniforms,
         vertexShader: copyShader.vertexShader,
         fragmentShader: copyShader.fragmentShader,
         blending: THREE.AdditiveBlending,
         depthTest: false,
         depthWrite: false,
         transparent: true
       } );
     
       this.enabled = true;
       this.needsSwap = false;
     
       this.oldClearColor = new THREE.Color();
       this.oldClearAlpha = 1;
     
       this.basic = new THREE.MeshBasicMaterial();
     
       this.fsQuad = new THREE.Pass.FullScreenQuad( null );
     
     };
     
     THREE.UnrealBloomPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
     
       constructor: THREE.UnrealBloomPass,
     
       dispose: function () {
     
         for ( var i = 0; i < this.renderTargetsHorizontal.length; i ++ ) {
     
           this.renderTargetsHorizontal[ i ].dispose();
     
         }
     
         for ( var i = 0; i < this.renderTargetsVertical.length; i ++ ) {
     
           this.renderTargetsVertical[ i ].dispose();
     
         }
     
         this.renderTargetBright.dispose();
     
       },
     
       setSize: function ( width, height ) {
     
         var resx = Math.round( width / 2 );
         var resy = Math.round( height / 2 );
     
         this.renderTargetBright.setSize( resx, resy );
     
         for ( var i = 0; i < this.nMips; i ++ ) {
     
           this.renderTargetsHorizontal[ i ].setSize( resx, resy );
           this.renderTargetsVertical[ i ].setSize( resx, resy );
     
           this.separableBlurMaterials[ i ].uniforms[ "texSize" ].value = new THREE.Vector2( resx, resy );
     
           resx = Math.round( resx / 2 );
           resy = Math.round( resy / 2 );
     
         }
     
       },
     
       render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
     
         this.oldClearColor.copy( renderer.getClearColor() );
         this.oldClearAlpha = renderer.getClearAlpha();
         var oldAutoClear = renderer.autoClear;
         renderer.autoClear = false;
     
         renderer.setClearColor( this.clearColor, 0 );
     
         if ( maskActive ) renderer.state.buffers.stencil.setTest( false );
     
         // Render input to screen
     
         if ( this.renderToScreen ) {
     
           this.fsQuad.material = this.basic;
           this.basic.map = readBuffer.texture;
     
           renderer.setRenderTarget( null );
           renderer.clear();
           this.fsQuad.render( renderer );
     
         }
     
         // 1. Extract Bright Areas
     
         this.highPassUniforms[ "tDiffuse" ].value = readBuffer.texture;
         this.highPassUniforms[ "luminosityThreshold" ].value = this.threshold;
         this.fsQuad.material = this.materialHighPassFilter;
     
         renderer.setRenderTarget( this.renderTargetBright );
         renderer.clear();
         this.fsQuad.render( renderer );
     
         // 2. Blur All the mips progressively
     
         var inputRenderTarget = this.renderTargetBright;
     
         for ( var i = 0; i < this.nMips; i ++ ) {
     
           this.fsQuad.material = this.separableBlurMaterials[ i ];
     
           this.separableBlurMaterials[ i ].uniforms[ "colorTexture" ].value = inputRenderTarget.texture;
           this.separableBlurMaterials[ i ].uniforms[ "direction" ].value = THREE.UnrealBloomPass.BlurDirectionX;
           renderer.setRenderTarget( this.renderTargetsHorizontal[ i ] );
           renderer.clear();
           this.fsQuad.render( renderer );
     
           this.separableBlurMaterials[ i ].uniforms[ "colorTexture" ].value = this.renderTargetsHorizontal[ i ].texture;
           this.separableBlurMaterials[ i ].uniforms[ "direction" ].value = THREE.UnrealBloomPass.BlurDirectionY;
           renderer.setRenderTarget( this.renderTargetsVertical[ i ] );
           renderer.clear();
           this.fsQuad.render( renderer );
     
           inputRenderTarget = this.renderTargetsVertical[ i ];
     
         }
     
         // Composite All the mips
     
         this.fsQuad.material = this.compositeMaterial;
         this.compositeMaterial.uniforms[ "bloomStrength" ].value = this.strength;
         this.compositeMaterial.uniforms[ "bloomRadius" ].value = this.radius;
         this.compositeMaterial.uniforms[ "bloomTintColors" ].value = this.bloomTintColors;
     
         renderer.setRenderTarget( this.renderTargetsHorizontal[ 0 ] );
         renderer.clear();
         this.fsQuad.render( renderer );
     
         // Blend it additively over the input texture
     
         this.fsQuad.material = this.materialCopy;
         this.copyUniforms[ "tDiffuse" ].value = this.renderTargetsHorizontal[ 0 ].texture;
     
         if ( maskActive ) renderer.state.buffers.stencil.setTest( true );
     
         if ( this.renderToScreen ) {
     
           renderer.setRenderTarget( null );
           this.fsQuad.render( renderer );
     
         } else {
     
           renderer.setRenderTarget( readBuffer );
           this.fsQuad.render( renderer );
     
         }
     
         // Restore renderer settings
     
         renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );
         renderer.autoClear = oldAutoClear;
     
       },
     
       getSeperableBlurMaterial: function ( kernelRadius ) {
     
         return new THREE.ShaderMaterial( {
     
           defines: {
             "KERNEL_RADIUS": kernelRadius,
             "SIGMA": kernelRadius
           },
     
           uniforms: {
             "colorTexture": { value: null },
             "texSize": { value: new THREE.Vector2( 0.5, 0.5 ) },
             "direction": { value: new THREE.Vector2( 0.5, 0.5 ) }
           },
     
           vertexShader:
             "varying vec2 vUv;\n\
             void main() {\n\
               vUv = uv;\n\
               gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
             }",
     
           fragmentShader:
             "#include <common>\
             varying vec2 vUv;\n\
             uniform sampler2D colorTexture;\n\
             uniform vec2 texSize;\
             uniform vec2 direction;\
             \
             float gaussianPdf(in float x, in float sigma) {\
               return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\
             }\
             void main() {\n\
               vec2 invSize = 1.0 / texSize;\
               float fSigma = float(SIGMA);\
               float weightSum = gaussianPdf(0.0, fSigma);\
               vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\
               for( int i = 1; i < KERNEL_RADIUS; i ++ ) {\
                 float x = float(i);\
                 float w = gaussianPdf(x, fSigma);\
                 vec2 uvOffset = direction * invSize * x;\
                 vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb;\
                 vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb;\
                 diffuseSum += (sample1 + sample2) * w;\
                 weightSum += 2.0 * w;\
               }\
               gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\n\
             }"
         } );
     
       },
     
       getCompositeMaterial: function ( nMips ) {
     
         return new THREE.ShaderMaterial( {
     
           defines: {
             "NUM_MIPS": nMips
           },
     
           uniforms: {
             "blurTexture1": { value: null },
             "blurTexture2": { value: null },
             "blurTexture3": { value: null },
             "blurTexture4": { value: null },
             "blurTexture5": { value: null },
             "dirtTexture": { value: null },
             "bloomStrength": { value: 1.0 },
             "bloomFactors": { value: null },
             "bloomTintColors": { value: null },
             "bloomRadius": { value: 0.0 }
           },
     
           vertexShader:
             "varying vec2 vUv;\n\
             void main() {\n\
               vUv = uv;\n\
               gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
             }",
     
           fragmentShader:
             "varying vec2 vUv;\
             uniform sampler2D blurTexture1;\
             uniform sampler2D blurTexture2;\
             uniform sampler2D blurTexture3;\
             uniform sampler2D blurTexture4;\
             uniform sampler2D blurTexture5;\
             uniform sampler2D dirtTexture;\
             uniform float bloomStrength;\
             uniform float bloomRadius;\
             uniform float bloomFactors[NUM_MIPS];\
             uniform vec3 bloomTintColors[NUM_MIPS];\
             \
             float lerpBloomFactor(const in float factor) { \
               float mirrorFactor = 1.2 - factor;\
               return mix(factor, mirrorFactor, bloomRadius);\
             }\
             \
             void main() {\
               gl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) + \
                                lerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) + \
                                lerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) + \
                                lerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) + \
                                lerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) );\
             }"
         } );
     
       }
     
     } );
     
     THREE.UnrealBloomPass.BlurDirectionX = new THREE.Vector2( 1.0, 0.0 );
     THREE.UnrealBloomPass.BlurDirectionY = new THREE.Vector2( 0.0, 1.0 );
     </script>

    <div id="overlay">
      <ul>
        <li class="title">To 萌萌:</li>
        <li>
          <button class="btn" id="btnA" type="button">
            <!-- Merry Christmas  -->
            🎁
          </button>
        </li>
        <!-- <li class="separator">或者</li>
        <li>
          <input type="file" id="upload" hidden />
          <label for="upload">Upload File</label>
        </li> -->
      </ul>
    </div>
    <div id="labels"></div>

    <script id="rendered-js">
      const my_labels = [
        "圣诞快乐!",
        "Merry Christmas!",
      ];
      const { PI, sin, cos } = Math;
      const TAU = 2 * PI;

      const map = (value, sMin, sMax, dMin, dMax) => {
        return dMin + ((value - sMin) / (sMax - sMin)) * (dMax - dMin);
      };

      const range = (n, m = 0) =>
        Array(n)
          .fill(m)
          .map((i, j) => i + j);

      const rand = (max, min = 0) => min + Math.random() * (max - min);
      const randInt = (max, min = 0) =>
        Math.floor(min + Math.random() * (max - min));
      const randChoise = (arr) => arr[randInt(arr.length)];
      const polar = (ang, r = 1) => [r * cos(ang), r * sin(ang)];

      let scene, camera, renderer, analyser;
      let step = 0;
      const uniforms = {
        time: { type: "f", value: 0.0 },
        step: { type: "f", value: 0.0 },
      };

      const params = {
        exposure: 1,
        bloomStrength: 0.9,
        bloomThreshold: 0,
        bloomRadius: 0.5,
      };

      let composer;

      const fftSize = 2048;
      const totalPoints = 4000;

      const listener = new THREE.AudioListener();

      const audio = new THREE.Audio(listener);

      //   document
      //     .querySelector("input")
      //     .addEventListener("change", uploadAudio, false);

      const buttons = document.querySelectorAll(".btn");
      buttons.forEach((button, index) =>
        button.addEventListener("click", () => loadAudio(index))
      );

      // loadAudio(0);

      function init() {
        const overlay = document.getElementById("overlay");
        overlay.remove();
        const labels = document.getElementById("labels");
        for (let i = 0; i < my_labels.length; i++) {
          setTimeout(() => {
            labels.className = "hide";
            labels.innerHTML = my_labels[i];
            labels.className = "show";
          }, 2000 * i);
        }

        scene = new THREE.Scene();
        renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        camera = new THREE.PerspectiveCamera(
          60,
          window.innerWidth / window.innerHeight,
          1,
          1000
        );

        camera.position.set(
          -0.09397456774197047,
          -2.5597086635726947,
          24.420789670889008
        );
        camera.rotation.set(
          0.10443543723052419,
          -0.003827152981119352,
          0.0004011488708739715
        );

        const format = renderer.capabilities.isWebGL2
          ? THREE.RedFormat
          : THREE.LuminanceFormat;

        uniforms.tAudioData = {
          value: new THREE.DataTexture(analyser.data, fftSize / 2, 1, format),
        };

        addPlane(scene, uniforms, 3000);
        addSnow(scene, uniforms);

        range(10).map((i) => {
          addTree(scene, uniforms, totalPoints, [20, 0, -20 * i]);
          addTree(scene, uniforms, totalPoints, [-20, 0, -20 * i]);
        });

        const renderScene = new THREE.RenderPass(scene, camera);

        const bloomPass = new THREE.UnrealBloomPass(
          new THREE.Vector2(window.innerWidth, window.innerHeight),
          1.5,
          0.4,
          0.85
        );

        bloomPass.threshold = params.bloomThreshold;
        bloomPass.strength = params.bloomStrength;
        bloomPass.radius = params.bloomRadius;

        composer = new THREE.EffectComposer(renderer);
        composer.addPass(renderScene);
        composer.addPass(bloomPass);

        addListners(camera, renderer, composer);
        animate();
      }

      function animate(time) {
        analyser.getFrequencyData();
        uniforms.tAudioData.value.needsUpdate = true;
        step = (step + 1) % 1000;
        uniforms.time.value = time;
        uniforms.step.value = step;
        composer.render();
        requestAnimationFrame(animate);
      }
      function loadAudio(i) {
        document.getElementById("overlay").innerHTML =
          '<div class="text-loading">Merry Christmas ...</div>';
        
        const files = [
           //"http://music.163.com/song/media/outer/url?id=448704788.mp3", // ! 音乐资源获取
          // 修改下面这个链接
          //"http://m10.music.126.net/20231210135814/b2ca7948cdbf1e3be2513d0a82c4bb92/ymusic/3bc8/7ba8/8643/56e188fb5a29b25ce695510164a28331.mp3",
          //"https://music.163.com/outchain/player?type=2&id=1824020871",
          //"这里填你自己的音乐链接",
          // 海外用户使用下面这个音乐平台
          "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Simon_Panrucker/Happy_Christmas_You_Guys/Simon_Panrucker_-_01_-_Snowflakes_Falling_Down.mp3",
        ];

        const file = files[i];
        
        const loader = new THREE.AudioLoader();
        loader.load(file, function (buffer) {
          console.log(buffer)
          audio.setBuffer(buffer);
          audio.play();
          analyser = new THREE.AudioAnalyser(audio, fftSize);
          init();
        });


function getJSON(url) {
    return new Promise(function(resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open('get', url, true);
        // xhr.responseType = 'json';
        console.log(xhr)
        xhr.onloadstart = function() {
          console.log(xhr);
        }
        xhr.onload = function() {
          console.log(xhr);
            var status = xhr.status;
            if (status == 200) {
                resolve(xhr.responseURL);
            } else {
                reject(status);
            }
        };
        xhr.send();
    });
  }


function requestListData(url) {
 getJSON(url).then(function(data) {
        const loader = new THREE.AudioLoader();
        loader.load(data, function (buffer) {
          console.log(buffer)
          audio.setBuffer(buffer);
          audio.play();
          analyser = new THREE.AudioAnalyser(audio, fftSize);
          init();
        });

 }, function(status) { //error detection....
     alert('Something went wrong.');
 });
}
      }

      function uploadAudio(event) {
        document.getElementById("overlay").innerHTML =
          '<div class="text-loading">请稍等...</div>';
        const files = event.target.files;
        const reader = new FileReader();

        reader.onload = function (file) {
          var arrayBuffer = file.target.result;

          listener.context.decodeAudioData(arrayBuffer, function (audioBuffer) {
            audio.setBuffer(audioBuffer);
            audio.play();
            analyser = new THREE.AudioAnalyser(audio, fftSize);
            init();
          });
        };

        reader.readAsArrayBuffer(files[0]);
      }

      function addTree(scene, uniforms, totalPoints, treePosition) {
        const vertexShader = `
      attribute float mIndex;
      varying vec3 vColor;
      varying float opacity;
      uniform sampler2D tAudioData;

      float norm(float value, float min, float max ){
       return (value - min) / (max - min);
      }
      float lerp(float norm, float min, float max){
       return (max - min) * norm + min;
      }

      float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
       return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
      }


      void main() {
       vColor = color;
       vec3 p = position;
       vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
       float amplitude = texture2D( tAudioData, vec2( mIndex, 0.1 ) ).r;
       float amplitudeClamped = clamp(amplitude-0.4,0.0, 0.6 );
       float sizeMapped = map(amplitudeClamped, 0.0, 0.6, 1.0, 20.0);
       opacity = map(mvPosition.z , -200.0, 15.0, 0.0, 1.0);
       gl_PointSize = sizeMapped * ( 100.0 / -mvPosition.z );
       gl_Position = projectionMatrix * mvPosition;
      }
      `;
        const fragmentShader = `
      varying vec3 vColor;
      varying float opacity;
      uniform sampler2D pointTexture;
      void main() {
       gl_FragColor = vec4( vColor, opacity );
       gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord ); 
      }
      `;
        const shaderMaterial = new THREE.ShaderMaterial({
          uniforms: {
            ...uniforms,
            pointTexture: {
              value: new THREE.TextureLoader().load(
                `https://assets.codepen.io/3685267/spark1.png`
              ),
            },
          },

          vertexShader,
          fragmentShader,
          blending: THREE.AdditiveBlending,
          depthTest: false,
          transparent: true,
          vertexColors: true,
        });

        const geometry = new THREE.BufferGeometry();
        const positions = [];
        const colors = [];
        const sizes = [];
        const phases = [];
        const mIndexs = [];

        const color = new THREE.Color();

        for (let i = 0; i < totalPoints; i++) {
          const t = Math.random();
          const y = map(t, 0, 1, -8, 10);
          const ang = map(t, 0, 1, 0, 6 * TAU) + (TAU / 2) * (i % 2);
          const [z, x] = polar(ang, map(t, 0, 1, 5, 0));

          const modifier = map(t, 0, 1, 1, 0);
          positions.push(x + rand(-0.3 * modifier, 0.3 * modifier));
          positions.push(y + rand(-0.3 * modifier, 0.3 * modifier));
          positions.push(z + rand(-0.3 * modifier, 0.3 * modifier));

          color.setHSL(map(i, 0, totalPoints, 1.0, 0.0), 1.0, 0.5);

          colors.push(color.r, color.g, color.b);
          phases.push(rand(1000));
          sizes.push(1);
          const mIndex = map(i, 0, totalPoints, 1.0, 0.0);
          mIndexs.push(mIndex);
        }

        geometry.setAttribute(
          "position",
          new THREE.Float32BufferAttribute(positions, 3).setUsage(
            THREE.DynamicDrawUsage
          )
        );

        geometry.setAttribute(
          "color",
          new THREE.Float32BufferAttribute(colors, 3)
        );
        geometry.setAttribute(
          "size",
          new THREE.Float32BufferAttribute(sizes, 1)
        );
        geometry.setAttribute(
          "phase",
          new THREE.Float32BufferAttribute(phases, 1)
        );
        geometry.setAttribute(
          "mIndex",
          new THREE.Float32BufferAttribute(mIndexs, 1)
        );

        const tree = new THREE.Points(geometry, shaderMaterial);

        const [px, py, pz] = treePosition;

        tree.position.x = px;
        tree.position.y = py;
        tree.position.z = pz;

        scene.add(tree);
      }

      function addSnow(scene, uniforms) {
        const vertexShader = `
      attribute float size;
      attribute float phase;
      attribute float phaseSecondary;

      varying vec3 vColor;
      varying float opacity;


      uniform float time;
      uniform float step;

      float norm(float value, float min, float max ){
       return (value - min) / (max - min);
      }
      float lerp(float norm, float min, float max){
       return (max - min) * norm + min;
      }

      float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
       return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
      }
      void main() {
       float t = time* 0.0006;

       vColor = color;

       vec3 p = position;

       p.y = map(mod(phase+step, 1000.0), 0.0, 1000.0, 25.0, -8.0);

       p.x += sin(t+phase);
       p.z += sin(t+phaseSecondary);

       opacity = map(p.z, -150.0, 15.0, 0.0, 1.0);

       vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );

       gl_PointSize = size * ( 100.0 / -mvPosition.z );

       gl_Position = projectionMatrix * mvPosition;

      }
      `;

        const fragmentShader = `
      uniform sampler2D pointTexture;
      varying vec3 vColor;
      varying float opacity;

      void main() {
       gl_FragColor = vec4( vColor, opacity );
       gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord ); 
      }
      `;
        function createSnowSet(sprite) {
          const totalPoints = 300;
          const shaderMaterial = new THREE.ShaderMaterial({
            uniforms: {
              ...uniforms,
              pointTexture: {
                value: new THREE.TextureLoader().load(sprite),
              },
            },

            vertexShader,
            fragmentShader,
            blending: THREE.AdditiveBlending,
            depthTest: false,
            transparent: true,
            vertexColors: true,
          });

          const geometry = new THREE.BufferGeometry();
          const positions = [];
          const colors = [];
          const sizes = [];
          const phases = [];
          const phaseSecondaries = [];

          const color = new THREE.Color();

          for (let i = 0; i < totalPoints; i++) {
            const [x, y, z] = [rand(25, -25), 0, rand(15, -150)];
            positions.push(x);
            positions.push(y);
            positions.push(z);

            color.set(randChoise(["#f1d4d4", "#f1f6f9", "#eeeeee", "#f1f1e8"]));

            colors.push(color.r, color.g, color.b);
            phases.push(rand(1000));
            phaseSecondaries.push(rand(1000));
            sizes.push(rand(4, 2));
          }

          geometry.setAttribute(
            "position",
            new THREE.Float32BufferAttribute(positions, 3)
          );

          geometry.setAttribute(
            "color",
            new THREE.Float32BufferAttribute(colors, 3)
          );
          geometry.setAttribute(
            "size",
            new THREE.Float32BufferAttribute(sizes, 1)
          );
          geometry.setAttribute(
            "phase",
            new THREE.Float32BufferAttribute(phases, 1)
          );
          geometry.setAttribute(
            "phaseSecondary",
            new THREE.Float32BufferAttribute(phaseSecondaries, 1)
          );

          const mesh = new THREE.Points(geometry, shaderMaterial);

          scene.add(mesh);
        }
        const sprites = [
          "https://assets.codepen.io/3685267/snowflake1.png",
          "https://assets.codepen.io/3685267/snowflake2.png",
          "https://assets.codepen.io/3685267/snowflake3.png",
          "https://assets.codepen.io/3685267/snowflake4.png",
          "https://assets.codepen.io/3685267/snowflake5.png",
        ];

        sprites.forEach((sprite) => {
          createSnowSet(sprite);
        });
      }

      function addPlane(scene, uniforms, totalPoints) {
        const vertexShader = `
      attribute float size;
      attribute vec3 customColor;
      varying vec3 vColor;

      void main() {
       vColor = customColor;
       vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
       gl_PointSize = size * ( 300.0 / -mvPosition.z );
       gl_Position = projectionMatrix * mvPosition;

      }
      `;
        const fragmentShader = `
      uniform vec3 color;
      uniform sampler2D pointTexture;
      varying vec3 vColor;

      void main() {
       gl_FragColor = vec4( vColor, 1.0 );
       gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );

      }
      `;
        const shaderMaterial = new THREE.ShaderMaterial({
          uniforms: {
            ...uniforms,
            pointTexture: {
              value: new THREE.TextureLoader().load(
                `https://assets.codepen.io/3685267/spark1.png`
              ),
            },
          },

          vertexShader,
          fragmentShader,
          blending: THREE.AdditiveBlending,
          depthTest: false,
          transparent: true,
          vertexColors: true,
        });

        const geometry = new THREE.BufferGeometry();
        const positions = [];
        const colors = [];
        const sizes = [];

        const color = new THREE.Color();

        for (let i = 0; i < totalPoints; i++) {
          const [x, y, z] = [rand(-25, 25), 0, rand(-150, 15)];
          positions.push(x);
          positions.push(y);
          positions.push(z);

          color.set(randChoise(["#93abd3", "#f2f4c0", "#9ddfd3"]));

          colors.push(color.r, color.g, color.b);
          sizes.push(1);
        }

        geometry.setAttribute(
          "position",
          new THREE.Float32BufferAttribute(positions, 3).setUsage(
            THREE.DynamicDrawUsage
          )
        );

        geometry.setAttribute(
          "customColor",
          new THREE.Float32BufferAttribute(colors, 3)
        );

        geometry.setAttribute(
          "size",
          new THREE.Float32BufferAttribute(sizes, 1)
        );

        const plane = new THREE.Points(geometry, shaderMaterial);

        plane.position.y = -8;
        scene.add(plane);
      }

      function addListners(camera, renderer, composer) {
        document.addEventListener("keydown", (e) => {
          const { x, y, z } = camera.position;
          console.log(`camera.position.set(${x},${y},${z})`);
          const { x: a, y: b, z: c } = camera.rotation;
          console.log(`camera.rotation.set(${a},${b},${c})`);
        });

        window.addEventListener(
          "resize",
          () => {
            const width = window.innerWidth;
            const height = window.innerHeight;

            camera.aspect = width / height;
            camera.updateProjectionMatrix();

            renderer.setSize(width, height);
            composer.setSize(width, height);
          },
          false
        );
      }
    </script>

  </body>
</html>

写在后面

我是一只有趣的兔子,感谢你的喜欢!