WebGL 3D 方向性光照:从点积、法线到逆转置矩阵的完整实战
图形学【免费下载链接】webgl-fundamentalsWebGL lessons that start with the basics项目地址https://gitcode.com/gh_mirrors/we/webgl-fundamentals点击查看免费下载方向性光照是 3D 图形中最简单的灯光模型——假设光从某个固定方向平行射入如晴天的太阳只需计算光方向与表面法线的点积就能得到每一点的明暗。本文基于 webgl-fundamentals 仓库中的方向性光照教程韩文版与其配套示例代码展开从点积原理、法线数据结构到顶点/片元着色器实现再到用世界矩阵与逆转置矩阵修正光照的两个经典陷阱完整走一遍可运行的实现链路。读完后你将能够独立为任意 3D 物体实现方向性光照并理解为什么法线变换必须用worldInverseTranspose而不能直接用世界矩阵。1. 方向性光照的原理一个点积就够光照的实现方式有很多种其中方向性光照directional lighting大概是最简单的一种。它的假设是光线从一个方向均匀地射入场景。晴朗天气的太阳通常被视为方向性光——因为它离物体足够远光线照射物体表面时可以近似看作全部平行。计算方向性光照实际上非常简单只要知道光线的传播方向又知道物体表面的朝向对这两个方向做点积dot product就能得到它们之间夹角的余弦值。仓库为这一节提供了两个可交互的演示页面建议在浏览器中打开体验点积演示拖动两点观察点积变化方向性光照演示旋转方向向量直观看到明暗如何随夹角变化。点积的取值规则针对单位向量两个向量的相对方向点积结果完全相反-1垂直0完全相同1把它用到了表面上当你知道 3D 物体表面的朝向和光照方向求出两者的点积就会得到这样一个标量——表面正对光时给出 1正背对光时给出 -1。然后只要用这个标量去乘颜色光照就做出来了。2. 法线Normal描述表面朝向的单位向量上面的思路引出一个问题3D 物体表面的朝向怎么表示答案是法线。法线一词来自拉丁语norma直角规和直角规一样法线与线或表面成直角。在 3D 图形中法线是描述表面朝向的单位向量。仓库中有一个专门的法线可视化页面同时展示立方体与球体的法线从物体表面向外伸出的短线即各顶点的法线并按方向着色x 为红、y 为绿、z 为蓝。这里有一个容易踩坑的细节立方体每个角上会有 3 个法线因为立方体的每个面朝向不同方向每个面都需要自己的法线。这也意味着带光照的模型往往需要按面拆分顶点每个顶点绑定所在面的法线这正是后面F 几何数据的设计方式。2.1 为示例几何F编写法线数据教程在前一篇文章WebGL 3D 相机的F模型基础上加光照。由于F是盒状结构、各面都与 x、y、z 轴对齐法线非常好写朝向前方的面法线0, 0, 1朝向后方的面法线0, 0, -1朝向左侧的面法线-1, 0, 0朝向右侧的面法线1, 0, 0上表面0, 1, 0下表面0, -1, 0完整的法线数据函数如下与示例 webgl-3d-lighting-directional.html 中setNormals完全一致注意法线数组的顺序必须与位置数组的面顺序一一对应每个三角形 6 个顶点、每面 6 个法线function setNormals(gl) { var normals new Float32Array([ // 左列前方 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // 上横档前方 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // 中横档前方 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // 左列后方 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, // 上横档后方 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, // 中横档后方 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, // 顶面 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // 上横档右侧 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // 上横档下方 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, // 上横档与中横档之间 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // 中横档顶面 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // 中横档右侧 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // 中横档底面 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, // 底部右侧 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // 底面 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, // 左侧面 -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0 ]); gl.bufferData(gl.ARRAY_BUFFER, normals, gl.STATIC_DRAW); }3. 把法线送上 GPU顶点属性替换与绑定教程把原先的顶点颜色属性替换为法线属性去掉颜色是为了让光照效果更明显。对应的 JS 改动是查找属性位置、创建并绑定法线缓冲区。// 查找顶点数据要放的位置 var positionLocation gl.getAttribLocation(program, a_position); -var colorLocation gl.getAttribLocation(program, a_color); var normalLocation gl.getAttribLocation(program, a_normal); ... -// 创建存放颜色的缓冲区 -var colorBuffer gl.createBuffer(); -// 绑定到 ARRAY_BUFFERARRAY_BUFFER colorBuffer -gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); -// 把几何数据写入缓冲区 -setColors(gl); // 创建存放法线的缓冲区 var normalBuffer gl.createBuffer(); // 绑定到 ARRAY_BUFFERARRAY_BUFFER normalBuffer gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer); // 把法线数据写入缓冲区 setNormals(gl);渲染循环中的属性启用与指针设置如下注意与颜色属性不同的三个参数法线是gl.FLOAT每分量 32 位浮点数且normalize为false因为数据本身已经是单位向量-// 启用颜色属性 -gl.enableVertexAttribArray(colorLocation); - -// 绑定颜色缓冲区 -gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); - -// 告诉属性如何从 colorBuffer(ARRAY_BUFFER) 读取数据 -var size 3; // 每次迭代 3 个分量 -var type gl.UNSIGNED_BYTE; // 数据是无符号 8 位值 -var normalize true; // 归一化数据0-255 转 0-1 -var stride 0; // 0 每次迭代前进 size * sizeof(type) 个字节 -var offset 0; // 从缓冲区开头开始 -gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset) // 启用法线属性 gl.enableVertexAttribArray(normalLocation); // 绑定法线缓冲区 gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer); // 告诉属性如何从 normalBuffer(ARRAY_BUFFER) 读取数据 var size 3; // 每次迭代 3 个分量 var type gl.FLOAT; // 数据是 32 位浮点数 var normalize false; // 不归一化数据数据已经是单位向量 var stride 0; // 0 每次迭代前进 size * sizeof(type) 个字节 var offset 0; // 从缓冲区开头开始 gl.vertexAttribPointer(normalLocation, size, type, normalize, stride, offset)这段代码在完整示例 webgl-3d-lighting-directional.html 中可以原样找到含位置属性的对应设置以及开启gl.DEPTH_TEST与gl.CULL_FACE的完整绘制流程。4. 着色器实现传递法线并计算光照4.1 顶点着色器把法线传递给片元着色器attribute vec4 a_position; -attribute vec4 a_color; attribute vec3 a_normal; uniform mat4 u_matrix; -varying vec4 v_color; varying vec3 v_normal; void main() { // 位置乘以矩阵 gl_Position u_matrix * a_position; - // 把颜色传给片元着色器 - v_color a_color; // 把法线传给片元着色器 v_normal a_normal; }4.2 片元着色器核心就三行precision mediump float; // 由顶点着色器传入 -varying vec4 v_color; varying vec3 v_normal; uniform vec3 u_reverseLightDirection; uniform vec4 u_color; void main() { // v_normal 是 varying会被插值因此不再是单位向量。 // 归一化后重新变回单位向量。 vec3 normal normalize(v_normal); float light dot(normal, u_reverseLightDirection); * gl_FragColor u_color; // 只把光强乘到颜色的 rgb 分量上不乘 alpha gl_FragColor.rgb * light; }两个关键细节normalize(v_normal)不可省略。varying变量在三角形内部被逐像素插值插值结果一般不再是单位向量而dot()得到夹角余弦的前提是两个单位向量。只乘rgb不乘alphagl_FragColor.rgb * light否则透明通道也会被照亮混合结果会跑偏。4.3 查找并设置 Uniform// 查找 uniform var matrixLocation gl.getUniformLocation(program, u_matrix); var colorLocation gl.getUniformLocation(program, u_color); var reverseLightDirectionLocation gl.getUniformLocation(program, u_reverseLightDirection);// 设置矩阵 gl.uniformMatrix4fv(matrixLocation, false, worldViewProjectionMatrix); // 设置要用的颜色 gl.uniform4fv(colorLocation, [0.2, 1, 0.2, 1]); // 绿色 // 设置光的方向 gl.uniform3fv(reverseLightDirectionLocation, m4.normalize([0.5, 0.7, 1]));关于u_reverseLightDirection的语义值得展开这是本教程命名里最容易误解的一点这里传入的是**从物体指向光源的方向**即光照传播方向的反方向而不是光线行进方向。之所以这样取是因为dot(normal, lightDir)在法线正对光源时取最大值 1。示例中先给[0.5, 0.7, 1]再经m4.normalize归一化。m4.normalize的实现见 m4.js#L200-L210先求长度长度大于0.00001时才逐分量除以长度避免零向量除零。各分量含义x 0.5正值表示光源在右侧、指向左方y 0.7正值表示光源在上方、指向下方z 1正值表示光源在前方、指向场景内部。相对大小意味着光整体指向场景、且比指向右方更强烈地指向下方。运行效果对应示例 webgl-3d-lighting-directional.html页面上有一个滑动条可以绕 y 轴旋转FfRotation取值 -360 ~ 360 度着色器与矩阵逻辑位于 该文件的 L22-L62 与 L183-L220。旋转一下F你会发现一个明显的问题F 在转但光照纹丝不动——因为法线还停留在模型局部空间没有被世界变换带动。5. 让光照跟随旋转法线乘以世界矩阵修法是当物体方向改变时同时改变法线的方向。和位置一样法线也可以乘一个矩阵最直接的矩阵就是world世界矩阵。目前着色器只接收一个矩阵u_matrix实为 worldViewProjection需要改成传两个u_world是世界矩阵u_worldViewProjection是原来u_matrix里的那一个。attribute vec4 a_position; attribute vec3 a_normal; *uniform mat4 u_worldViewProjection; uniform mat4 u_world; varying vec3 v_normal; void main() { // 位置乘以矩阵 * gl_Position u_worldViewProjection * a_position; * // 设定法线方向并传给片元着色器 * v_normal mat3(u_world) * a_normal; }注意这里用mat3(u_world) * a_normal而不是完整 4x4 矩阵法线是方向不参与平移而行列式中与平移相关的部分在 4x4 矩阵的最后一列方向变换只需要 3x3 的旋转/缩放部分。JS 侧相应地查找并设置两个矩阵 uniform// 查找 uniform *var worldViewProjectionLocation * gl.getUniformLocation(program, u_worldViewProjection); var worldLocation gl.getUniformLocation(program, u_world);*// 设置矩阵 *gl.uniformMatrix4fv( * worldViewProjectionLocation, false, worldViewProjectionMatrix); *gl.uniformMatrix4fv(worldLocation, false, worldMatrix);对应示例 webgl-3d-lighting-directional-world.html。该文件中世界矩阵由滑块驱动的绕 y 轴旋转生成m4.yRotation(fRotationRadians)见 L204-L213旋转F即可看到现在朝向光的那一面始终最亮光照正确跟随了物体的旋转。6. 为什么缩放会破坏法线逆转置矩阵登场用u_world变换法线还有一个隐患仓库提供了交互演示 normals-scaled.html 来展示点击可切换不同变换方式紫色球不改变大小基准红色球左改变了大小法线用world矩阵乘蓝色球右改变了大小法线用worldInverseTranspose逆转置矩阵乘。问题当 world 矩阵包含缩放时直接用它变换法线会得到错误的法线——法线不再垂直于缩放后的表面。把缩放调到极端时对比非常明显左侧world的法线歪离球面右侧worldInverseTranspose的法线始终垂直于球面。最后一个对比模式把三个球都渲染成带光照的样子可以看到两种矩阵下外部两个球的明暗差异巨大。解法取 world 矩阵的逆矩阵再对它做转置inverse transpose用这个矩阵变换法线就正确了。6.1 着色器改动attribute vec4 a_position; attribute vec3 a_normal; uniform mat4 u_worldViewProjection; *uniform mat4 u_worldInverseTranspose; varying vec3 v_normal; void main() { // 位置乘以矩阵 gl_Position u_worldViewProjection * a_position; // 设定法线方向并传给片元着色器 * v_normal mat3(u_worldInverseTranspose) * a_normal; }教程原文特意说明技术上也可以只更新u_world的值但把 uniform 改名为真实含义的u_worldInverseTranspose更不容易混淆。6.2 JS 侧求逆、转置、上传var worldViewProjectionMatrix m4.multiply(viewProjectionMatrix, worldMatrix); var worldInverseMatrix m4.inverse(worldMatrix); var worldInverseTransposeMatrix m4.transpose(worldInverseMatrix); // 设置矩阵 gl.uniformMatrix4fv( worldViewProjectionLocation, false, worldViewProjectionMatrix); -gl.uniformMatrix4fv( - worldLocation, false, worldMatrix); gl.uniformMatrix4fv( worldInverseTransposeLocation, false, worldInverseTransposeMatrix);uniform 查找处同步替换-var worldLocation gl.getUniformLocation(program, u_world); var worldInverseTransposeLocation gl.getUniformLocation(program, u_worldInverseTranspose);6.3 源码印证m4 库里的转置与求逆上面的m4.transpose在仓库矩阵库中的实现m4.js#L317-L336与教程中给出的行转列逻辑一致采用列主序column-major存储的 16 元素数组function transpose(m, dst) { dst[ 0] m[0]; dst[ 1] m[4]; dst[ 2] m[8]; dst[ 3] m[12]; dst[ 4] m[1]; dst[ 5] m[5]; // ... 依此类推行列互换 dst[15] m[15]; return dst; }对应的inverse实现在 m4.js#L1215。此外从源码结构看m4 库还提供了 transformNormal 函数它内部先用inverse(m)求逆再只取逆矩阵的 3x3 部分第 0、4、8、1、5、9、2、6、10 个元素与法线相乘注释明确说明效果等同于用 m 的逆转置把 v 作为方向变换——这进一步印证了逆转置就是法线变换的标准做法而且实际只需 3x3 部分。完整示例见 webgl-3d-lighting-directional-worldinversetranspose.html着色器中 L36 为v_normal mat3(u_worldInverseTranspose) * a_normal;JS 中 L208-L213 依次执行m4.inverse(worldMatrix)→m4.transpose(...)并上传。由于该示例本身没有缩放画面差异很微妙但代码已经对缩放做好了准备。7. 备选写法与工程取舍教程末尾给出了mat3(u_worldInverseTranspose) * a_normal这一行的替代方案值得单独梳理写法一4x4 矩阵 w0v_normal (u_worldInverseTranspose * vec4(a_normal, 0)).xyz;作者认为这更通用因为乘法前把w设为 0矩阵中的平移分量被 0 乘掉、事实上被移除所以无需额外构造 3x3 矩阵。为什么教程仍选择 mat4 而非直接把u_worldInverseTranspose声明为mat3作者给了两条理由u_worldInverseTranspose作为 4x4 整体可能被其他需求复用传完整mat4保留了这种灵活性JavaScript 侧的 m4 库所有矩阵函数都产出 4x4 矩阵专门为 3x3 再维护一套函数、或加一层 4x4→3x3 的转换在没有更充分理由时不值得。8. 小结与下一步把整条链路串起来方向性光照的完整实现包含五步数据为每个顶点提供与面垂直的单位法线setNormals上传法线缓冲区 gl.vertexAttribPointergl.FLOAT、normalizefalse顶点着色器v_normal传递法线并乘mat3(u_worldInverseTranspose)进入世界空间片元着色器normalize(v_normal)抵消插值畸变dot(normal, u_reverseLightDirection)得光强gl_FragColor.rgb * lightJS 侧m4.inversem4.transpose计算并上传逆转置矩阵。两个常见错误——不乘世界矩阵导致光照不随物体旋转、乘了世界矩阵但在缩放时法线失真——分别对应本文第 5、6 节的两处修正。掌握这套基础后下一篇教程点光源Point Lighting会在此基础上引入光源位置概念与距离衰减教程的起点可回顾 WebGL 基础 与 WebGL 3D 相机。赞分享图形学【免费下载链接】webgl-fundamentalsWebGL lessons that start with the basics项目地址https://gitcode.com/gh_mirrors/we/webgl-fundamentals点击查看免费下载相关推荐WebGL 方向光照明实战从点积公式到法线逆转置矩阵的完整实现WebGL 方向光照明实战从点积公式到法线逆转置矩阵的完整实现 本篇技术指南基于 webgl fundamentals 教程中“方向光照明Direction图形学WebGL 3D 指向性光源Directional Lighting完全指南从点积原理到法线矩阵变换WebGL 3D 指向性光源Directional Lighting完全指南从点积原理到法线矩阵变换 本篇是 webgl fundamentals htt图形学WebGL 三维相机逆矩阵视图变换与 lookAt 朝向矩阵实战WebGL 三维相机逆矩阵视图变换与 lookAt 朝向矩阵实战 本篇是 webgl fundamentals 系列教程中讲解三维相机的一课。前文 三维透视投图形学创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

C8051F340 USB编程实例:HID/CDC设备固件开发与常见坑解决

C8051F340 USB编程实例:HID/CDC设备固件开发与常见坑解决

简介:这是一份基于Silicon Labs C8051F340微控制器的USB编程实例,以工程化代码详细解析USB设备开发方法,面向具备一定单片机基础、希望掌握USB通信的嵌入式工程师与学习者,适合数据采集、嵌入式设备与PC互联等场景。实例从USB协议…

2026/10/13 22:51:12 阅读更多 →
Altium Designer复现33个经典电路:从电路图仿真到PCB的完整实战方法

Altium Designer复现33个经典电路:从电路图仿真到PCB的完整实战方法

简介:这套《学习Altium Designer—33个经典电路制作实例》压缩包面向电子爱好者、单片机初学者及硬件开发入门者,用于通过完整实例掌握Altium Designer的原理图设计、PCB布局与仿真流程。压缩包共535个文件,大小约36.3MB,包含33个…

2026/10/13 22:51:12 阅读更多 →
OpenCV Haar级联分类器XML:零训练快速实现人脸与多目标检测

OpenCV Haar级联分类器XML:零训练快速实现人脸与多目标检测

简介:这是一套面向计算机视觉初学者与OpenCV开发者的级联分类器模型集合,主要解决人脸、人眼、鼻子、耳朵、嘴巴、微笑、上身、下半身、全身以及车牌等目标的检测需求,适用于图像识别入门实验、课堂演示与轻量级项目原型开发。压缩包共29个文…

2026/10/13 22:51:12 阅读更多 →

最新新闻

Nmap端口扫描实战:从协议原理到企业级资产测绘

Nmap端口扫描实战:从协议原理到企业级资产测绘

/* 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 1:24:07 阅读更多 →
Proteus仿真实战:从原理图到单片机LED点亮全程指南

Proteus仿真实战:从原理图到单片机LED点亮全程指南

/* 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 1:24:07 阅读更多 →
STM32F407寄存器版ADC双通道DMA采集详解与代码实现

STM32F407寄存器版ADC双通道DMA采集详解与代码实现

/* 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 1:24:07 阅读更多 →
deepseek 的 CED 到底在干什么?——把 Transformer 掰开讲清楚

deepseek 的 CED 到底在干什么?——把 Transformer 掰开讲清楚

deepseek 的 ced 为什么会"自然分化" 目录 deepseek 的 ced 为什么会"自然分化" CED 到底在干什么?——把 Transformer 掰开讲清楚 一、先放结论:一句话版 二、先把普通 Transformer 讲透:每层都在干什么 普通 LLM 的一次推理 这就是 KV cache 吃显存的…

2026/10/14 1:24:07 阅读更多 →
NVLink跨卡原子操作与单调计数器:实现多GPU无锁同步的工程实践

NVLink跨卡原子操作与单调计数器:实现多GPU无锁同步的工程实践

/* 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 1:24:07 阅读更多 →
Kafka 生产环境分区热点倾斜治理:基于 Key 加盐与动态再均衡的高并发解法

Kafka 生产环境分区热点倾斜治理:基于 Key 加盐与动态再均衡的高并发解法

在每年双 11 的大促峰值期,许多负责消息中间件保障的架构师都会遇到一个极具迷惑性的“假象报警”: 打开 Kafka 全局监控大盘,集群整体的 CPU 利用率仅仅只有 35%,网络入网总带宽距离物理网卡上限还有一半以上的富余,看…

2026/10/14 1:23:07 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →