Я создал следующая рабочий пример, чтобы проиллюстрировать свой вопрос.
Обратите внимание, что когда я инициализирую средство визуализации в строке 55, я включаю альфа-канал:
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, которое соответствует тому, как далеко по линии находится конкретная вершина. В строке 19 html я передаю этот атрибут фраг-шейдеру как переменный. В строке 28 html я устанавливаю альфа-канал строки равным этому атрибуту (Вы можете легко убедиться, что fragPos правильно передается во фраг-шейдер).
Однако линия не визуализируется с альфа-каналом. Если бы это было так, вы бы увидели, как хвостовая часть медленно исчезает, а не просто исчезает.
Итак, мой вопрос: Как я могу отобразить строку в three.js с альфа-каналом?
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>


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


How can I render a line in three.js with an alpha channel?
Задайте свойство .transparent объекта THREE.Materialtrue:
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>