Skip to content

Instantly share code, notes, and snippets.

@mikatalk
Last active Oct 20, 2016
Embed
What would you like to do?
var THREE = require( 'three' );
var OrbitControls = require( 'three-orbit-controls' );
var ColladaLoader = require( '../../libs/loaders/ColladaLoader' );
import * as dat from '../../libs/utils/dat.gui.min';
const SIZE = 256;
const vertexShader = `
precision highp float;
attribute vec3 position;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform sampler2D img1;
uniform sampler2D img2;
uniform float ratio;
varying vec4 color;
const float numIndexes = ${(SIZE*SIZE).toFixed(1)};
void main() {
vec3 pos = position.xyz / ${SIZE.toFixed(1)};
float index = position.y + position.x*${SIZE.toFixed(1)};
pos = mix( texture2D( img1, pos.xy ).rgb, texture2D( img2, pos.xy ).rgb, ratio);
pos.xyz -= vec3(.5);
color = vec4(index/numIndexes/${SIZE.toFixed(1)}, 1.0-index/numIndexes, .6, .2);
if (pos.xyz == vec3(-1.0, -1.0, -1.0))
color.a = 0.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1. );
}
`;
const fragmentShader = `
precision highp float;
varying vec4 color;
uniform float time;
void main() {
if ( color.a == 0.0 )
discard;
gl_FragColor = color.rgba;
}
`;
export default class Experiment028 {
constructor () {
let loader = new THREE.ColladaLoader(THREE);
loader.load('img/hand.dae', ( object ) => {
let geometries = [
object.scene.children[0].children[0].geometry,
object.scene.children[1].children[0].geometry
];
this.start(geometries);
})
}
start(geometries){
this.options = {
animate: true,
ratio: 0,
}
var gui = new dat.dat.GUI();
gui.add( this.options, 'animate', false, true );
gui.add( this.options, 'ratio', 0, 1 );
this.clock = new THREE.Clock;
this.camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 0.00001, 10000000 );
this.camera.position.set(0, 10, 10);
this.camera.rotation.set(0, 0, 0);
this.camera.lookAt( new THREE.Vector3(0, 0, 0));
this.scene = new THREE.Scene();
this.scene.position.y = -3;
this.renderer = new THREE.WebGLRenderer({ antialias:true, alpha:false });
this.renderer.gammaInput = true;
this.renderer.gammaOutput = true;
this.renderer.setPixelRatio( window.devicePixelRatio );
this.renderer.setClearColor( 0x052525 );
// this.renderer.setClearColor( this.scene.fog.color );
this.controls = new (OrbitControls(THREE))( this.camera, this.renderer.domElement );
this.controls.enableZoom = true;
document.body.appendChild( this.renderer.domElement );
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( SIZE * SIZE * 3 );
var colors = new Float32Array( SIZE * SIZE * 4 );
for ( var i=0, i3=0, l=SIZE*SIZE; i3<l; i++, i3+=3 ) {
let x = i % SIZE;
let y = Math.floor(i / SIZE);
positions[ i3 + 0 ] = x;
positions[ i3 + 1 ] = y;
positions[ i3 + 2 ] = 0;
}
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
let faces = [];
while ( geometries[0].faces.length ) {
let face = geometries[0].faces.pop();
faces.push( {
a: { x: geometries[0].vertices[face.a].x, y: geometries[0].vertices[face.a].y, z: geometries[0].vertices[face.a].z },
b: { x: geometries[0].vertices[face.b].x, y: geometries[0].vertices[face.b].y, z: geometries[0].vertices[face.b].z },
c: { x: geometries[0].vertices[face.c].x, y: geometries[0].vertices[face.c].y, z: geometries[0].vertices[face.c].z },
});
}
this.sortFacesOn(faces, 'x');
this.sortFacesOn(faces, 'y');
this.sortFacesOn(faces, 'z');
console.log(faces.length, 'faces.');
let x = 0;
let y = 0;
let data1 = new Float32Array( SIZE*SIZE*4 ).fill(-1);
while ( faces.length ) {
let face = faces.shift();
// iterate over 3 triangles xyz x 4 channels rgba => 12
for ( var i=0; i<12; i++ ) {
data1[ (x + y * SIZE) ] = (face[i<4?'a':i<8?'b':'c'][i%4==0?'x':i%4==1?'y':'z']);
if ( ++x>=SIZE ) {
x = 0;
if ( ++y>=SIZE ) {
break;
}
}
}
}
this.fbo1 = this.createDataTexture(data1, SIZE, SIZE);
faces = [];
while ( geometries[1].faces.length ) {
let face = geometries[1].faces.pop();
faces.push( {
a: { x: geometries[1].vertices[face.a].x, y: geometries[1].vertices[face.a].y, z: geometries[1].vertices[face.a].z },
b: { x: geometries[1].vertices[face.b].x, y: geometries[1].vertices[face.b].y, z: geometries[1].vertices[face.b].z },
c: { x: geometries[1].vertices[face.c].x, y: geometries[1].vertices[face.c].y, z: geometries[1].vertices[face.c].z },
});
}
this.sortFacesOn(faces, 'x');
this.sortFacesOn(faces, 'y');
this.sortFacesOn(faces, 'z');
console.log(faces.length, 'faces.');
x = 0;
y = 0;
var data2 = new Float32Array( SIZE*SIZE*4 ).fill(-1);
while ( faces.length ) {
let face = faces.shift();
// iterate over 3 triangles xyz x 4 channels rgba => 12
for ( var i=0; i<12; i++ ) {
data2[ (x + y * SIZE) ] = (face[i<4?'a':i<8?'b':'c'][i%4==0?'x':i%4==1?'y':'z']);
if ( ++x>=SIZE ) {
x = 0;
if ( ++y>=SIZE ) {
break;
}
}
}
}
this.fbo2 = this.createDataTexture(data2, SIZE, SIZE);
this.currentTriangle = 0;
var material = new THREE.RawShaderMaterial( {
uniforms:{
ratio: { type: 'f', value: 1. },
img1: { type: 't', value: this.fbo1 },
img2: { type: 't', value: this.fbo2 },
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
depthTest: !true,
depthWrite: true,
// depthWrite: true,
side: THREE.DoubleSide,
blending: THREE.AdditiveBlending,
shading: THREE.FlatShading,
// wireframe: true,
transparent: true,
alphaTest: .2,
// vertexColors: THREE.VertexColors,
} );
geometry.dynamic = true;
this.mesh = new THREE.Mesh( geometry, material );
this.scene.add( this.mesh );
window.addEventListener( 'resize', this.onWindowResize.bind(this), false );
// this.renderer.domElement.addEventListener( moveEvent, this.onMove.bind(this), false );
this.onWindowResize();
this.animate();
}
sortFacesOn ( faces, key) {
faces = faces.sort(function(face1, face2){
let count1 = face1.a[key] + face1.b[key] + face1.c[key];
let count2 = face2.a[key] + face2.b[key] + face2.c[key];
if ( count1 < count2 ) return -1;
if ( count1 > count2 ) return 1;
return 0;
});
}
createDataTexture (data, width, height) {
let texture = new THREE.DataTexture( data, width, height, THREE.RGBAFormat, THREE.FloatType );
texture.minFilter = THREE.NearestFilter;
texture.magFilter = THREE.NearestFilter;
texture.needsUpdate = true;
return texture;
}
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize( window.innerWidth, window.innerHeight );
}
animate() {
requestAnimationFrame( this.animate.bind(this) );
let delta = this.clock.getDelta();
if ( this.options.animate ) {
this.scene.rotation.y = this.clock.elapsedTime;
}
this.mesh.material.uniforms.ratio.value = this.options.ratio;
this.renderer.render( this.scene, this.camera );
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment