我试图在半透明的粒子云中画出半透明的球体。球体在粒子前面是半透明的,但是一旦它在粒子之间变成不透明(即,如果粒子顶点位于相机和球体表面之间,则球体变得不透明)。查看下面的代码段(点击“整页”,它看起来好多了。)
三个已删除.sortParticles
的新版本已在此处发挥作用,但我正在通过复制this example中的sortPoints
函数解决此问题。
每个粒子和球体的深度似乎都是准确的,只是失去了不透明度。也许混合在某些情况下失败了?
有没有办法在半透明颗粒中绘制半透明网格?
var renderer, scene, camera, sphere;
var particleSystem, uniforms, geometry;
var particles = 200;
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(40, WIDTH / HEIGHT, 1, 10000);
camera.position.z = 70;
scene = new THREE.Scene();
uniforms = {
color: {
type: "c",
value: new THREE.Color(0xffffff)
},
};
var shaderMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
depthTest: true,
depthWrite: false,
transparent: true
});
var sphere_geometry = new THREE.SphereGeometry(10, 32, 32);
var sphere_material = new THREE.MeshNormalMaterial();
sphere_material.transparent = true;
sphere_material.opacity = 0.6;
sphere_material.depthTest = true;
//sphere_material.depthWrite = false;
sphere = new THREE.Mesh(sphere_geometry, sphere_material);
//sphere.renderOrder = -1;
scene.add(sphere);
camera.lookAt(sphere.position);
var radius = 30;
geometry = new THREE.BufferGeometry();
var positions = new Float32Array(particles * 3);
var colors = new Float32Array(particles * 3);
var sizes = new Float32Array(particles);
var color = new THREE.Color();
for (var i = 0, i3 = 0; i < particles; i++, i3 += 3) {
positions[i3 + 0] = i - 50;
positions[i3 + 1] = i - 50;
positions[i3 + 2] = 2*i - 100;
color.setHSL(i / particles, 1.0, 0.5);
colors[i3 + 0] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
sizes[i] = 3000;
}
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.addAttribute('customColor', new THREE.BufferAttribute(colors, 3));
geometry.addAttribute('size', new THREE.BufferAttribute(sizes, 1));
particleSystem = new THREE.Points(geometry, shaderMaterial);
scene.add(particleSystem);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(WIDTH, HEIGHT);
var container = document.getElementById('container');
container.appendChild(renderer.domElement);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var time = Date.now() * 0.005;
var n = 30;
sphere.position.z = n * (1 + Math.sin(0.2 * time)) - n * 1.5;
sortPoints();
renderer.render(scene, camera);
}
function sortPoints() {
var vector = new THREE.Vector3();
// Model View Projection matrix
var matrix = new THREE.Matrix4();
matrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
// matrix.multiply( particleSystem.matrixWorld );
//
var index = geometry.getIndex();
var positions = geometry.getAttribute('position').array;
var length = positions.length / 3;
if (index === null) {
var array = new Uint16Array(length);
for (var i = 0; i < length; i++) {
array[i] = i;
}
index = new THREE.BufferAttribute(array, 1);
geometry.setIndex(index);
}
var sortArray = [];
for (var i = 0; i < length; i++) {
vector.fromArray(positions, i * 3);
vector.applyProjection(matrix);
sortArray.push([vector.z, i]);
}
function numericalSort(a, b) {
return b[0] - a[0];
}
sortArray.sort(numericalSort);
var indices = index.array;
for (var i = 0; i < length; i++) {
indices[i] = sortArray[i][1];
}
geometry.index.needsUpdate = true;
}
body {
color: #ffffff;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #000000;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 0px;
width: 100%;
padding: 5px;
z-index:100;
}
<script src="http://threejs.org/build/three.min.js"></script>
<div id="info">translucent mesh amidst translucent particles</div>
<script type="x-shader/x-vertex" id="vertexshader">
attribute float size;
attribute vec3 customColor;
varying vec3 vColor;
void main() {
vColor = customColor;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = size / length(mvPosition.xyz);
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform vec3 color;
varying vec3 vColor;
void main() {
gl_FragColor = vec4(color * vColor, 0.2);
}
</script>
<div id="container"></div>