mirror of
https://github.com/jiawanlong/Cesium-Examples.git
synced 2025-07-05 15:47:34 +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;
|
|
}
|
|
}
|
|
};
|