一个实验性尝试,使用 webgl 开发的三维开放世界笔记系统《赛博城寨》
2026/7/28 20:30:59 网站建设 项目流程

一个实验性尝试,使用 WebGL 开发的三维开放世界笔记系统《赛博城寨》

在数字时代的浪潮中,笔记工具从纸质笔记本进化到云笔记,再到如今的三维空间笔记,每一步都承载着人类对信息组织方式的探索。今天,我想分享一个实验性的项目——《赛博城寨》,它是一个使用 WebGL 技术构建的三维开放世界笔记系统。在这里,笔记不再是一维的文本列表,而是漂浮在虚拟城市中的“知识建筑”,用户可以像探索城市一样穿梭于自己的思维之间。## 从零搭建:WebGL 基础与三维世界的诞生WebGL(Web Graphics Library)是浏览器中的 3D 图形 API,它允许 JavaScript 直接调用 GPU 渲染三维场景。要理解《赛博城寨》的底层逻辑,我们先从最基础的 WebGL 渲染管线开始。### 基础概念:顶点、着色器与三角形三维世界由无数个三角形组成。每个三角形有三个顶点,每个顶点包含位置、颜色等信息。WebGL 通过两个关键程序——顶点着色器和片元着色器——将数据处理成屏幕上的像素。下面是一个最简单的 WebGL 示例,绘制一个彩色三角形:javascript// 步骤1:获取 WebGL 上下文const canvas = document.getElementById('myCanvas');const gl = canvas.getContext('webgl');// 步骤2:定义三角形的三个顶点(x, y, z 坐标)const vertices = [ -0.5, -0.5, 0.0, // 左下 0.5, -0.5, 0.0, // 右下 0.0, 0.5, 0.0 // 顶部];// 步骤3:创建缓冲区存储顶点数据const vertexBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);// 步骤4:编写顶点着色器(处理顶点位置)const vertexShaderSource = ` attribute vec3 aPosition; void main() { gl_Position = vec4(aPosition, 1.0); }`;// 步骤5:编写片元着色器(决定颜色)const fragmentShaderSource = ` void main() { gl_FragColor = vec4(0.0, 0.8, 0.6, 1.0); // 青色 }`;// 步骤6:编译并链接着色器function createShader(gl, source, type) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); return shader;}const vertexShader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);const fragmentShader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);const program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);gl.useProgram(program);// 步骤7:绑定顶点属性const positionAttrib = gl.getAttribLocation(program, 'aPosition');gl.vertexAttribPointer(positionAttrib, 3, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(positionAttrib);// 步骤8:绘制三角形gl.clearColor(0.1, 0.1, 0.2, 1.0); // 深蓝背景gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, 3);这段代码展示了 WebGL 的核心流程:定义几何数据 → 编写着色器 → 编译链接 → 绘制。在《赛博城寨》中,每个笔记卡片都被视为一个独立的“建筑”,其六面体结构就是由 12 个三角形(每个面 2 个)构成的。## 进阶探索:从静态三角形到动态开放世界掌握了基础之后,我们进入《赛博城寨》的核心:如何让笔记在三维空间中交互?这里需要引入矩阵变换和用户输入处理。### 三维变换:让笔记“漂浮”起来每个笔记卡片在场景中有一个位置、旋转和缩放。这些通过模型矩阵(Model Matrix)实现。同时,我们需要相机矩阵(View Matrix)和投影矩阵(Projection Matrix)来实现第一人称视角。下面是一个更完整的交互示例,用户可以通过鼠标拖拽旋转视角,点击笔记卡片查看内容:javascript// 假设已加载 Three.js 库(简化 WebGL 开发)import * as THREE from 'three';// 初始化场景、相机、渲染器const scene = new THREE.Scene();scene.background = new THREE.Color(0x0a0a23); // 赛博朋克风格深蓝const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.set(10, 5, 15);camera.lookAt(0, 0, 0);const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 创建笔记卡片(一个带文字的立方体)function createNoteCard(content, position, color = 0x00ffcc) { // 几何体:立方体 const geometry = new THREE.BoxGeometry(2, 1.5, 0.3); const material = new THREE.MeshPhongMaterial({ color: color, emissive: 0x004422, transparent: true, opacity: 0.9 }); const cube = new THREE.Mesh(geometry, material); cube.position.set(position.x, position.y, position.z); // 添加文字标签(使用 Canvas 纹理) const canvas = document.createElement('canvas'); canvas.width = 256; canvas.height = 128; const ctx = canvas.getContext('2d'); ctx.fillStyle = 'rgba(0,0,0,0.8)'; ctx.fillRect(0, 0, 256, 128); ctx.fillStyle = '#00ffcc'; ctx.font = '20px monospace'; ctx.fillText(content.substring(0, 12) + '...', 10, 60); const texture = new THREE.CanvasTexture(canvas); const textMaterial = new THREE.SpriteMaterial({ map: texture }); const sprite = new THREE.Sprite(textMaterial); sprite.position.set(0, 0, 0.2); // 在立方体前面 cube.add(sprite); return cube;}// 添加几个笔记卡片到场景const notes = [];notes.push(createNoteCard('WebGL 基础:顶点与着色器', { x: 2, y: 0, z: -3 }, 0xff6600));notes.push(createNoteCard('Three.js 高级:粒子系统', { x: -2, y: 1, z: 1 }, 0x00ccff));notes.push(createNoteCard('赛博城寨架构设计', { x: 0, y: -1, z: 4 }, 0xff00aa));notes.forEach(note => scene.add(note));// 添加灯光const ambientLight = new THREE.AmbientLight(0x404040);scene.add(ambientLight);const dirLight = new THREE.DirectionalLight(0xffffff, 1);dirLight.position.set(5, 10, 7);scene.add(dirLight);// 鼠标交互:点击检测const raycaster = new THREE.Raycaster();const mouse = new THREE.Vector2();document.addEventListener('click', (event) => { // 将鼠标坐标转换为归一化设备坐标 mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(notes); if (intersects.length > 0) { const clickedNote = intersects[0].object; // 打开笔记详情(此处简化为控制台输出) console.log('打开笔记:', clickedNote.children[0].material.map.image.toDataURL()); // 实际项目中可弹出模态框显示完整内容 }});// 动画循环function animate() { requestAnimationFrame(animate); // 让笔记卡片缓慢旋转,增加沉浸感 notes.forEach((note, index) => { note.rotation.y += 0.005 * (index + 1); }); renderer.render(scene, camera);}animate();这段代码展示了《赛博城寨》的交互核心:每个笔记卡片是一个独立的 3D 对象,拥有自己的位置和外观;通过射线检测实现点击交互;通过动画循环保持场景动态。用户可以在城市中漫步,点击漂浮的“知识建筑”查看内容。## 架构设计:如何组织三维笔记系统《赛博城寨》的架构分为三层:1.数据层:使用 IndexedDB 存储笔记元数据(标题、内容、位置坐标)。每个笔记是一个 JSON 对象,包含{id, title, content, x, y, z, color}。2.逻辑层:管理笔记的增删改查,以及三维世界的更新。当用户新建笔记时,逻辑层会在场景中生成新的卡片,并分配唯一的空间坐标。3.渲染层:基于 Three.js(WebGL 封装库)实现 3D 渲染,包括光照、阴影、粒子特效(模拟城市灯光)。### 核心流程-加载:从数据库读取所有笔记,按坐标生成卡片,用户看到的是“知识城市”。-导航:用户通过键盘 WASD 移动,鼠标拖动旋转视角,实现第一人称探索。-交互:点击卡片打开笔记详情,长按可拖拽移动卡片位置(重新组织“建筑布局”)。-持久化:任何位置变化都会自动保存到 IndexedDB。## 总结《赛博城寨》是一个实验性的尝试,它将笔记系统从二维平面提升到三维空间,利用 WebGL 技术创造了一个可交互的“知识城市”。从最基础的三角形绘制,到动态的交互式世界,我们看到了 WebGL 在数据可视化领域的潜力。虽然这个项目目前还处于原型阶段,但它展示了几个有趣的可能性:-空间记忆:人类对空间的记忆优于对列表的记忆,三维布局可能帮助用户更直观地组织知识。-沉浸式学习:在虚拟城市中“漫步”于自己的笔记之间,可能激发新的思维连接。-技术栈融合:WebGL + IndexedDB + 现代前端框架,可以构建轻量级的 3D 应用。如果你也想尝试,可以从上面的代码片段开始,逐步添加更多功能——比如笔记之间的“空中走廊”(连接线)、按主题划分的“街区”(区域颜色编码)、甚至多人协作的“城市共建”。这只是一个起点,三维笔记的世界等待你的探索。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询