diff --git a/client/src/layers/sceneSync.ts b/client/src/layers/sceneSync.ts index 9b38830..7c3810f 100644 --- a/client/src/layers/sceneSync.ts +++ b/client/src/layers/sceneSync.ts @@ -12,8 +12,42 @@ export class SceneSync { private _selectedFaceIds: Id[] = []; - private readonly baseMaterial = new THREE.MeshPhongMaterial({ - color: 0x4a7fc8, shininess: 40, specular: 0x223344, wireframe: false, + private readonly baseMaterial = new THREE.ShaderMaterial({ + side: THREE.DoubleSide, + transparent: true, + depthWrite: false, + uniforms: { + frontColor: { value: new THREE.Color(0x88ccff) }, + frontOpacity: { value: 0.6 }, + backColor: { value: new THREE.Color(0xcc88ff) }, + backOpacity: { value: 0.2 }, + selected: { value: 0 }, + selectedOpacity: { value: 0.8 }, + }, + vertexShader: ` + varying vec3 vNormal; + attribute float selected; + varying float vSelected; + void main() { + vNormal = normalMatrix * normal; + vSelected = selected; + gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); + } + `, + fragmentShader: ` + uniform vec3 frontColor; + uniform float frontOpacity; + uniform vec3 backColor; + uniform float backOpacity; + uniform float selectedOpacity; + varying float vSelected; + varying vec3 vNormal; + void main() { + float opacity = vSelected > 0.5 ? selectedOpacity : (gl_FrontFacing ? frontOpacity : backOpacity); + vec3 color = gl_FrontFacing ? frontColor : backColor; + gl_FragColor = vec4(color, opacity); + } + `, }); constructor(scene: THREE.Scene, cache: GeometryCache) { @@ -53,7 +87,9 @@ export class SceneSync { return; const geo = this.cache.getOrCreate(faceId, 0, dto); - const mesh = new THREE.Mesh(geo, this.baseMaterial.clone()); + const geoVCount = geo.attributes.position.count; + geo.setAttribute('selected', new THREE.BufferAttribute(new Float32Array(geoVCount), 1)); + const mesh = new THREE.Mesh(geo, this.baseMaterial); mesh.userData.faceId = faceId; mesh.userData.vertexIds = dto.vertexIds; mesh.userData.surfaceId = dto.surfaceId; @@ -67,16 +103,9 @@ export class SceneSync { this._selectedFaceIds = faceIds; for (const [sid, mesh] of Object.entries(this.meshByFace)) { - const mat = mesh.material as THREE.MeshPhongMaterial; - - if (faceIds.includes(sid)) { - mat.color.setHex(0xf0a040); - mat.emissive.setHex(0x221100); - } - else { - mat.color.setHex(0x4a7fc8); - mat.emissive.setHex(0x000000); - } + const attr = mesh.geometry.attributes.selected; + attr.array.fill(faceIds.includes(sid) ? 1.0 : 0.0); + attr.needsUpdate = true; // required! } }