face selection via shader, not multimat colors

This commit is contained in:
azykov@mail.ru 2026-05-24 13:38:05 +03:00
parent df90158cb0
commit da42c146bd
No known key found for this signature in database
1 changed files with 42 additions and 13 deletions

View File

@ -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!
}
}