gpt4 book ai didi

javascript - BufferGeometry 创建粒子 z 索引

转载 作者:行者123 更新时间:2023-12-01 02:45:27 25 4
gpt4 key购买 nike

我用三个js的BufferGeometry创建了两个粒子,我想点击每个粒子显示对应的图像。

但是当我点击粒子时,图像被显示,另一个粒子覆盖了它。

我想知道如何使粒子脱离层次结构的控制并使单击的粒子始终位于顶部。

代码:`

var scene, camera, renderer,controls;
var points;
var shaderMaterial;

var particleCount = 2;

function init () {
scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 15;
camera.position.y = 16;
camera.position.z = 35;
camera.lookAt(scene.position);

renderer = new THREE.WebGLRenderer();

renderer.setClearColor(0x000000, 1.0);

renderer.setSize(window.innerWidth, window.innerHeight);

var light = new THREE.AmbientLight( 0xcccccc );

scene.add(light);

document.body.appendChild(renderer.domElement);

createParticles();

createGrid();

render();

document.querySelector('canvas').addEventListener( 'click', interactive, false );

}

function createParticles () {
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( particleCount * 3 );
var sizes = new Float32Array( particleCount );
var pop = new Float32Array( particleCount);

for (var i = 0, i3 = 0; i < particleCount; i ++, i3 += 3) {
positions[i3 + 0] = i* 10;
positions[i3 + 1] = 0.1;
positions[i3 + 2] = 1;

sizes[i] = 15;
pop[i] = 0.0;
}

geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'size', new THREE.BufferAttribute( sizes, 1 ) );
geometry.addAttribute( 'pop', new THREE.BufferAttribute( pop, 1 ) );

shaderMaterial = new THREE.ShaderMaterial({
uniforms: {
'u_time': {type: 'f', value: 1.0},
'u_texture_0': { value: new THREE.TextureLoader().load('https://avatars2.githubusercontent.com/u/5829050?s=256&v=4') }},
vertexShader: document.getElementById( 'vs' ).textContent,
fragmentShader: document.getElementById( 'fs' ).textContent,
// blending: THREE.AdditiveBlending,
depthTest: false,
transparent: true
});
shaderMaterial.uniforms['u_texture_0'].value.flipY = false;

points = new THREE.Points(geometry, shaderMaterial);

scene.add(points);

}
var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = 5;

var touch = new THREE.Vector2();
var intersects, INTERSECTED;
var beforeIndex;

function interactive (event) {
touch.x = ( event.clientX / window.innerWidth ) * 2 - 1;
touch.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
points.geometry.computeBoundingSphere();
camera.updateMatrixWorld();
var vector = new THREE.Vector3(touch.x, touch.y, 0.5 ).unproject(camera);
raycaster.set(camera.position, vector.sub(camera.position ).normalize());

raycaster.setFromCamera( touch, camera );

intersects = raycaster.intersectObject(points);
if ( intersects.length > 0 ) {
if ( INTERSECTED != intersects[ 0 ].index ) {
INTERSECTED = intersects[ 0 ].index;
if (beforeIndex != INTERSECTED) {
points.geometry.attributes.pop.array[ beforeIndex ] = 0.0;
}
points.geometry.attributes.pop.array[ INTERSECTED ] = 1.0;

beforeIndex = INTERSECTED;

}
}

points.geometry.attributes.size.needsUpdate = true;
points.geometry.attributes.pop.needsUpdate = true;
}

function createGrid () {
var helper = new THREE.GridHelper( 100, 20, 0x303030, 0x303030 );
scene.add( helper );
}
function render () {

renderer.render(scene, camera);

requestAnimationFrame(render);
}

init();
* {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
background: #000;
}
canvas {
display: block;
}
<script src="https://threejs.org/build/three.js"></script>
<script id="fs" type="x-shader/x-fragment">
precision highp float;
uniform sampler2D u_texture_0;
uniform float u_time;
varying float u_pop;

void main () {
vec2 uv = gl_PointCoord.xy;
vec4 rval = texture2D(u_texture_0,uv);

vec2 posToCenter = (uv - vec2(.5, .5)) * 2.0;
float distanceToCenter = length(posToCenter);
float fadeOpacity = 1. - smoothstep(0.8, 1., distanceToCenter);
float opacity = (1. - step(0.8, distanceToCenter)) + fadeOpacity;

vec3 bgColor = mix(vec3(255., 255., 255.), vec3(252., 222., 184.), distanceToCenter) / 255.;

vec4 color = vec4(mix(bgColor, rval.rgb, u_pop), 1.);
color.a = opacity;

gl_FragColor = color;
}
</script>
<script type="x-shader/x-vertex" id="vs">
attribute float size;
attribute float pop;

varying float u_pop;
void main() {
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 300.0 / -mvPosition.z );
gl_Position = projectionMatrix * mvPosition;

u_pop = pop;
}
</script>

`

最佳答案

您对 3D 的工作原理存在误解,因此使用了错误的概念和术语。 3D 中没有“Z 索引”。有Z-buffer or Depth-buffer (两个名字,同一件事),它反射(reflect)了从渲染者的 Angular (相机,虚拟观察者)的物体距离。当然,具有深度测试的深度缓冲区的目的是防止最远的对象在最近的对象之前渲染(这也可以通过防止计算看不见的像素来进行优化)。

此外,背景到前景显示不受任何层次结构控制(除非引擎故意实现此类功能),对象只是按照提供的顺序进行渲染。如果禁用深度测试,则最新渲染的对象将显示在所有先前渲染的对象之前。在 3D 场景中,层次结构与变换相关,而不是显示顺序(除非对象在没有深度测试的情况下按照场景的层次结构顺序渲染)。

为了以稳健的方式实现您想要的效果,您必须禁用深度目标并手动控制渲染 Sprite 的顺序,以确保必须位于“前面”的 Sprite 是最后渲染的 Sprite 。这是一个相当低级的操作,除非 Three.JS 允许您控制它(我对此表示怀疑),否则您可能必须改变您的策略,或者实现您自己的 WebGL 引擎。

关于javascript - BufferGeometry 创建粒子 z 索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47280277/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com