现代JavaScript网页设计

news2025/1/27 3:52:09

现代JavaScript网页设计:打造沉浸式3D粒子交互系统

案例概述

本文将实现一个基于WebGL的3D粒子交互系统,结合物理引擎与光线追踪技术,创造出具有以下高级特性的现代网页体验:

  1. 动态粒子矩阵(100,000+粒子实时渲染)

  2. 六自由度相机控制系统

  3. GPU加速的物理碰撞检测

  4. 基于SDF的流体模拟效果

  5. 实时屏幕空间反射(SSR)

  6. WebAssembly加速计算

核心技术栈

plaintext

复制

- Three.js (r158)
- GSAP 3.12
- WebGL 2.0
- GLSL 300
- Web Workers
- SIMD WebAssembly

关键实现步骤

1. WebGL渲染器初始化(性能优化版)

javascript

复制

class ParticleSystem {
  constructor() {
    this.renderer = new THREE.WebGLRenderer({
      antialias: true,
      powerPreference: "high-performance"
    });
    this.renderer.setPixelRatio(Math.min(2, window.devicePixelRatio));
    this.renderer.outputColorSpace = THREE.SRGBColorSpace;
    this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
    
    // 启用高级渲染特性
    this.renderer.physicallyCorrectLights = true;
    this.renderer.useLegacyLights = false;
  }
}

2. 基于计算着色器的粒子初始化

glsl

复制

// particleSimulation.comp.glsl
#version 310 es
layout(local_size_x = 256) in;
layout(std430, binding=0) buffer ParticleBuffer {
  vec4 positions[];
};

uniform float uTime;
uniform vec3 uMouse;

void main() {
  uint idx = gl_GlobalInvocationID.x;
  
  // 基于柏林噪声生成初始位置
  vec3 seed = vec3(idx*0.01, uTime*0.1, 0);
  positions[idx].xyz = vec3(
    cnoise(seed),
    cnoise(seed + 100.0),
    cnoise(seed + 200.0)
  ) * 10.0;
  
  // 动态颜色计算
  float hue = fract(uTime*0.1 + length(positions[idx].xyz)*0.1);
  positions[idx].w = hue; // 将色相存储在w分量
}

3. 基于SIMD的物理计算(WebAssembly)

cpp

复制

// physics.cc
#include <wasm_simd128.h>

void updateParticles(float* positions, float* velocities, int count) {
  const v128_t dt = wasm_f32x4_splat(0.016);
  const v128_t gravity = wasm_f32x4_make(0, -9.8, 0, 0);
  
  for (int i = 0; i < count; i += 4) {
    v128_t pos = wasm_v128_load(positions + i*3);
    v128_t vel = wasm_v128_load(velocities + i*3);
    
    vel = wasm_f32x4_add(vel, wasm_f32x4_mul(gravity, dt));
    pos = wasm_f32x4_add(pos, wasm_f32x4_mul(vel, dt));
    
    wasm_v128_store(positions + i*3, pos);
    wasm_v128_store(velocities + i*3, vel);
  }
}

4. 交互式相机控制系统

javascript

复制

class OrbitalControls {
  constructor(camera, domElement) {
    this.camera = camera;
    this.dom = domElement;
    this.theta = 0;
    this.phi = Math.PI/2;
    this.radius = 50;
    
    this.initGestures();
  }

  initGestures() {
    // 混合触摸/鼠标事件处理
    const pointer = {
      x: 0,
      y: 0,
      active: false
    };

    const onMove = (e) => {
      const dx = e.clientX - pointer.x;
      const dy = e.clientY - pointer.y;
      
      this.theta -= dx * 0.005;
      this.phi = Math.min(Math.PI-0.01, Math.max(0.01, this.phi - dy*0.005));
      
      this.update();
    };

    // 统一事件处理
    ['mousedown', 'touchstart'].forEach(event => {
      this.dom.addEventListener(event, (e) => {
        pointer.active = true;
        pointer.x = e.clientX;
        pointer.y = e.clientY;
      });
    });

    ['mousemove', 'touchmove'].forEach(event => {
      this.dom.addEventListener(event, (e) => {
        if (!pointer.active) return;
        onMove(e.touches ? e.touches[0] : e);
      });
    });

    ['mouseup', 'touchend'].forEach(event => {
      this.dom.addEventListener(event, () => pointer.active = false);
    });
  }
}

5. 动态光线追踪材质

javascript

复制

function createRTMaterial() {
  return new THREE.ShaderMaterial({
    uniforms: {
      uTime: { value: 0 },
      uResolution: { value: new THREE.Vector2() }
    },
    vertexShader: `...`,
    fragmentShader: `
      #include <packing>
      
      vec3 traceRay(vec3 origin, vec3 direction) {
        // 光线步进算法
        for(int i=0; i<128; i++) {
          // SDF场景查询
          float d = sceneSDF(origin + direction*t);
          if(d < 0.001) {
            return calculateLighting();
          }
          t += d;
        }
        return vec3(0);
      }
      
      void main() {
        vec2 uv = (gl_FragCoord.xy*2.0 - uResolution)/min(uResolution.x, uResolution.y);
        vec3 rayDir = normalize(vec3(uv, 1));
        
        vec3 color = traceRay(cameraPos, rayDir);
        gl_FragColor = vec4(color, 1.0);
      }
    `
  });
}

性能优化策略

  1. 多线程架构

javascript

复制

// 主线程
const physicsWorker = new Worker('physics.js');
physicsWorker.postMessage(positions.buffer, [positions.buffer]);

// Worker线程
onmessage = (e) => {
  const positions = new Float32Array(e.data);
  // 执行物理计算...
  postMessage(positions.buffer, [positions.buffer]);
};
  1. GPU实例化渲染

javascript

复制

const geometry = new THREE.InstancedBufferGeometry();
geometry.instanceCount = PARTICLE_COUNT;

const material = new THREE.MeshBasicMaterial({
  onBeforeCompile: (shader) => {
    shader.vertexShader = shader.vertexShader.replace(
      '#include <common>',
      `
        #include <common>
        attribute vec3 instancePosition;
        attribute float instanceHue;
      `
    );
  }
});
  1. 分层渲染策略

javascript

复制

// 创建多个渲染目标
const rt1 = new THREE.WebGLRenderTarget(WIDTH, HEIGHT, {
  samples: 8,
  type: THREE.HalfFloatType
});

const rt2 = new THREE.WebGLRenderTarget(WIDTH, HEIGHT, {
  samples: 8,
  type: THREE.HalfFloatType
});

// 渲染循环
function render() {
  // 第一遍:几何体渲染
  renderer.setRenderTarget(rt1);
  renderer.render(scene, camera);
  
  // 第二遍:后处理效果
  postProcessingPass(rt1, rt2);
  
  // 最终合成
  renderer.setRenderTarget(null);
  composer.render();
}

完整效果集成

javascript

复制

class AdvancedParticleDemo {
  async init() {
    // 初始化WebAssembly模块
    this.physicsModule = await WebAssembly.instantiateStreaming(
      fetch('physics.wasm'),
      { env: { Math } }
    );

    // 创建三维场景
    this.scene = new THREE.Scene();
    this.setupLighting();
    
    // 初始化粒子系统
    await this.createParticles(100000);
    
    // 设置交互控制
    this.controls = new HybridControls(this.camera, renderer.domElement);
    
    // 启动动画循环
    this.startAnimation();
  }

  startAnimation() {
    const update = (time) => {
      // 并行更新逻辑
      Promise.all([
        this.updatePhysics(),
        this.updateParticles(),
        this.updatePostProcessing()
      ]).then(() => {
        renderer.render(scene, camera);
        requestAnimationFrame(update);
      });
    };
    requestAnimationFrame(update);
  }
}

创新点解析

  1. 混合精度计算

    • 在WebAssembly中使用FP32计算物理

    • 在WebGL中使用FP16存储颜色数据

    • CPU端使用FP64进行精确计算

  2. 渐进式加载策略

javascript

复制

const LOD_LEVELS = {
  0: { detail: 100, distance: 50 },
  1: { detail: 30, distance: 100 },
  2: { detail: 10, distance: Infinity }
};

function updateLOD(cameraPosition) {
  particles.forEach(particle => {
    const dist = distance(particle.position, cameraPosition);
    const lod = Object.values(LOD_LEVELS).find(l => dist < l.distance);
    particle.setDetailLevel(lod.detail);
  });
}
  1. 智能缓存策略

javascript

复制

const particleCache = new Map();

function getParticleGeometry(count) {
  if (!particleCache.has(count)) {
    const geometry = createOptimizedGeometry(count);
    geometry.cacheKey = count;
    particleCache.set(count, geometry);
  }
  return particleCache.get(count);
}

效果增强技巧

  1. 屏幕空间环境光遮蔽(SSAO)

glsl

复制

float computeSSAO(vec2 uv, float depth) {
  const int samples = 32;
  float occlusion = 0.0;
  
  for(int i=0; i<samples; ++i) {
    vec2 offset = poissonDisk[i] * 0.02;
    float sampleDepth = texture2D(depthTexture, uv + offset).r;
    float rangeCheck = smoothstep(0.0, 0.1, abs(depth - sampleDepth));
    occlusion += (sampleDepth < depth ? 1.0 : 0.0) * rangeCheck;
  }
  
  return 1.0 - (occlusion / float(samples));
}
  1. 动态焦距效果

javascript

复制

function updateDepthOfField() {
  const focusPoint = this.controls.getFocusPoint();
  const depthShader = this.composer.passes[1];
  
  depthShader.uniforms.focus.value = focusPoint.z;
  depthShader.uniforms.aperture.value = this.controls.movementSpeed * 0.1;
}

部署与优化

  1. 构建配置示例

javascript

复制

// vite.config.js
export default defineConfig({
  build: {
    target: 'esnext',
    assetsInlineLimit: 0,
    rollupOptions: {
      output: {
        manualChunks: {
          three: ['three'],
          physics: ['@physics/core']
        }
      }
    }
  },
  optimizeDeps: {
    include: ['three > WebGLRenderer']
  }
});
  1. 渐进式Web应用配置

javascript

复制

// service-worker.js
const CORE_ASSETS = [
  '/wasm/physics.wasm',
  '/glsl/particle.vert',
  '/glsl/particle.frag',
  '/models/skybox.draco.glb'
];

self.addEventListener('install', (e) => {
  e.waitUntil(
    caches.open('v1-core').then(cache => cache.addAll(CORE_ASSETS))
  );
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2283160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【基于无线电的数据通信链】Link 11 仿真测试

〇、废话 Link 11 仿真测试 涉及多个方面&#xff0c;包括信号仿真、协议模拟、数据链路层的仿真以及网络性能评估等。Link 11 是一种基于 HF&#xff08;高频&#xff09; 或 UHF&#xff08;超高频&#xff09; 波段的无线通信协议&#xff0c;主要用于军事通信系统中。为了…

VScode 开发 Springboot 程序

1. 通过maven创建springboot程序 输入 mvn archetype:generate 选择模板&#xff0c;一般默认选择为第 7 种方式&#xff1b; 选择之后&#xff0c;一般要你填写如下内容&#xff1a; groupId: 组织名称&#xff1b;artifactId: 项目名称&#xff1b;version: 版本&#xff0…

深入MapReduce——引入

引入 前面我们已经深入了HDFS的设计与实现&#xff0c;对于分布式系统也有了不错的理解。 但HDFS仅仅解决了海量数据存储和读写的问题。要想让数据产生价值&#xff0c;一定是需要从数据中挖掘出价值才行&#xff0c;这就需要我们拥有海量数据的计算处理能力。 下面我们还是…

springfox-swagger-ui 3.0.0 配置

在3.0中&#xff0c;访问地址URL变了。 http://地址:端口/项目名/swagger-ui/ SpringBoot maven项目引入 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>3.0.0</version> </…

如何解压7z文件?8种方法(Win/Mac/手机/网页端)

7z 文件是一种高效的压缩文件格式&#xff0c;由 7 - Zip 软件开发者所采用。它运用独特的压缩算法&#xff0c;能显著缩小文件体积&#xff0c;便于存储与传输各类数据&#xff0c;像软件安装包、大型资料集等。但要使用其中内容&#xff0c;就必须解压&#xff0c;因为处于压…

Spring Boot 邂逅Netty:构建高性能网络应用的奇妙之旅

一、引言 在当今数字化时代&#xff0c;构建高效、可靠的网络应用是开发者面临的重要挑战。Spring Boot 作为一款强大的 Java 开发框架&#xff0c;以其快速开发、简洁配置和丰富的生态支持&#xff0c;深受广大开发者喜爱。而 Netty 作为高性能、异步的网络通信框架&#xff…

[STM32 - 野火] - - - 固件库学习笔记 - - -十一.电源管理系统

一、电源管理系统简介 电源管理系统是STM32硬件设计和系统运行的基础&#xff0c;它不仅为芯片本身提供稳定的电源&#xff0c;还通过多种电源管理功能优化功耗、延长电池寿命&#xff0c;并确保系统的可靠性和稳定性。 二、电源监控器 作用&#xff1a;保证STM32芯片工作在…

从 Web2 到 Web3:技术演进中的关键变革

随着互联网的快速发展&#xff0c;Web 技术经历了从 Web1 到 Web2&#xff0c;再到当前热议的 Web3 的演变。每一次技术迭代不仅仅是技术本身的升级&#xff0c;更代表着对社会、经济和文化的深刻影响。本文将带你走过 Web2 到 Web3 的技术演进&#xff0c;探讨其中的关键变革&…

Android实战经验篇-玩转Selinux(详解版)

列文章转如下链接&#xff1a; Android Display Graphics系列文章-汇总 Android实战经验篇-系列文章汇总 本文主要包括部分&#xff1a; 一、Selinux概述 1.1 SELinux是什么&#xff1f; 1.2 自主访问控制&#xff08;DAC&#xff09; 1.3 强制访问控制&#xff08;MAC&…

CLOUDFLARE代理请求重定向你太多次

现象 使用CLOUDFLARE代理前请求正常&#xff0c;使用CLOUDFLARE代理请求后出现 原因分析 以下是我的猜测&#xff0c;在默认情况下 CLOUDFLARE代理&#xff0c;可能是直接请求我们服务器的IP&#xff0c;比如&#xff1a;http://1.1.1.1 而不是通过域名的方式&#xff08;如…

U-Net - U型网络:用于图像分割的卷积神经网络

U-Net是一种专为图像分割任务设计的卷积神经网络&#xff08;CNN&#xff09;&#xff0c;最初由Olaf Ronneberger等人于2015年提出。它被广泛应用于医学影像分析、遥感图像分割、自动驾驶和其他许多需要对图像进行像素级分类的任务中。U-Net具有强大的特征提取和恢复能力&…

第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组

第十五届的题目在规定时间内做出了前5道&#xff0c;还有2道找时间再磨一磨。现在把做的一些思路总结如下&#xff1a; 题1&#xff1a;握手问题 问题描述 小蓝组织了一场算法交流会议&#xff0c;总共有 50人参加了本次会议。在会议上&#xff0c;大家进行了握手交流。按照惯例…

Vue3 + TS 实现批量拖拽 文件夹和文件 组件封装

一、html 代码&#xff1a; 代码中的表格引入了 vxe-table 插件 <Tag /> 是自己封装的说明组件 表格列表这块我使用了插槽来增加扩展性&#xff0c;可根据自己需求&#xff0c;在组件外部做调整 <template><div class"dragUpload"><el-dial…

DX12 快速教程(4) —— 画钻石原矿

快速导航 新建项目 "004-DrawTexture"纹理贴图纹理采样纹理过滤邻近点采样双线性过滤Mipmap 多级渐远纹理三线性过滤各向异性过滤 纹理环绕LOD 细节层次 开始画钻石原矿吧加载纹理到内存中&#xff1a;LoadTexture什么是 WIC如何用 WIC 读取一帧图片获取图片格式并转…

LBS 开发微课堂|AI向导接口服务:重塑用户的出行体验

为了让广大开发者 更深入地了解 百度地图开放平台的 技术能力 轻松掌握满满的 技术干货 更加简单地接入 位置服务 我们特别推出了 “位置服务&#xff08;LBS&#xff09;开发微课堂” 系列技术案例 第六期的主题是 《AI向导接口服务的能力与接入方案》 随着地图应…

mysql 学习3 SQL语句--整体概述。SQL通用语法;DDL创建数据库,查看当前数据库是那个,删除数据库,使用数据库;查看当前数据库有哪些表

SQL通用语法 SQL语句分类 DDL data definition language : 用来创建数据库&#xff0c;创建表&#xff0c;创建表中的字段&#xff0c;创建索引。因此成为 数据定义语言 DML data manipulation language 有了数据库和表以及字段后&#xff0c;那么我们就需要给这个表中 添加数…

【Bug 记录】el-sub-menu 第一次进入默认不高亮

项目场景&#xff1a; 项目场景&#xff1a;el-sub-menu 第一次进入默认不高亮 问题描述 例如&#xff1a;sub-menu 的 index 后端默认传过来是 number&#xff0c;我们需要手动转为 string&#xff0c;否则会有警告&#xff0c;而且第一次进入 sub-menu 默认不高亮。 解决方…

深入探讨ncnn::Mat类——ncnn中的核心数据结构

最近在学习 ncnn 推理框架&#xff0c;下面整理了 ncnn::Mat 的使用方法。 ncnn作为一个高性能的神经网络推理框架&#xff0c;其核心数据结构ncnn::Mat在数据存储与处理上扮演了至关重要的角色。本文将从基础到高级&#xff0c;详细介绍ncnn::Mat类的各个方面&#xff0c;帮助…

npm:升级自身时报错:EBADENGINE

具体报错信息如下&#xff1a; 1.原因分析 npm和当前的node版本不兼容。 // 当前实际版本: Actual: {"npm":"10.2.4","node":"v20.11.0"}可以通过官网文档查看与自己 node 版本 兼容的是哪一版本的npm&#xff0c;相对应进行更新即可…

ipad和macbook同步zotero文献附件失败的解决办法

背景&#xff1a;我所有的文献及其附件pdf都是在台式机&#xff08;windows系统&#xff09;&#xff0c;想要把这些文献同步到云上&#xff0c;然后再从云上同步到平板和其他笔记本电脑比如macbook。文献同步虽已成功&#xff0c;但文献附件都无法打开。 平板报错如下&#xf…