mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 01:04:17 +00:00 
			
		
		
		
	
		
			
	
	
		
			288 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			288 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								// Monkey patching particle renderer for:
							 | 
						||
| 
								 | 
							
								// - limiting RAM usage (around 10 times less)
							 | 
						||
| 
								 | 
							
								// - customizing to our target: we want to render markers (e.g. scale is now a uniform)
							 | 
						||
| 
								 | 
							
								// Hope one day i'll have some times for a better solution
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var ParticleContainer = PIXI.particles.ParticleContainer;
							 | 
						||
| 
								 | 
							
								var ParticleRenderer = PIXI.particles.ParticleRenderer;
							 | 
						||
| 
								 | 
							
								var utils = PIXI.utils;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ParticleContainer.prototype.addChild = function(child) {
							 | 
						||
| 
								 | 
							
								    var argumentsLength = arguments.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // if there is only one argument we can bypass looping through the them
							 | 
						||
| 
								 | 
							
								    if (argumentsLength > 1) {
							 | 
						||
| 
								 | 
							
								        // loop through the arguments property and add all children
							 | 
						||
| 
								 | 
							
								        // use it the right way (.length and [i]) so that this function can still be optimised by JS runtimes
							 | 
						||
| 
								 | 
							
								        for (var i = 0; i < argumentsLength; i++) {
							 | 
						||
| 
								 | 
							
								            this.addChild(arguments[i]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        this.children.push(child);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // ensure bounds will be recalculated
							 | 
						||
| 
								 | 
							
								        this._boundsID++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // TODO - lets either do all callbacks or all events.. not both!
							 | 
						||
| 
								 | 
							
								        this.onChildrenChange(this.children.length - 1);
							 | 
						||
| 
								 | 
							
								        // child.emit('added', this);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return child;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ParticleContainer.prototype.setProperties = function(properties) {
							 | 
						||
| 
								 | 
							
								    this._properties = [false, true];
							 | 
						||
| 
								 | 
							
								    if (properties) {
							 | 
						||
| 
								 | 
							
								        this._properties[0] =
							 | 
						||
| 
								 | 
							
								            'vertices' in properties || 'scale' in properties
							 | 
						||
| 
								 | 
							
								                ? !!properties.vertices || !!properties.scale
							 | 
						||
| 
								 | 
							
								                : this._properties[0];
							 | 
						||
| 
								 | 
							
								        this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ParticleRenderer.prototype.onContextChange = function() {
							 | 
						||
| 
								 | 
							
								    const gl = this.renderer.gl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this.CONTEXT_UID = this.renderer.CONTEXT_UID;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // setup default shader
							 | 
						||
| 
								 | 
							
								    this.shader = new PIXI.Shader(
							 | 
						||
| 
								 | 
							
								        gl,
							 | 
						||
| 
								 | 
							
								        [
							 | 
						||
| 
								 | 
							
								            'attribute vec2 aVertexPosition;',
							 | 
						||
| 
								 | 
							
								            'attribute vec2 aTextureCoord;',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'attribute vec2 aPositionCoord;',
							 | 
						||
| 
								 | 
							
								            'uniform float scale;',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'uniform mat3 projectionMatrix;',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'varying vec2 vTextureCoord;',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'void main(void){',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            '   vec2 v = scale * aVertexPosition + aPositionCoord;',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            '   gl_Position = vec4((projectionMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            '   vTextureCoord = aTextureCoord;',
							 | 
						||
| 
								 | 
							
								            '}'
							 | 
						||
| 
								 | 
							
								        ].join('\n'),
							 | 
						||
| 
								 | 
							
								        [
							 | 
						||
| 
								 | 
							
								            'varying vec2 vTextureCoord;',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'uniform sampler2D uSampler;',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'void main(void){',
							 | 
						||
| 
								 | 
							
								            '  vec4 color = texture2D(uSampler, vTextureCoord);',
							 | 
						||
| 
								 | 
							
								            '  gl_FragColor = color;',
							 | 
						||
| 
								 | 
							
								            '}'
							 | 
						||
| 
								 | 
							
								        ].join('\n')
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this.properties = [
							 | 
						||
| 
								 | 
							
								        // verticesData
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            attribute: this.shader.attributes.aVertexPosition,
							 | 
						||
| 
								 | 
							
								            size: 2,
							 | 
						||
| 
								 | 
							
								            uploadFunction: this.uploadVertices.bind(this),
							 | 
						||
| 
								 | 
							
								            offset: 0
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        // positionData
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            attribute: this.shader.attributes.aPositionCoord,
							 | 
						||
| 
								 | 
							
								            size: 2,
							 | 
						||
| 
								 | 
							
								            uploadFunction: this.uploadPosition,
							 | 
						||
| 
								 | 
							
								            offset: 0
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        // uvsData
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            attribute: this.shader.attributes.aTextureCoord,
							 | 
						||
| 
								 | 
							
								            size: 2,
							 | 
						||
| 
								 | 
							
								            uploadFunction: this.uploadUvs.bind(this),
							 | 
						||
| 
								 | 
							
								            offset: 0
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    ];
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ParticleRenderer.prototype.render = function(container) {
							 | 
						||
| 
								 | 
							
								    const children = container.children;
							 | 
						||
| 
								 | 
							
								    const texture = container.texture;
							 | 
						||
| 
								 | 
							
								    const maxSize = container._maxSize;
							 | 
						||
| 
								 | 
							
								    const batchSize = container._batchSize;
							 | 
						||
| 
								 | 
							
								    const renderer = this.renderer;
							 | 
						||
| 
								 | 
							
								    let totalChildren = children.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (totalChildren === 0) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								    } else if (totalChildren > maxSize) {
							 | 
						||
| 
								 | 
							
								        totalChildren = maxSize;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let buffers = container._glBuffers[renderer.CONTEXT_UID];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!buffers) {
							 | 
						||
| 
								 | 
							
								        buffers = container._glBuffers[renderer.CONTEXT_UID] = this.generateBuffers(container);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this.texture = texture;
							 | 
						||
| 
								 | 
							
								    this.anchor = container.anchor;
							 | 
						||
| 
								 | 
							
								    const baseTexture = texture.baseTexture;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // if the uvs have not updated then no point rendering just yet!
							 | 
						||
| 
								 | 
							
								    // this.renderer.setBlendMode(utils.correctBlendMode(container.blendMode, baseTexture.premultipliedAlpha));
							 | 
						||
| 
								 | 
							
								    this.renderer.setBlendMode(0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const gl = renderer.gl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const m = container.worldTransform.copy(this.tempMatrix);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m.prepend(renderer._activeRenderTarget.projectionMatrix);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this.shader.uniforms.projectionMatrix = m.toArray(true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // make sure the texture is bound..
							 | 
						||
| 
								 | 
							
								    this.shader.uniforms.uSampler = renderer.bindTexture(baseTexture);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this.shader.uniforms.scale = container.localScale;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let updateStatic = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // now lets upload and render the buffers..
							 | 
						||
| 
								 | 
							
								    for (let i = 0, j = 0; i < totalChildren; i += batchSize, j += 1) {
							 | 
						||
| 
								 | 
							
								        let amount = totalChildren - i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (amount > batchSize) {
							 | 
						||
| 
								 | 
							
								            amount = batchSize;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (j >= buffers.length) {
							 | 
						||
| 
								 | 
							
								            if (!container.autoResize) {
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            buffers.push(this._generateOneMoreBuffer(container));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const buffer = buffers[j];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // we always upload the dynamic
							 | 
						||
| 
								 | 
							
								        buffer.uploadDynamic(children, i, amount);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const bid = container._bufferUpdateIDs[i] || 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        updateStatic = updateStatic || buffer._updateID < bid;
							 | 
						||
| 
								 | 
							
								        // we only upload the static content when we have to!
							 | 
						||
| 
								 | 
							
								        if (updateStatic) {
							 | 
						||
| 
								 | 
							
								            buffer._updateID = container._updateID;
							 | 
						||
| 
								 | 
							
								            buffer.uploadStatic(children, i, amount);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // bind the buffer
							 | 
						||
| 
								 | 
							
								        renderer.bindVao(buffer.vao);
							 | 
						||
| 
								 | 
							
								        buffer.vao.draw(gl.TRIANGLES, amount * 6);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ParticleRenderer.prototype.uploadVertices = function(children, startIndex, amount, array, stride, offset) {
							 | 
						||
| 
								 | 
							
								    let w0 = 0;
							 | 
						||
| 
								 | 
							
								    let w1 = 0;
							 | 
						||
| 
								 | 
							
								    let h0 = 0;
							 | 
						||
| 
								 | 
							
								    let h1 = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const anchor = this.anchor;
							 | 
						||
| 
								 | 
							
								    const texture = this.texture;
							 | 
						||
| 
								 | 
							
								    const trim = texture.trim;
							 | 
						||
| 
								 | 
							
								    const orig = texture.orig;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let i = 0; i < amount; ++i) {
							 | 
						||
| 
								 | 
							
								        if (trim) {
							 | 
						||
| 
								 | 
							
								            // if the sprite is trimmed and is not a tilingsprite then we need to add the
							 | 
						||
| 
								 | 
							
								            // extra space before transforming the sprite coords..
							 | 
						||
| 
								 | 
							
								            w1 = trim.x - anchor.x * orig.width;
							 | 
						||
| 
								 | 
							
								            w0 = w1 + trim.width;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            h1 = trim.y - anchor.y * orig.height;
							 | 
						||
| 
								 | 
							
								            h0 = h1 + trim.height;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            w0 = orig.width * (1 - anchor.x);
							 | 
						||
| 
								 | 
							
								            w1 = orig.width * -anchor.x;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            h0 = orig.height * (1 - anchor.y);
							 | 
						||
| 
								 | 
							
								            h1 = orig.height * -anchor.y;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array[offset] = w1;
							 | 
						||
| 
								 | 
							
								        array[offset + 1] = h1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array[offset + stride] = w0;
							 | 
						||
| 
								 | 
							
								        array[offset + stride + 1] = h1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array[offset + stride * 2] = w0;
							 | 
						||
| 
								 | 
							
								        array[offset + stride * 2 + 1] = h0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array[offset + stride * 3] = w1;
							 | 
						||
| 
								 | 
							
								        array[offset + stride * 3 + 1] = h0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        offset += stride * 4;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ParticleRenderer.prototype.uploadPosition = function(children, startIndex, amount, array, stride, offset) {
							 | 
						||
| 
								 | 
							
								    for (let i = 0; i < amount; i++) {
							 | 
						||
| 
								 | 
							
								        const spritePosition = children[startIndex + i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array[offset] = spritePosition.x;
							 | 
						||
| 
								 | 
							
								        array[offset + 1] = spritePosition.y;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array[offset + stride] = spritePosition.x;
							 | 
						||
| 
								 | 
							
								        array[offset + stride + 1] = spritePosition.y;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array[offset + stride * 2] = spritePosition.x;
							 | 
						||
| 
								 | 
							
								        array[offset + stride * 2 + 1] = spritePosition.y;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array[offset + stride * 3] = spritePosition.x;
							 | 
						||
| 
								 | 
							
								        array[offset + stride * 3 + 1] = spritePosition.y;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        offset += stride * 4;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ParticleRenderer.prototype.uploadUvs = function(children, startIndex, amount, array, stride, offset) {
							 | 
						||
| 
								 | 
							
								    const textureUvs = this.texture._uvs;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let i = 0; i < amount; ++i) {
							 | 
						||
| 
								 | 
							
								        if (textureUvs) {
							 | 
						||
| 
								 | 
							
								            array[offset] = textureUvs.x0;
							 | 
						||
| 
								 | 
							
								            array[offset + 1] = textureUvs.y0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            array[offset + stride] = textureUvs.x1;
							 | 
						||
| 
								 | 
							
								            array[offset + stride + 1] = textureUvs.y1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            array[offset + stride * 2] = textureUvs.x2;
							 | 
						||
| 
								 | 
							
								            array[offset + stride * 2 + 1] = textureUvs.y2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            array[offset + stride * 3] = textureUvs.x3;
							 | 
						||
| 
								 | 
							
								            array[offset + stride * 3 + 1] = textureUvs.y3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            offset += stride * 4;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            // TODO you know this can be easier!
							 | 
						||
| 
								 | 
							
								            array[offset] = 0;
							 | 
						||
| 
								 | 
							
								            array[offset + 1] = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            array[offset + stride] = 0;
							 | 
						||
| 
								 | 
							
								            array[offset + stride + 1] = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            array[offset + stride * 2] = 0;
							 | 
						||
| 
								 | 
							
								            array[offset + stride * 2 + 1] = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            array[offset + stride * 3] = 0;
							 | 
						||
| 
								 | 
							
								            array[offset + stride * 3 + 1] = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            offset += stride * 4;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 |