Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
车家大少爷
three.js
提交
d3b3b6f0
T
three.js
项目概览
车家大少爷
/
three.js
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
three.js
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d3b3b6f0
编写于
8月 13, 2015
作者:
M
Mr.doob
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Removed Sparks (Unmaintained)
上级
0ccc3570
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
0 addition
and
1990 deletion
+0
-1990
examples/canvas_particles_shapes.html
examples/canvas_particles_shapes.html
+0
-345
examples/index.html
examples/index.html
+0
-2
examples/js/Sparks.js
examples/js/Sparks.js
+0
-981
examples/webgl_particles_shapes.html
examples/webgl_particles_shapes.html
+0
-662
未找到文件。
examples/canvas_particles_shapes.html
已删除
100644 → 0
浏览文件 @
0ccc3570
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<title>
three.js canvas - particles with shapes
</title>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
>
<style>
body
{
font-family
:
Monospace
;
background-color
:
#f0f0f0
;
margin
:
0px
;
overflow
:
hidden
;
}
</style>
</head>
<body>
<script
src=
"../build/three.min.js"
></script>
<script
src=
"js/renderers/Projector.js"
></script>
<script
src=
"js/renderers/CanvasRenderer.js"
></script>
<script
src=
"js/libs/stats.min.js"
></script>
<script
src=
"js/libs/tween.min.js"
></script>
<script
src=
"js/Sparks.js"
></script>
<!-- load the font file from canvas-text -->
<script
src=
"fonts/helvetiker_regular.typeface.js"
></script>
<script>
var
container
,
stats
;
var
camera
,
scene
,
renderer
;
var
group
,
text
,
plane
;
var
targetRotation
=
0
;
var
targetRotationOnMouseDown
=
0
;
var
mouseX
=
0
;
var
mouseXOnMouseDown
=
0
;
var
windowHalfX
=
window
.
innerWidth
/
2
;
var
windowHalfY
=
window
.
innerHeight
/
2
;
var
heartShape
,
particleCloud
,
sparksEmitter
,
emitterPos
;
var
_rotation
=
0
;
var
timeOnShapePath
=
0
;
init
();
animate
();
function
init
()
{
container
=
document
.
createElement
(
'
div
'
);
document
.
body
.
appendChild
(
container
);
var
info
=
document
.
createElement
(
'
div
'
);
info
.
style
.
position
=
'
absolute
'
;
info
.
style
.
top
=
'
10px
'
;
info
.
style
.
width
=
'
100%
'
;
info
.
style
.
textAlign
=
'
center
'
;
info
.
innerHTML
=
'
Three.js with Love. Simple Particle Systems with Shapes by <a href="http://www.lab4games.net/zz85/blog">zz85</a><br>Move your mouse.
'
;
container
.
appendChild
(
info
);
camera
=
new
THREE
.
PerspectiveCamera
(
50
,
window
.
innerWidth
/
window
.
innerHeight
,
1
,
1000
);
camera
.
position
.
set
(
0
,
150
,
700
);
scene
=
new
THREE
.
Scene
();
group
=
new
THREE
.
Group
();
scene
.
add
(
group
);
// Get text from hash
var
string
=
"
THREE.JS
"
;
var
hash
=
document
.
location
.
hash
.
substr
(
1
);
if
(
hash
.
length
!==
0
)
{
string
=
hash
;
}
var
text3d
=
new
THREE
.
TextGeometry
(
string
,
{
size
:
80
,
height
:
20
,
curveSegments
:
2
,
font
:
"
helvetiker
"
});
text3d
.
computeBoundingBox
();
var
centerOffset
=
-
0.5
*
(
text3d
.
boundingBox
.
max
.
x
-
text3d
.
boundingBox
.
min
.
x
);
var
textMaterial
=
new
THREE
.
MeshBasicMaterial
(
{
color
:
Math
.
random
()
*
0xffffff
,
overdraw
:
0.5
}
);
text
=
new
THREE
.
Mesh
(
text3d
,
textMaterial
);
// Potentially, we can extract the vertices or faces of the text to generate particles too.
// Geo > Vertices > Position
text
.
position
.
x
=
centerOffset
;
text
.
position
.
y
=
100
;
text
.
position
.
z
=
0
;
text
.
rotation
.
x
=
0
;
text
.
rotation
.
y
=
Math
.
PI
*
2
;
group
.
add
(
text
);
particleCloud
=
new
THREE
.
Object3D
();
// Just a group
particleCloud
.
y
=
800
;
group
.
add
(
particleCloud
);
// Create Particle Systems
// Heart
var
x
=
0
,
y
=
0
;
heartShape
=
new
THREE
.
Shape
();
heartShape
.
moveTo
(
x
+
25
,
y
+
25
);
heartShape
.
bezierCurveTo
(
x
+
25
,
y
+
25
,
x
+
20
,
y
,
x
,
y
);
heartShape
.
bezierCurveTo
(
x
-
30
,
y
,
x
-
30
,
y
+
35
,
x
-
30
,
y
+
35
);
heartShape
.
bezierCurveTo
(
x
-
30
,
y
+
55
,
x
-
10
,
y
+
77
,
x
+
25
,
y
+
95
);
heartShape
.
bezierCurveTo
(
x
+
60
,
y
+
77
,
x
+
80
,
y
+
55
,
x
+
80
,
y
+
35
);
heartShape
.
bezierCurveTo
(
x
+
80
,
y
+
35
,
x
+
80
,
y
,
x
+
50
,
y
);
heartShape
.
bezierCurveTo
(
x
+
35
,
y
,
x
+
25
,
y
+
25
,
x
+
25
,
y
+
25
);
var
hue
=
0
;
var
hearts
=
function
(
context
)
{
context
.
globalAlpha
=
0.5
;
var
x
=
0
,
y
=
0
;
context
.
scale
(
0.05
,
-
0.05
);
// Scale so canvas render can redraw within bounds
context
.
beginPath
();
// From http://blog.burlock.org/html5/130-paths
context
.
bezierCurveTo
(
x
+
2.5
,
y
+
2.5
,
x
+
2.0
,
y
,
x
,
y
);
context
.
bezierCurveTo
(
x
-
3.0
,
y
,
x
-
3.0
,
y
+
3.5
,
x
-
3.0
,
y
+
3.5
);
context
.
bezierCurveTo
(
x
-
3.0
,
y
+
5.5
,
x
-
1.0
,
y
+
7.7
,
x
+
2.5
,
y
+
9.5
);
context
.
bezierCurveTo
(
x
+
6.0
,
y
+
7.7
,
x
+
8.0
,
y
+
5.5
,
x
+
8.0
,
y
+
3.5
);
context
.
bezierCurveTo
(
x
+
8.0
,
y
+
3.5
,
x
+
8.0
,
y
,
x
+
5.0
,
y
);
context
.
bezierCurveTo
(
x
+
3.5
,
y
,
x
+
2.5
,
y
+
2.5
,
x
+
2.5
,
y
+
2.5
);
context
.
fill
();
context
.
lineWidth
=
0.5
;
//0.05
context
.
stroke
();
};
var
setTargetParticle
=
function
()
{
var
material
=
new
THREE
.
SpriteCanvasMaterial
(
{
program
:
hearts
}
);
material
.
color
.
setHSL
(
hue
,
1
,
0.75
);
hue
+=
0.001
;
if
(
hue
>
1
)
hue
-=
1
;
particle
=
new
THREE
.
Sprite
(
material
);
particle
.
scale
.
x
=
particle
.
scale
.
y
=
Math
.
random
()
*
40
+
40
;
particleCloud
.
add
(
particle
);
return
particle
;
};
var
onParticleCreated
=
function
(
p
)
{
p
.
target
.
position
.
copy
(
p
.
position
);
};
var
onParticleDead
=
function
(
particle
)
{
particle
.
target
.
visible
=
false
;
particleCloud
.
remove
(
particle
.
target
);
};
sparksEmitter
=
new
SPARKS
.
Emitter
(
new
SPARKS
.
SteadyCounter
(
160
));
emitterpos
=
new
THREE
.
Vector3
();
sparksEmitter
.
addInitializer
(
new
SPARKS
.
Position
(
new
SPARKS
.
PointZone
(
emitterpos
)
)
);
sparksEmitter
.
addInitializer
(
new
SPARKS
.
Lifetime
(
0
,
2
));
sparksEmitter
.
addInitializer
(
new
SPARKS
.
Target
(
null
,
setTargetParticle
));
sparksEmitter
.
addInitializer
(
new
SPARKS
.
Velocity
(
new
SPARKS
.
PointZone
(
new
THREE
.
Vector3
(
0
,
-
50
,
10
))));
// TOTRY Set velocity to move away from centroid
sparksEmitter
.
addAction
(
new
SPARKS
.
Age
());
//sparksEmitter.addAction(new SPARKS.Accelerate(0.2));
sparksEmitter
.
addAction
(
new
SPARKS
.
Move
());
sparksEmitter
.
addAction
(
new
SPARKS
.
RandomDrift
(
50
,
50
,
2000
));
sparksEmitter
.
addCallback
(
"
created
"
,
onParticleCreated
);
sparksEmitter
.
addCallback
(
"
dead
"
,
onParticleDead
);
sparksEmitter
.
addCallback
(
"
updated
"
,
function
(
particle
)
{
particle
.
target
.
position
.
copy
(
particle
.
position
);
});
sparksEmitter
.
start
();
// End Particles
renderer
=
new
THREE
.
CanvasRenderer
();
renderer
.
setClearColor
(
0xf0f0f0
);
renderer
.
setPixelRatio
(
window
.
devicePixelRatio
);
renderer
.
setSize
(
window
.
innerWidth
,
window
.
innerHeight
);
container
.
appendChild
(
renderer
.
domElement
);
stats
=
new
Stats
();
stats
.
domElement
.
style
.
position
=
'
absolute
'
;
stats
.
domElement
.
style
.
top
=
'
0px
'
;
container
.
appendChild
(
stats
.
domElement
);
document
.
addEventListener
(
'
mousedown
'
,
onDocumentMouseDown
,
false
);
document
.
addEventListener
(
'
touchstart
'
,
onDocumentTouchStart
,
false
);
document
.
addEventListener
(
'
touchmove
'
,
onDocumentTouchMove
,
false
);
//
window
.
addEventListener
(
'
resize
'
,
onWindowResize
,
false
);
}
function
onWindowResize
()
{
windowHalfX
=
window
.
innerWidth
/
2
;
windowHalfY
=
window
.
innerHeight
/
2
;
camera
.
aspect
=
window
.
innerWidth
/
window
.
innerHeight
;
camera
.
updateProjectionMatrix
();
renderer
.
setSize
(
window
.
innerWidth
,
window
.
innerHeight
);
}
//
document
.
addEventListener
(
'
mousemove
'
,
onDocumentMouseMove
,
false
);
function
onDocumentMouseDown
(
event
)
{
event
.
preventDefault
();
mouseXOnMouseDown
=
event
.
clientX
-
windowHalfX
;
targetRotationOnMouseDown
=
targetRotation
;
if
(
sparksEmitter
.
isRunning
()
)
{
sparksEmitter
.
stop
();
}
else
{
sparksEmitter
.
start
();
}
}
function
onDocumentMouseMove
(
event
)
{
mouseX
=
event
.
clientX
-
windowHalfX
;
targetRotation
=
targetRotationOnMouseDown
+
(
mouseX
-
mouseXOnMouseDown
)
*
0.02
;
}
function
onDocumentTouchStart
(
event
)
{
if
(
event
.
touches
.
length
==
1
)
{
event
.
preventDefault
();
mouseXOnMouseDown
=
event
.
touches
[
0
].
pageX
-
windowHalfX
;
targetRotationOnMouseDown
=
targetRotation
;
}
}
function
onDocumentTouchMove
(
event
)
{
if
(
event
.
touches
.
length
==
1
)
{
event
.
preventDefault
();
mouseX
=
event
.
touches
[
0
].
pageX
-
windowHalfX
;
targetRotation
=
targetRotationOnMouseDown
+
(
mouseX
-
mouseXOnMouseDown
)
*
0.05
;
}
}
//
function
animate
()
{
requestAnimationFrame
(
animate
);
render
();
stats
.
update
();
}
function
render
()
{
timeOnShapePath
+=
0.0337
;
if
(
timeOnShapePath
>
1
)
timeOnShapePath
-=
1
;
// TODO Create a PointOnShape Action/Zone in the particle engine
var
pointOnShape
=
heartShape
.
getPointAt
(
timeOnShapePath
);
emitterpos
.
x
=
pointOnShape
.
x
*
5
-
100
;
emitterpos
.
y
=
-
pointOnShape
.
y
*
5
+
400
;
// Pretty cool effect if you enable this
// particleCloud.rotation.y += 0.05;
group
.
rotation
.
y
+=
(
targetRotation
-
group
.
rotation
.
y
)
*
0.05
;
renderer
.
render
(
scene
,
camera
);
}
</script>
</body>
</html>
examples/index.html
浏览文件 @
d3b3b6f0
...
...
@@ -334,7 +334,6 @@
"
webgl_particles_billboards_colors
"
,
"
webgl_particles_dynamic
"
,
"
webgl_particles_random
"
,
"
webgl_particles_shapes
"
,
"
webgl_particles_sprites
"
,
"
webgl_performance
"
,
"
webgl_performance_doublesided
"
,
...
...
@@ -460,7 +459,6 @@
"
canvas_morphtargets_horse
"
,
"
canvas_particles_floor
"
,
"
canvas_particles_random
"
,
"
canvas_particles_shapes
"
,
"
canvas_particles_sprites
"
,
"
canvas_particles_waves
"
,
"
canvas_performance
"
,
...
...
examples/js/Sparks.js
已删除
100644 → 0
浏览文件 @
0ccc3570
/*
* @author zz85 (http://github.com/zz85 http://www.lab4games.net/zz85/blog)
*
* a simple to use javascript 3d particles system inspired by FliNT and Stardust
* created with TWEEN.js and THREE.js
*
* for feature requests or bugs, please visit https://github.com/zz85/sparks.js
*
* licensed under the MIT license
*/
var
SPARKS
=
{};
/********************************
* Emitter Class
*
* Creates and Manages Particles
*********************************/
SPARKS
.
Emitter
=
function
(
counter
)
{
this
.
_counter
=
counter
?
counter
:
new
SPARKS
.
SteadyCounter
(
10
);
// provides number of particles to produce
this
.
_particles
=
[];
this
.
_initializers
=
[];
// use for creation of particles
this
.
_actions
=
[];
// uses action to update particles
this
.
_activities
=
[];
// not supported yet
this
.
_handlers
=
[];
this
.
callbacks
=
{};
};
SPARKS
.
Emitter
.
prototype
=
{
_TIMESTEP
:
15
,
_timer
:
null
,
_lastTime
:
null
,
_timerStep
:
10
,
_velocityVerlet
:
true
,
// run its built in timer / stepping
start
:
function
()
{
this
.
_lastTime
=
Date
.
now
();
this
.
_timer
=
setTimeout
(
this
.
step
,
this
.
_timerStep
,
this
);
this
.
_isRunning
=
true
;
},
stop
:
function
()
{
this
.
_isRunning
=
false
;
clearTimeout
(
this
.
_timer
);
},
isRunning
:
function
()
{
return
this
.
_isRunning
&
true
;
},
// Step gets called upon by the engine
// but attempts to call update() on a regular basics
// This method is also described in http://gameclosure.com/2011/04/11/deterministic-delta-tee-in-js-games/
step
:
function
(
emitter
)
{
var
time
=
Date
.
now
();
var
elapsed
=
time
-
emitter
.
_lastTime
;
if
(
!
this
.
_velocityVerlet
)
{
// if elapsed is way higher than time step, (usually after switching tabs, or excution cached in ff)
// we will drop cycles. perhaps set to a limit of 10 or something?
var
maxBlock
=
emitter
.
_TIMESTEP
*
20
;
if
(
elapsed
>=
maxBlock
)
{
//console.log('warning: sparks.js is fast fowarding engine, skipping steps', elapsed / emitter._TIMESTEP);
//emitter.update( (elapsed - maxBlock) / 1000);
elapsed
=
maxBlock
;
}
while
(
elapsed
>=
emitter
.
_TIMESTEP
)
{
emitter
.
update
(
emitter
.
_TIMESTEP
/
1000
);
elapsed
-=
emitter
.
_TIMESTEP
;
}
emitter
.
_lastTime
=
time
-
elapsed
;
}
else
{
emitter
.
update
(
elapsed
/
1000
);
emitter
.
_lastTime
=
time
;
}
if
(
emitter
.
_isRunning
)
setTimeout
(
emitter
.
step
,
emitter
.
_timerStep
,
emitter
);
},
// Update particle engine in seconds, not milliseconds
update
:
function
(
time
)
{
var
i
,
j
;
var
len
=
this
.
_counter
.
updateEmitter
(
this
,
time
);
// Create particles
for
(
i
=
0
;
i
<
len
;
i
++
)
{
this
.
createParticle
();
}
// Update activities
len
=
this
.
_activities
.
length
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
this
.
_activities
[
i
].
update
(
this
,
time
);
}
len
=
this
.
_actions
.
length
;
var
particle
;
var
action
;
var
len2
=
this
.
_particles
.
length
;
for
(
j
=
0
;
j
<
len
;
j
++
)
{
action
=
this
.
_actions
[
j
];
for
(
i
=
0
;
i
<
len2
;
++
i
)
{
particle
=
this
.
_particles
[
i
];
action
.
update
(
this
,
particle
,
time
);
}
}
// remove dead particles
for
(
i
=
len2
;
i
--
;
)
{
particle
=
this
.
_particles
[
i
];
if
(
particle
.
isDead
)
{
//particle =
this
.
_particles
.
splice
(
i
,
1
);
this
.
dispatchEvent
(
"
dead
"
,
particle
);
SPARKS
.
VectorPool
.
release
(
particle
.
position
);
//
SPARKS
.
VectorPool
.
release
(
particle
.
velocity
);
}
else
{
this
.
dispatchEvent
(
"
updated
"
,
particle
);
}
}
this
.
dispatchEvent
(
"
loopUpdated
"
);
},
createParticle
:
function
()
{
var
particle
=
new
SPARKS
.
Particle
();
// In future, use a Particle Factory
var
len
=
this
.
_initializers
.
length
,
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
this
.
_initializers
[
i
].
initialize
(
this
,
particle
);
}
this
.
_particles
.
push
(
particle
);
this
.
dispatchEvent
(
"
created
"
,
particle
);
// ParticleCreated
return
particle
;
},
addInitializer
:
function
(
initializer
)
{
this
.
_initializers
.
push
(
initializer
);
},
addAction
:
function
(
action
)
{
this
.
_actions
.
push
(
action
);
},
removeInitializer
:
function
(
initializer
)
{
var
index
=
this
.
_initializers
.
indexOf
(
initializer
);
if
(
index
>
-
1
)
{
this
.
_initializers
.
splice
(
index
,
1
);
}
},
removeAction
:
function
(
action
)
{
var
index
=
this
.
_actions
.
indexOf
(
action
);
if
(
index
>
-
1
)
{
this
.
_actions
.
splice
(
index
,
1
);
}
//console.log('removeAction', index, this._actions);
},
addCallback
:
function
(
name
,
callback
)
{
this
.
callbacks
[
name
]
=
callback
;
},
dispatchEvent
:
function
(
name
,
args
)
{
var
callback
=
this
.
callbacks
[
name
];
if
(
callback
)
{
callback
(
args
);
}
}
};
/*
* Constant Names for
* Events called by emitter.dispatchEvent()
*
*/
SPARKS
.
EVENT_PARTICLE_CREATED
=
"
created
"
;
SPARKS
.
EVENT_PARTICLE_UPDATED
=
"
updated
"
;
SPARKS
.
EVENT_PARTICLE_DEAD
=
"
dead
"
;
SPARKS
.
EVENT_LOOP_UPDATED
=
"
loopUpdated
"
;
/*
* Steady Counter attempts to produces a particle rate steadily
*
*/
// Number of particles per seconds
SPARKS
.
SteadyCounter
=
function
(
rate
)
{
this
.
rate
=
rate
;
// we use a shortfall counter to make up for slow emitters
this
.
leftover
=
0
;
};
SPARKS
.
SteadyCounter
.
prototype
.
updateEmitter
=
function
(
emitter
,
time
)
{
var
targetRelease
=
time
*
this
.
rate
+
this
.
leftover
;
var
actualRelease
=
Math
.
floor
(
targetRelease
);
this
.
leftover
=
targetRelease
-
actualRelease
;
return
actualRelease
;
};
/*
* Shot Counter produces specified particles
* on a single impluse or burst
*/
SPARKS
.
ShotCounter
=
function
(
particles
)
{
this
.
particles
=
particles
;
this
.
used
=
false
;
};
SPARKS
.
ShotCounter
.
prototype
.
updateEmitter
=
function
(
emitter
,
time
)
{
if
(
this
.
used
)
{
return
0
;
}
else
{
this
.
used
=
true
;
}
return
this
.
particles
;
};
/********************************
* Particle Class
*
* Represents a single particle
*********************************/
SPARKS
.
Particle
=
function
()
{
/**
* The lifetime of the particle, in seconds.
*/
this
.
lifetime
=
0
;
/**
* The age of the particle, in seconds.
*/
this
.
age
=
0
;
/**
* The energy of the particle.
*/
this
.
energy
=
1
;
/**
* Whether the particle is dead and should be removed from the stage.
*/
this
.
isDead
=
false
;
this
.
target
=
null
;
// tag
/**
* For 3D
*/
this
.
position
=
SPARKS
.
VectorPool
.
get
().
set
(
0
,
0
,
0
);
//new THREE.Vector3( 0, 0, 0 );
this
.
velocity
=
SPARKS
.
VectorPool
.
get
().
set
(
0
,
0
,
0
);
//new THREE.Vector3( 0, 0, 0 );
this
.
_oldvelocity
=
SPARKS
.
VectorPool
.
get
().
set
(
0
,
0
,
0
);
// rotation vec3
// angVelocity vec3
// faceAxis vec3
};
/********************************
* Action Classes
*
* An abstract class which have
* update function
*********************************/
SPARKS
.
Action
=
function
()
{
this
.
_priority
=
0
;
};
SPARKS
.
Age
=
function
(
easing
)
{
this
.
_easing
=
(
easing
==
null
)
?
TWEEN
.
Easing
.
Linear
.
None
:
easing
;
};
SPARKS
.
Age
.
prototype
.
update
=
function
(
emitter
,
particle
,
time
)
{
particle
.
age
+=
time
;
if
(
particle
.
age
>=
particle
.
lifetime
)
{
particle
.
energy
=
0
;
particle
.
isDead
=
true
;
}
else
{
var
t
=
this
.
_easing
(
particle
.
age
/
particle
.
lifetime
);
particle
.
energy
=
-
1
*
t
+
1
;
}
};
/*
// Mark particle as dead when particle's < 0
SPARKS.Death = function(easing) {
this._easing = (easing == null) ? TWEEN.Linear.None : easing;
};
SPARKS.Death.prototype.update = function (emitter, particle, time) {
if (particle.life <= 0) {
particle.isDead = true;
}
};
*/
SPARKS
.
Move
=
function
()
{
};
SPARKS
.
Move
.
prototype
.
update
=
function
(
emitter
,
particle
,
time
)
{
// attempt verlet velocity updating.
var
p
=
particle
.
position
;
var
v
=
particle
.
velocity
;
var
old
=
particle
.
_oldvelocity
;
if
(
this
.
_velocityVerlet
)
{
p
.
x
+=
(
v
.
x
+
old
.
x
)
*
0.5
*
time
;
p
.
y
+=
(
v
.
y
+
old
.
y
)
*
0.5
*
time
;
p
.
z
+=
(
v
.
z
+
old
.
z
)
*
0.5
*
time
;
}
else
{
p
.
x
+=
v
.
x
*
time
;
p
.
y
+=
v
.
y
*
time
;
p
.
z
+=
v
.
z
*
time
;
}
// OldVel = Vel;
// Vel = Vel + Accel * dt;
// Pos = Pos + (vel + Vel + Accel * dt) * 0.5 * dt;
};
/* Marks particles found in specified zone dead */
SPARKS
.
DeathZone
=
function
(
zone
)
{
this
.
zone
=
zone
;
};
SPARKS
.
DeathZone
.
prototype
.
update
=
function
(
emitter
,
particle
,
time
)
{
if
(
this
.
zone
.
contains
(
particle
.
position
)
)
{
particle
.
isDead
=
true
;
}
};
/*
* SPARKS.ActionZone applies an action when particle is found in zone
*/
SPARKS
.
ActionZone
=
function
(
action
,
zone
)
{
this
.
action
=
action
;
this
.
zone
=
zone
;
};
SPARKS
.
ActionZone
.
prototype
.
update
=
function
(
emitter
,
particle
,
time
)
{
if
(
this
.
zone
.
contains
(
particle
.
position
)
)
{
this
.
action
.
update
(
emitter
,
particle
,
time
);
}
};
/*
* Accelerate action affects velocity in specified 3d direction
*/
SPARKS
.
Accelerate
=
function
(
x
,
y
,
z
)
{
if
(
x
instanceof
THREE
.
Vector3
)
{
this
.
acceleration
=
x
;
return
;
}
this
.
acceleration
=
new
THREE
.
Vector3
(
x
,
y
,
z
);
};
SPARKS
.
Accelerate
.
prototype
.
update
=
function
(
emitter
,
particle
,
time
)
{
var
acc
=
this
.
acceleration
;
var
v
=
particle
.
velocity
;
particle
.
_oldvelocity
.
set
(
v
.
x
,
v
.
y
,
v
.
z
);
v
.
x
+=
acc
.
x
*
time
;
v
.
y
+=
acc
.
y
*
time
;
v
.
z
+=
acc
.
z
*
time
;
};
/*
* Accelerate Factor accelerate based on a factor of particle's velocity.
*/
SPARKS
.
AccelerateFactor
=
function
(
factor
)
{
this
.
factor
=
factor
;
};
SPARKS
.
AccelerateFactor
.
prototype
.
update
=
function
(
emitter
,
particle
,
time
)
{
var
factor
=
this
.
factor
;
var
v
=
particle
.
velocity
;
var
len
=
v
.
length
();
var
adjFactor
;
if
(
len
>
0
)
{
adjFactor
=
factor
*
time
/
len
;
adjFactor
+=
1
;
v
.
multiplyScalar
(
adjFactor
);
// v.x *= adjFactor;
// v.y *= adjFactor;
// v.z *= adjFactor;
}
};
/*
AccelerateNormal
* AccelerateVelocity affects velocity based on its velocity direction
*/
SPARKS
.
AccelerateVelocity
=
function
(
factor
)
{
this
.
factor
=
factor
;
};
SPARKS
.
AccelerateVelocity
.
prototype
.
update
=
function
(
emitter
,
particle
,
time
)
{
var
factor
=
this
.
factor
;
var
v
=
particle
.
velocity
;
v
.
z
+=
-
v
.
x
*
factor
;
v
.
y
+=
v
.
z
*
factor
;
v
.
x
+=
v
.
y
*
factor
;
};
/* Set the max ammount of x,y,z drift movements in a second */
SPARKS
.
RandomDrift
=
function
(
x
,
y
,
z
)
{
if
(
x
instanceof
THREE
.
Vector3
)
{
this
.
drift
=
x
;
return
;
}
this
.
drift
=
new
THREE
.
Vector3
(
x
,
y
,
z
);
};
SPARKS
.
RandomDrift
.
prototype
.
update
=
function
(
emitter
,
particle
,
time
)
{
var
drift
=
this
.
drift
;
var
v
=
particle
.
velocity
;
v
.
x
+=
(
Math
.
random
()
-
0.5
)
*
drift
.
x
*
time
;
v
.
y
+=
(
Math
.
random
()
-
0.5
)
*
drift
.
y
*
time
;
v
.
z
+=
(
Math
.
random
()
-
0.5
)
*
drift
.
z
*
time
;
};
/********************************
* Zone Classes
*
* An abstract classes which have
* getLocation() function
*********************************/
SPARKS
.
Zone
=
function
()
{
};
// TODO, contains() for Zone
SPARKS
.
PointZone
=
function
(
pos
)
{
this
.
pos
=
pos
;
};
SPARKS
.
PointZone
.
prototype
.
getLocation
=
function
()
{
return
this
.
pos
;
};
SPARKS
.
PointZone
=
function
(
pos
)
{
this
.
pos
=
pos
;
};
SPARKS
.
PointZone
.
prototype
.
getLocation
=
function
()
{
return
this
.
pos
;
};
SPARKS
.
LineZone
=
function
(
start
,
end
)
{
this
.
start
=
start
;
this
.
end
=
end
;
this
.
_length
=
end
.
clone
().
sub
(
start
);
};
SPARKS
.
LineZone
.
prototype
.
getLocation
=
function
()
{
var
len
=
this
.
_length
.
clone
();
len
.
multiplyScalar
(
Math
.
random
()
);
return
len
.
add
(
this
.
start
);
};
// Basically a RectangleZone
SPARKS
.
ParallelogramZone
=
function
(
corner
,
side1
,
side2
)
{
this
.
corner
=
corner
;
this
.
side1
=
side1
;
this
.
side2
=
side2
;
};
SPARKS
.
ParallelogramZone
.
prototype
.
getLocation
=
function
()
{
var
d1
=
this
.
side1
.
clone
().
multiplyScalar
(
Math
.
random
()
);
var
d2
=
this
.
side2
.
clone
().
multiplyScalar
(
Math
.
random
()
);
d1
.
add
(
d2
);
return
d1
.
add
(
this
.
corner
);
};
SPARKS
.
CubeZone
=
function
(
position
,
x
,
y
,
z
)
{
this
.
position
=
position
;
this
.
x
=
x
;
this
.
y
=
y
;
this
.
z
=
z
;
};
SPARKS
.
CubeZone
.
prototype
.
getLocation
=
function
()
{
//TODO use pool?
var
location
=
this
.
position
.
clone
();
location
.
x
+=
Math
.
random
()
*
this
.
x
;
location
.
y
+=
Math
.
random
()
*
this
.
y
;
location
.
z
+=
Math
.
random
()
*
this
.
z
;
return
location
;
};
SPARKS
.
CubeZone
.
prototype
.
contains
=
function
(
position
)
{
var
startX
=
this
.
position
.
x
;
var
startY
=
this
.
position
.
y
;
var
startZ
=
this
.
position
.
z
;
var
x
=
this
.
x
;
// width
var
y
=
this
.
y
;
// depth
var
z
=
this
.
z
;
// height
if
(
x
<
0
)
{
startX
+=
x
;
x
=
Math
.
abs
(
x
);
}
if
(
y
<
0
)
{
startY
+=
y
;
y
=
Math
.
abs
(
y
);
}
if
(
z
<
0
)
{
startZ
+=
z
;
z
=
Math
.
abs
(
z
);
}
var
diffX
=
position
.
x
-
startX
;
var
diffY
=
position
.
y
-
startY
;
var
diffZ
=
position
.
z
-
startZ
;
if
(
(
diffX
>
0
)
&&
(
diffX
<
x
)
&&
(
diffY
>
0
)
&&
(
diffY
<
y
)
&&
(
diffZ
>
0
)
&&
(
diffZ
<
z
)
)
{
return
true
;
}
return
false
;
};
/**
* The constructor creates a DiscZone 3D zone.
*
* @param centre The point at the center of the disc.
* @param normal A vector normal to the disc.
* @param outerRadius The outer radius of the disc.
* @param innerRadius The inner radius of the disc. This defines the hole
* in the center of the disc. If set to zero, there is no hole.
*/
/*
// BUGGY!!
SPARKS.DiscZone = function(center, radiusNormal, outerRadius, innerRadius) {
this.center = center;
this.radiusNormal = radiusNormal;
this.outerRadius = (outerRadius==undefined) ? 0 : outerRadius;
this.innerRadius = (innerRadius==undefined) ? 0 : innerRadius;
};
SPARKS.DiscZone.prototype.getLocation = function() {
var rand = Math.random();
var _innerRadius = this.innerRadius;
var _outerRadius = this.outerRadius;
var center = this.center;
var _normal = this.radiusNormal;
_distToOrigin = _normal.dot( center );
var radius = _innerRadius + (1 - rand * rand ) * ( _outerRadius - _innerRadius );
var angle = Math.random() * SPARKS.Utils.TWOPI;
var _distToOrigin = _normal.dot( center );
var axes = SPARKS.Utils.getPerpendiculars( _normal.clone() );
var _planeAxis1 = axes[0];
var _planeAxis2 = axes[1];
var p = _planeAxis1.clone();
p.multiplyScalar( radius * Math.cos( angle ) );
var p2 = _planeAxis2.clone();
p2.multiplyScalar( radius * Math.sin( angle ) );
p.add( p2 );
return _center.add( p );
};
*/
SPARKS
.
SphereCapZone
=
function
(
x
,
y
,
z
,
minr
,
maxr
,
angle
)
{
this
.
x
=
x
;
this
.
y
=
y
;
this
.
z
=
z
;
this
.
minr
=
minr
;
this
.
maxr
=
maxr
;
this
.
angle
=
angle
;
};
SPARKS
.
SphereCapZone
.
prototype
.
getLocation
=
function
()
{
var
theta
=
Math
.
PI
*
2
*
SPARKS
.
Utils
.
random
();
var
r
=
SPARKS
.
Utils
.
random
();
//new THREE.Vector3
var
v
=
SPARKS
.
VectorPool
.
get
().
set
(
r
*
Math
.
cos
(
theta
),
-
1
/
Math
.
tan
(
this
.
angle
*
SPARKS
.
Utils
.
DEGREE_TO_RADIAN
),
r
*
Math
.
sin
(
theta
)
);
//v.length = StardustMath.interpolate(0, _minRadius, 1, _maxRadius, Math.random());
var
i
=
this
.
minr
-
(
(
this
.
minr
-
this
.
maxr
)
*
Math
.
random
()
);
v
.
multiplyScalar
(
i
);
v
.
__markedForReleased
=
true
;
return
v
;
};
/********************************
* Initializer Classes
*
* Classes which initializes
* particles. Implements initialize( emitter:Emitter, particle:Particle )
*********************************/
// Specifies random life between max and min
SPARKS
.
Lifetime
=
function
(
min
,
max
)
{
this
.
_min
=
min
;
this
.
_max
=
max
?
max
:
min
;
};
SPARKS
.
Lifetime
.
prototype
.
initialize
=
function
(
emitter
/*Emitter*/
,
particle
/*Particle*/
)
{
particle
.
lifetime
=
this
.
_min
+
SPARKS
.
Utils
.
random
()
*
(
this
.
_max
-
this
.
_min
);
};
SPARKS
.
Position
=
function
(
zone
)
{
this
.
zone
=
zone
;
};
SPARKS
.
Position
.
prototype
.
initialize
=
function
(
emitter
/*Emitter*/
,
particle
/*Particle*/
)
{
var
pos
=
this
.
zone
.
getLocation
();
particle
.
position
.
set
(
pos
.
x
,
pos
.
y
,
pos
.
z
);
};
SPARKS
.
Velocity
=
function
(
zone
)
{
this
.
zone
=
zone
;
};
SPARKS
.
Velocity
.
prototype
.
initialize
=
function
(
emitter
/*Emitter*/
,
particle
/*Particle*/
)
{
var
pos
=
this
.
zone
.
getLocation
();
particle
.
velocity
.
set
(
pos
.
x
,
pos
.
y
,
pos
.
z
);
if
(
pos
.
__markedForReleased
)
{
//console.log("release");
SPARKS
.
VectorPool
.
release
(
pos
);
pos
.
__markedForReleased
=
false
;
}
};
SPARKS
.
Target
=
function
(
target
,
callback
)
{
this
.
target
=
target
;
this
.
callback
=
callback
;
};
SPARKS
.
Target
.
prototype
.
initialize
=
function
(
emitter
,
particle
)
{
if
(
this
.
callback
)
{
particle
.
target
=
this
.
callback
();
}
else
{
particle
.
target
=
this
.
target
;
}
};
/********************************
* VectorPool
*
* Reuse much of Vectors if possible
*********************************/
SPARKS
.
VectorPool
=
{
__pools
:
[],
// Get a new Vector
get
:
function
()
{
if
(
this
.
__pools
.
length
>
0
)
{
return
this
.
__pools
.
pop
();
}
return
this
.
_addToPool
();
},
// Release a vector back into the pool
release
:
function
(
v
)
{
this
.
__pools
.
push
(
v
);
},
// Create a bunch of vectors and add to the pool
_addToPool
:
function
()
{
//console.log("creating some pools");
for
(
var
i
=
0
,
size
=
100
;
i
<
size
;
i
++
)
{
this
.
__pools
.
push
(
new
THREE
.
Vector3
()
);
}
return
new
THREE
.
Vector3
();
}
};
/********************************
* Util Classes
*
* Classes which initializes
* particles. Implements initialize( emitter:Emitter, particle:Particle )
*********************************/
SPARKS
.
Utils
=
{
random
:
function
()
{
return
Math
.
random
();
},
DEGREE_TO_RADIAN
:
Math
.
PI
/
180
,
TWOPI
:
Math
.
PI
*
2
,
getPerpendiculars
:
function
(
normal
)
{
var
p1
=
this
.
getPerpendicular
(
normal
);
var
p2
=
normal
.
cross
(
p1
);
p2
.
normalize
();
return
[
p1
,
p2
];
},
getPerpendicular
:
function
(
v
)
{
if
(
v
.
x
==
0
)
{
return
new
THREE
.
Vector3D
(
1
,
0
,
0
);
}
else
{
var
temp
=
new
THREE
.
Vector3
(
v
.
y
,
-
v
.
x
,
0
);
return
temp
.
normalize
();
}
}
};
examples/webgl_particles_shapes.html
已删除
100644 → 0
浏览文件 @
0ccc3570
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<title>
three.js webgl - particles - shapes
</title>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
>
<style>
body
{
font-family
:
Monospace
;
color
:
#aaa
;
background-color
:
#000
;
margin
:
0px
;
overflow
:
hidden
;
}
</style>
</head>
<body>
<script
src=
"../build/three.min.js"
></script>
<script
src=
"js/libs/stats.min.js"
></script>
<script
src=
"js/libs/tween.min.js"
></script>
<script
src=
"js/Sparks.js"
></script>
<script
src=
"js/shaders/CopyShader.js"
></script>
<script
src=
"js/shaders/FilmShader.js"
></script>
<script
src=
"js/shaders/FocusShader.js"
></script>
<script
src=
"js/shaders/HorizontalBlurShader.js"
></script>
<script
src=
"js/shaders/TriangleBlurShader.js"
></script>
<script
src=
"js/shaders/VerticalBlurShader.js"
></script>
<script
src=
"js/postprocessing/EffectComposer.js"
></script>
<script
src=
"js/postprocessing/RenderPass.js"
></script>
<script
src=
"js/postprocessing/ShaderPass.js"
></script>
<script
src=
"js/postprocessing/MaskPass.js"
></script>
<script
src=
"js/postprocessing/BloomPass.js"
></script>
<script
src=
"js/postprocessing/FilmPass.js"
></script>
<!-- load the font file from canvas-text -->
<script
src=
"fonts/helvetiker_regular.typeface.js"
></script>
<script
type=
"x-shader/x-vertex"
id=
"vertexshader"
>
attribute
float
size
;
attribute
vec3
pcolor
;
varying
vec3
vColor
;
void
main
()
{
vColor
=
pcolor
;
vec4
mvPosition
=
modelViewMatrix
*
vec4
(
position
,
1.0
);
gl_PointSize
=
size
*
(
200.0
/
length
(
mvPosition
.
xyz
)
);
gl_Position
=
projectionMatrix
*
mvPosition
;
}
</script>
<script
type=
"x-shader/x-fragment"
id=
"fragmentshader"
>
uniform
sampler2D
texture
;
varying
vec3
vColor
;
void
main
()
{
vec4
outColor
=
texture2D
(
texture
,
gl_PointCoord
);
gl_FragColor
=
outColor
*
vec4
(
vColor
,
1.0
);
}
</script>
<script>
var
container
,
stats
;
var
camera
,
scene
,
renderer
;
var
group
,
text
,
plane
;
var
speed
=
50
;
var
pointLight
;
var
targetRotation
=
0
;
var
targetRotationOnMouseDown
=
0
;
var
mouseX
=
0
;
var
mouseXOnMouseDown
=
0
;
var
windowHalfX
=
window
.
innerWidth
/
2
;
var
windowHalfY
=
window
.
innerHeight
/
2
;
var
delta
=
1
,
clock
=
new
THREE
.
Clock
();
var
heartShape
,
particleCloud
,
sparksEmitter
,
emitterPos
;
var
_rotation
=
0
;
var
timeOnShapePath
=
0
;
var
composer
;
var
effectBlurX
,
effectBlurY
,
hblur
,
vblur
;
init
();
animate
();
function
init
()
{
container
=
document
.
createElement
(
'
div
'
);
document
.
body
.
appendChild
(
container
);
var
info
=
document
.
createElement
(
'
div
'
);
info
.
style
.
position
=
'
absolute
'
;
info
.
style
.
top
=
'
10px
'
;
info
.
style
.
width
=
'
100%
'
;
info
.
style
.
textAlign
=
'
center
'
;
info
.
innerHTML
=
'
Three.js - simple particle systems with shapes by <a href="http://www.lab4games.net/zz85/blog">zz85</a><br>Move your mouse. Click to pause/resume.
'
;
container
.
appendChild
(
info
);
// CAMERA
camera
=
new
THREE
.
PerspectiveCamera
(
70
,
window
.
innerWidth
/
window
.
innerHeight
,
1
,
2000
);
camera
.
position
.
set
(
0
,
150
,
400
);
// SCENE
scene
=
new
THREE
.
Scene
();
// LIGHTS
var
directionalLight
=
new
THREE
.
DirectionalLight
(
0xffffff
,
0.5
);
directionalLight
.
position
.
set
(
0
,
-
1
,
1
);
directionalLight
.
position
.
normalize
();
scene
.
add
(
directionalLight
);
pointLight
=
new
THREE
.
PointLight
(
0xffffff
,
2
,
300
);
pointLight
.
position
.
set
(
0
,
0
,
0
);
scene
.
add
(
pointLight
);
// TEXT
var
theText
=
"
THREE.JS
"
;
// Get text from hash
var
hash
=
document
.
location
.
hash
.
substr
(
1
);
if
(
hash
.
length
!==
0
)
{
theText
=
hash
;
}
var
material
=
new
THREE
.
MeshFaceMaterial
(
[
new
THREE
.
MeshLambertMaterial
(
{
color
:
0xffffff
,
shading
:
THREE
.
FlatShading
,
opacity
:
0.95
}
),
new
THREE
.
MeshLambertMaterial
(
{
color
:
0xffffff
}
)
]
);
var
text3d
=
new
THREE
.
TextGeometry
(
theText
,
{
size
:
70
,
height
:
25
,
curveSegments
:
4
,
font
:
"
helvetiker
"
,
bevelEnabled
:
true
,
bevelThickness
:
2
,
bevelSize
:
2
,
material
:
0
,
extrudeMaterial
:
1
});
text3d
.
computeVertexNormals
();
text3d
.
computeBoundingBox
();
var
centerOffset
=
-
0.5
*
(
text3d
.
boundingBox
.
max
.
x
-
text3d
.
boundingBox
.
min
.
x
);
group
=
new
THREE
.
Group
();
scene
.
add
(
group
);
text
=
new
THREE
.
Mesh
(
text3d
,
material
);
// Potentially, we can extract the vertices or faces of the text to generate particles too.
// Geo > Vertices > Position
text
.
position
.
x
=
centerOffset
;
text
.
position
.
y
=
130
;
text
.
position
.
z
=
-
50
;
text
.
rotation
.
x
=
0
;
text
.
rotation
.
y
=
Math
.
PI
*
2
;
group
.
add
(
text
);
// Create particle objects for Three.js
var
particlesLength
=
70000
;
var
particles
=
new
THREE
.
Geometry
();
var
Pool
=
{
__pools
:
[],
// Get a new Vector
get
:
function
()
{
if
(
this
.
__pools
.
length
>
0
)
{
return
this
.
__pools
.
pop
();
}
console
.
log
(
"
pool ran out!
"
);
return
null
;
},
// Release a vector back into the pool
add
:
function
(
v
)
{
this
.
__pools
.
push
(
v
);
}
};
for
(
i
=
0
;
i
<
particlesLength
;
i
++
)
{
particles
.
vertices
.
push
(
new
THREE
.
Vector3
(
Math
.
random
()
*
200
-
100
,
Math
.
random
()
*
100
+
150
,
Math
.
random
()
*
50
)
);
Pool
.
add
(
i
);
}
// Create pools of vectors
attributes
=
{
size
:
{
type
:
'
f
'
,
value
:
[]
},
pcolor
:
{
type
:
'
c
'
,
value
:
[]
}
};
var
sprite
=
generateSprite
()
;
texture
=
new
THREE
.
Texture
(
sprite
);
texture
.
needsUpdate
=
true
;
uniforms
=
{
texture
:
{
type
:
"
t
"
,
value
:
texture
}
};
// PARAMETERS
// Steadycounter
// Life
// Opacity
// Hue Speed
// Movement Speed
function
generateSprite
()
{
var
canvas
=
document
.
createElement
(
'
canvas
'
);
canvas
.
width
=
128
;
canvas
.
height
=
128
;
var
context
=
canvas
.
getContext
(
'
2d
'
);
// Just a square, doesnt work too bad with blur pp.
// context.fillStyle = "white";
// context.strokeStyle = "white";
// context.fillRect(0, 0, 63, 63) ;
// Heart Shapes are not too pretty here
// var x = 4, y = 0;
// context.save();
// context.scale(8, 8); // Scale so canvas render can redraw within bounds
// context.beginPath();
// context.bezierCurveTo( x + 2.5, y + 2.5, x + 2.0, y, x, y );
// context.bezierCurveTo( x - 3.0, y, x - 3.0, y + 3.5,x - 3.0,y + 3.5 );
// context.bezierCurveTo( x - 3.0, y + 5.5, x - 1.0, y + 7.7, x + 2.5, y + 9.5 );
// context.bezierCurveTo( x + 6.0, y + 7.7, x + 8.0, y + 5.5, x + 8.0, y + 3.5 );
// context.bezierCurveTo( x + 8.0, y + 3.5, x + 8.0, y, x + 5.0, y );
// context.bezierCurveTo( x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5 );
context
.
beginPath
();
context
.
arc
(
64
,
64
,
60
,
0
,
Math
.
PI
*
2
,
false
)
;
context
.
lineWidth
=
0.5
;
//0.05
context
.
stroke
();
context
.
restore
();
var
gradient
=
context
.
createRadialGradient
(
canvas
.
width
/
2
,
canvas
.
height
/
2
,
0
,
canvas
.
width
/
2
,
canvas
.
height
/
2
,
canvas
.
width
/
2
);
gradient
.
addColorStop
(
0
,
'
rgba(255,255,255,1)
'
);
gradient
.
addColorStop
(
0.2
,
'
rgba(255,255,255,1)
'
);
gradient
.
addColorStop
(
0.4
,
'
rgba(200,200,200,1)
'
);
gradient
.
addColorStop
(
1
,
'
rgba(0,0,0,1)
'
);
context
.
fillStyle
=
gradient
;
context
.
fill
();
return
canvas
;
}
var
shaderMaterial
=
new
THREE
.
ShaderMaterial
(
{
uniforms
:
uniforms
,
attributes
:
attributes
,
vertexShader
:
document
.
getElementById
(
'
vertexshader
'
).
textContent
,
fragmentShader
:
document
.
getElementById
(
'
fragmentshader
'
).
textContent
,
blending
:
THREE
.
AdditiveBlending
,
depthWrite
:
false
,
transparent
:
true
});
particleCloud
=
new
THREE
.
PointCloud
(
particles
,
shaderMaterial
);
var
vertices
=
particles
.
vertices
;
var
values_size
=
attributes
.
size
.
value
;
var
values_color
=
attributes
.
pcolor
.
value
;
for
(
var
v
=
0
;
v
<
vertices
.
length
;
v
++
)
{
values_size
[
v
]
=
50
;
values_color
[
v
]
=
new
THREE
.
Color
(
0x000000
);
}
group
.
add
(
particleCloud
);
particleCloud
.
y
=
800
;
// Create Particle Systems
// EMITTER STUFF
// Heart
var
x
=
0
,
y
=
0
;
heartShape
=
new
THREE
.
Shape
();
heartShape
.
moveTo
(
x
+
25
,
y
+
25
);
heartShape
.
bezierCurveTo
(
x
+
25
,
y
+
25
,
x
+
20
,
y
,
x
,
y
);
heartShape
.
bezierCurveTo
(
x
-
30
,
y
,
x
-
30
,
y
+
35
,
x
-
30
,
y
+
35
);
heartShape
.
bezierCurveTo
(
x
-
30
,
y
+
55
,
x
-
10
,
y
+
77
,
x
+
25
,
y
+
95
);
heartShape
.
bezierCurveTo
(
x
+
60
,
y
+
77
,
x
+
80
,
y
+
55
,
x
+
80
,
y
+
35
);
heartShape
.
bezierCurveTo
(
x
+
80
,
y
+
35
,
x
+
80
,
y
,
x
+
50
,
y
);
heartShape
.
bezierCurveTo
(
x
+
35
,
y
,
x
+
25
,
y
+
25
,
x
+
25
,
y
+
25
);
var
hue
=
0
;
var
setTargetParticle
=
function
()
{
var
target
=
Pool
.
get
();
values_size
[
target
]
=
Math
.
random
()
*
200
+
100
;
return
target
;
};
var
onParticleCreated
=
function
(
p
)
{
var
position
=
p
.
position
;
p
.
target
.
position
=
position
;
var
target
=
p
.
target
;
if
(
target
)
{
// console.log(target,particles.vertices[target]);
// values_size[target]
// values_color[target]
hue
+=
0.0003
*
delta
;
if
(
hue
>
1
)
hue
-=
1
;
// TODO Create a PointOnShape Action/Zone in the particle engine
timeOnShapePath
+=
0.00035
*
delta
;
if
(
timeOnShapePath
>
1
)
timeOnShapePath
-=
1
;
var
pointOnShape
=
heartShape
.
getPointAt
(
timeOnShapePath
);
emitterpos
.
x
=
pointOnShape
.
x
*
5
-
100
;
emitterpos
.
y
=
-
pointOnShape
.
y
*
5
+
400
;
// pointLight.position.copy( emitterpos );
pointLight
.
position
.
x
=
emitterpos
.
x
;
pointLight
.
position
.
y
=
emitterpos
.
y
;
pointLight
.
position
.
z
=
100
;
particles
.
vertices
[
target
]
=
p
.
position
;
values_color
[
target
].
setHSL
(
hue
,
0.6
,
0.1
);
pointLight
.
color
.
setHSL
(
hue
,
0.8
,
0.5
);
}
};
var
onParticleDead
=
function
(
particle
)
{
var
target
=
particle
.
target
;
if
(
target
)
{
// Hide the particle
values_color
[
target
].
setRGB
(
0
,
0
,
0
);
particles
.
vertices
[
target
].
set
(
Number
.
POSITIVE_INFINITY
,
Number
.
POSITIVE_INFINITY
,
Number
.
POSITIVE_INFINITY
);
// Mark particle system as available by returning to pool
Pool
.
add
(
particle
.
target
);
}
};
var
engineLoopUpdate
=
function
()
{
};
sparksEmitter
=
new
SPARKS
.
Emitter
(
new
SPARKS
.
SteadyCounter
(
500
)
);
emitterpos
=
new
THREE
.
Vector3
(
0
,
0
,
0
);
sparksEmitter
.
addInitializer
(
new
SPARKS
.
Position
(
new
SPARKS
.
PointZone
(
emitterpos
)
)
);
sparksEmitter
.
addInitializer
(
new
SPARKS
.
Lifetime
(
1
,
15
));
sparksEmitter
.
addInitializer
(
new
SPARKS
.
Target
(
null
,
setTargetParticle
)
);
sparksEmitter
.
addInitializer
(
new
SPARKS
.
Velocity
(
new
SPARKS
.
PointZone
(
new
THREE
.
Vector3
(
0
,
-
5
,
1
)
)
)
);
sparksEmitter
.
addAction
(
new
SPARKS
.
Age
()
);
sparksEmitter
.
addAction
(
new
SPARKS
.
Accelerate
(
0
,
0
,
-
50
)
);
sparksEmitter
.
addAction
(
new
SPARKS
.
Move
()
);
sparksEmitter
.
addAction
(
new
SPARKS
.
RandomDrift
(
90
,
100
,
2000
)
);
sparksEmitter
.
addCallback
(
"
created
"
,
onParticleCreated
);
sparksEmitter
.
addCallback
(
"
dead
"
,
onParticleDead
);
sparksEmitter
.
start
();
// End Particles
renderer
=
new
THREE
.
WebGLRenderer
();
renderer
.
setPixelRatio
(
window
.
devicePixelRatio
);
renderer
.
setSize
(
window
.
innerWidth
,
window
.
innerHeight
);
container
.
appendChild
(
renderer
.
domElement
);
stats
=
new
Stats
();
stats
.
domElement
.
style
.
position
=
'
absolute
'
;
stats
.
domElement
.
style
.
top
=
'
0px
'
;
container
.
appendChild
(
stats
.
domElement
);
// POST PROCESSING
var
effectFocus
=
new
THREE
.
ShaderPass
(
THREE
.
FocusShader
);
var
effectCopy
=
new
THREE
.
ShaderPass
(
THREE
.
CopyShader
);
effectFilm
=
new
THREE
.
FilmPass
(
0.5
,
0.25
,
2048
,
false
);
var
shaderBlur
=
THREE
.
TriangleBlurShader
;
effectBlurX
=
new
THREE
.
ShaderPass
(
shaderBlur
,
'
texture
'
);
effectBlurY
=
new
THREE
.
ShaderPass
(
shaderBlur
,
'
texture
'
);
var
radius
=
15
;
var
blurAmountX
=
radius
/
window
.
innerWidth
;
var
blurAmountY
=
radius
/
window
.
innerHeight
;
hblur
=
new
THREE
.
ShaderPass
(
THREE
.
HorizontalBlurShader
);
vblur
=
new
THREE
.
ShaderPass
(
THREE
.
VerticalBlurShader
);
hblur
.
uniforms
[
'
h
'
].
value
=
1
/
window
.
innerWidth
;
vblur
.
uniforms
[
'
v
'
].
value
=
1
/
window
.
innerHeight
;
effectBlurX
.
uniforms
[
'
delta
'
].
value
=
new
THREE
.
Vector2
(
blurAmountX
,
0
);
effectBlurY
.
uniforms
[
'
delta
'
].
value
=
new
THREE
.
Vector2
(
0
,
blurAmountY
);
effectFocus
.
uniforms
[
'
sampleDistance
'
].
value
=
0.99
;
//0.94
effectFocus
.
uniforms
[
'
waveFactor
'
].
value
=
0.003
;
//0.00125
var
renderScene
=
new
THREE
.
RenderPass
(
scene
,
camera
);
composer
=
new
THREE
.
EffectComposer
(
renderer
);
composer
.
addPass
(
renderScene
);
composer
.
addPass
(
hblur
);
composer
.
addPass
(
vblur
);
// composer.addPass( effectBlurX );
// composer.addPass( effectBlurY );
// composer.addPass( effectCopy );
// composer.addPass( effectFocus );
// composer.addPass( effectFilm );
vblur
.
renderToScreen
=
true
;
effectBlurY
.
renderToScreen
=
true
;
effectFocus
.
renderToScreen
=
true
;
effectCopy
.
renderToScreen
=
true
;
effectFilm
.
renderToScreen
=
true
;
document
.
addEventListener
(
'
mousedown
'
,
onDocumentMouseDown
,
false
);
document
.
addEventListener
(
'
touchstart
'
,
onDocumentTouchStart
,
false
);
document
.
addEventListener
(
'
touchmove
'
,
onDocumentTouchMove
,
false
);
//
window
.
addEventListener
(
'
resize
'
,
onWindowResize
,
false
);
}
function
onWindowResize
()
{
windowHalfX
=
window
.
innerWidth
/
2
;
windowHalfY
=
window
.
innerHeight
/
2
;
camera
.
aspect
=
window
.
innerWidth
/
window
.
innerHeight
;
camera
.
updateProjectionMatrix
();
renderer
.
setSize
(
window
.
innerWidth
,
window
.
innerHeight
);
//
hblur
.
uniforms
[
'
h
'
].
value
=
1
/
window
.
innerWidth
;
vblur
.
uniforms
[
'
v
'
].
value
=
1
/
window
.
innerHeight
;
var
radius
=
15
;
var
blurAmountX
=
radius
/
window
.
innerWidth
;
var
blurAmountY
=
radius
/
window
.
innerHeight
;
effectBlurX
.
uniforms
[
'
delta
'
].
value
=
new
THREE
.
Vector2
(
blurAmountX
,
0
);
effectBlurY
.
uniforms
[
'
delta
'
].
value
=
new
THREE
.
Vector2
(
0
,
blurAmountY
);
composer
.
reset
();
}
//
document
.
addEventListener
(
'
mousemove
'
,
onDocumentMouseMove
,
false
);
function
onDocumentMouseDown
(
event
)
{
event
.
preventDefault
();
mouseXOnMouseDown
=
event
.
clientX
-
windowHalfX
;
targetRotationOnMouseDown
=
targetRotation
;
if
(
sparksEmitter
.
isRunning
()
)
{
sparksEmitter
.
stop
();
}
else
{
sparksEmitter
.
start
();
}
}
function
onDocumentMouseMove
(
event
)
{
mouseX
=
event
.
clientX
-
windowHalfX
;
targetRotation
=
targetRotationOnMouseDown
+
(
mouseX
-
mouseXOnMouseDown
)
*
0.02
;
}
function
onDocumentTouchStart
(
event
)
{
if
(
event
.
touches
.
length
===
1
)
{
event
.
preventDefault
();
mouseXOnMouseDown
=
event
.
touches
[
0
].
pageX
-
windowHalfX
;
targetRotationOnMouseDown
=
targetRotation
;
}
}
function
onDocumentTouchMove
(
event
)
{
if
(
event
.
touches
.
length
===
1
)
{
event
.
preventDefault
();
mouseX
=
event
.
touches
[
0
].
pageX
-
windowHalfX
;
targetRotation
=
targetRotationOnMouseDown
+
(
mouseX
-
mouseXOnMouseDown
)
*
0.05
;
}
}
//
function
animate
()
{
requestAnimationFrame
(
animate
);
render
();
stats
.
update
();
}
function
render
()
{
delta
=
speed
*
clock
.
getDelta
();
particleCloud
.
geometry
.
verticesNeedUpdate
=
true
;
attributes
.
size
.
needsUpdate
=
true
;
attributes
.
pcolor
.
needsUpdate
=
true
;
// Pretty cool effect if you enable this
// particleCloud.rotation.y += 0.05;
group
.
rotation
.
y
+=
(
targetRotation
-
group
.
rotation
.
y
)
*
0.05
;
renderer
.
clear
();
// renderer.render( scene, camera );
composer
.
render
(
0.1
);
}
</script>
</body>
</html>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录