1

I created the following fiddle to illustrate my question.

Notice that when I initialize the renderer at line 55, I include an alpha channel:

renderer = new THREE.WebGLRenderer({
  canvas: canvas,
  antialias: aa,
  alpha: true
});
renderer.setSize(canvas.clientWidth, canvas.clientHeight);

I also add the following attribute to the geometry at line 32:

var ds = 1.0 / maxPoints;
var vertPos = new Float32Array(maxPoints);
for (var i = 1; i < maxPoints; i++)
  vertPos[i] = i * ds;
geometry.addAttribute('vertPos', new THREE.BufferAttribute(vertPos, 1));

This attribute is a float between 0 and 1 that corresponds to how far along the line a particular vertex is. In line 19 of the html I pass this attribute to the frag shader as a varying. In line 28 of the html I set the alpha channel of the line equal to this attribute (You can easily verify that fragPos is being passed into the frag shader correctly).

However, the line is not being rendered with an alpha channel. If it were, you would see the tail end slowly fading out instead of just disappearing.

Thus, my question: How can I render a line in three.js with an alpha channel?

var canvas;
var scene;
var renderer;
var material;
var geometry;
var line;

var maxPoints = 256;
var drawCount = 1;

//intialize rendering
function init(aa, cdist, fov, lw, col) {

  canvas = document.getElementById('gl_canvas');

  camera = new THREE.PerspectiveCamera(fov, canvas.clientWidth / canvas.clientHeight, 1, 500);
  camera.position.set(0, 0, cdist);
  camera.lookAt(new THREE.Vector3(0, 0, 0));

  geometry = new THREE.BufferGeometry();
  var positions = new Float32Array(3 * maxPoints);
  positions[0] = Math.random();
  positions[1] = Math.random();
  positions[2] = Math.random();
  geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));

  //ADD vertPos ATTRIBUTE
  var ds = 1.0 / maxPoints;
  var vertPos = new Float32Array(maxPoints);
  for (var i = 1; i < maxPoints; i++)
    vertPos[i] = i * ds;
  geometry.addAttribute('vertPos', new THREE.BufferAttribute(vertPos, 1));

  geometry.setDrawRange(0, drawCount);

  material = new THREE.ShaderMaterial({
    vertexShader: document.getElementById('vshader').textContent,
    fragmentShader: document.getElementById('fshader').textContent,
    uniforms: {
      color: {
        type: 'v3',
        value: col
      }
    },
    depthWrite: false,
    depthTest: false,
    lineWidth: lw //this always defaults to 1, unfortunately
  });

  scene = new THREE.Scene();
  line = new THREE.Line(geometry, material);
  scene.add(line);

  //set up renderer WITH alpha channel
  renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: aa,
    alpha: true
  });
  renderer.setSize(canvas.clientWidth, canvas.clientHeight);
}

function shift(array) {
  for (var i = 0; i < maxPoints - 1; i++) {
    for (var j = 0; j < 3; j++) {
      array[3 * i + j] = array[3 * i + j + 3];
    }
  }
}

function animate() {
  requestAnimationFrame(animate);

  var currentGeometry = line.geometry;
  var currentPositions = currentGeometry.getAttribute('position');
  var posArray = currentPositions.array;

  if (drawCount < maxPoints) {
    for (var i = 0; i < 3; i++)
      posArray[3 * drawCount + i] = posArray[3 * drawCount - 3 + i] + 0.5 * Math.random() - 0.25;
    drawCount++;
    currentPositions.needsUpdate = true;
    geometry.setDrawRange(0, drawCount);
  } else {
    shift(posArray);
    for (var j = 0; j < 3; j++)
      posArray[3 * maxPoints - j] = posArray[3 * maxPoints - j] + 0.5 * Math.random() - 0.25;
    currentPositions.needsUpdate = true;
  }

  renderer.render(scene, camera);
}

init(true, 10, 60, 2, new THREE.Vector3(1, 1, 1));
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>

<canvas id="gl_canvas" style="background-color: black;height: 480px;width: 680px;"></canvas>

<script type="glsl" id="vshader">
  attribute float vertPos; varying float fragPos; void main() { gl_Position = projectionMatrix*modelViewMatrix*vec4(position, 1.0); fragPos = vertPos; }
</script>

<script type="glsl" id="fshader">
  uniform vec3 color; varying float fragPos; void main() { gl_FragColor = vec4(color, fragPos); }
</script>
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Eben Kadile
  • 759
  • 4
  • 21

1 Answers1

1

How can I render a line in three.js with an alpha channel?

Set the .transparent property of the THREE.Material object true:

material = new THREE.ShaderMaterial({
    vertexShader: document.getElementById('vshader').textContent,
    fragmentShader: document.getElementById('fshader').textContent,
    uniforms: {
    color: {
        type: 'v3',
        value: col
    }
    },
    depthWrite: false,
    depthTest: false,
    lineWidth: lw, //this always defaults to 1, unfortunately
    transparent: true
});

See the example, where I applied the change to your original code:

var canvas, scene, renderer, material, geometry, line;
var maxPoints = 256;
var drawCount = 1;

//intialize rendering
function init(aa, cdist, fov, lw, col) {

  canvas = document.getElementById('gl_canvas');

  camera = new THREE.PerspectiveCamera(fov, window.innerWidth / window.innerHeight, 1, 500);
  camera.position.set(0, 0, cdist);
  camera.lookAt(new THREE.Vector3(0, 0, 0));

  geometry = new THREE.BufferGeometry();
  var positions = new Float32Array(3 * maxPoints);
  positions[0] = Math.random();
  positions[1] = Math.random();
  positions[2] = Math.random();
  geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));

  //ADD vertPos ATTRIBUTE
  var ds = 1.0 / maxPoints;
  var vertPos = new Float32Array(maxPoints);
  for (var i = 1; i < maxPoints; i++)
    vertPos[i] = i * ds;
  geometry.addAttribute('vertPos', new THREE.BufferAttribute(vertPos, 1));

  geometry.setDrawRange(0, drawCount);

  material = new THREE.ShaderMaterial({
    vertexShader: document.getElementById('vshader').textContent,
    fragmentShader: document.getElementById('fshader').textContent,
    uniforms: {
      color: {
        type: 'v3',
        value: col
      }
    },
    depthWrite: false,
    depthTest: false,
    lineWidth: lw, //this always defaults to 1, unfortunately
    transparent: true
  });

  scene = new THREE.Scene();
  line = new THREE.Line(geometry, material);
  scene.add(line);

  //set up renderer WITH alpha channel
  renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: aa,
    alpha: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);

  window.onresize = function() {
      renderer.setSize(window.innerWidth, window.innerHeight);
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
  }
}

function shift(array) {
  for (var i = 0; i < maxPoints - 1; i++) {
    for (var j = 0; j < 3; j++) {
      array[3 * i + j] = array[3 * i + j + 3];
    }
  }
}

function animate() {
  requestAnimationFrame(animate);

  var currentGeometry = line.geometry;
  var currentPositions = currentGeometry.getAttribute('position');
  var posArray = currentPositions.array;

  if (drawCount < maxPoints) {
    for (var i = 0; i < 3; i++)
      posArray[3 * drawCount + i] = posArray[3 * drawCount - 3 + i] + 0.5 * Math.random() - 0.25;
    drawCount++;
    currentPositions.needsUpdate = true;
    geometry.setDrawRange(0, drawCount);
  } else {
    shift(posArray);
    for (var j = 0; j < 3; j++)
      posArray[3 * maxPoints - j] = posArray[3 * maxPoints - j] + 0.5 * Math.random() - 0.25;
    currentPositions.needsUpdate = true;
  }

  renderer.render(scene, camera);
}

init(true, 10, 60, 2, new THREE.Vector3(1, 1, 1));
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>

<canvas id="gl_canvas" style="background-color: black;height: 480px;width: 680px;"></canvas>

<script type="glsl" id="vshader">
  attribute float vertPos; varying float fragPos; void main() { gl_Position = projectionMatrix*modelViewMatrix*vec4(position, 1.0); fragPos = vertPos; }
</script>

<script type="glsl" id="fshader">
  uniform vec3 color; varying float fragPos; void main() { gl_FragColor = vec4(color, fragPos); }
</script>
Rabbid76
  • 202,892
  • 27
  • 131
  • 174