face selection via shader, not multimat colors
This commit is contained in:
parent
df90158cb0
commit
da42c146bd
|
|
@ -12,8 +12,42 @@ export class SceneSync {
|
||||||
|
|
||||||
private _selectedFaceIds: Id[] = [];
|
private _selectedFaceIds: Id[] = [];
|
||||||
|
|
||||||
private readonly baseMaterial = new THREE.MeshPhongMaterial({
|
private readonly baseMaterial = new THREE.ShaderMaterial({
|
||||||
color: 0x4a7fc8, shininess: 40, specular: 0x223344, wireframe: false,
|
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) {
|
constructor(scene: THREE.Scene, cache: GeometryCache) {
|
||||||
|
|
@ -53,7 +87,9 @@ export class SceneSync {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const geo = this.cache.getOrCreate(faceId, 0, dto);
|
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.faceId = faceId;
|
||||||
mesh.userData.vertexIds = dto.vertexIds;
|
mesh.userData.vertexIds = dto.vertexIds;
|
||||||
mesh.userData.surfaceId = dto.surfaceId;
|
mesh.userData.surfaceId = dto.surfaceId;
|
||||||
|
|
@ -67,16 +103,9 @@ export class SceneSync {
|
||||||
this._selectedFaceIds = faceIds;
|
this._selectedFaceIds = faceIds;
|
||||||
|
|
||||||
for (const [sid, mesh] of Object.entries(this.meshByFace)) {
|
for (const [sid, mesh] of Object.entries(this.meshByFace)) {
|
||||||
const mat = mesh.material as THREE.MeshPhongMaterial;
|
const attr = mesh.geometry.attributes.selected;
|
||||||
|
attr.array.fill(faceIds.includes(sid) ? 1.0 : 0.0);
|
||||||
if (faceIds.includes(sid)) {
|
attr.needsUpdate = true; // required!
|
||||||
mat.color.setHex(0xf0a040);
|
|
||||||
mat.emissive.setHex(0x221100);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mat.color.setHex(0x4a7fc8);
|
|
||||||
mat.emissive.setHex(0x000000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue