提交 414d9142 编写于 作者: A alteredq

Merge remote-tracking branch 'remotes/zz85/experimental' into dev

<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js canvas/webgl - geometry - text</title>
<title>three.js canvas - particles with shapes</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<style type="text/css">
......
......@@ -12,7 +12,8 @@
* vignette
* bleachbypass
* basic
*
* dofmipmap
* focus
*/
THREE.ShaderExtras = {
......@@ -734,6 +735,67 @@ THREE.ShaderExtras = {
].join("\n")
},
/* -------------------------------------------------------------------------
// Triangle Blur shader
// - based on glfx.js triangle blur shader
// A basic blur filter, which convolves the image with a
// pyramid filter. The pyramid filter is separable and is applied as two
// radius The radius of the pyramid convolved with the image.
// https://github.com/evanw/glfx.js
------------------------------------------------------------------------- */
'triangleBlur': {
uniforms : {
"texture": { type: "t", value: 0, texture: null },
"delta": { type: "v2", value:new THREE.Vector2( 1, 1 ) }
},
vertexShader: [
"varying vec2 texCoord;",
"void main() {",
"texCoord = vec2( uv.x, 1.0 - uv.y );",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader:[
"#define ITERATIONS 30.0\n" +
'uniform sampler2D texture;\
uniform vec2 delta;\
varying vec2 texCoord;\
\
float random(vec3 scale, float seed) {\
/* use the fragment position for a different seed per-pixel */\
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\
}\
void main() {\
vec4 color = vec4(0.0);\
float total = 0.0;\
\
/* randomize the lookup values to hide the fixed number of samples */\
float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\
\
for (float t = -ITERATIONS; t <= ITERATIONS; t++) {\
float percent = (t + offset - 0.5) / ITERATIONS;\
float weight = 1.0 - abs(percent);\
color += texture2D(texture, texCoord + delta * percent) * weight;\
total += weight;\
}\
gl_FragColor = color / total;\
}\
'
]
},
/* -------------------------------------------------------------------------
// Simple test shader
......
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js canvas/webgl - geometry - text</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<style type="text/css">
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script type="text/javascript" src="../build/Three.js"></script>
<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
<script type="text/javascript" src="js/Stats.js"></script>
<script type="text/javascript" src="js/Tween.js"></script>
<script type="text/javascript" src="js/Sparks.js"></script>
<script type="text/javascript" src="js/ShaderExtras.js"></script>
<script type="text/javascript" src="js/postprocessing/EffectComposer.js"></script>
<script type="text/javascript" src="js/postprocessing/RenderPass.js"></script>
<script type="text/javascript" src="js/postprocessing/ShaderPass.js"></script>
<script type="text/javascript" src="js/postprocessing/MaskPass.js"></script>
<script type="text/javascript" src="js/postprocessing/BloomPass.js"></script>
<!-- load the font file from canvas-text -->
<script type="text/javascript" src="fonts/helvetiker_regular.typeface.js"></script>
<script type="x-shader/x-vertex" id="vertexshader">
attribute float size;
attribute vec4 ca;
varying vec4 vColor;
void main() {
vColor = ca;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 150.0 / length( mvPosition.xyz ) );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform vec3 color;
uniform sampler2D texture;
varying vec4 vColor;
uniform float radius;
uniform vec2 delta;
varying vec2 texCoord;
void main() {
vec4 outColor = texture2D( texture, gl_PointCoord );
if ( outColor.a < 0.5 ) discard;
gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );
//float depth = gl_FragCoord.z / gl_FragCoord.w;
///const vec3 fogColor = vec3( 0.0 );
//float fogFactor = smoothstep( 200.0, 600.0, depth );
//gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );
}
</script>
<script type="text/javascript">
var container, stats;
var camera, scene, renderer;
var 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 WebGL Love. 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 = new THREE.Camera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.y = 150;
camera.position.z = 700;
camera.target.position.y = 150;
scene = new THREE.Scene();
// Get text from hash
var theText = "THREE.JS";
var hash = document.location.hash.substr( 1 );
if ( hash.length !== 0 ) {
theText = hash;
}
var text3d = new THREE.TextGeometry( theText, {
size: 80,
height: 20,
curveSegments: 2,
font: "helvetiker"
});
text3d.computeBoundingBox();
var centerOffset = -0.5 * ( text3d.boundingBox.x[ 1 ] - text3d.boundingBox.x[ 0 ] );
var textMaterial = new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, wireframe: false } );
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.doubleSided = false;
text.position.x = centerOffset;
text.position.y = 100;
text.position.z = 0;
text.rotation.x = 0;
text.rotation.y = Math.PI * 2;
text.overdraw = true;
parent = new THREE.Object3D();
parent.addChild( text );
scene.addObject( parent );
///// Create particle objects for Three.js
var particleslength = 50000;
var particles = new THREE.Geometry();
function newpos(x, y, z) {
return new THREE.Vertex(
new THREE.Vector3(x, y, z)
);
}
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(newpos(Math.random() *200 - 100, Math.random() *100+150, Math.random() *50));
Pool.add(i);
}
// Create pools of vectors
attributes = {
size: { type: 'f', value: [] },
ca: { type: 'c', value: [] } //ca //customColor
};
var sprite = generateSprite() ;
textu = new THREE.Texture ( sprite );
textu.needsUpdate = true;
uniforms = {
amplitude: { type: "f", value: 1.0 },
color: { type: "c", value: new THREE.Color( 0xffffff ) },
texture: { type: "t", value: 0, texture:textu} //
//
};
// PARAMS.
// 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.closePath();
context.beginPath();
context.arc(64, 64, 60, 0, Math.PI*2, false);
context.closePath();
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.6, 'rgba(200,200,200,1)' );
gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' );
gradient.addColorStop( 1, 'rgba(0,0,0,1)' );
context.fillStyle = gradient;
context.fill();
//var idata =context.getImageData(0, 0, canvas.width, canvas.height);
//document.body.appendChild(canvas);
return canvas;
}
var shaderMaterial = new THREE.MeshShaderMaterial( {
uniforms: uniforms,
attributes: attributes,
vertexShader: document.getElementById( 'vertexshader' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader' ).textContent
,
blending: THREE.AdditiveBlending,
depthTest: false,
transparent: true
});
particleCloud = new THREE.ParticleSystem( particles, shaderMaterial );
particleCloud.dynamic = true;
//particleCloud.sortParticles = true;
var vertices = particleCloud.geometry.vertices;
var values_size = attributes.size.value;
var values_color = attributes.ca.value;
for( var v = 0; v < vertices.length; v++ ) {
values_size[ v ] = 50;
values_color[ v ] = new THREE.Color( 0xaaff00 );
values_color[ v ].setHSV( 0, 0, 0 );
particles.vertices[v].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
}
parent.addChild( particleCloud );
//scene.addObject( 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.0006;
if (hue>1) hue-=1;
// TODO Create a PointOnShape Action/Zone in the particle engine
timeOnShapePath += 0.002;
if (timeOnShapePath > 1) timeOnShapePath -= 1;
var pointOnShape = heartShape.getPointAt(timeOnShapePath);
emitterpos.x = pointOnShape.x * 5 - 100;
emitterpos.y = -pointOnShape.y * 5 + 400;
particles.vertices[target].position = p.position;
values_color[target].setHSV(hue, 0.8, 0.15);
};
};
var onParticleDead = function(particle) {
var target = particle.target;
if (target) {
// Hide the particle
values_color[target].setHSV(0, 0, 0);
particles.vertices[target].position.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(600));
emitterpos = new THREE.Vector3(0,0,0);
sparksEmitter.addInitializer(new SPARKS.Position( new SPARKS.PointZone( emitterpos ) ) );
sparksEmitter.addInitializer(new SPARKS.Lifetime(1,4));
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,0,50));
sparksEmitter.addAction(new SPARKS.Move());
sparksEmitter.addAction(new SPARKS.RandomDrift(50,50,2000));
sparksEmitter.addCallback("created", onParticleCreated);
sparksEmitter.addCallback("dead", onParticleDead);
sparksEmitter.start();
//sparksEmitter.addCallback("loopUpdated", engineLoopUpdate);
//sparksEmitter.addCallback("updated", function(p) {
// var target = particle.target;
// if (target) {
// // update energy properties
// //values_size[target] = Math.random()*100;
// }
//});
//
// End Particles
renderer = new THREE.WebGLRenderer();
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 shaderFocus = THREE.ShaderExtras[ "focus" ];
var effectFocus = new THREE.ShaderPass( shaderFocus );
var shaderBlur = THREE.ShaderExtras[ "triangleBlur" ];
var effectBlur = new THREE.ShaderPass( shaderBlur, 'texture' );; //
var blurAmount = 0.0020;
effectBlur.uniforms['delta'].value = new THREE.Vector2(blurAmount,blurAmount);
effectFocus.uniforms['sampleDistance'].value = 0.99; //0.94
effectFocus.uniforms['waveFactor'].value = 0.002; //0.00125
var renderScene = new THREE.RenderPass( scene, camera );
composer = new THREE.EffectComposer( renderer );
composer.addPass( renderScene );
composer.addPass( effectBlur ); // effectBlur effectFocus
effectBlur.renderToScreen = true;
effectFocus.renderToScreen = true;
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
}
//
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() {
particleCloud.geometry.__dirtyVertices = true;
particleCloud.geometry.__dirtyColors = true;
attributes.size.needsUpdate = true;
attributes.ca.needsUpdate = true;
// Pretty cool effect if you enable this
//particleCloud.rotation.y += 0.05;
parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05;
//renderer.render( scene, camera );
composer.render( );
}
</script>
</body>
</html>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册