javascript - three.js - 如何渲染带有 alpha channel 的线条?

标签 javascript three.js alpha

<分区>

我创建了 the following fiddle来说明我的问题。

请注意,当我在第 55 行初始化渲染器时,我包含了一个 alpha channel :

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

我还在第 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));

此属性是一个介于 0 和 1 之间的 float ,对应于特定顶点沿直线的距离。在 html 的第 19 行中,我将此属性作为变量传递给片段着色器。在 html 的第 28 行中,我将该行的 alpha channel 设置为等于此属性(您可以轻松验证 fragPos 是否已正确传递到片段着色器中)。

但是,该线条未使用 alpha channel 渲染。如果是这样,您会看到尾端慢慢淡出而不是消失。

因此,我的问题是:如何在 three.js 中使用 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>

最佳答案

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

设置.transparent THREE.Material 的属性(property)对象 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
});

查看示例,其中我将更改应用于您的原始代码:

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>

关于javascript - three.js - 如何渲染带有 alpha channel 的线条?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54620512/

相关文章:

css - 用背景颜色填充 png 图像的 alpha channel

javascript - 减去不透明度而不是乘以

javascript - 让 Three.js 项目在 ruby​​ on rails 应用程序中工作的最有效方法?

javascript - 帧率: relationship between FPS and MS (milliseconds needed to render a frame) in stats plugin

JavaScript promise 如何隐藏一些细节?

javascript - 当不使用 'return' 时,2 个 Promise 同时运行

java - 将矩阵应用于球体/Object3D

java - Java.Robot.createScreenCapture 中的透明度

javascript - 使用 es6 类进行自调用类实例化

php - 动态 HTML 表格上的 jQuery 循环产生意外结果