Converting from PointsMaterial to ShaderMaterial, but not seeing points

I am currently in the process of converting a project over to use TheeJS, and an initial implementation made use of PointsMaterial to help render a collection of points orbiting a planet, but now I am trying to use ShaderMaterial in its place, so that I can make these points more circular and add the glow effect in the original. The problem is now I don’t see any points being rendered, and being a newbie with shaders I am a little confused as to what I am doing wrong?

I am using one of the ThreeJS example projects as reference, but I not sure where I am going wrong.

The code using PointsMaterial:

const geometry = new BufferGeometry();

geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );

const material= new PointsMaterial({
  color: 'grey',
  size: 3,
  sizeAttenuation: false,
  vertexColors: true,
  blending: AdditiveBlending,
});

this.geometry = geometry;
this.particles = new Points( geometry, material );

if (this.scene) {
  this.scene.add( this.particles );
}

Then I swapped out the PointsMaterial for the ShaderMaterial:

const shader = this.shaderStore.getShader('dot');

const material = new ShaderMaterial({
  uniforms: {
	color: { value: new Color( 0xffffff ) },
	pointTexture: { value: new TextureLoader().load( '/StuffInSpace/images/spark1.png' ) }
  },
  vertexShader: shader.vertex,
  fragmentShader: shader.fragment,
  blending: AdditiveBlending,
  depthTest: false,
  transparent: true
});

Then shaders code, for the fragement:

uniform vec3 color;
uniform sampler2D pointTexture;

varying vec3 vColor;

void main() {
  gl_FragColor = vec4( color * vColor, 1.0 );
  gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
}

and for the vertex:

attribute float size;
attribute vec3 color;

varying vec3 vColor;

void main() {
  vColor = color;

  vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

  gl_PointSize = size * ( 300.0 / -mvPosition.z );

  gl_Position = projectionMatrix * mvPosition;
}

Can anyone point me int the right direction?

BTW the project source, with the draft branch is available at: GitHub - ajmas/StuffInSpace at issue-1-threejs

This is not an answer to your request, but just a wink that you do not need a custom shader for round points with a glow. Left snapshot is without additive blending, right snapshot is with it (line 81 in the source):

https://codepen.io/boytchev/full/ZEwvRbe

image

Thanks.

As is the code just create what looks like sun, but if I adjust the values to avoid this, then I find the textures of one point masking the texture of the next point, creates a square cut off:

image

The adjust code:

const material= new PointsMaterial({
  color: 'white',
  vertexColors: true,
  size: 0.1, // reduced the size to try to keep the 'point' appearance
  sizeAttenuation: false,
  map: texture,
  transparent: true,
  blending: AdditiveBlending,
  depthTest: true, // necessary so those behind the Earth get hidden
});

This is it original WebGL version I am trying to replicate:

image

Having another look at the original WebGL code, it would appear the effect didn’t need a texture, but somehow achieved the magic in the shader. If I can avoid shader code that would certainly makes things easier, but right now I am not sure?

Then try with:

depthWrite: false

https://codepen.io/boytchev/full/JjxMaay

image

1 Like

Thank you. That looks to have given an acceptable solution.

1 Like