当前位置: 首页 > article >正文

JavaScript系列(46)-- WebGL图形编程详解

JavaScript WebGL图形编程详解 🎨

今天,让我们深入探讨JavaScript的WebGL图形编程。WebGL是一种基于OpenGL ES的JavaScript API,它允许我们在浏览器中渲染高性能的2D和3D图形。

WebGL基础概念 🌟

💡 小知识:WebGL直接与GPU通信,使用GLSL着色器语言编写顶点和片段着色器。它提供了底层的图形API,让我们能够充分利用硬件加速进行图形渲染。

基本实现 📊

// 1. WebGL上下文初始化
class WebGLContext {constructor(canvas) {this.canvas = canvas;this.gl = canvas.getContext('webgl2') || canvas.getContext('webgl');if (!this.gl) {throw new Error('WebGL not supported');}// 初始化基本设置this.gl.clearColor(0.0, 0.0, 0.0, 1.0);this.gl.enable(this.gl.DEPTH_TEST);this.gl.enable(this.gl.CULL_FACE);this.gl.viewport(0, 0, canvas.width, canvas.height);}// 清除画布clear() {this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);}// 设置视口setViewport(width, height) {this.canvas.width = width;this.canvas.height = height;this.gl.viewport(0, 0, width, height);}
}// 2. 着色器程序管理
class ShaderProgram {constructor(gl, vertexSource, fragmentSource) {this.gl = gl;this.program = this.createProgram(vertexSource, fragmentSource);this.attributes = this.getAttributes();this.uniforms = this.getUniforms();}// 创建着色器程序createProgram(vertexSource, fragmentSource) {const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);const program = this.gl.createProgram();this.gl.attachShader(program, vertexShader);this.gl.attachShader(program, fragmentShader);this.gl.linkProgram(program);if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {throw new Error('Failed to link shader program');}return program;}// 创建着色器createShader(type, source) {const shader = this.gl.createShader(type);this.gl.shaderSource(shader, source);this.gl.compileShader(shader);if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {throw new Error(`Failed to compile shader: ${this.gl.getShaderInfoLog(shader)}`);}return shader;}// 获取所有属性位置getAttributes() {const attributes = {};const count = this.gl.getProgramParameter(this.program, this.gl.ACTIVE_ATTRIBUTES);for (let i = 0; i < count; i++) {const info = this.gl.getActiveAttrib(this.program, i);attributes[info.name] = this.gl.getAttribLocation(this.program, info.name);}return attributes;}// 获取所有统一变量位置getUniforms() {const uniforms = {};const count = this.gl.getProgramParameter(this.program, this.gl.ACTIVE_UNIFORMS);for (let i = 0; i < count; i++) {const info = this.gl.getActiveUniform(this.program, i);uniforms[info.name] = this.gl.getUniformLocation(this.program, info.name);}return uniforms;}// 使用程序use() {this.gl.useProgram(this.program);}
}// 3. 几何体管理
class Geometry {constructor(gl) {this.gl = gl;this.vao = this.gl.createVertexArray();this.buffers = new Map();}// 创建缓冲区createBuffer(name, data, target = this.gl.ARRAY_BUFFER) {const buffer = this.gl.createBuffer();this.gl.bindBuffer(target, buffer);this.gl.bufferData(target, data, this.gl.STATIC_DRAW);this.buffers.set(name, { buffer, target });}// 设置顶点属性setAttribute(location, size, type, normalized = false, stride = 0, offset = 0) {this.gl.vertexAttribPointer(location, size, type, normalized, stride, offset);this.gl.enableVertexAttribArray(location);}// 绑定几何体bind() {this.gl.bindVertexArray(this.vao);}// 解绑几何体unbind() {this.gl.bindVertexArray(null);}
}

高级功能实现 🚀

// 1. 矩阵变换
class Transform {constructor() {this.position = vec3.create();this.rotation = quat.create();this.scale = vec3.fromValues(1, 1, 1);this.matrix = mat4.create();}// 更新变换矩阵updateMatrix() {mat4.fromRotationTranslationScale(this.matrix,this.rotation,this.position,this.scale);return this.matrix;}// 设置位置setPosition(x, y, z) {vec3.set(this.position, x, y, z);return this;}// 设置旋转setRotation(x, y, z) {quat.fromEuler(this.rotation, x, y, z);return this;}// 设置缩放setScale(x, y, z) {vec3.set(this.scale, x, y, z);return this;}
}// 2. 相机系统
class Camera {constructor() {this.position = vec3.create();this.target = vec3.create();this.up = vec3.fromValues(0, 1, 0);this.viewMatrix = mat4.create();this.projectionMatrix = mat4.create();}// 更新视图矩阵updateViewMatrix() {mat4.lookAt(this.viewMatrix, this.position, this.target, this.up);return this.viewMatrix;}// 设置透视投影setPerspective(fov, aspect, near, far) {mat4.perspective(this.projectionMatrix, fov, aspect, near, far);return this;}// 设置正交投影setOrthographic(left, right, bottom, top, near, far) {mat4.ortho(this.projectionMatrix, left, right, bottom, top, near, far);return this;}
}// 3. 材质系统
class Material {constructor(gl, shader) {this.gl = gl;this.shader = shader;this.uniforms = new Map();}// 设置统一变量setUniform(name, value) {this.uniforms.set(name, value);return this;}// 应用材质apply() {this.shader.use();for (const [name, value] of this.uniforms) {const location = this.shader.uniforms[name];if (location) {this.setUniformValue(location, value);}}}// 设置统一变量值setUniformValue(location, value) {if (Array.isArray(value)) {switch (value.length) {case 2:this.gl.uniform2fv(location, value);break;case 3:this.gl.uniform3fv(location, value);break;case 4:this.gl.uniform4fv(location, value);break;case 16:this.gl.uniformMatrix4fv(location, false, value);break;}} else if (typeof value === 'number') {this.gl.uniform1f(location, value);} else if (value instanceof WebGLTexture) {this.gl.uniform1i(location, 0);this.gl.activeTexture(this.gl.TEXTURE0);this.gl.bindTexture(this.gl.TEXTURE_2D, value);}}
}

实际应用场景 💼

// 1. 3D场景渲染
class Scene {constructor(gl) {this.gl = gl;this.objects = new Set();this.camera = new Camera();}// 添加对象add(object) {this.objects.add(object);}// 移除对象remove(object) {this.objects.delete(object);}// 渲染场景render() {this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);const viewProjection = mat4.create();mat4.multiply(viewProjection,this.camera.projectionMatrix,this.camera.viewMatrix);for (const object of this.objects) {object.render(viewProjection);}}
}// 2. 粒子系统
class ParticleSystem {constructor(gl, maxParticles) {this.gl = gl;this.maxParticles = maxParticles;this.particles = [];this.geometry = this.createParticleGeometry();this.shader = this.createParticleShader();}// 创建粒子几何体createParticleGeometry() {const positions = new Float32Array(this.maxParticles * 3);const colors = new Float32Array(this.maxParticles * 4);const sizes = new Float32Array(this.maxParticles);const geometry = new Geometry(this.gl);geometry.createBuffer('position', positions);geometry.createBuffer('color', colors);geometry.createBuffer('size', sizes);return geometry;}// 更新粒子update(deltaTime) {for (const particle of this.particles) {particle.life -= deltaTime;if (particle.life <= 0) {this.resetParticle(particle);} else {particle.position[0] += particle.velocity[0] * deltaTime;particle.position[1] += particle.velocity[1] * deltaTime;particle.position[2] += particle.velocity[2] * deltaTime;}}this.updateGeometry();}// 渲染粒子render(viewProjection) {this.shader.use();this.shader.setUniform('viewProjection', viewProjection);this.geometry.bind();this.gl.drawArrays(this.gl.POINTS, 0, this.particles.length);this.geometry.unbind();}
}// 3. 后处理效果
class PostProcessor {constructor(gl) {this.gl = gl;this.framebuffer = this.createFramebuffer();this.shader = this.createPostProcessShader();this.quad = this.createScreenQuad();}// 创建帧缓冲区createFramebuffer() {const framebuffer = this.gl.createFramebuffer();this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);// 创建纹理附件const texture = this.gl.createTexture();this.gl.bindTexture(this.gl.TEXTURE_2D, texture);this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA,this.gl.canvas.width, this.gl.canvas.height,0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR);this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR);// 附加纹理this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER,this.gl.COLOR_ATTACHMENT0,this.gl.TEXTURE_2D,texture,0);return {framebuffer,texture};}// 应用后处理效果apply(scene) {// 渲染场景到帧缓冲区this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer.framebuffer);scene.render();// 渲染后处理效果到屏幕this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);this.shader.use();this.gl.activeTexture(this.gl.TEXTURE0);this.gl.bindTexture(this.gl.TEXTURE_2D, this.framebuffer.texture);this.quad.bind();this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);this.quad.unbind();}
}

性能优化技巧 ⚡

// 1. 实例化渲染
class InstancedRenderer {constructor(gl, geometry, maxInstances) {this.gl = gl;this.geometry = geometry;this.maxInstances = maxInstances;this.setupInstancedBuffers();}// 设置实例化缓冲区setupInstancedBuffers() {const matrices = new Float32Array(this.maxInstances * 16);const colors = new Float32Array(this.maxInstances * 4);// 创建矩阵缓冲区const matrixBuffer = this.gl.createBuffer();this.gl.bindBuffer(this.gl.ARRAY_BUFFER, matrixBuffer);this.gl.bufferData(this.gl.ARRAY_BUFFER, matrices, this.gl.DYNAMIC_DRAW);// 设置矩阵属性for (let i = 0; i < 4; i++) {const location = this.geometry.shader.attributes[`instanceMatrix${i}`];this.gl.enableVertexAttribArray(location);this.gl.vertexAttribPointer(location, 4, this.gl.FLOAT, false,64, i * 16);this.gl.vertexAttribDivisor(location, 1);}// 创建颜色缓冲区const colorBuffer = this.gl.createBuffer();this.gl.bindBuffer(this.gl.ARRAY_BUFFER, colorBuffer);this.gl.bufferData(this.gl.ARRAY_BUFFER, colors, this.gl.DYNAMIC_DRAW);const colorLocation = this.geometry.shader.attributes.instanceColor;this.gl.enableVertexAttribArray(colorLocation);this.gl.vertexAttribPointer(colorLocation, 4, this.gl.FLOAT, false,0, 0);this.gl.vertexAttribDivisor(colorLocation, 1);}// 更新实例数据updateInstances(matrices, colors) {this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.matrixBuffer);this.gl.bufferSubData(this.gl.ARRAY_BUFFER, 0, matrices);this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.colorBuffer);this.gl.bufferSubData(this.gl.ARRAY_BUFFER, 0, colors);}// 渲染实例render(instanceCount) {this.geometry.bind();this.gl.drawArraysInstanced(this.gl.TRIANGLES,0,this.geometry.vertexCount,instanceCount);this.geometry.unbind();}
}// 2. 批处理渲染
class BatchRenderer {constructor(gl, maxBatchSize) {this.gl = gl;this.maxBatchSize = maxBatchSize;this.batch = [];}// 添加到批处理add(object) {if (this.batch.length >= this.maxBatchSize) {this.flush();}this.batch.push(object);}// 刷新批处理flush() {if (this.batch.length === 0) return;// 合并几何体数据const vertices = [];const indices = [];let indexOffset = 0;for (const object of this.batch) {vertices.push(...object.vertices);indices.push(...object.indices.map(i => i + indexOffset));indexOffset += object.vertices.length / 3;}// 更新缓冲区this.updateBuffers(vertices, indices);// 渲染批处理this.render();// 清空批处理this.batch.length = 0;}
}// 3. 视锥体剔除
class Frustum {constructor() {this.planes = new Array(6);for (let i = 0; i < 6; i++) {this.planes[i] = vec4.create();}}// 从投影视图矩阵更新视锥体updateFromMatrix(matrix) {// 提取平面for (let i = 0; i < 6; i++) {const plane = this.planes[i];const row = Math.floor(i / 2);const sign = i % 2 === 0 ? 1 : -1;vec4.set(plane,matrix[3] + sign * matrix[row],matrix[7] + sign * matrix[row + 4],matrix[11] + sign * matrix[row + 8],matrix[15] + sign * matrix[row + 12]);vec4.normalize(plane, plane);}}// 检查点是否在视锥体内containsPoint(point) {for (const plane of this.planes) {if (vec4.dot(plane, [...point, 1]) < 0) {return false;}}return true;}// 检查包围球是否在视锥体内containsSphere(center, radius) {for (const plane of this.planes) {if (vec4.dot(plane, [...center, 1]) < -radius) {return false;}}return true;}
}

最佳实践建议 💡

  1. 性能优化模式
// 1. 状态管理
class GLState {constructor(gl) {this.gl = gl;this.currentProgram = null;this.currentTexture = null;this.currentVAO = null;}// 使用着色器程序useProgram(program) {if (this.currentProgram !== program) {this.gl.useProgram(program);this.currentProgram = program;}}// 绑定纹理bindTexture(texture) {if (this.currentTexture !== texture) {this.gl.bindTexture(this.gl.TEXTURE_2D, texture);this.currentTexture = texture;}}// 绑定VAObindVAO(vao) {if (this.currentVAO !== vao) {this.gl.bindVertexArray(vao);this.currentVAO = vao;}}
}// 2. 资源管理
class ResourceManager {constructor() {this.resources = new Map();this.loading = new Set();}// 加载资源async load(url, type) {if (this.resources.has(url)) {return this.resources.get(url);}if (this.loading.has(url)) {return new Promise(resolve => {const check = () => {if (this.resources.has(url)) {resolve(this.resources.get(url));} else {requestAnimationFrame(check);}};check();});}this.loading.add(url);try {const resource = await this.loadResource(url, type);this.resources.set(url, resource);this.loading.delete(url);return resource;} catch (error) {this.loading.delete(url);throw error;}}// 释放资源unload(url) {const resource = this.resources.get(url);if (resource) {if (resource.dispose) {resource.dispose();}this.resources.delete(url);}}
}// 3. 渲染队列
class RenderQueue {constructor() {this.opaque = [];this.transparent = [];}// 添加渲染对象add(object) {if (object.material.transparent) {this.transparent.push(object);} else {this.opaque.push(object);}}// 排序渲染队列sort(cameraPosition) {// 不透明物体从前往后排序this.opaque.sort((a, b) => {return a.material.renderOrder - b.material.renderOrder;});// 透明物体从后往前排序this.transparent.sort((a, b) => {const distA = vec3.distance(a.position, cameraPosition);const distB = vec3.distance(b.position, cameraPosition);return distB - distA;});}// 执行渲染render(scene) {// 渲染不透明物体for (const object of this.opaque) {object.render(scene);}// 渲染透明物体this.gl.enable(this.gl.BLEND);this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);for (const object of this.transparent) {object.render(scene);}this.gl.disable(this.gl.BLEND);}
}

结语 📝

WebGL为JavaScript提供了强大的图形渲染能力。通过本文,我们学习了:

  1. WebGL的基本概念和初始化
  2. 着色器程序和几何体管理
  3. 高级渲染技术
  4. 性能优化策略
  5. 最佳实践和设计模式

💡 学习建议:在使用WebGL时,要注意性能优化和内存管理。合理使用批处理和实例化渲染,避免频繁的状态切换。同时,要考虑跨平台兼容性和降级处理。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关文章:

JavaScript系列(46)-- WebGL图形编程详解

JavaScript WebGL图形编程详解 &#x1f3a8; 今天&#xff0c;让我们深入探讨JavaScript的WebGL图形编程。WebGL是一种基于OpenGL ES的JavaScript API&#xff0c;它允许我们在浏览器中渲染高性能的2D和3D图形。 WebGL基础概念 &#x1f31f; &#x1f4a1; 小知识&#xff…...

MySQL(表空间)

​开始前先打开此图配合食用 MySQL表空间| ProcessOn免费在线作图,在线流程图,在线思维导图 InnoDB 空间文件中的页面管理 后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都…...

C26.【C++ Cont】动态内存管理和面向对象的方式实现链表

&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;除夕篇&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8;&#x1f9e8; 目录 1.知识回顾…...

使用numpy自定义数据集 使用tensorflow框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预

1. 引言 逻辑回归&#xff08;Logistic Regression&#xff09;是一种常见的分类算法&#xff0c;广泛应用于二分类问题。在本篇博客中&#xff0c;我们将使用numpy生成一个简单的自定义数据集&#xff0c;并使用TensorFlow框架构建和训练逻辑回归模型。训练完成后&#xff0c…...

Java Web 开发基础介绍

Java学习资料 Java学习资料 Java学习资料 一、引言 在当今数字化时代&#xff0c;Web 应用无处不在。Java 凭借其强大的功能、良好的跨平台性和丰富的开发框架&#xff0c;成为 Web 开发领域的热门选择之一。Java Web 开发允许开发者构建动态、交互式的 Web 应用程序&#x…...

求解旅行商问题的三种精确性建模方法,性能差距巨大

文章目录 旅行商问题介绍三种模型对比求解模型1决策变量目标函数约束条件Python代码 求解模型2决策变量目标函数约束条件Python代码 求解模型3决策变量目标函数约束条件Python代码 三个模型的优势与不足 旅行商问题介绍 旅行商问题 (Traveling Salesman Problem, TSP) 是一个经…...

C++:多继承习题3

题目内容&#xff1a; 声明一个时间类Time&#xff0c;时间类中有3个私有数据成员(Hour&#xff0c;Minute&#xff0c;Second)和两个公有成员函数(SetTime和PrintTime)。要求&#xff1a; &#xff08;1&#xff09; SetTime根据传递的3个参数为对象设置时间&#xff1b; &a…...

低代码系统-产品架构案例介绍、得帆云(八)

产品名称 得帆云DeCode低代码平台-私有化 得帆云DeMDM主数据管理平台 得帆云DeCode低代码平台-公有云 得帆云DePortal企业门户 得帆云DeFusion融合集成平台 得帆云DeHoop数据中台 名词 概念 云原生 指自己搭建的运维平台&#xff0c;区别于阿里云、腾讯云 Dehoop 指…...

python Flask-Redis 连接远程redis

当使用Flask-Redis连接远程Redis时&#xff0c;首先需要安装Flask-Redis库。可以通过以下命令进行安装&#xff1a; pip install Flask-Redis然后&#xff0c;你可以使用以下示例代码连接远程Redis&#xff1a; from flask import Flask from flask_redis import FlaskRedisa…...

【Unity3D】实现Decal贴花效果,模拟战旗游戏地形效果

目录 一、基础版 二、Post Process 辉光Bloom效果 矩形渐隐 涉及知识点&#xff1a;Decal贴花、屏幕后处理Bloom、屏幕空间构建世界空间、ChracterController物体移动、Terrain地形创建 一、基础版 Unity 2019.4.0f1 普通渲染管线&#xff08;非URP、非HDRP&#xff09; UR…...

实践网络安全:常见威胁与应对策略详解

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在数字化转型的浪潮中&#xff0c;网络安全的重要性已达到前所未有的高度。无论是个人用户、企业&#xff0c;还是政府机构…...

《 C++ 点滴漫谈: 二十四 》深入 C++ 变量与类型的世界:高性能编程的根基

摘要 本文深入探讨了 C 中变量与类型的方方面面&#xff0c;包括变量的基本概念、基本与复合数据类型、动态类型与内存管理、类型推导与模板支持&#xff0c;以及类型系统的高级特性。通过全面的理论讲解与实际案例分析&#xff0c;展示了 C 类型系统的强大灵活性与实践价值。…...

UART、I2C和SPI对比

UARTSPII2C英文Universal Asynchronous Receive/TransmitSerial Peripheral InterfaceInner Integrated Communication通讯速度115200、38400 bit/s高达100M bit/s 100k、400k、1M、3.4M bit/s时钟同/异步性时钟异步时钟同步时钟同步接线方式3线(Rx、Tx、GND) 4线(MISO、…...

开源项目Umami网站统计MySQL8.0版本Docker+Linux安装部署教程

Umami是什么&#xff1f; Umami是一个开源项目&#xff0c;简单、快速、专注用户隐私的网站统计项目。 下面来介绍如何本地安装部署Umami项目&#xff0c;进行你的网站统计接入。特别对于首次使用docker的萌新有非常好的指导、参考和帮助作用。 Umami的github和docker镜像地…...

C# INotifyPropertyChanged接口在list类型中的应用

我们在项目开发时遇到监听List<T>中成员的值发生变化。我们一般使用INotifyPropertyChanged...

KIMI K1.5:用大语言模型扩展强化学习(论文翻译)

文章目录 KIMI K1.5技术报告摘要 1. 引言2. 方法&#xff1a;基于大语言模型的强化学习2.1 强化学习提示集整理2.2 长思维链监督微调2.3 强化学习2.3.1 问题设定2.3.2 策略优化2.3.3 长度惩罚2.3.4 采样策略2.3.5 训练方法的更多细节 2.4 长到短&#xff1a;短思维链模型的上下…...

Kiwi 安卓浏览器本月停止维护,扩展功能迁移至 Edge Canary

IT之家 1 月 25 日消息&#xff0c;科技媒体 Android Authority 今天&#xff08;1 月 25 日&#xff09;发布博文&#xff0c;报道称 Kiwi 安卓浏览器将于本月停止维护&#xff0c;相关扩展支持功能已整合到微软 Edge Canary 浏览器中。 开发者 Arnaud42 表示 Kiwi 安卓浏览器…...

思科交换机telnet配置案例

目录 1.telnet简述2.网络拓扑3.设备说明4.网络配置4.1 电脑PC ip设置4.2 网络交换机telnet配置 5.小结 1.telnet简述 Telnet是远程登录服务的一个协议&#xff0c;该协议定义了远程登录用户与服务器交互的方式。它允许用户在一台联网的计算机上登录到一个远程分时系统中&#…...

计算机毕业设计Django+Tensorflow音乐推荐系统 机器学习 深度学习 音乐可视化 音乐爬虫 知识图谱 混合神经网络推荐算法 大数据毕设

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

基于蓝牙6.0的RSSI和UWB融合定位方法,可行性分析

融合RSSI&#xff08;接收信号强度指示&#xff09;和UWB&#xff08;超宽带&#xff09;两种技术进行蓝牙6.0定位是完全可行的&#xff0c;并且可以带来更高的定位精度和稳定性。本文给出分析和MATLAB仿真结果 文章目录 技术优势RSSIUWB融合的优势 实现方案数据融合算法硬件要…...

【开源免费】基于Vue和SpringBoot的在线文档管理系统(附论文)

本文项目编号 T 038 &#xff0c;文末自助获取源码 \color{red}{T038&#xff0c;文末自助获取源码} T038&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…...

【Elasticsearch】 索引模板 ignore_missing_component_templates

解释 ignore_missing_component_templates 配置 在Elasticsearch中&#xff0c;ignore_missing_component_templates 是一个配置选项&#xff0c;用于处理索引模板中引用的组件模板可能不存在的情况。当您创建一个索引模板时&#xff0c;可以指定一个或多个组件模板&#xff0…...

AI DeepSeek

DeepSeek 文字解析 上传图片解析 视乎结果出入很大啊&#xff0c;或许我们应该描述更加清楚自己的需求。...

QT使用eigen

QT使用eigen 1. 下载eigen https://eigen.tuxfamily.org/index.php?titleMain_Page#Download 下载后解压 2. QT引入eigen eigen源码好像只有头文件&#xff0c;因此只需要引入头文件就好了 qt新建项目后。修改pro文件. INCLUDEPATH E:\222078\qt\eigen-3.4.0\eigen-3.…...

C#面试常考随笔6:ArrayList和 List的主要区别?

在 C# 中&#xff0c;ArrayList和List<T>&#xff08;泛型列表&#xff09;都可用于存储一组对象。推荐优先使用List<T>&#xff0c;因为它具有更好的类型安全性、性能和语法简洁性&#xff0c;并且提供了更丰富的功能。只有在需要与旧代码兼容或存储不同类型对象的…...

mysql学习笔记-数据库其他调优策略

1、如何定位调优问题 用户的反馈&#xff08;主要&#xff09; 日志分析&#xff08;主要&#xff09; 服务器资源使用监控 数据库内部状况监控 2、调优的维度和步骤 第1步&#xff1a;选择适合的 DBMS 第2步&#xff1a;优化表设计 第3步&#xff1a;优化逻辑查询 第4步&am…...

HTB:Forest[WriteUP]

连接至HTB服务器并启动靶机 分配IP&#xff1a;10.10.16.21 靶机IP&#xff1a;10.10.10.161 靶机Domain&#xff1a;forest.htb 目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端…...

实验七 带函数查询和综合查询(2)

1 检索至少选修课程“数据结构”和“C语言”的学生学号 方法一&#xff1a; select Stu_id from StudentGrade,Course where Course.Course_idStudentGrade.Course_id and Course_name‘数据结构’ and Stu_id in (select Stu_id from StudentGrade,Course where Course.Course…...

Bootloader升级功能实现:从理论到工程实践

Bootloader升级功能实现:从原理到工程实践 目录 Bootloader升级功能实现:从原理到工程实践引言1. Bootloader架构解析1.1 分层架构设计1.2 典型启动流程2. 关键设计要素2.1 内存分区规划2.2 看门狗管理策略3. 通信协议实现3.1 基于UDS的升级协议3.2 报文格式规范4. 六大典型案…...

物业软件推动物业行业数字化转型 实现高效管理和优质客户体验

内容概要 在当今高速发展的数字化时代&#xff0c;物业软件的出现不仅使物业管理变得更加高效&#xff0c;也为行业转型提供了强大的支持。通过整合多种功能&#xff0c;物业软件显著提升了管理效率和客户体验。例如&#xff0c;在线收费和停车管理功能&#xff0c;让业主享受…...