Unity Shader编程】之复杂光照
在Unity Shader的LightMode
标签中,除了前向渲染和延迟渲染外,还支持多种渲染模式设置。以下是主要分类及用途:
一、核心渲染路径模式
-
前向渲染相关
ForwardBase
用于基础光照计算,处理环境光、主平行光、逐顶点/SH光源及光照贴图。ForwardAdd
处理额外逐像素光源,每个Pass对应一个光源(如点光源、聚光灯)。
-
延迟渲染相关
Deferred
用于现代延迟渲染路径,负责将几何数据写入G-Buffer(法线、位置、材质参数等)。
二、辅助功能模式
3. 阴影处理
ShadowCaster
将物体深度信息写入阴影贴图或深度纹理,用于生成动态阴影。
- 遗留模式
PrepassBase
旧版延迟渲染的第一阶段,渲染法线和高光反射的指数部分。PrepassFinal
旧版延迟渲染的最终阶段,合并光照和自发光生成最终颜色。
三、特殊用途模式
5. 无条件渲染
Always
无论当前渲染路径如何,该Pass总被执行,但不参与光照计算(如全屏后处理)。
- 顶点光照模式(已弃用)
Vertex
、VertexLMRGBM
、VertexLM
用于旧版顶点照明渲染路径,Unity 5.0后已废弃。
四、选择建议
- 多光源场景:优先使用延迟渲染(
Deferred
),通过G-Buffer优化计算。 - 移动端优化:前向渲染(
ForwardBase
+ForwardAdd
)更节省带宽。 - 阴影生成:必须包含
ShadowCaster
Pass以保证动态阴影正常渲染。
具体设置示例:
Pass {Tags { "LightMode" = "ForwardBase" } // 主光源Pass // Shader代码...
}Pass {Tags { "LightMode" = "ShadowCaster" } // 阴影投射Pass // 阴影生成逻辑...
}
前向渲染
一、核心渲染路径类型
前向渲染路径(Forward Rendering)
ForwardBase:处理主平行光(逐像素)、环境光、光照贴图及顶点光照,必须存在且仅调用一次。
ForwardAdd:处理附加逐像素光源(点光源、聚光灯、次要平行光),每盏光源触发一次 Pass 调用。
以下是 Unity 前向渲染中 ForwardAdd Pass 的关键设定与注意事项:
一、基础配置
混合模式
必须设置 Blend One One:叠加多光源贡献(默认 Blend Off 会导致后续光源覆盖先前结果)。
错误示例:未启用混合时,仅保留最后一次光源计算结果。
深度缓冲
关闭深度写入:设置 ZWrite Off,避免覆盖 ForwardBase 写入的深度值。
Pass 标签
强制声明 LightMode:
glsl
Copy Code
Tags { “LightMode” = “ForwardAdd” }
否则 Unity 无法识别为附加光源处理 Pass。
二、光源处理规则
光源分配逻辑
仅处理逐像素光源:包括点光源、聚光灯及次要方向光,且需满足以下条件之一:
光源的 Render Mode 设为 Important
光源强度在场景中排名靠前(受 QualitySettings.pixelLightCount 限制)
每光源触发一次 Pass:场景中有 N 个逐像素光源时,ForwardAdd 会被调用 N-1 次(主方向光由 ForwardBase 处理)。
光源数据获取
_WorldSpaceLightPos0:
方向光时为世界空间方向向量
点光源/聚光灯时为世界空间坐标
_LightColor0:当前光源颜色与强度(含衰减后的值)。
三、阴影与衰减
阴影支持
需显式启用宏:
glsl
Copy Code
#pragma multi_compile_fwdadd_fullshadows
否则附加光源的阴影不会生效。
使用 UNITY_LIGHT_ATTENUATION:自动计算光源衰减与阴影(需包含 AutoLight.cginc)。
衰减纹理
点光源/聚光灯依赖 _LightTexture0:Unity 自动根据光源类型生成衰减纹理。
四、性能优化
控制光源数量
减少 Important 模式光源:避免过多逐像素光源触发 ForwardAdd Pass。
调整 pixelLightCount:在 Project Settings > Quality 中限制最大逐像素光源数。
剔除不必要计算
禁用无关宏:若无需阴影,移除 _fullshadows 以减少 Shader 变体。
简化光照计算:在 ForwardAdd 中避免复杂运算(如 PBR 高光)。
五、调试建议
Frame Debugger
查看每个 ForwardAdd Pass 对应的实际光源及调用次数。
光源排序验证
通过 _LightColor0 输出颜色值,确认光源是否按强度降序处理。
六、典型代码示例
glsl
Copy Code
Pass {
Tags { “LightMode” = “ForwardAdd” }
Blend One One // 叠加模式
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdadd_fullshadows // 阴影支持
#include "UnityCG.cginc"
#include "AutoLight.cginc" // 衰减与阴影计算struct v2f {float4 pos : SV_POSITION;float3 worldPos : TEXCOORD0;float3 normal : TEXCOORD1;UNITY_SHADOW_COORDS(2) // 阴影坐标
};v2f vert (appdata_base v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.normal = UnityObjectToWorldNormal(v.normal);UNITY_TRANSFER_SHADOW(o, o.worldPos); // 传递阴影数据return o;
}fixed4 frag (v2f i) : SV_Target {float3 lightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos); // 点光源方向float3 diffuse = _LightColor0.rgb * max(0, dot(i.normal, lightDir));UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos); // 衰减+阴影return fixed4(diffuse * atten, 1.0);
}
ENDCG
}
总结
ForwardAdd 的核心设定包括:混合模式、光源筛选规则、阴影宏启用、衰减计算及性能优化策略。正确配置后可实现高效多光源叠加,同时需避免因逐像素光源过多导致的性能瓶颈。
在ForwardAdd中,可能需要判断光源类型,距离,强度等,来得出正确的效果
// 片段着色器函数,输入结构体v2f,返回像素颜色
fixed4 frag(v2f i) : SV_Target {// 规范化世界空间法线(从顶点着色器插值得到)fixed3 worldNormal = normalize(i.worldNormal);// 根据光源类型计算光线方向#ifdef USING_DIRECTIONAL_LIGHT// 方向光:_WorldSpaceLightPos0直接存储方向向量fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);#else// 点光源/聚光灯:需要计算光源到片段的向量(_WorldSpaceLightPos0存储的是光源位置)fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);#endif// 漫反射计算(Lambert光照模型)// _LightColor0:当前光源颜色和强度// _Diffuse:材质漫反射颜色fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));// 高光计算(Blinn-Phong模型)// 计算视线方向:摄像机位置 - 片段位置fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);// 计算半角向量:光线方向 + 视线方向fixed3 halfDir = normalize(worldLightDir + viewDir);// _Specular:材质高光颜色,_Gloss:高光指数fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);// 衰减计算#ifdef USING_DIRECTIONAL_LIGHT// 方向光没有衰减fixed atten = 1.0;#else#if defined (POINT)// 点光源衰减计算(使用立方体贴图衰减)// 将世界坐标转换到光源空间float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;// 根据距离采样衰减纹理(dot(lightCoord,lightCoord)得到距离平方)fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;#elif defined (SPOT)// 聚光灯衰减计算(结合角度衰减和距离衰减)float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));// 角度衰减:使用投影纹理坐标float spotAtten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w;// 距离衰减:使用二次衰减纹理float distAtten = tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;fixed atten = spotAtten * distAtten;#else// 未知光源类型默认无衰减fixed atten = 1.0;#endif#endif// 最终颜色 = (漫反射 + 高光) * 衰减return fixed4((diffuse + specular) * atten, 1.0);
}
二、阴影
开启阴影对硬件资源的影响分析
一、核心硬件影响维度
-
GPU负载显著提升
- 阴影渲染涉及大量光栅化计算和像素填充率消耗,尤其是动态阴影和高质量软阴影
- 实时光追阴影的计算复杂度更高,可能占用50%以上的GPU算力(如《黑神话:悟空》开启光追阴影时)
-
CPU参与计算
- 负责处理物体位置关系和光源投影逻辑等基础数据
- 多光源场景中,CPU需为每个光源生成阴影贴图计算指令
-
显存占用增加
- 高分辨率阴影贴图可能占用200MB+显存(如4K阴影贴图)
- 虚拟阴影技术可降低显存消耗但需要GPU支持
二、硬件影响程度对比
硬件类型 | 影响程度 | 典型场景案例 |
---|---|---|
GPU | ★★★★★ | 开启高质量软阴影后帧率下降40%+ |
CPU | ★★☆ | 百人同屏战斗时阴影计算导致CPU占用提升15% |
内存 | ★☆☆ | 8GB显存显卡开启最高阴影需预留2GB空间 |
-
阴影的基础知识
阴影是 3D 图形中用于表现物体遮挡光线的重要技术,能够增强场景的真实感。在 Unity 中,阴影主要分为以下几种类型:
实时阴影(Real-time Shadows):适用于动态物体和光源,实时计算阴影效果。
烘焙阴影(Baked Shadows):适用于静态物体和光源,预先计算并存储在光照贴图中。
阴影贴图(Shadow Maps):一种常见的实时阴影技术,通过渲染光源视角下的深度图来判断哪些区域被遮挡。
在 Unity Shader 中,阴影的实现主要依赖 阴影贴图(Shadow Maps) 技术。 -
Unity 中的阴影实现
1.渲染阴影投射:
Unity 会为每个投射阴影的光源(如方向光)生成一张阴影贴图。这张贴图记录了从光源视角看到的场景深度信息。
2,物体的 Shader 需要包含一个特殊的 Pass(称为 “ShadowCaster” Pass),以将物体的深度信息渲染到阴影贴图中。
采样阴影贴图:
在渲染物体时,Shader 会根据物体的世界坐标采样阴影贴图,判断当前像素是否处于阴影中。
Unity 提供了内置函数(如 UnitySampleShadow 或 SHADOW_ATTENUATION),方便开发者获取阴影信息。
3.应用阴影效果:
根据采样结果,Shader 调整光照强度(通常是乘以一个阴影衰减值),从而实现阴影的显示。 -
自定义阴影 Shader 的编写
要添加pass
Pass
{
Tags { “LightMode” = “ShadowCaster” }}
}
这样子就有阴影
3,阴影原理
深度比较原理与阴影判断逻辑
核心判断逻辑
当屏幕空间像素在光源空间下的深度值 > 阴影映射纹理中的对应值时,该像素处于阴影中。这一结论源于以下三维空间遮挡关系的数学表达:
-
光源视角的深度记录
阴影映射纹理记录了光源可见范围内所有物体表面的最近深度值(即光源到物体表面的最小距离)。 -
当前像素的深度计算
将屏幕空间像素的坐标转换到光源空间后,计算其到光源的距离(即当前深度值)。 -
遮挡关系判定
- 若当前深度值 > 阴影映射值 → 光源路径上存在更近的物体遮挡 → 处于阴影中
- 若当前深度值 ≤ 阴影映射值 → 无遮挡 → 未被阴影覆盖
(注:此处的比较方向需根据坐标系定义调整,部分API可能相反)
几何原理可视化
- 光源空间坐标系
- Z轴方向:通常指向光源正前方(左手或右手系根据引擎定义)
- 深度值:沿Z轴方向的距离(范围由投影矩阵决定)
- 实例分析
| 位置状态 | 光源深度图值 | 当前像素深度值 | 结果 |
|--------------------|--------------|----------------|----------|
| 遮挡物表面点 | 0.3 | 0.5 | 阴影区域 |
| 遮挡物自身表面点 | 0.3 | 0.3 | 非阴影 |
| 无遮挡区域 | 0.3 | 0.2 | 非阴影 |
技术实现关键点
- 坐标系对齐
- 需保证屏幕空间与光源空间的坐标转换矩阵一致(涉及VP矩阵链式乘法)
- 常见误差来源:浮点数精度问题、非均匀深度分布
Screen Space Shadow Mapping(SSSM)与传统Shadow Mapping对比解析
一、核心差异对比
-
处理阶段与数据来源
| 技术类型 | 处理阶段 | 数据来源 | 计算范围 |
|--------------------|-------------------|----------------------------|---------------------|
| 传统Shadow Mapping | 物体渲染阶段(Forward模式) | 光源视角生成的深度图(ShadowMap) | 场景中所有可能投射阴影的物体 |
| SSSM | 屏幕空间阶段(Deferred模式) | 摄像机深度图+光源ShadowMap | 仅通过深度测试的可见像素 | -
实现原理差异
-
传统Shadow Mapping
- 光源视角渲染场景生成ShadowMap(记录最近深度)
- 实际渲染时,将物体顶点转换到光源空间,与ShadowMap中的深度对比
- 必须处理所有可能遮挡的物体,即使这些物体在摄像机视角不可见
-
Screen Space Shadow Mapping
- 预生成摄像机深度图(屏幕空间可见像素的深度)
- 结合光源ShadowMap,仅在屏幕空间中对可见像素进行阴影计算
- 通过
CollectShadows
阶段生成屏幕空间阴影纹理,其他物体采样该纹理即可
二、性能与效率对比
- 传统Shadow Mapping的局限性
- Overdraw问题:在Forward渲染中,阴影计算可能因物体覆盖而被浪费
- 全场景计算:需处理所有可能投射阴影的物体,包括视锥体外不可见物体
- SSSM的优势
- 精准裁剪:仅处理摄像机可见像素,减少冗余计算
- 硬件优化:利用屏幕空间深度图(如
_CameraDepthTexture
),避免重复渲染 - 移动端友好:统计显示优化后的SSSM在移动端可提升30%+渲染效率
三、应用场景选择
- 推荐使用SSSM的情况
- Deferred渲染管线:需屏幕空间数据支持
- 复杂场景交互:当存在大量动态物体且需要高效剔除不可见阴影时
- 移动端项目:需减少GPU计算负载的场景
- 传统Shadow Mapping的适用场景
- 简单场景/低端设备:硬件不支持SSSM时
- 特殊效果需求:如需要自定义阴影投射逻辑(如透明物体阴影)
四、开发者注意事项
-
深度图生成
- SSSM依赖
_CameraDepthTexture
,需确保摄像机开启深度渲染 - 传统方法需实现
ShadowCaster
Pass生成光源ShadowMap
- SSSM依赖
-
坐标系转换
- 在SSSM中需将屏幕空间坐标转换到光源空间:
float4 lightSpacePos = mul(_LightMatrix, float4(worldPos, 1.0));
- 在SSSM中需将屏幕空间坐标转换到光源空间:
-
性能权衡
- SSSM在复杂场景中更高效,但会占用更多显存(存储屏幕空间阴影纹理)
- 传统方法在小场景中可能更节省资源
半透明物体的阴影技术解析
核心结论
是的,半透明物体在 Shadow Mapping 中可以通过特定方法生成阴影,但在 Screen Space Shadow Mapping 中通常无法正确显示阴影。具体原因如下:
- Shadow Mapping 中的表现
实现原理
- 传统阴影贴图技术:通过光源视角生成深度图(ShadowMap),在渲染时比较物体深度与ShadowMap深度判断是否处于阴影中。
- 半透明处理方式:
- 透明度测试(Alpha Test):通过
clip()
丢弃部分像素,保留深度信息,可在ShadowMap中生成硬边阴影 。 - 透明度混合(Alpha Blend):需自定义Shader,在
ShadowCaster
Pass中强制写入深度,使半透明物体参与阴影计算 。
- 透明度测试(Alpha Test):通过
代码示例
// 自定义ShadowCaster Pass处理半透明阴影
struct v2f_shadow {float4 pos : SV_POSITION;float2 uv : TEXCOORD0;
};v2f_shadow vert_shadow(appdata_base v) {v2f_shadow o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);return o;
}fixed4 frag_shadow(v2f_shadow i) : SV_Target {fixed alpha = tex2D(_MainTex, i.uv).a;clip(alpha - _Cutoff); // 强制写入深度 return 0;
}
- Screen Space Shadow Mapping 中的限制
技术缺陷
- 依赖深度缓冲:屏幕空间阴影映射基于摄像机深度纹理,但半透明物体默认关闭深度写入(
ZWrite Off
),导致其无法正确参与阴影计算 。 - 混合模式冲突:Alpha混合的物体在屏幕空间中无法生成有效的深度数据,导致阴影缺失。
典型现象
- 半透明物体(如水面)可能投射不完整阴影(仅部分区域可见)或无阴影 。
- 阴影边缘可能出现伪影(Artifacts),因光线追踪算法无法正确处理透明区域 。
- 解决方案对比
| 技术类型 | 适用场景 | 实现难度 | 性能消耗 | 阴影质量 |
|-------------------------|------------------------|----------|----------|----------------|
| Shadow Mapping | 静态光源、硬边阴影 | 中等 | 低 | 高(需优化) |
| Screen Space Shadows| 动态场景、软阴影 | 高 | 中高 | 低(半透明失效)|
-
开发者注意事项
-
渲染队列设置
- 将半透明物体的
RenderQueue
设为AlphaTest
(2500以下),以兼容阴影系统 。
- 将半透明物体的
-
Shader优化
- 使用
alphatest
处理阴影投射,同时保留主Pass的alphablend
效果 。
- 使用
-
光照模式限制
- 屏幕空间阴影要求Shader为
Pixel-Lit
且使用Geometry
渲染队列 。
- 屏幕空间阴影要求Shader为
相关文章:
Unity Shader编程】之复杂光照
在Unity Shader的LightMode标签中,除了前向渲染和延迟渲染外,还支持多种渲染模式设置。以下是主要分类及用途: 一、核心渲染路径模式 前向渲染相关 ForwardBase 用于基础光照计算,处理环境光、主平行光、逐顶点/SH光源及光照贴图。…...
从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.1.3前馈网络(FFN)与激活函数(GELU)优化
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 2.1.3 前馈网络(FFN)与激活函数(GELU)优化1. 前馈网络(FFN)的架构设计与数学原理1.1 FFN在Transformer中的核心作用2. GELU激活函数的数学特性与优化2.1 GELU的数学形式与近似计算3. 逐行代码实现…...
STM32 MODBUS-RTU主从站库移植
代码地址 STM32MODBUSRTU: stm32上的modbus工程 从站 FreeModbus是一个开源的Modbus通信协议栈实现。它允许开发者在各种平台上轻松地实现Modbus通信功能,包括串口和以太网。FreeMODBUS提供了用于从设备和主站通信的功能,支持Modbus RTU和Modbus TCP协…...
计算机是如何工作的
目录 冯诺依曼体系 CPU基本工作流程: 逻辑门 门电路 算术逻辑单元 ALU(Arithmetic&LogicUnit) 算术单元(Arithmetic Unit) 逻辑单元(Logic Unit) ALU符号 寄存器(Register)和内存(RAM) 控制单元 CU(Control Unit) 指令(Instruc…...
Arduino、ESP32驱动GUVA-S12SD UV紫外线传感器(光照传感器篇)
目录 1、传感器特性 2、控制器和传感器连线图 3、驱动程序 UV紫外线传感器是一个测试紫外线总量的最佳传感器,它不需要使用波长滤波器,只对紫外线敏感。 Arduino UV紫外线传感器,直接输出对应紫外线指数(UV INDEX)的线性电压,输出电压范围大约0~1100mV(对应UV INDEX值…...
【NLP 48、大语言模型的神秘力量 —— ICL:in context learning】
目录 一、ICL的优势 1.传统做法 2.ICL做法 二、ICL的发展 三、ICL成因的两种看法 1.meta learning 2.Bayesian Inference 四、ICL要点 ① 语言模型的规模 ② 提示词prompt中提供的examples数量和顺序 ③ 提示词prompt的形式(format) 五、fine-tune VS I…...
面向对象软件工程实践软件案例
智力运动-数字化思维训练课程介绍 数字化思维训练是科技赋能素质教育创新实践项目,通过数字化信息化手段,深度融合优质原创智力运动教育课程资源,服务幼儿园与小学,提供信息时代校园素质教育教学解决方案。在《面向对象软件工程》…...
PX4飞控-接收MAVLINK消息(2)-生成MAVLINK_MSG_ID_***.h文件
我在自制的底板上跑vxworks操作系统中移植了MAVLINK的C库用来与PX4飞控进行通信,其中使用的C库和其他依赖文件,例如common文件夹均为从飞控源码中获取,文件获取位置为px4-Autopolite/bulid/mavlink中,因为PX4源码中自带MAVLINK的依…...
Spring Boot 连接 MySQL 配置参数详解
Spring Boot 连接 MySQL 配置参数详解 前言参数及含义常用参数及讲解和示例useUnicode 参数说明: 完整配置示例注意事项 前言 在 Spring Boot 中使用 Druid 连接池配置 MySQL 数据库连接时,URL 中 ? 后面的参数用于指定连接的各种属性。以下是常见参数…...
【数据结构】_单链表_相关面试题(二)
本章重点 hello友友们~ 今天我们将对单链表的后半部分的相关面试题进行详细解析,下面就跟着我一起开启吧~ really GO! 1.相交链表 题目: 输入两个链表,找出它们的第一个公共结点。 代码分析: //找到相交结点…...
深入理解指针(2)(C语言版)
文章目录 前言一、数组名的理解二、使用指针访问数组三、一维数组传参的本质四、冒泡排序五、二级指针六、指针数组七、指针数组模拟二维数组总结 前言 在上一篇文章中,我们初步了解了指针的基本概念和用法。今天,我们将继续深入探索指针在数组、函数传…...
二叉树相关算法实现:判断子树与单值二叉树
目录 一、判断一棵树是否为另一棵树的子树 (一)核心思路 (二)代码实现 (三)注意要点 二、判断一棵树是否为单值二叉树 (一)核心思路 (二)代码实现…...
redux ,react-redux,redux-toolkit 简单总结
Redux、React-Redux 和 Redux Toolkit 是协同工作的三个库,各自承担不同角色,相互协同。 Redux:基础底座 底层状态管理库,负责状态存储、Action 派发和 Reducer 执行 React-Redux:连接 React 组件与 Redux Store 通…...
5. 实现一个中间件
原文地址: 实现一个中间件 更多内容请关注:php代码框架 理解中间件 中间件(Middleware) 是一种在请求被路由到控制器方法之前或响应返回客户端之前执行的代码。它通常用于处理通用任务,如身份验证、日志记录、CORS 处理等。 在…...
数据库理论基础
数据库理论基础 1.1 什么是数据库 数据: 描述事物的符号记录, 可以是数字、 文字、图形、图像、声音、语言等,数据有多种形式,它们都可以经过数字化后存入计算机。 数据库: 存储数据的仓库,是长期存放在…...
STM32学习笔记之振荡器(原理篇)
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...
SQL Server安装程序无法启动:系统兼容性检查失败
问题现象: 运行 SQL Server 2022 安装程序时,提示 “硬件或软件不满足最低要求”,安装向导直接退出或无法继续。 快速诊断 操作系统版本检查: # 查看 Windows 版本(需 20H2 或更高) winver 支持的系统&…...
C++20 中的std::c8rtomb和 std::mbrtoc8
文章目录 1. 引言2. std::c8rtomb 函数详解3. std::mbrtoc8 函数详解4. 使用示例5. 注意事项6. 总结 1. 引言 C20 标准引入了对 UTF-8 编码的更好支持,其中包括两个重要的函数:std::c8rtomb 和 std::mbrtoc8。这两个函数分别用于将 UTF-8 编码的字符转换…...
树形结构的工具类TreeUtil
这个地方是以null为根节点,相关以null或者0自己在TreeUtil中加代码,就行 基础类 package com.jm.common.entity;import lombok.Data;import java.util.ArrayList; import java.util.List;/*** Author:JianWu* Date: 2025/3/26 9:02*/ Data public clas…...
【零基础入门unity游戏开发——2D篇】2D物理系统 —— 2D刚体组件(Rigidbody2D)
考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…...
人员进出新视界:视觉分析算法的力量
视觉分析赋能离岗检测新策略 随着时代的发展,失业率增加,社会安保压力也随之增大。企业为了提升管理效率,保障园区安全,对员工离岗检测的需求日益迫切。传统的离岗管理方式,如人工巡逻、打卡记录等,不仅效率…...
LabVIEW液压振动锤控制系统
在现代工程机械领域,液压振动锤的高效与精准控制日益显得重要。本文通过LabVIEW软件,展开液压振动锤启停共振控制技术的研究与应用,探讨如何通过改进控制系统来优化液压振动锤的工作性能,确保其在复杂工况下的稳定性与效率。 …...
Slidev使用(一)安装
文章目录 1. **安装位置**2. **使用方式**3. **适用场景**4. **管理和维护** 全局安装1. **检查 Node.js 和 npm 是否已安装**2. **全局安装 Slidev CLI**3. **验证安装是否成功**4. **创建幻灯片文件**5. **启动 Slidev**6. **实时编辑和预览**7. **构建和导出(可选…...
浙大:DeepSeek技术溯源及前沿探索
浙江大学DS系列专题《DeepSeek技术溯源及前沿探索》由朱强教授主讲,内容主要包括 语言模型、Transformer、ChatGPT、DeepSeek及新一代智能体 等核心主题。 下载方式:关注“渡江客涂鸦板”,回复ds1253免费获取下载地址 语言模型:语…...
【八股】未知宽高元素水平垂直居中的三种方法
在笔试/面试中,经常出现的一个问题就是:如何实现元素水平垂直居中? 本文会直接使用代码,介绍未知宽高元素水平垂直居中的三种方法: 方法一:绝对定位absolute //绝对定位,将元素的左右位置设置…...
23种设计模式-中介者(Mediator)设计模式
中介者设计模式 🚩什么是中介者设计模式?🚩中介者设计模式的特点🚩中介者设计模式的结构🚩中介者设计模式的优缺点🚩中介者设计模式的Java实现🚩代码总结🚩总结 🚩什么是…...
(免费开源)图片去水印以及照片擦除功能,你会选择使用吗?
图片去水印以及相关人物擦除是一个非常小众的需求,就是将原本图片上的文字或者logo去除让变成一个干净的图片,但市面上很多都是付费的,今天就介绍一下这款免费工具。 工具演示效果 工具介绍 名称:lama-projct 利用AI模型训练LaM…...
Rust 学习笔记(一)
本文是博主学Rust的学习笔记,将学习经历整理下来,学习接收的内容更加条理且以便回顾。 参照学习资料为Rust官方文档,如内容中有误还请指点(一般没有☺) 一. 项目搭建 1.创建项目 cargo new hello_cargo cd hello_c…...
C++vector常用接口和模拟实现
C中的vector是一个可变容量的数组容器,它可以像数组一样使用[]进行数据的访问,但是又不像C语言数组空间是静态的,它的空间是动态可变的。 在日常中我们只需要了解常用的接口即可,不常用的接口查文档即可。 1.构造函数 //空构造…...
AI数据分析:一键生成数据分析报告
作为一名数据分析师,我们经常需要做一些数据分析报告,今天我就来手把手教你如何使用大模型一键生成高质量的数据分析报告,提高你的工作效率。 假设你是一家新零售企业的销售分析师,有一份销售数据,数据结构如数据结构…...
leetcode 2829. k-avoiding 数组的最小总和 中等
给你两个整数 n 和 k 。 对于一个由 不同 正整数组成的数组,如果其中不存在任何求和等于 k 的不同元素对,则称其为 k-avoiding 数组。 返回长度为 n 的 k-avoiding 数组的可能的最小总和。 示例 1: 输入:n 5, k 4 输出&…...
微信小程序登录和获取手机号
目录 准备工作 实现流程 实现代码 公共部分 通过code获取openid等信息 解密手机号 扩展 不借助工具类实现解密 借助工具类获取access_token 准备工作 需要小程序账号(可以去微信公众平台创建一个测试号或者正式号) appid:小程序id …...
漫画|基于SprinBoot+vue的漫画网站(源码+数据库+文档)
漫画网站 目录 基于SprinBootvue的漫画网站 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大…...
华鲲振宇天工TG225 B1国产服务器试装openEuler22.03 -SP4系统
今天测试了一下在华鲲振宇公司的天工TG225 B1国产服务器上进行openEuler22.03 -SP4操作系统的试装,本文记录整个测试过程。 一、服务器信息 1、服务器型号 Huakun TG225 B1 (D) 2、登录IPMI帐户信息 初始用户名Tech.ON 密码TianGong8000 二、磁盘RAID配置 测试…...
Graphpad Prism for Mac医学绘图
Graphpad Prism for Mac医学绘图 文章目录 Graphpad Prism for Mac医学绘图一、介绍二、效果三、下载 一、介绍 GraphPad Prism for Mac是一款功能强大、易于使用的科学和统计分析软件,适用于各种类型的数据处理和可视化需求。无论您是进行基础研究、临床试验还是学…...
单多表查询练习
课堂代码练习 mysql> select * from t_heros; ----------------------------- | id | name | books | ----------------------------- | 1 | 孙悟空 | 西游记 | | 2 | 猪八戒 | 西游记 | | 3 | 林黛玉 | 红楼梦 | | 4 | 贾宝玉…...
SICAR标准 汽车焊装生产线触摸屏操作说明
目录 SIMATIC HMI 是西门子工业自动化解决方案的核心组件,支持实时设备监控与交互,文档中展示了其在焊装生产线中以SICAR标准为基础的具体应用,包括车型切换(如 AY2/A26)、KMC 夹具配置及能源效率分析,适用…...
Photoshop 2025安装教程包含下载安装包,2025最新版图文安装教程
文章目录 前言一、Photoshop 2025下载二、Photoshop 2025安装教程1. 安装包解压2. 找到安装程序3. 以管理员身份运行4. 安装选项设置5. 选择安装路径6. 开始安装7. 安装完成8. 启动软件9. 软件主界面 前言 无论你是专业设计师,还是刚接触图像处理的新手,…...
SylixOS 中 select 原理及使用分析
1、select接口简介 1.1 select接口使用用例 select 是操作系统多路 I/O 复用技术实现的方式之一。 select 函数允许程序监视多个文件描述符,等待所监视的一个或者多个文件描述符变为“准备好”的状态。所谓的”准备好“状态是指:文件描述符不再是阻塞状…...
F1C200S编译
一、查看荔枝派Nano的分区内容 分成了两个分区 将第一个分区通过mount进行挂载,查看到内容包括:主要是dtb设备树和zImage压缩的内核。由于u-boot不是是通过dd指令传输到指定的位置,因此这里不显示。还有一个scr,这是一个uboot启动…...
边缘计算 vs. 云计算,谁才是工业物联网的未来?
前言 在物联网(IoT)飞速发展的今天,边缘计算正在彻底改变数据的处理、存储和分析方式。传统的IoT设备数据通常需要发送到云端进行处理,但随着设备数量的激增,这种模式在延迟、带宽和安全性方面暴露出诸多局限。边缘计…...
vue 使用v-model实现父子组件传值——子父组件同步更新
基于vue2和vue3两个版本的框架略显不同,所以我分开的来讲: 1、vue2 子组件(my-input.vue): <template><input type"text" :value"name" input"inputChange" /> </tem…...
监控易运维在北京某医药集团数字新基建项目中的应用
随着信息技术的快速发展,企业数字化转型已成为当今时代的趋势。北京某医药公司作为一家知名的中医药企业,也在积极推进数字化建设。在数字新基建招标项目中,监控易管理平台 6.0 凭借其强大的功能和特点,成功中标,为医药…...
小智AI音频开发 libopus + Eclipse C/C++ MinGW 编解码测试用例
小智AI音频开发 libopus Eclipse C/C MinGW 编解码测试用例 目录 小智AI音频开发 libopus Eclipse C/C MinGW 编解码测试用例前言移植编解码测试libopus编码器的控制参数信号类型比特率带宽编码复杂度前向纠错声道不连续传输位深帧持续时长码率VBR约束应用类型 示例代码 前言…...
Spring Boot定时任务设置与实现
Spring Boot定时任务设置与实现 在Spring Boot中,可以使用Scheduled注解来创建定时任务。以下是一个简单的示例,展示了如何在项目启动后每5秒调用一次指定的方法。 1. 添加依赖 首先,确保你的pom.xml文件中包含Spring Boot的依赖ÿ…...
海康/大华/宇视/华为/汉邦/天地伟业/英飞拓/科达/中星微/同为/天视通等主流监控设备RTSP地址
RTSP协议是TCP/IP协议体系中的一个应用层协议,该协议主要规定了一对多应用程序如何有效地通过IP网络传送多媒体数据,特别适用于音视频数据的实时传输和控制。 目前监控市场厂家众多,各个厂家的RTSP地址格式不尽一致 以下是海康威视、大华股份…...
FreeRTOS 队列结构体 xQUEUE 深度解析
一、核心成员与功能设计 FreeRTOS 的队列结构体 xQUEUE 是任务间通信(IPC)的核心数据结构,通过统一的设计支持队列、信号量、互斥量等多种同步机制。其设计体现了 **"数据拷贝 结构复用"** 的理念,兼顾轻量化与扩展…...
system V 消息队列信息量(了解)
目录 system V 消息队列 消息队列的基本原理 消息队列数据结构 消息队列接口介绍 消息队列相关函数 消息队列的释放 向消息队列发送数据 向消息队列接收消息 System V 信号量 信号量相关概念 信号量的数据结构 信号量相关函数 进程互斥 system V IPC联系 system V…...
CSS rem、vw/vh、less
目录 分辨率、视口与二倍图 一、分辨率与像素基础 1. 物理像素(Physical Pixels) 2. 逻辑像素(CSS 像素) 二、视口(Viewport)控制 1. 视口类型 2. 设置理想视口 三、二倍图(Retina/HiD…...
CHI协议——retry
一、核心目标 防止请求阻塞:当Completer暂时无法处理请求(比如tracker不够被占满)时,通过retry机制避免请求在 REQ Channel堆积,确保系统流畅运行。 retry机制只存在于REQ Channel,在DAT/RSP/SNP Channel不存在 二、Retry Flow…...