-
-
Save cwervo/b4cfdbc46fe056832d822871522ae3bb to your computer and use it in GitHub Desktop.
| // Note: requires https://rawgit.com/jeromeetienne/ar.js/master/aframe/build/aframe-ar.js | |
| // or A-Frame.js + AR.js + THREEx + some other bindings, | |
| // basically, just use Jerome Etienne's A-Frame AR lib ¯\_(ツ)_/¯ | |
| // This is all based off Jerome Etienne's work, and he originally linked to | |
| // these two sources, so I'll do the same here: | |
| // http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter07.html | |
| // https://www.clicktorelease.com/code/streetViewReflectionMapping/#51.50700703827454,-0.12791916931155356 | |
| AFRAME.registerComponent('refraction-shader', { | |
| init: function () { | |
| const data = this.data; | |
| const vertexShader = `varying vec3 vRefract; | |
| uniform float refractionRatio; | |
| void main() { | |
| vec4 mPosition = modelMatrix * vec4( position, 1.0 ); | |
| vec3 nWorld = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal ); | |
| vRefract = normalize( refract( normalize( mPosition.xyz - cameraPosition ), nWorld, refractionRatio ) ); | |
| gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); | |
| }` | |
| const fragShader = `uniform sampler2D texture; | |
| varying vec3 vRefract; | |
| // experiment with distance to the video plane. should do real ray-plane-intersection! | |
| uniform float distance; | |
| void main(void) { | |
| vec2 p = vec2(vRefract.x*distance + 0.5, vRefract.y*distance + 0.5); | |
| vec3 color = texture2D( texture, p ).rgb; | |
| gl_FragColor = vec4( color, 1.0 ); | |
| }` | |
| var texture = new THREE.VideoTexture(this.el.sceneEl.systems.arjs.arToolkitSource.domElement) | |
| texture.minFilter = THREE.NearestFilter | |
| this.material = new THREE.ShaderMaterial({ | |
| uniforms: { | |
| time: { value: 0.0 }, | |
| texture: { type: 't', value: texture }, | |
| // pull to see the throshold: 0.7-ish solid glass/water ("upsidevdown"), 0.8+ thinner glass ("magnifying glass") | |
| refractionRatio: { type: 'f', value: 0.9 }, | |
| // experiment to adjust offset to video-plane. set to 1 for no effect | |
| distance: { type: 'f', value: 1 } | |
| }, | |
| // Note, idk why exactly, but it appears that you NEED to explicitly | |
| // name the vertexShader & fragmentShader arguments and not just as: | |
| // vertexShader, | |
| // fragShader | |
| // | |
| // Will expore this some other time ¯\_(ツ)_/¯ | |
| vertexShader : vertexShader, | |
| fragmentShader : fragShader | |
| }); | |
| this.material.uniforms.texture.value.wrapS = this.material.uniforms.texture.value.wrapT = THREE.ClampToEdgeWrapping; | |
| this.applyToMesh(); | |
| this.el.addEventListener('model-loaded', () => this.applyToMesh()); | |
| }, | |
| /** | |
| * Apply the material to the current entity. | |
| */ | |
| applyToMesh: function() { | |
| const mesh = this.el.getObject3D('mesh'); | |
| if (mesh) { | |
| mesh.material = this.material; | |
| } | |
| }, | |
| /** | |
| * On each frame, update the 'time' uniform in the shaders. | |
| */ | |
| tick: function (t) { | |
| this.material.uniforms.time.value = t / 1000; | |
| } | |
| }) |
How can I get this to work on an imported model? I tried using a .obj with no material, but that didn't work.
applyToMesh: function () { const object = this.el.getObject3D('mesh'); if (object) { object.traverse((node) => { if (node.isMesh) { node.material = this.material; } }); } },
It would be grateful if you could give me a solutions about following issue or give a HTML sample that use this component and ar-aframe.js.
I get an error "TypeError: Cannot read property 'domElement' of undefined".
It seems "this.el.sceneEl.systems.arjs.arToolkitSource" is undefined.
Does anyone have an up-to-date version of this? I'm getting the same error as Mizuo07 and the link that @tommensink posted doesn't actually do any refraction for me.
Here it is working with latest
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js"></script>
https://gist.github.com/ofedo/c8c971de706ea140e10790b503c9b4d0
Very nice! thanks for doing this :)
btw uniforms.time seems useless.