Last active
October 20, 2016 05:38
-
-
Save mikatalk/a0a49fcd410e03ffad1bd5e10983d17b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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