There are many threads regarding difficulties getting good results with semi-transparent objects and I have non-systematically explored various solutions proposed. This include changing the renderOrder, multiple combinations of depthWrite and depthTest as well as all blending modes all to no avail.
I have an object leaving a trail that becomes more transparent as the objects is further away from the tail of the trail. When the camera is quite close to the trail I see no artifacts but when it’s further apart I see what appear to be triangles that are simply not rendered.
Here is how it looks like when it’s glitchy
but if I zoom in (same frame, the animation is stopped)
it all looks good.
Here is the constructor for my class which I believe has the relevant parts to get this working
export class Trail {
private geometry: THREE.BufferGeometry;
private material: THREE.ShaderMaterial;
private mesh: THREE.Mesh;
private trailVertices: Float32Array;
private trailIndices: Uint16Array;
private trailAlpha: Float32Array;
private currentSegmentIndex: number = 0;
private currentCurveIndex: number = 0;
private totalSegments: number = 0;
private prevCurve: THREE.Vector3[] | null;
private lastPosition: THREE.Vector3;
private color: THREE.Color;
constructor(
pointGroup: THREE.Group,
initialPosition: THREE.Vector3,
scene: THREE.Scene,
) {
this.trailVertices = new Float32Array(MAX_VERTICES * 3);
this.trailIndices = new Uint16Array(
MAX_SEGMENTS * (NUM_CURVE_POINTS - 1) * 6,
);
this.trailAlpha = new Float32Array(MAX_VERTICES).fill(1.0);
this.lastPosition = initialPosition.clone();
this.geometry = new THREE.BufferGeometry();
this.geometry.setAttribute(
'position',
new THREE.BufferAttribute(this.trailVertices, 3),
);
this.geometry.setIndex(new THREE.BufferAttribute(this.trailIndices, 1));
this.geometry.setAttribute(
'alpha',
new THREE.BufferAttribute(this.trailAlpha, 1),
);
const sphere = pointGroup.getObjectByName('point-sphere');
// @ts-ignore `point-sphere` is a THREE.Mesh
this.color = sphere!.material.color;
this.material = new THREE.ShaderMaterial({
vertexShader: `
precision highp float;
varying float vAlpha;
attribute float alpha;
void main() {
vAlpha = alpha;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision highp float;
varying float vAlpha;
uniform vec3 uColor;
void main() {
gl_FragColor = vec4(uColor, vAlpha);
}
`,
uniforms: {
uColor: { value: this.color },
},
//transparent: true,
//depthWrite: false,
//depthTest: true,
blending: THREE.AdditiveBlending,
side: THREE.DoubleSide,
});
this.mesh = new THREE.Mesh(this.geometry, this.material);
this.mesh.renderOrder=1;
scene.add(this.mesh);
this.mesh.layers.set(1);
this.prevCurve = null;
}
Commenting in/out this lines:
//transparent: true,
//depthWrite: false,
//depthTest: true,
makes no difference to the final result.
If anybody could help with this it would be greatly appreciated.
Finally if somebody wants to see this in action you could attempt to visit my app: https://quaternions.maxwellrules.com/
and then once it’s loaded:
- control+o (or cmd if mac)
- select the adding satellites script
- click execute script
- play with the time control on the bottom of the canvas to make things go faster and make the trail appear more clearly. (The moving objects starts somewhere between South Africa and Antarctica)