[SOLVED] Why are my BufferGeometry, RawShaderMaterial points not visible (no errors)?

I am trying to render a bunch points with THREE.Points using vertex & fragment shaders and buffer geometry. Can you tell me why they do not show up on the screen (there are no errors in the console)?
I have tested the particles with no GLSL shaders and they show up just fine, so it cannot be my physics code that is causing the problem.

You should see red points.

<html>
<head>
<script src='three.min.js'></script>
<script type='text/javascript' src='orbitcontrols.js'></script>
<style>body{margin:0}</style>
</head>
<body>
<script type="x-shader/x-vertex" id="vertexshader">
	precision mediump float;
	precision mediump int;
	
    attribute float alpha;
	attribute vec3 position;
	attribute vec4 color;
	attribute float size;
	uniform mat4 modelViewMatrix; 
	uniform mat4 projectionMatrix; 
	
    varying vec3 vPosition;
	varying float vAlpha;
	varying vec4 vColor;
	
	void main() 
	{
        vAlpha = alpha;
		vPosition = position;
		gl_PointSize = size;
		gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
</script>

<script type="x-shader/x-fragment" id="fragmentshader">
	precision mediump float;
	precision mediump int;

    varying float vAlpha;
	varying vec4 vColor;
	
    void main() 
	{
		vec4 color = vec4(vColor);
		gl_FragColor = color;
    }
</script>

<script>
	//All numeric values use SI units.
	var camera, scene, renderer;
	var gravity = -9.81;
	var particleindex = 0, particleCount = 1000,
    particle_geometry = new THREE.BufferGeometry();
	var positions = [];
	var colors = [];
	var size = [];
	
	for(var i = 0; i < particleCount; ++i)
	{
		colors.push(255);
		colors.push(0);
		colors.push(0);
		colors.push(255);
		size.push(5);
		positions.push(0.0);
		positions.push(0.0);
		positions.push(0.0);
	}
	
	var colorAttribute = new THREE.Uint8BufferAttribute(colors, 4);
	colorAttribute.normalized = true;
	
	particle_geometry.addAttribute('position', 
    new THREE.Float32BufferAttribute(positions, 3));
	particle_geometry.addAttribute('color', colorAttribute);
	particle_geometry.addAttribute('size', new THREE.Float32BufferAttribute(size, 1));
	
	var material = new THREE.RawShaderMaterial
	({
		uniforms: 
		{
			time: {value: 1.0}
		},
		vertexShader: document.getElementById( 'vertexshader' ).textContent,
		fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
		side: THREE.DoubleSide,
		transparent: true
	});
	
	var particleSystem = new THREE.Points(particle_geometry, material),
	height = 10, max_pos_dist_xz = 20, max_neg_dist_xz = max_pos_dist_xz / 2;
	var planegeometry, planematerial, planemesh;
	planegeometry = new THREE.PlaneGeometry(200, 200, 0);
	planematerial = new THREE.MeshBasicMaterial();
	planemesh = new THREE.Mesh(planegeometry, planematerial);
	
	var particle_offset = particle_geometry.attributes.size.array[0] / 2;
	var particle_emitted = [];
	var particle_has_bounced = [];
	var particle_velocity = [];
	var particle_velocities = [];
	var particle_life = 10;
	var particle_lives = [];
	var propellant_mass = 1000;
	var particle_mass = propellant_mass / particleCount;
	var particle_deceleration = -0.5 * 1000 * 1000 * 1.225 * 
    particle_geometry.attributes.size.array[0] *
    particle_geometry.attributes.size.array[0] / particle_mass;
	var dt = 1 / 60;

	function init()
	{
		camera = new THREE.PerspectiveCamera(70, window.innerWidth /
        window.innerHeight, 0.01, 1e6);
		var controls = new THREE.OrbitControls( camera );
		camera.position.set(50, 500, 50);
		controls.update();
		
		scene = new THREE.Scene();
		
		planemesh.position.y = 0;
		planemesh.rotation.x = -Math.PI / 2;
		scene.add(planemesh);
		
		particleSystem.sortParticles = true;
		particleSystem.visible = false;
		scene.add(particleSystem);
		
		for(var i = 0; i < particleCount; ++i)
		{
			particle_emitted.push(false);
			
			particle_velocities.push([0.0, -1000.0, 0.0]);
			
			particle_has_bounced.push(false);
			//particle_bounce_vel_factor.push((Math.random() * (1 - -1) + -1))
			
			//particle_lives.push(particle_life);
		}
		
		renderer = new THREE.WebGLRenderer({antialias: true});
		renderer.setSize(window.innerWidth, window.innerHeight);
		document.body.appendChild(renderer.domElement);

		particleSystem.visible = true;
	}

	function animate()
	{
		//Set the particle xy position
		if(particleindex < particleCount)
		{	
			if(max_pos_dist_xz > 0)
			{
				max_neg_dist_xz = max_pos_dist_xz / 2;
			}
			
			particle_geometry.attributes.position.setXYZ(particleindex, 
            Math.random() * max_pos_dist_xz - max_neg_dist_xz, height, Math.random()
            * max_pos_dist_xz - max_neg_dist_xz);
			++particleindex;
			++height;
			particle_emitted[particleindex] = true;
		}
		
		for(var i = 0; i < particleCount; ++i)
		{
			if(particle_emitted[i])
			{		
					//Tell us when the particle has bounced
					if(particle_geometry.attributes.position.getY(i) + 0.0001
                    * particle_offset <= 0)
					{
						particle_geometry.attributes.position.setY(i, 
                        particle_geometry.attributes.position.getY(i) +
                        particle_offset);
						
						particle_velocities[i][0] = particle_velocities[i][1] *
                        (Math.random() * (1 - -1) -1);
						particle_velocities[i][2] = particle_velocities[i][1] *
                        (Math.random() * (1 - -1) -1);
						particle_velocities[i][1] *= (Math.random() * (1 - -1) -1);
						
						particle_has_bounced[i] = true;
					}
					
					//Particle deccelerating upwards
					if(particle_has_bounced[i])
					{	
						particle_velocities[i][0] +=
                        -Math.sign(particle_velocities[i][0]) * ((0.5 * 0.01 * 
                        particle_velocities[i][0] * particle_velocities[i][0] * 
                        particle_geometry.attributes.size.array[0] *
                        particle_geometry.attributes.size.array[0]) / particle_mass) *
                        dt;
		                particle_velocities[i][1] +=
                        -Math.sign(particle_velocities[i][1]) * ((0.5 * 0.01 * 
                        particle_velocities[i][1] * particle_velocities[i][1] *
                        particle_geometry.attributes.size.array[0] * 
                        particle_geometry.attributes.size.array[0]) / particle_mass) *
                        dt;
						particle_velocities[i][2] +=
                        -Math.sign(particle_velocities[i][2]) *
                        ((0.5 * 0.01 * particle_velocities[i][2] *
                        particle_velocities[i][2] * 
                        particle_geometry.attributes.size.array[0] *
                        particle_geometry.attributes.size.array[0]) / particle_mass) *
                        dt;
						
						particle_geometry.attributes.position.setXYZ
						(
							i,
							particle_geometry.attributes.position.getX(i) + 
                            /*particle_bounce_vel_factor[i] * */
                            particle_velocities[i][0] *
                            dt, particle_geometry.attributes.position.getY(i) + 
                            /*particle_bounce_vel_factor[i + 1] * */
                            particle_velocities[i][1] * dt,
				            particle_geometry.attributes.position.getZ(i) + 
                            /*particle_bounce_vel_factor[i + 2] * */
                            particle_velocities[i][2] * dt
						);
						
					//Particle deccelerating downwards	
					}else
					{
						particle_velocities[i][1] +=
                        ((0.5 * 0.01 * particle_velocities[i][1] *
                        particle_velocities[i][1] * 
                        particle_geometry.attributes.size.array[0] * 
                        particle_geometry.attributes.size.array[0]) / particle_mass) *
                        dt;
		                particle_geometry.attributes.position.setY(i, 
                        particle_geometry.attributes.position.getY(i) +
                        particle_velocities[i][1] * dt);
					}	
			}
		}
		
		particleSystem.geometry.verticesNeedUpdate = true;
		
		renderer.render(scene, camera);
		requestAnimationFrame(animate);
	}

	init();
	animate();
</script>
</body>
</html>

Your point size (gl_PointSize) seems a bit too small in order to see the points. I’ve increase the size in the following live demo and added a red color in the fragment shader so you can better see the points:

https://jsfiddle.net/f2Lommf5/8947/

Some other minor stuff:

  • You did not add an alpha attribute to your BufferGeometry.
  • The varying vPosition is not read in the fragment shader.
1 Like