123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // import { vertexShader, fragmentShader } from './shaders'
- // import Tween from './tween'
- import * as THREE from "../../../../libs/three.js/build/three.module.js";
- import { vertexShader, fragmentShader } from './shader.js'
- let ONE_SPRITE_ROW_LENGTH = 0.25 //对应着色器的0.25
- let texture
-
- const getTexture = ()=>{
- if(!texture){
- texture = new THREE.TextureLoader().load( Potree.resourcePath+'/textures/fire.png')
- }
- return texture
- }
- class FireParticle extends THREE.Points{
-
- constructor (prop) {
- super()
-
- for ( var key in prop ){
- this[key] = prop[key]
- }
-
-
-
- this.density = this.density || 1
-
-
-
- this.fireRadius = prop.fireRadius || 1;
- this.fireHeight = prop.fireHeight || 5;
-
- this.computeParams()
- this.geometry = this.createGeometry( this.fireRadius, this.fireHeight, this.particleCount );
-
-
-
- this.material = this.createMaterial( prop.fov, 0xff3200 ); //小蓝火:0x00338f
-
-
-
- //---?:
- this.velocity = new THREE.Vector3()
- this.acceleration = new THREE.Vector3()
-
- this.angle = 0
- this.angleVelocity = 0
- this.angleAcceleration = 0
- this.size = 16
- this.color = new THREE.Color()
- this.opacity = 1
- this.age = 0
- this.alive = 0
- this.sizeTween = null
- this.colorTween = null
- this.opacityTween = null
-
-
- this.setSize({viewport:viewer.mainViewport})
- this.setFov(viewer.fov)
- viewer.addEventListener('resize',(e)=>{
- if(e.viewport.name != "MainView")return
- this.setSize(e)
- })
- viewer.addEventListener('fov_changed',(e)=>{
- this.setFov(e.fov)
- })
- }
-
- computeParams(){
- let length = (this.curve ? this.curve.wholeLength : 0) + this.fireRadius * 2 //加上首尾的半径
- this.particleCount = Math.ceil( this.fireRadius * this.fireHeight * length * this.density * 5 )
- console.log('fire particleCount',this.particleCount)
- }
- createGeometry( radius, height, particleCount){
- let geometry = new THREE.BufferGeometry()
-
-
-
- var halfHeight = height * 0.5;
-
- let count , points
- if(this.positions.length>1){
-
- const spaceDis = 0.2;//间隔距离
-
- count = Math.ceil(this.curve.wholeLength / spaceDis) + 1
- console.log('count', count)
- points = this.curve.getSpacedPoints( count ); //得到的数量会比count多一个
- count = points.length
- //得到的点不太均匀,两端容易点少。
-
-
- }
-
-
- var position = new Float32Array(particleCount * 3);
- var randam = new Float32Array(particleCount);
- var sprite = new Float32Array(particleCount);
- var centerHeight = new Float32Array(particleCount);
-
- for (var i = 0; i < particleCount; i++) {
-
- var center = new THREE.Vector3().copy(this.positions.length>1 ? points[Math.floor(i/particleCount * count)] : this.positions[0])
- centerHeight[i] = center.z
-
- if (i === 0) {
- // to avoid going out of Frustum
- position[i * 3 + 0] = center.x;
- position[i * 3 + 1] = center.y;
- position[i * 3 + 2] = center.z;
- }else{
- var r = Math.sqrt(Math.random()) * radius;
- var angle = Math.random() * 2 * Math.PI;
- position[i * 3 + 0] = center.x + Math.cos(angle) * r;
- position[i * 3 + 1] = center.y + Math.sin(angle) * r;
- position[i * 3 + 2] = center.z + (radius - r) / radius * halfHeight + halfHeight; //不太明白这句为什么能达到height高度
-
- sprite[i] = 0.25 * (Math.random() * 4 | 0);
- randam[i] = Math.random();
- //center在底部
- }
-
-
- }
-
- geometry.setAttribute('centerHeight', new THREE.BufferAttribute(centerHeight, 1));
- geometry.setAttribute('position', new THREE.BufferAttribute(position, 3));
- geometry.setAttribute('randam', new THREE.BufferAttribute(randam, 1));
- geometry.setAttribute('sprite', new THREE.BufferAttribute(sprite, 1));
- return geometry;
- }
-
-
-
-
- updateGeometry(){
- this.computeParams()
- this.geometry.dispose()
- this.geometry = this.createGeometry( this.fireRadius, this.fireHeight, this.particleCount )
-
- }
- createMaterial(fov, color){
-
- const material = new THREE.ShaderMaterial( {
- uniforms:{
- color: { type: "c", value: new THREE.Color(color) },
- size: { type: "f", value: THREE.Math.clamp(this.fireRadius * 1.2, 0.5, 5)},
- u_sampler: { type: "t", value: getTexture() },
- time: { type: "f", value: 0.0 },
- heightOfNearPlane: { type: "f", value:0}, //相对far ,以确保画面缩放时点的大小也会缩放
- fireHeight :{ type: "f", value:this.fireHeight} ,
- },
- vertexShader,
- fragmentShader,
- blending: THREE.AdditiveBlending, //加法融合模式 glBlendFunc(GL_ONE, GL_ONE)
- depthTest: true,
- depthWrite: false,
- transparent: true
- } );
-
-
- return material
- }
- setSize(e){
- let viewport = e.viewport
- this.screenHeight = viewport.resolution.y
- this.setPerspective(this.fov, this.screenHeight)
- }
-
- setFov(fov){
- this.fov = fov
- this.setPerspective(this.fov, this.screenHeight)
- }
-
-
- setPerspective(fov, height){
- //this.uniforms.heightOfNearPlane.value = Math.abs(height / (2 * Math.tan(THREE.Math.degToRad(fov * 0.5))));
- let far = Math.abs(height / (2 * Math.tan(THREE.Math.degToRad(fov * 0.5))));
- this.material.uniforms.heightOfNearPlane.value = far
- }
-
-
- update(delta){
-
- delta *= 1//更改速度
-
- this.material.uniforms.time.value = (this.material.uniforms.time.value + delta) % 1;
-
-
- }
- }
- export default FireParticle
|