# ShaderMaterial.depthWrite with THREE.Points and transparency

**URL:** <https://discourse.threejs.org/t/shadermaterial-depthwrite-with-three-points-and-transparency/30509>\
**Category:** Questions\
**Tags:** transparency, materials, particles, shaders\
**Created:** [October 4, 2021, 11:38am UTC](https://discourse.threejs.org/t/shadermaterial-depthwrite-with-three-points-and-transparency/30509 "2021-10-04T11:38:22Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![srand](https://avatars.discourse-cdn.com/v4/letter/s/ee7513/32.png) [@srand](https://discourse.threejs.org/u/srand)\
**Post date:** [October 4, 2021, 11:38am UTC](https://discourse.threejs.org/t/shadermaterial-depthwrite-with-three-points-and-transparency/30509/1 "2021-10-04T11:38:22Z")

</div>

Hi everyone.

I want to create a cloud of points placed on the surface of a geometry. The desired result should look like this but with circle-shaped particles.

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/f/1/f12fa20b09fa93b2c3ec2ce234e0a6df1d9e04b0.png)

This is the code I am using to instantiate the Points object:

```javascript
const baseGeometry = new THREE.SphereGeometry(...)
const particlesMaterial = new THREE.ShaderMaterial({
    vertexShader: particleVertexShader,
    fragmentShader: particleFragmentShader,
})

const pointsPositions = baseGeometry.getAttribute('position').clone()
const particlesGeometry = new THREE.BufferGeometry()
particlesGeometry.setAttribute('position', pointsPositions)

const particles = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particles)

```

In the vertex shader I just increase the `gl_PointSize` and account for size attenuation using the formula `gl_PointSize *= (1.0 / - viewPosition.z)`.

Now the most relevant part: the fragment shader. I tried different solutions:

1. get the circle shape using this fragment shader:

```javascript
float strength = distance(gl_PointCoord, vec2(0.5));
strength = step(0.4, strength);
strength = 1.0 - strength;

vec3 color = vec3(0.5137, 0.8039, 1.0);

gl_FragColor = vec4(color * strength, 1.0);

```

But with this I can still see the black square outline, as expected.  
To solve this, I thought adding `blending: THREE.AdditiveBlending` to the `ShaderMaterial` initialization parameters should have solved the issue, but it turns out background particles can be seen through foreground ones as if the latter were semi-transparent. After a second though this made sense given pixel color values were added each other so overlapping particles would result in white pixels.

1. use the alpha channel to make parts of a particles’ pixels transparent: the fragment code was the same as before but instead of multiplying the `strength` variable with the color, I used it as the value for the alpha channel of `gl_FragColor`.  
I added `transparent: true` to the `ShaderMaterial` initialization parameters as well to make three.js respect the transparency values (`alphaTest: 0.001` didn’t seem to have any effect).  
 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/3/5/359c46b1d536cffd6c9014ef9565154ab24b1c4b.png)  
As you can see in the image, some particles still have the dark square outline, even though it should be transparent. I noticed anyway that only SOME particles have this problem, and that the outline isn’t black as before but it has the background color instead.  
What solved this issue was adding `depthWrite: false` to the `ShaderMaterial` initialization parameters.

So, is this the correct way to do this kind of thing? Does it have any drawbacks?  
And why does this work? I read several articles and questions about the order three.js uses to render things and from what I understand disabling `depthWrite` prevents rendering the material to affect the depth buffer [[1]](https://threejs.org/docs/index.html#api/en/materials/Material.depthWrite). Does this means that rendering materials on already “placed” objects would normally cause their depth buffer to be rewritten, which in turns potentially lead to background objects being rendered on top of foreground ones?

Sorry for the quite long post and thanks in advance to anyone who will help me!

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [October 4, 2021, 1:19pm UTC](https://discourse.threejs.org/t/shadermaterial-depthwrite-with-three-points-and-transparency/30509/2 "2021-10-04T13:19:44Z")

</div>

Hi!  
You can discard pixels that are further than 0.4, changing this

> [@srand](#):
>
> ```javascript
> float strength = distance(gl_PointCoord, vec2(0.5));
> strength = step(0.4, strength);
> strength = 1.0 - strength;
> 
> vec3 color = vec3(0.5137, 0.8039, 1.0);
> 
> gl_FragColor = vec4(color * strength, 1.0);
> 
> ```

to this

```js
if (distance(gl_PointCoord, vec2(0.5)) > 0.4) discard;
vec3 color = vec3(0.5137, 0.8039, 1.0);
gl_FragColor = vec4(color, 1.0);

```

---

<div class="post-metadata">

**Author:** ![srand](https://avatars.discourse-cdn.com/v4/letter/s/ee7513/32.png) [@srand](https://discourse.threejs.org/u/srand)\
**Post date:** [October 4, 2021, 1:53pm UTC](https://discourse.threejs.org/t/shadermaterial-depthwrite-with-three-points-and-transparency/30509/3 "2021-10-04T13:53:47Z")

</div>

Oh I didn’t though about discard! Is this faster performance-wise than accounting for transparency (now that I can disable it entirely for that material)?

---

<div class="post-metadata">

**Author:** ![AntShestak](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/antshestak/32/37226_2.png) [@AntShestak](https://discourse.threejs.org/u/AntShestak)\
**Post date:** [June 14, 2023, 4:28pm UTC](https://discourse.threejs.org/t/shadermaterial-depthwrite-with-three-points-and-transparency/30509/4 "2023-06-14T16:28:25Z")

</div>

I have similar issue. To render particles properly on top of each other you have to disable depthWrite on ShaderMaterial, but then particles wouldn’t blend correctly with transparent objects like glass. Any solution to this?
