Skip to content

Commit

Permalink
motion-controller: Add hologram shader for hands
Browse files Browse the repository at this point in the history
  • Loading branch information
mrxz committed Feb 5, 2024
1 parent 0158d5d commit 6d5d7c6
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 7 deletions.
10 changes: 5 additions & 5 deletions motion-controller/example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@
<script></script>
</head>
<body>
<a-scene>
<a-scene xr-mode-ui="XRMode: xr">
<a-assets>
</a-assets>

<a-entity id="rig" position="0 0 2">
<a-entity motion-controller-space="hand: left; space: gripSpace" motion-controller-model="hand: left"></a-entity>
<a-entity motion-controller-space="hand: left; space: gripSpace" motion-controller-model="hand: left; overrideMaterial: hologram"></a-entity>
<a-entity motion-controller-space="hand: left; space: targetRaySpace">
<a-box width="0.002" height="0.002" depth="2" color="red" position="0 0 -1"></a-box>
</a-entity>
<a-entity motion-controller-space="hand: right; space: gripSpace" motion-controller-model="hand: right"></a-entity>
<a-entity motion-controller-space="hand: right; space: gripSpace" motion-controller-model="hand: right; overrideMaterial: hologram"></a-entity>
<a-entity motion-controller-space="hand: right; space: targetRaySpace">
<a-box width="0.002" height="0.002" depth="2" color="red" position="0 0 -1"></a-box>
</a-entity>
<a-camera></a-camera>
</a-entity>

<a-plane color="gray" width="10" height="10" rotation="-90 0 0"></a-plane>
<a-plane color="gray" width="10" height="10" rotation="-90 0 0" hide-on-enter-ar></a-plane>

<a-sky color="aquamarine"></a-sky>
<a-sky color="aquamarine" hide-on-enter-ar></a-sky>
</a-scene>

<!-- GITHUB_CORNER_LEFT -->
Expand Down
7 changes: 5 additions & 2 deletions motion-controller/src/motion-controller-model.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as AFRAME from 'aframe';
import * as THREE from 'three';
import { strict } from 'aframe-typescript';
import { MotionController, VisualResponse } from '@webxr-input-profiles/motion-controllers';
import { occluderMaterialFromStandardMaterial, phongMaterialFromStandardMaterial } from './utils';
import { hologramMaterialFromStandardMaterial, occluderMaterialFromStandardMaterial, phongMaterialFromStandardMaterial } from './utils';
import { HAND_JOINT_NAMES } from './hand-joint-names';
import { InputSourceRecord } from './motion-controller.system';

Expand All @@ -27,7 +27,7 @@ const MotionControllerModelComponent = AFRAME.registerComponent('motion-controll
}>().component({
schema: {
hand: { type: 'string', oneOf: ['left', 'right'], default: 'left' },
overrideMaterial: { type: 'string', oneOf: ['none', 'phong', 'occluder'], default: 'phong'},
overrideMaterial: { type: 'string', oneOf: ['none', 'phong', 'occluder', 'hologram'], default: 'phong'},
buttonTouchColor: { type: 'color', default: '#8AB' },
buttonPressColor: { type: 'color', default: '#2DF' }
},
Expand Down Expand Up @@ -79,6 +79,9 @@ const MotionControllerModelComponent = AFRAME.registerComponent('motion-controll
case 'occluder':
mesh.material = occluderMaterialFromStandardMaterial(mesh.material as THREE.MeshStandardMaterial);
break;
case 'hologram':
mesh.material = hologramMaterialFromStandardMaterial(mesh.material as THREE.MeshStandardMaterial);
break;
}
});

Expand Down
65 changes: 65 additions & 0 deletions motion-controller/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,69 @@ export function occluderMaterialFromStandardMaterial(sourceMaterial: THREE.MeshS
colorWrite: false,
side: sourceMaterial.side,
});
}

interface MaterialOnBeforeRender {
onBeforeRender: (renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, geometry: THREE.BufferGeometry, object: THREE.Object3D, group: any) => void;
}
export function hologramMaterialFromStandardMaterial(sourceMaterial: THREE.MeshStandardMaterial) {
const hologramMaterial = new THREE.ShaderMaterial({
side: sourceMaterial.side,
opacity: 0.4,
transparent: true,
vertexShader: /* glsl */`
#include <common>
#include <normal_pars_vertex>
#include <skinning_pars_vertex>
varying vec3 vObjectPosition;
varying vec3 vWorldPosition;
void main() {
#include <beginnormal_vertex>
#include <skinbase_vertex>
#include <skinnormal_vertex>
#include <defaultnormal_vertex>
#include <normal_vertex>
#include <begin_vertex>
#include <skinning_vertex>
#include <project_vertex>
vObjectPosition = position;
vWorldPosition = mvPosition.xyz;
}
`,
// Note: this shader is hard-coded and optimized for the generic-hand asset
fragmentShader: /* glsl */`
#include <common>
#include <dithering_pars_fragment>
#include <normal_pars_fragment>
varying vec3 vObjectPosition;
varying vec3 vWorldPosition;
void main() {
vec3 toCamera = normalize(cameraPosition - vWorldPosition);
float factor = pow(1.0 - dot(toCamera, vNormal), 10.0);
vec3 color = mix(vec3(0.0), vec3(0.8, 0.8, 1.0), factor);
float alpha = 0.5 * min((-vObjectPosition.y + 0.06)/0.15, 1.0);
gl_FragColor = vec4(color, alpha);
#include <tonemapping_fragment>
#include <colorspace_fragment>
}
`,
});

// Note: onBeforeRender on material lacks types (internal for Three.js), but is slightly more convenient
// in our case, so use it anyway.
(hologramMaterial as unknown as MaterialOnBeforeRender).onBeforeRender = (renderer, scene, camera, geometry, object, group) => {
hologramMaterial.colorWrite = false;
renderer.renderBufferDirect(camera, scene, geometry, hologramMaterial, object, group);
hologramMaterial.colorWrite = true;
}

return hologramMaterial;
}

0 comments on commit 6d5d7c6

Please sign in to comment.