Skip to content

Commit

Permalink
Merge a38bae2 into fb88666
Browse files Browse the repository at this point in the history
  • Loading branch information
rohan-deshpande committed Nov 14, 2020
2 parents fb88666 + a38bae2 commit c661bae
Show file tree
Hide file tree
Showing 22 changed files with 718 additions and 325 deletions.
266 changes: 266 additions & 0 deletions src/renderer/GPURenderer/Desktop/index.js
@@ -0,0 +1,266 @@
import { ParticleBuffer, Target, TextureAtlas, UniqueList } from '../common';
import { fragmentShader, vertexShader } from './shaders';

import BaseRenderer from '../../BaseRenderer';
import { DEFAULT_RENDERER_OPTIONS } from '../common/constants';
import { Pool } from '../../../core';
import { RENDERER_TYPE_GPU_DESKTOP } from '../../types';

let THREE;

/**
* GPURenderer for devices that support floating point textures.
*
* @author thrax <manthrax@gmail.com>
* @author rohan-deshpande <rohan@creativelifeform.com>
*/
export default class DesktopGPURenderer extends BaseRenderer {
constructor(container, three, options = DEFAULT_RENDERER_OPTIONS) {
super(RENDERER_TYPE_GPU_DESKTOP);

THREE = this.three = three;
const props = { ...DEFAULT_RENDERER_OPTIONS, ...options };
const {
camera,
maxParticles,
baseColor,
blending,
depthTest,
depthWrite,
transparent,
shouldDebugTextureAtlas,
} = props;
const particleBuffer = new ParticleBuffer(maxParticles, THREE);
const material = new THREE.ShaderMaterial({
uniforms: {
baseColor: { value: new THREE.Color(baseColor) },
uTexture: { value: null },
atlasIndex: { value: null },
},
vertexShader: vertexShader(),
fragmentShader: fragmentShader(),
blending: THREE[blending],
depthTest,
depthWrite,
transparent,
});

this.camera = camera;
this.targetPool = new Pool();
this.uniqueList = new UniqueList(maxParticles);
this.particleBuffer = particleBuffer;
this.buffer = particleBuffer.buffer;
this.stride = particleBuffer.stride;
this.geometry = particleBuffer.geometry;
this.material = material;
this.points = new THREE.Points(this.geometry, this.material);
this.points.frustumCulled = false;
this.shouldDebugTextureAtlas = shouldDebugTextureAtlas;

container.add(this.points);
}

onSystemUpdate(system) {
super.onSystemUpdate(system);

this.buffer.needsUpdate = true;

DesktopGPURenderer.textureAtlas && DesktopGPURenderer.textureAtlas.update();
}

/**
* Pools the particle target if it does not exist.
* Updates the target and maps particle properties to the point.
*
* @param {Particle}
*/
onParticleCreated(particle) {
if (!particle.target) {
particle.target = this.targetPool.get(Target, THREE);
this.uniqueList.add(particle.id);
}

this.updateTarget(particle).mapParticleTargetPropsToPoint(particle);
}

/**
* Maps particle properties to the point if the particle has a target.
*
* @param {Particle}
*/
onParticleUpdate(particle) {
if (!particle.target) {
return;
}

this.updateTarget(particle).mapParticleTargetPropsToPoint(particle);
}

/**
* Resets and clears the particle target.
*
* @param {Particle}
*/
onParticleDead(particle) {
if (!particle.target) {
return;
}

particle.target.reset();
this.mapParticleTargetPropsToPoint(particle);

particle.target = null;
}

/**
* Maps all mutable properties from the particle to the target.
*
* @param {Particle}
* @return {DesktopGPURenderer}
*/
updateTarget(particle) {
const { position, scale, radius, color, alpha, body, id } = particle;
const { r, g, b } = color;

particle.target.position.copy(position);
particle.target.size = scale * radius;
particle.target.color.setRGB(r, g, b);
particle.target.alpha = alpha;
particle.target.index = this.uniqueList.find(id);

if (body && body instanceof THREE.Sprite) {
const { map } = body.material;

particle.target.texture = map;
particle.target.textureIndex = DesktopGPURenderer.getTextureID(
this,
map,
this.shouldDebugTextureAtlas
);
}

return this;
}

/**
* Entry point for mapping particle properties to buffer geometry points.
*
* @param {Particle} particle - The particle containing the properties to map
* @return {DesktopGPURenderer}
*/
mapParticleTargetPropsToPoint(particle) {
this.updatePointPosition(particle)
.updatePointSize(particle)
.updatePointColor(particle)
.updatePointAlpha(particle)
.updatePointTextureIndex(particle);

return this;
}

/**
* Updates the point's position according to the particle's target position.
*
* @param {Particle} particle - The particle containing the target position.
* @return {DesktopGPURenderer}
*/
updatePointPosition(particle) {
const attribute = 'position';
const { geometry, stride, buffer } = this;
const { target } = particle;
const { offset } = geometry.attributes[attribute];

buffer.array[target.index * stride + offset + 0] = target.position.x;
buffer.array[target.index * stride + offset + 1] = target.position.y;
buffer.array[target.index * stride + offset + 2] = target.position.z;

return this;
}

/**
* Updates the point's size relative to the particle's target scale and radius.
*
* @param {Particle} particle - The particle containing the target scale.
* @return {DesktopGPURenderer}
*/
updatePointSize(particle) {
const attribute = 'size';
const { geometry, stride, buffer } = this;
const { target } = particle;
const { offset } = geometry.attributes[attribute];

buffer.array[target.index * stride + offset + 0] = target.size;

return this;
}

/**
* Updates the point's color attribute according with the particle's target color.
*
* @param {Particle} particle - The particle containing the target color and alpha.
* @return {DesktopGPURenderer}
*/
updatePointColor(particle) {
const attribute = 'color';
const { geometry, stride, buffer } = this;
const { target } = particle;
const { offset } = geometry.attributes[attribute];

buffer.array[target.index * stride + offset + 0] = target.color.r;
buffer.array[target.index * stride + offset + 1] = target.color.g;
buffer.array[target.index * stride + offset + 2] = target.color.b;

return this;
}

/**
* Updates the point alpha attribute with the particle's target alpha.
*
* @param {Particle} particle - The particle containing the target alpha.
* @return {DesktopGPURenderer}
*/
updatePointAlpha(particle) {
const attribute = 'alpha';
const { geometry, stride, buffer } = this;
const { target } = particle;
const { offset } = geometry.attributes[attribute];

buffer.array[target.index * stride + offset + 0] = target.alpha;

return this;
}

/**
* Updates the point texture attribute with the particle's target texture.
*
* @param {Particle} particle - The particle containing the target texture.
* @return {DesktopGPURenderer}
*/
updatePointTextureIndex(particle) {
const attribute = 'texID';
const { geometry, stride, buffer } = this;
const { target } = particle;
const { offset } = geometry.attributes[attribute];

buffer.array[target.index * stride + offset + 0] = target.textureIndex;

return this;
}
}

DesktopGPURenderer.getTextureID = (renderer, texture, debug) => {
if (texture.textureIndex === undefined) {
let atlas = DesktopGPURenderer.textureAtlas;

if (!atlas) {
atlas = DesktopGPURenderer.textureAtlas = new TextureAtlas(
renderer,
debug
);
}

atlas.addTexture(texture);
}

return texture.textureIndex;
};
Expand Up @@ -2,18 +2,18 @@ export const fragmentShader = () => {
return `
uniform vec3 baseColor;
uniform sampler2D uTexture;
uniform sampler2D atlasIndex; //GPU
uniform sampler2D atlasIndex;
varying vec3 targetColor;
varying float targetAlpha;
varying vec4 tileRect; //GPU
varying float tileID; //GPU
varying vec4 tileRect;
varying float tileID;
void main() {
gl_FragColor = vec4(baseColor * targetColor, targetAlpha);
vec2 uv = gl_PointCoord;
uv = mix(tileRect.xy, tileRect.zw, gl_PointCoord); //GPU
uv = mix(tileRect.xy, tileRect.zw, gl_PointCoord);
gl_FragColor = gl_FragColor * texture2D(uTexture, uv);
Expand Down
File renamed without changes.
@@ -1,32 +1,32 @@
import { DATA_TEXTURE_SIZE } from '../TextureAtlas/constants';
import { SIZE_ATTENUATION_FACTOR } from './constants';
import { DATA_TEXTURE_SIZE } from '../../common/TextureAtlas/constants';
import { SIZE_ATTENUATION_FACTOR } from '../../common/shaders/constants';

export const vertexShader = () => {
return `
uniform sampler2D uTexture; //GPU
uniform sampler2D uTexture;
//atlasIndex is a 256x1 float texture of tile rectangles as r=minx g=miny b=maxx a=maxy
uniform sampler2D atlasIndex; //GPU
uniform sampler2D atlasIndex;
attribute float size;
attribute vec3 color;
attribute float alpha;
attribute float texID; //GPU
attribute float texID;
varying vec3 targetColor;
varying float targetAlpha;
varying vec4 tileRect; //GPU
varying float tileID; //GPU
varying vec4 tileRect;
varying float tileID;
void main() {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
targetColor = color;
targetAlpha = alpha;
tileID = texID; //GPU
tileID = texID;
//get the tile rectangle from the atlasIndex texture..
tileRect = texture2D(atlasIndex, vec2((tileID + 0.5) / ${DATA_TEXTURE_SIZE}.0, 0.5)); //GPU
tileRect = texture2D(atlasIndex, vec2((tileID + 0.5) / ${DATA_TEXTURE_SIZE}.0, 0.5));
gl_PointSize = ((size*${SIZE_ATTENUATION_FACTOR}) / -mvPosition.z);
gl_PointSize = ((size * ${SIZE_ATTENUATION_FACTOR}) / -mvPosition.z);
gl_Position = projectionMatrix * mvPosition;
}
`;
Expand Down

0 comments on commit c661bae

Please sign in to comment.