diff --git a/src/components/wall-shader.js b/src/components/wall-shader.js index c202cc8..2ef56e4 100644 --- a/src/components/wall-shader.js +++ b/src/components/wall-shader.js @@ -3,18 +3,20 @@ AFRAME.registerShader('wall-shader', { schema: { iTime: {type: 'time', is: 'uniform'}, tex: {type: 'map', is: 'uniform'}, - env: {type: 'map', is: 'uniform'} + env: {type: 'map', is: 'uniform'}, + hitRight: {type: 'vec3', is: 'uniform', default: {x: 0, y: 1, z: 0}}, + hitLeft: {type: 'vec3', is: 'uniform', default: {x: 0, y: 0, z: 0}} }, vertexShader: ` varying vec2 uvs; varying vec3 nrml; - varying vec3 pos; + varying vec3 worldPos; void main() { uvs.xy = uv.xy; nrml.xyz = normal.xyz; vec4 p = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - pos = position; + worldPos = (modelMatrix * vec4( position, 1.0 )).xyz; gl_Position = p; } `, @@ -23,10 +25,12 @@ AFRAME.registerShader('wall-shader', { // based on https://www.shadertoy.com/view/ldlXRS varying vec2 uvs; varying vec3 nrml; - varying vec3 pos; + varying vec3 worldPos; uniform float iTime; uniform sampler2D tex; uniform sampler2D env; + uniform vec3 hitRight; + uniform vec3 hitLeft; #define time iTime/1000.0*0.15 #define tau 6.2831853 @@ -56,6 +60,10 @@ AFRAME.registerShader('wall-shader', { return fbm(p*makem2(time*0.2)); } + vec3 drawCircle(vec3 p, vec3 center, float radius, float edgeWidth, vec3 color) { + return color*(1.0-smoothstep(radius, radius+edgeWidth, length(p-center))); + } + void main() { vec2 p = uvs.xy-0.5;// / iResolution.xy-0.5; @@ -74,15 +82,18 @@ AFRAME.registerShader('wall-shader', { col += smoothstep(0.48, 0.495, abs(pp.x)); col += smoothstep(0.48, 0.495, abs(pp.y)); + col += drawCircle(worldPos, hitRight, 0.04, 0.05, vec3(1.0, 0.4, 0.4)); + col += drawCircle(worldPos, hitRight, 0.02, 0.005, vec3(1.0, 1.0, 1.0)); + col += drawCircle(worldPos, hitLeft, 0.04, 0.05, vec3(1.0, 0.4, 0.4)); + col += drawCircle(worldPos, hitLeft, 0.02, 0.005, vec3(1.0, 1.0, 1.0)); + //gl_FragColor = vec4(col, 1.0); // add environment reflection - - vec3 worldNormal = normalize( ( vec4( nrml + col, 0.0 ) * viewMatrix ).xyz ); - vec3 reflectVec = normalize(reflect(normalize(pos - cameraPosition), worldNormal)); + vec3 reflectVec = normalize(reflect(normalize(worldPos - cameraPosition), normalize(nrml + col))); vec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) ); - gl_FragColor = vec4(texture2D(env, reflectView.xy * 0.5 + 0.5).xyz + col, 1.0); + gl_FragColor = vec4(texture2D(env, reflectView.xy * 0.5 + 0.5).xyz * 0.05 + col, 0.9 + col.x); } ` }); diff --git a/src/components/wall.js b/src/components/wall.js index b7f7bc4..bc464ab 100644 --- a/src/components/wall.js +++ b/src/components/wall.js @@ -8,21 +8,63 @@ AFRAME.registerComponent('wall', { init: function () { this.maxZ = 10; + this.saberHit = { + 'rightHand': { + active: false, + position: null, + raycaster: document.getElementById('rightHand').components['raycaster__game'] + }, + 'leftHand': { + active: false, + position: null, + raycaster: document.getElementById('leftHand').components['raycaster__game'] + } + }; + this.intersecting = false; }, pause: function () { this.el.object3D.visible = false; this.el.removeAttribute('data-collidable-head'); this.el.removeAttribute('raycastable-game'); + this.el.removeEventListener('mouseenter', this.saberEnter); + this.el.removeEventListener('mouseleave', this.saberLeave); }, play: function () { this.el.object3D.visible = true; this.el.setAttribute('data-collidable-head', ''); this.el.setAttribute('raycastable-game', ''); + this.el.addEventListener('mouseenter', this.saberEnter.bind(this)); + this.el.addEventListener('mouseleave', this.saberLeave.bind(this)); + this.material = this.el.object3D.children[0].material; + }, + + saberEnter: function (evt) { + this.saberHit[evt.detail.cursorEl.id].active = true; + this.intersecting = true; + }, + + saberLeave: function (evt) { + const hand = evt.detail.cursorEl.id; + this.saberHit[hand].active = false; + this.material.uniforms[hand == 'rightHand' ? 'hitRight' : 'hitLeft'].value = {x: 999, y: 0, z: 0}; + this.intersecting = this.saberHit['rightHand'].active || this.saberHit['leftHand'].active; }, tock: function (time, delta) { + if (this.intersecting) { + var int; + if (this.saberHit['rightHand'].active) { + int = this.saberHit['rightHand'].raycaster.getIntersection(this.el); + if (int) { this.material.uniforms.hitRight.value = int.point; } + } + if (this.saberHit['leftHand'].active) { + int = this.saberHit['leftHand'].raycaster.getIntersection(this.el); + if (int) { this.material.uniforms.hitLeft.value = int.point; } + } + } + this.el.object3D.position.z += this.data.speed * (delta / 1000); if (this.el.object3D.position.z > this.maxZ) { this.returnToPool();