一个实验性尝试,使用 webgl 开发的三维开放世界笔记系统《赛博城寨》
一个实验性尝试使用 WebGL 开发的三维开放世界笔记系统《赛博城寨》在数字时代的浪潮中笔记工具从纸质笔记本进化到云笔记再到如今的三维空间笔记每一步都承载着人类对信息组织方式的探索。今天我想分享一个实验性的项目——《赛博城寨》它是一个使用 WebGL 技术构建的三维开放世界笔记系统。在这里笔记不再是一维的文本列表而是漂浮在虚拟城市中的“知识建筑”用户可以像探索城市一样穿梭于自己的思维之间。## 从零搭建WebGL 基础与三维世界的诞生WebGLWeb 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.jsWebGL 封装库实现 3D 渲染包括光照、阴影、粒子特效模拟城市灯光。### 核心流程-加载从数据库读取所有笔记按坐标生成卡片用户看到的是“知识城市”。-导航用户通过键盘 WASD 移动鼠标拖动旋转视角实现第一人称探索。-交互点击卡片打开笔记详情长按可拖拽移动卡片位置重新组织“建筑布局”。-持久化任何位置变化都会自动保存到 IndexedDB。## 总结《赛博城寨》是一个实验性的尝试它将笔记系统从二维平面提升到三维空间利用 WebGL 技术创造了一个可交互的“知识城市”。从最基础的三角形绘制到动态的交互式世界我们看到了 WebGL 在数据可视化领域的潜力。虽然这个项目目前还处于原型阶段但它展示了几个有趣的可能性-空间记忆人类对空间的记忆优于对列表的记忆三维布局可能帮助用户更直观地组织知识。-沉浸式学习在虚拟城市中“漫步”于自己的笔记之间可能激发新的思维连接。-技术栈融合WebGL IndexedDB 现代前端框架可以构建轻量级的 3D 应用。如果你也想尝试可以从上面的代码片段开始逐步添加更多功能——比如笔记之间的“空中走廊”连接线、按主题划分的“街区”区域颜色编码、甚至多人协作的“城市共建”。这只是一个起点三维笔记的世界等待你的探索。

相关新闻

VLC视频转码架构深度解析:如何实现多格式媒体转换的底层机制

VLC视频转码架构深度解析:如何实现多格式媒体转换的底层机制

VLC视频转码架构深度解析:如何实现多格式媒体转换的底层机制 【免费下载链接】vlc VLC media player - plays everything, runs anywhere. Code here: https://code.videolan.org/videolan/vlc 项目地址: https://gitcode.com/gh_mirrors/vl/vlc VLC媒体播放…

2026/10/15 17:34:49 阅读更多 →
统一拦截操作(Filter和interceptor)Filter的实现

统一拦截操作(Filter和interceptor)Filter的实现

tlias中的改动根据字母排序先后执行过滤器

2026/10/2 6:52:32 阅读更多 →
抖音无水印下载神器:从零开始高效管理你的视频素材库

抖音无水印下载神器:从零开始高效管理你的视频素材库

抖音无水印下载神器:从零开始高效管理你的视频素材库 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback suppor…

2026/10/10 7:30:44 阅读更多 →

最新新闻

迪文串口TFT屏通用驱动程序:从协议解析到多屏适配

迪文串口TFT屏通用驱动程序:从协议解析到多屏适配

简介:这份资源是面向AVR平台开发者的迪文串口TFT屏通用驱动程序,用标准C语言编写,帮助嵌入式工程师在工业控制、智能家居、物联网等项目中快速集成迪文显示屏,无需深入硬件细节即可完成图形与文本显示。压缩包为rar格式&#xff0…

2026/10/15 17:34:53 阅读更多 →
精度是“筛”出来的:源头厂商的逐片出厂关

精度是“筛”出来的:源头厂商的逐片出厂关

管网和窖井里的液位计,大概是城市里最“够不着”的电子设备之一。装进去的那一刻起,它就进入了长期无人值守的状态。想检查它一眼,要先下井,或者封路开盖。一次现场维护的综合代价,往往超过设备本身。所以在液位监测这…

2026/10/15 17:34:53 阅读更多 →
FPGA静态时序分析从入门到实战:约束编写、报告解读与优化技巧

FPGA静态时序分析从入门到实战:约束编写、报告解读与优化技巧

1. 为什么静态时序分析是FPGA开发的必修课 做FPGA开发的人都有一个共识:代码写完了,仿真跑通了,下载到板子上却跑不起来,十有八九是时序问题。而静态时序分析(Static Timing Analysis,简称STA)就…

2026/10/15 17:34:53 阅读更多 →
vLLM-Ascend 大规模专家并行(Large-Scale EP)下的分布式 DP Server 部署指南:PD 分离、多节点环境验证与负载均衡代理

vLLM-Ascend 大规模专家并行(Large-Scale EP)下的分布式 DP Server 部署指南:PD 分离、多节点环境验证与负载均衡代理

人工智能大模型模型推理服务AscendCANN 【免费下载链接】vllm-ascend Community maintained hardware plugin for vLLM on Huawei Ascend 项目地址: https://gitcode.com/gh_mirrors/vl/vllm-ascend 点击查看 免费下载 导读 本文档聚焦 vLLM-Ascend 在大规模 Expe…

2026/10/15 17:34:53 阅读更多 →
迷宫寻宝算法实战:BFS最短路径与状态压缩技巧详解

迷宫寻宝算法实战:BFS最短路径与状态压缩技巧详解

1. 迷宫寻宝类问题的整体解题思路拆解迷宫寻宝这个题型在算法竞赛里出现的频率相当高,几乎每一本算法入门教材都会把它当作搜索算法的经典案例。它的核心设定通常是这样的:给定一个二维网格,网格里有起点、终点、墙壁、通道,可能还…

2026/10/15 17:34:53 阅读更多 →
COMSOL热传导仿真全流程:从方程设定到网格与边界排查

COMSOL热传导仿真全流程:从方程设定到网格与边界排查

简介:COMSOL是一款功能强大的多物理场仿真软件,在热传导领域应用十分广泛。这份docx文档以“一维固体中的热传导”为例,完整演示了如何通过COMSOL的PDE模块求解热传导方程。文档涵盖物理场添加、瞬态研究设置、几何与边界条件配置&#xff0c…

2026/10/15 17:33:53 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →