代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html lang="en">
<head>
<title>Verge3D webgl - custom attributes [particles][billboards]</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info"><a href="https://www.soft8soft.com/verge3d" target="_blank" rel="noopener">Verge3D</a> - custom attributes example - particles - billboards</div>
<div id="container"></div>
<script type="x-shader/x-vertex" id="vertexshader">
attribute float size;
attribute vec3 ca;
varying vec3 vColor;
void main() {
vColor = ca;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = size * (300.0 / -mvPosition.z);
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform vec3 color;
uniform sampler2D pointTexture;
varying vec3 vColor;
void main() {
vec4 color = vec4(color * vColor, 1.0) * texture2D(pointTexture, gl_PointCoord);
gl_FragColor = color;
}
</script>
<script type="module">
import * as v3d from '../build/v3d.module.js';
import Stats from './jsm/libs/stats.module.js';
let renderer, scene, camera, stats;
let sphere, length1;
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;
init();
animate();
function init() {
camera = new v3d.PerspectiveCamera(45, WIDTH / HEIGHT, 1, 10000);
camera.position.z = 300;
scene = new v3d.Scene();
const radius = 100, segments = 68, rings = 38;
const vertices1 = new v3d.SphereGeometry(radius, segments, rings).vertices;
const vertices2 = new v3d.BoxGeometry(0.8 * radius, 0.8 * radius, 0.8 * radius, 10, 10, 10).vertices;
length1 = vertices1.length;
const vertices = vertices1.concat(vertices2);
const positions = new Float32Array(vertices.length * 3);
const colors = new Float32Array(vertices.length * 3);
const sizes = new Float32Array(vertices.length);
const color = new v3d.Color();
for (let i = 0, l = vertices.length; i < l; i++) {
const vertex = vertices[i];
vertex.toArray(positions, i * 3);
if (i < length1) {
color.setHSL(0.01 + 0.1 * (i / length1), 0.99, (vertex.y + radius) / (4 * radius));
} else {
color.setHSL(0.6, 0.75, 0.25 + vertex.y / (2 * radius));
}
color.toArray(colors, i * 3);
sizes[i] = i < length1 ? 10 : 40;
}
const geometry = new v3d.BufferGeometry();
geometry.setAttribute('position', new v3d.BufferAttribute(positions, 3));
geometry.setAttribute('size', new v3d.BufferAttribute(sizes, 1));
geometry.setAttribute('ca', new v3d.BufferAttribute(colors, 3));
//
const texture = new v3d.TextureLoader().load("textures/sprites/disc.png");
texture.wrapS = v3d.RepeatWrapping;
texture.wrapT = v3d.RepeatWrapping;
const material = new v3d.ShaderMaterial({
uniforms: {
color: { value: new v3d.Color(0xffffff) },
pointTexture: { value: texture }
},
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
transparent: true
});
//
sphere = new v3d.Points(geometry, material);
scene.add(sphere);
//
renderer = new v3d.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(WIDTH, HEIGHT);
const container = document.getElementById('container');
container.appendChild(renderer.domElement);
stats = new Stats();
container.appendChild(stats.dom);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function sortPoints() {
const vector = new v3d.Vector3();
// Model View Projection matrix
const matrix = new v3d.Matrix4();
matrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
matrix.multiply(sphere.matrixWorld);
//
const geometry = sphere.geometry;
let index = geometry.getIndex();
const positions = geometry.getAttribute('position').array;
const length = positions.length / 3;
if (index === null) {
const array = new Uint16Array(length);
for (let i = 0; i < length; i++) {
array[i] = i;
}
index = new v3d.BufferAttribute(array, 1);
geometry.setIndex(index);
}
const sortArray = [];
for (let i = 0; i < length; i++) {
vector.fromArray(positions, i * 3);
vector.applyMatrix4(matrix);
sortArray.push([vector.z, i]);
}
function numericalSort(a, b) {
return b[0] - a[0];
}
sortArray.sort(numericalSort);
const indices = index.array;
for (let i = 0; i < length; i++) {
indices[i] = sortArray[i][1];
}
geometry.index.needsUpdate = true;
}
function animate() {
requestAnimationFrame(animate);
render();
stats.update();
}
function render() {
const time = Date.now() * 0.005;
sphere.rotation.y = 0.02 * time;
sphere.rotation.z = 0.02 * time;
const geometry = sphere.geometry;
const attributes = geometry.attributes;
for (let i = 0; i < attributes.size.array.length; i++) {
if (i < length1) {
attributes.size.array[i] = 16 + 12 * Math.sin(0.1 * i + time);
}
}
attributes.size.needsUpdate = true;
sortPoints();
renderer.render(scene, camera);
}
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。