Skip to content

Commit

Permalink
Merge e667546 into d908ca5
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewleek-droplab committed Apr 27, 2022
2 parents d908ca5 + e667546 commit fa9732c
Show file tree
Hide file tree
Showing 20 changed files with 325 additions and 9 deletions.
146 changes: 146 additions & 0 deletions sandbox/experiments/particle-rotation/data.js

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions sandbox/experiments/particle-rotation/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Particle Rotation</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" type="text/css" href="/style/reset.css" />
<link rel="stylesheet" type="text/css" href="/style/app.css" />
</head>

<body>
<div id="app">
<canvas id="canvas"></canvas>
</div>

<script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
<script src="https://unpkg.com/three@0.122.0/examples/js/controls/OrbitControls.js"></script>
<script src="https://unpkg.com/stats-js@1.0.1/build/stats.min.js"></script>
<script src="/common/three-nebula.js"></script>
<script src="/common/Visualization.js"></script>
<script src="/common/safeLog.js"></script>
<script src="/common/run.js"></script>
<script src="/experiments/particle-rotation/data.js"></script>
<script src="/experiments/particle-rotation/index.js"></script>
<script>
run(init).then(() => console.log(`APP LOADED`));
</script>
</body>
</html>
11 changes: 11 additions & 0 deletions sandbox/experiments/particle-rotation/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { System, SpriteRenderer, GPURenderer } = window.Nebula;

window.init = async ({ scene, camera, renderer }) => {
const { particleSystemState } = window.SYSTEM;
const spriteRenderer = new SpriteRenderer(scene, THREE);
const pointsRenderer = new GPURenderer(scene, THREE);
const systemRenderer = pointsRenderer;
const system = await System.fromJSONAsync(particleSystemState, THREE);

return system.addRenderer(systemRenderer);
};
5 changes: 5 additions & 0 deletions sandbox/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
GPU Rendered Point Zone
</a>
</li>
<li>
<a href="experiments/particle-rotation/index.html">
Particle Rotation
</a>
</li>
</ul>
</nav>
<script src="https://threejs.org/build/three.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion src/behaviour/Rotate.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export default class Rotate extends Behaviour {
particle.rotation = new Vector3D();
}

particle.rotation.eulerFromDir(particle.velocity);
particle.rotation.copy(particle.velocity);
break;

case 'set':
Expand Down
2 changes: 2 additions & 0 deletions src/core/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
INITIALIZER_TYPE_MASS,
INITIALIZER_TYPE_POLAR_VELOCITY,
INITIALIZER_TYPE_POSITION,
INITIALIZER_TYPE_ROTATION,
INITIALIZER_TYPE_RADIAL_VELOCITY,
INITIALIZER_TYPE_RADIUS,
INITIALIZER_TYPE_TEXTURE,
Expand Down Expand Up @@ -123,6 +124,7 @@ export const DEFAULT_SYSTEM_DELTA = 0.0167;
*/
export const SUPPORTED_JSON_INITIALIZER_TYPES = [
INITIALIZER_TYPE_POSITION,
INITIALIZER_TYPE_ROTATION,
INITIALIZER_TYPE_LIFE,
INITIALIZER_TYPE_RADIUS,
INITIALIZER_TYPE_MASS,
Expand Down
49 changes: 49 additions & 0 deletions src/initializer/Rotation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Vector3 } from '../core/three';
import Initializer from './Initializer';
import { INITIALIZER_TYPE_ROTATION as type } from './types';

/**
* Sets the rotation property on initialized particles.
*
*/
export default class Rotation extends Initializer {
/**
* Constructs a Rotation property instance.
*
* @param {number} x - X axis rotation
* @param {number} y - Y axis rotation
* @param {number} z - Z axis rotation
* @param {boolean} [useEmitterRotation=true] - Determines if we should use the emitter's rotation as the starting rotation
* @param {boolean} [isEnabled=true] - Determines if the initializer should be enabled or not
* @return void
*/
constructor(x, y, z, useEmitterRotation=true, isEnabled = true) {
super(type, isEnabled);
this.rotation = new Vector3(x,y,z);
this.useEmitterRotation = useEmitterRotation;
}

/**
* Sets the particle's initial rotation.
*
* @param {Particle} particle - the particle to initialize the property on
* @return void
*/
initialize(particle) {
if(this.useEmitterRotation)
{
// set initial particle rotation to that of the particle's emitter then add our set rotation
particle.rotation.copy(particle.parent.rotation).add(this.rotation);
}
else
{
particle.rotation.copy(this.rotation);
}
}

static fromJSON(json) {
const { x, y, z, useEmitterRotation = true, isEnabled = true } = json;

return new Rotation(x, y, z, useEmitterRotation, isEnabled);
}
}
1 change: 1 addition & 0 deletions src/initializer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { default as InitializerUtil } from './InitializerUtil';
export { default as Life } from './Life';
export { default as Mass } from './Mass';
export { default as Position } from './Position';
export { default as Rotation } from './Rotation';
export { default as Radius } from './Radius';
export { default as Rate } from './Rate';
export { default as Texture } from './Texture';
Expand Down
1 change: 1 addition & 0 deletions src/initializer/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const INITIALIZER_TYPE_TEXTURE = 'Texture';
export const INITIALIZER_TYPE_LIFE = 'Life';
export const INITIALIZER_TYPE_MASS = 'Mass';
export const INITIALIZER_TYPE_POSITION = 'Position';
export const INITIALIZER_TYPE_ROTATION = 'Rotation';
export const INITIALIZER_TYPE_RADIUS = 'Radius';
export const INITIALIZER_TYPE_ZONE = 'Zone';
export const INITIALIZER_TYPE_VECTOR_VELOCITY = 'VectorVelocity';
Expand Down
21 changes: 20 additions & 1 deletion src/renderer/GPURenderer/Desktop/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,11 @@ export default class DesktopGPURenderer extends BaseRenderer {
* @return {DesktopGPURenderer}
*/
updateTarget(particle) {
const { position, scale, radius, color, alpha, body, id } = particle;
const { position, rotation, scale, radius, color, alpha, body, id } = particle;
const { r, g, b } = color;

particle.target.position.copy(position);
particle.target.rotation.copy(rotation);
particle.target.size = scale * radius;
particle.target.color.setRGB(r, g, b);
particle.target.alpha = alpha;
Expand Down Expand Up @@ -151,6 +152,7 @@ export default class DesktopGPURenderer extends BaseRenderer {
mapParticleTargetPropsToPoint(particle) {
this.updatePointPosition(particle)
.updatePointSize(particle)
.updatePointRotation(particle)
.updatePointColor(particle)
.updatePointAlpha(particle)
.updatePointTextureIndex(particle);
Expand Down Expand Up @@ -194,6 +196,23 @@ export default class DesktopGPURenderer extends BaseRenderer {
return this;
}

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

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

return this;
}

/**
* Updates the point's color attribute according with the particle's target color.
*
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/GPURenderer/Desktop/shaders/fragmentShader.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const fragmentShader = () => {
uniform sampler2D uTexture;
uniform sampler2D atlasIndex;
varying float vRotation;
varying vec3 targetColor;
varying float targetAlpha;
varying vec4 tileRect;
Expand All @@ -15,6 +16,12 @@ export const fragmentShader = () => {
vec2 uv = gl_PointCoord;
uv = mix(tileRect.xy, tileRect.zw, gl_PointCoord);
float mid = 0.5;
uv = vec2(
cos(vRotation) * (uv.x - mid) - sin(vRotation) * (uv.y - mid) + mid,
cos(vRotation) * (uv.y - mid) + sin(vRotation) * (uv.x - mid) + mid
);
gl_FragColor = gl_FragColor * texture2D(uTexture, uv);
}
Expand Down
3 changes: 3 additions & 0 deletions src/renderer/GPURenderer/Desktop/shaders/vertexShader.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export const vertexShader = () => {
attribute vec3 color;
attribute float alpha;
attribute float texID;
attribute float rotation;
varying float vRotation;
varying vec3 targetColor;
varying float targetAlpha;
varying vec4 tileRect;
Expand All @@ -21,6 +23,7 @@ export const vertexShader = () => {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
targetColor = color;
targetAlpha = alpha;
vRotation = rotation;
tileID = texID;
//get the tile rectangle from the atlasIndex texture..
Expand Down
21 changes: 20 additions & 1 deletion src/renderer/GPURenderer/Mobile/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,11 @@ export default class MobileGPURenderer extends BaseRenderer {
* @return {GPURenderer}
*/
updateTarget(particle) {
const { position, scale, radius, color, alpha, body, id } = particle;
const { position, rotation, scale, radius, color, alpha, body, id } = particle;
const { r, g, b } = color;

particle.target.position.copy(position);
particle.target.rotation.copy(rotation);
particle.target.size = scale * radius;
particle.target.color.setRGB(r, g, b);
particle.target.alpha = alpha;
Expand Down Expand Up @@ -159,6 +160,7 @@ export default class MobileGPURenderer extends BaseRenderer {
mapParticleTargetPropsToPoint(particle) {
this.updatePointPosition(particle)
.updatePointSize(particle)
.updatePointRotation(particle)
.updatePointColor(particle)
.updatePointAlpha(particle)
.updatePointTextureIndex(particle);
Expand Down Expand Up @@ -202,6 +204,23 @@ export default class MobileGPURenderer extends BaseRenderer {
return this;
}

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

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

return this;
}

/**
* Updates the point's color attribute according with the particle's target color.
*
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/GPURenderer/Mobile/shaders/fragmentShader.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const fragmentShader = () => {
uniform vec3 baseColor;
uniform sampler2D uTexture;
varying float vRotation;
varying vec3 targetColor;
varying float targetAlpha;
varying vec4 tileRect;
Expand All @@ -13,6 +14,12 @@ export const fragmentShader = () => {
vec2 uv = gl_PointCoord;
uv = mix(tileRect.xy, tileRect.zw, gl_PointCoord);
float mid = 0.5;
uv = vec2(
cos(vRotation) * (uv.x - mid) - sin(vRotation) * (uv.y - mid) + mid,
cos(vRotation) * (uv.y - mid) + sin(vRotation) * (uv.x - mid) + mid
);
gl_FragColor = gl_FragColor * texture2D(uTexture, uv);
}
`;
Expand Down
3 changes: 3 additions & 0 deletions src/renderer/GPURenderer/Mobile/shaders/vertexShader.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export const vertexShader = () => {
attribute vec3 color;
attribute float alpha;
attribute vec2 texID;
attribute float rotation;
varying float vRotation;
varying vec3 targetColor;
varying float targetAlpha;
varying vec4 tileRect;
Expand All @@ -18,6 +20,7 @@ export const vertexShader = () => {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
targetColor = color;
targetAlpha = alpha;
vRotation = rotation;
vec2 tmin = floor(texID) / atlasDim;
vec2 tmax = fract(texID);
Expand Down
5 changes: 5 additions & 0 deletions src/renderer/GPURenderer/common/ParticleBuffer/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ export const FLOAT_BYTE_SIZE = 4;

// Byte sizes
export const POSITION_BYTE_SIZE = VECTOR_3_SIZE * FLOAT_BYTE_SIZE;
export const ROTATION_BYTE_SIZE = FLOAT_BYTE_SIZE;
export const SIZE_BYTE_SIZE = FLOAT_BYTE_SIZE;
export const RGBA_BYTE_SIZE = RGBA_SIZE * FLOAT_BYTE_SIZE;
export const ALL_BYTE_SIZES = [
POSITION_BYTE_SIZE,
ROTATION_BYTE_SIZE,
SIZE_BYTE_SIZE,
RGBA_BYTE_SIZE,
];
Expand All @@ -19,13 +21,15 @@ export const PARTICLE_BYTE_SIZE = ALL_BYTE_SIZES.reduce(

// Attributes
export const POSITION_ATTRIBUTE_BUFFER_SIZE = VECTOR_3_SIZE;
export const ROTATION_ATTRIBUTE_BUFFER_SIZE = 1;
export const SIZE_ATTRIBUTE_BUFFER_SIZE = 1;
export const RGBA_ATTRIBUTE_BUFFER_SIZE = RGBA_SIZE;
export const ALPHA_ATTRIBUTE_BUFFER_SIZE = 1;
export const TEXID_ATTRIBUTE_BUFFER_SIZE = 2;

export const ATTRIBUTE_TO_SIZE_MAP = {
position: POSITION_ATTRIBUTE_BUFFER_SIZE,
rotation: ROTATION_ATTRIBUTE_BUFFER_SIZE,
size: SIZE_ATTRIBUTE_BUFFER_SIZE,
// THREE.Color does not contain alpha, so we will have separate attributes for these
color: RGBA_ATTRIBUTE_BUFFER_SIZE,
Expand All @@ -35,6 +39,7 @@ export const ATTRIBUTE_TO_SIZE_MAP = {

export const PARTICLE_STRIDE = [
POSITION_ATTRIBUTE_BUFFER_SIZE,
ROTATION_ATTRIBUTE_BUFFER_SIZE,
SIZE_ATTRIBUTE_BUFFER_SIZE,
RGBA_ATTRIBUTE_BUFFER_SIZE,
ALPHA_ATTRIBUTE_BUFFER_SIZE,
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/GPURenderer/common/stores/Target.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
export class Target {
constructor(THREE) {
this.position = new THREE.Vector3();
this.rotation = new THREE.Vector3();
this.size = 0;
this.color = new THREE.Color();
this.alpha = 0;
Expand All @@ -14,6 +15,7 @@ export class Target {

reset() {
this.position.set(0, 0, 0);
this.rotation.set(0, 0, 0);
this.size = 0;
this.color.setRGB(0, 0, 0);
this.alpha = 0;
Expand Down
10 changes: 6 additions & 4 deletions src/renderer/MeshRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,15 @@ export default class MeshRenderer extends BaseRenderer {
}

onParticleUpdate(particle) {
const { target, useAlpha, useColor, rotation } = particle;
const { target, useAlpha, useColor } = particle;

if (!target) {
return;
}

target.position.copy(particle.position);

if (!this.isThreeSprite(particle)) {
target.rotation.set(rotation.x, rotation.y, rotation.z);
}
this.rotate(particle);

this.scale(particle);

Expand All @@ -75,6 +73,10 @@ export default class MeshRenderer extends BaseRenderer {
}
}

rotate(particle) {
particle.target.rotation.set(particle.rotation.x, particle.rotation.y, particle.rotation.z);
}

scale(particle) {
particle.target.scale.set(particle.scale, particle.scale, particle.scale);
}
Expand Down
Loading

0 comments on commit fa9732c

Please sign in to comment.