Unity Shader技巧:移动端伪次表面散射模拟实战

1. 为什么我要写一篇“假”的次表面散射

先聊点实在的。在Unity里做皮肤、蜡烛、树叶、大理石这类材质时,大家第一反应都是上真正的次表面散射(Subsurface Scattering,SSS)——就是光打进去之后在物体内部散射、再从其他地方溢出来的效果。手放在手电筒后面会透出红光,蜡烛耳朵被光一照会亮得发透,这些都是典型的次表面散射。

但真SSS术贵啊。无论是预积分皮肤还是屏幕空间散射,随便一套方案下来要么是纹理烘焙复杂,要么是后处理Pass多到手机扛不住。我自己最开始做项目时跟很多朋友一样,直接上了一个完整的SSS方案,结果真机帧率掉得惨不忍睹。后来才意识到:很多时候我们并不需要物理上“正确”的散射,只需要让观众“看过去像那么回事”就行。这就是伪次表面散射模拟的出发点。

这篇文章我想分享的,就是一套我自己在手机端项目里验证过、成本可控、效果又很能打的Unity Shader方案。它的核心思路是用“厚度 + 背面光照 + 半透明混合”来伪造出光穿透物体的感觉。听起来不复杂,但真正做好看、做自然,中间有不少坑。我尽量把每一步的原理和参数都讲透,适合正在做风格化渲染、或者想在移动端做低成本皮肤/植物材质的朋友参考。

2. 方案选型:为什么是“伪SSS”而不是真SSS

2.1 先搞清楚真SSS是怎么算的

我们首先要理解真实次表面散射的物理过程:光线进入物体表面后,并不会立刻反射出来,而是在材质内部跟微粒反复碰撞、被吸收、再改变方向,最终从表面的另一个点射出。能量在这个过程中会被“抹开”——所以皮肤看起来柔和,关节处会泛红,蜡烛耳朵边缘会透光。

物理上描述这个过程,靠的是双向散射表面反射分布函数(BSSRDF),它比普通的BRDF多了一个“空间偏移”的维度。渲染时需要对散射半径内的多个点做采样和积分,计算量非常大。离线渲染器还能接受,游戏实时渲染就得靠各种近似。

常见的实时近似方案主要有这几种:

  • 预积分皮肤着色:把散射效果预先烘焙到一张查找表(LUT)里,运行时根据“曲率+光线方向”查表,效果很好但需要预处理网格数据。
  • 屏幕空间散射:在屏幕后处理阶段做模糊,模拟光线在表面下的弥散,效果也不错,但需要额外的深度和法线信息,移动端带宽压力大。
  • 基于厚度图的散射:预先把模型“由内到外”的厚度烘焙出来,运行时用厚度值和光照方向做衰减,这是最接近“伪SSS”思路的做法,但厚度图需要额外烘焙工具链。

这些方案在PC和主机上都有成熟落地案例,但放到移动端,要么是采样次数太多,要么是需要额外的G-Buffer。而伪SSS的思路很直接:我们不看复杂的物理,只看“光从哪里来、材质有多薄、视线在哪个方向”,用这几个变量组合出一个足够可信的散射光。

2.2 伪SSS的核心假设

伪SSS方案成立,依靠的是三个关键假设:

第一,散射光主要从“背面”进入。也就是说,当一个物体背对光源时,光的入射方向跟视线方向相反,散射光会从物体边缘透出来。这正好可以模拟蜡烛耳朵、树叶边缘那种“亮边”。

第二,散射强度跟厚度强相关。材质越薄的地方,光穿透过来的能量越多。这可以用轮廓线、曲率或者预烘焙的厚度贴图来衡量。

第三,散射光有明显的光谱偏移。物理上,短波长的光更容易被散射、长波长的光更容易被吸收,所以皮肤内部散射光偏红橙色。这个偏移我们可以直接用一个“透射颜色”来控制,甚至不需要物理模拟。

基于这三个假设,在Shader里模拟散射就变成一个很轻量的光照计算分支:检测“光源在背面”的方向关系,乘以一个衰减因子,再乘上透射颜色。整个过程只需要几次向量点积和一张可选纹理,移动端跑起来毫无压力。

2.3 效果对比:什么场景适合用伪SSS

伪SSS并不适合所有场景,用之前你得先评估需求。我自己用过之后总结了一张对比表,可以帮大家快速判断:

需求场景真SSS方案伪SSS方案
写实人物皮肤(近距离特写)必须不建议,精度不够
风格化角色皮肤可选推荐,表现力足够
蜡烛、灯笼、玉石可用强烈推荐
树叶、花瓣等植物可选推荐
半透明塑料、磨砂玻璃不适用推荐
手机端低中端机型吃力流畅运行

用一句话总结就是:如果你做的是写实向、需要角色面部特写级别的皮肤渲染,老老实实上真SSS方案;如果你做的是风格化、或者材质本身就是“半透不透”的质感,伪SSS的性价比几乎无敌。

3. 从零开始实现伪SSS Shader

3.1 准备基础Shader框架

我习惯在Unity内置渲染管线下用一个Surface Shader来写这套逻辑,然后在URP下单独维护一套HLSL版本。先讲内置管线的版本,因为它的代码结构更容易看懂,方便大家理解原理。

新建一个Shader文件,先搭出基础框架:

Shader "Custom/FakeSSS" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} _Tint ("Tint", Color) = (1,1,1,1) _SSSColor ("SSS Color", Color) = (0.8,0.2,0.1,1) _SSSPower ("SSS Power", Range(1,16)) = 4 _SSSStrength ("SSS Strength", Range(0,5)) = 1 _Transmission ("Transmission", Range(0,1)) = 0.5 } SubShader { Tags { "RenderType"="Opaque" "Queue"="Geometry" } LOD 200 CGPROGRAM #pragma surface surf FakeSSS fullforwardshadows sampler2D _MainTex; fixed4 _Tint; fixed4 _SSSColor; float _SSSPower; float _SSSStrength; float _Transmission; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Tint; o.Albedo = c.rgb; o.Alpha = c.a; } // 自定义光照函数 half4 LightingFakeSSS (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) { // 这里填入散射计算 } ENDCG } FallBack "Diffuse" }

这里我用了Surface Shader的自定义光照函数功能,这样可以直接复用Unity的阴影、雾效等管线,把精力集中在散射计算本身。

3.2 核心散射计算

接下来是重头戏:怎么算出一个自然的透射光强。先理一下需要的变量:

  • 法线方向s.Normal
  • 光照方向lightDir(注意这里用的是指向光源的方向,也就是从表面指向光源)
  • 视线方向viewDir(从表面指向相机)

前面提到,散射光主要来自“背面入射”。这里的关键量是“法线与光线的夹角”和“法线与视线的夹角”。当我们看到物体的边缘时,视线跟法线接近垂直,此时如果光源在物体另一侧,光就会从边缘透出来。

我的实现思路分两步:

第一步,计算“厚度感”。最简单的方法是用法线与视线的点积:

float thickness = 1.0 - saturate(dot(s.Normal, viewDir));

当视线垂直于法线(比如观察物体边缘)时,这个值趋近于1,说明我们正对着物体的轮廓边缘,透光应该最强。而当视线正对法线(看物体正面)时,这个值趋近于0。

第二步,计算“光在背面”的程度。用光照方向与法线的点积:

float backLight = saturate(dot(s.Normal, -lightDir));

为什么要用-lightDir?因为Unity的lightDir方向是“指向光源”的,而“光从背面来”意味着光线方向跟法线方向相反。当法线恰好朝光源时,dot(s.Normal, lightDir)接近1,这时是正面受光,背面散射应该非常弱;而当法线背对光源时,dot(s.Normal, -lightDir)接近1,散射最强。

把这两部分乘起来:

float sss = backLight * pow(thickness, _SSSPower) * _SSSStrength;

这里加了个pow是为了控制厚度衰减的锐利程度。_SSSPower越大,散射越集中在轮廓线附近,看起来越“锐利”;越小,散射扩散范围越大,看起来越“朦胧”。

最终把散射光加到漫反射结果上:

half4 LightingFakeSSS (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) { half NdotL = saturate(dot(s.Normal, lightDir)); half3 diffuse = s.Albedo * _LightColor0.rgb * NdotL; float thickness = 1.0 - saturate(dot(s.Normal, viewDir)); float backLight = saturate(dot(s.Normal, -lightDir)); float sss = backLight * pow(thickness, _SSSPower) * _SSSStrength; half3 sssColor = _SSSColor.rgb * _LightColor0.rgb * sss * _Transmission; half3 finalColor = diffuse + sssColor; half4 c; c.rgb = finalColor * atten; c.a = s.Alpha; return c; }

这段代码跑起来,模型边缘会透出_SSSColor的散射光,而且越薄的边缘越亮。

3.3 不要忽略的半透明混合细节

上面这套方案有个问题:如果模型本身是一个不透明体,它的“背面”会被遮挡,散射光只能出现在轮廓边缘——这其实已经能满足很多需求了。但如果你想让“背面”也透出光来,那就需要让背面参与渲染。

我常用的做法是给Shader加一个透明混合模式,然后渲染两次:第一次渲染背面并输出散射光,第二次照常渲染正面。这样光就能“穿透”物体,从背面溢出来。

Unity的Surface Shader里控制这个,可以通过设置Blend和Cull实现。注意,Surface Shader里其实不好直接写两个Pass,我通常是分成两个SubShader,或者直接改用顶点片元Shader。这里给一个简化写法:

SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" } Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Front // 背面Pass:只输出散射光 // 正面Pass:正常光照+少量散射 }

背面Pass的Cull Front会剔除正面,只渲染朝向相机内部的三角形。这里我用背面Pass输出纯散射光,Alpha用厚度控制;正面Pass输出正常光照和边缘散射。这样近看会有明显层次,远看就是一个半透明的发光体。

需要注意,透明物体渲染时深度写入要关掉,否则物体会挡住自己。但关掉ZWrite可能让物体跟场景其他物体穿插时排序出问题,这属于透明渲染的通病,一般通过调整Queue来控制。

4. 实操过程:做一个蜡烛和一片叶子

4.1 蜡烛材质的关键参数调优

理论说得再多,不如直接上手调。我拿了一个蜡烛模型做实验,这种“光从内部透出来”的材质,对SSS参数极其敏感。

先给蜡烛模型赋上上面写的Shader,初始参数:

_SSSColor (0.8, 0.3, 0.1, 1) _SSSPower 4.0 _SSSStrength 1.0 _Transmission 0.6

我先把蜡烛放进一个黑暗场景,用一个点光源在侧面打光。看效果,第一版的问题是散射光太散,整个蜡烛看起来像在发光,而不是“透光”。这时候把_SSSPower从4提到8,散射范围立刻聚拢到蜡烛边缘,看起来就自然多了。

接下来蜡烛的顶部被火苗照亮的部分,应该有最强的透光感。我发现_Transmission调高会让整个物体发亮,调低又不够通透。后来我把_Transmission设成0.4,加大_SSSStrength到1.5,局部补光后效果好了很多。这个组合意味着:散射整体强度提高,但只出现在很薄的区域,反而更像真实的透光。

再给蜡烛加一点自发光贴图,不然暗面太死板。蜡烛材质里我加了_EmissionMap通道,用火苗位置做发光,替代了原本需要额外补的光。

蜡烛调完之后,我有一个感受:_SSSPower是这套方案里最关键的参数,它决定了“透光带”的宽度,其他参数都只是微调亮度和颜色。

4.2 叶子材质:用半透明玩出透光感

叶子跟蜡烛不太一样,叶子是平面结构,没有蜡烛那种立体厚度。我用了一片双面叶子模型,按照下面步骤调:

第一步,把Shader的Cull Off打开,让叶片两面都可见。叶子背面的光照在真实世界中非常重要,尤其是阳光穿透叶片的时候。

第二步,调整散射参数。叶子透光颜色应该是黄绿色,而不是橙红色。我设:

_SSSColor (0.6, 0.9, 0.2, 1) _SSSPower 2.0 _SSSStrength 2.0 _Transmission 0.5

因为叶片很薄,散射范围其实不需要特别窄,反而要大面积地透光才有真实感。

第三步,添加一张“叶片厚度”纹理作为Alpha贴图。叶脉、叶片边缘比较薄,透光强;叶柄和主叶脉比较厚,透光弱。这里我手工画了一张灰度图,白色代表薄(透光强),黑色代表厚(透光弱),在Shader里用这张图乘以散射强度:

float thicknessMask = tex2D(_ThicknessMap, IN.uv_MainTex).r; sss *= thicknessMask;

这样透光效果会跟随叶脉分布,一下子从“均匀塑料”变成“真实叶片”。这也是伪SSS方案最灵活的地方——你可以用任意美术资源控制散射的“形状”。

4.3 参数速查与制作清单

调过几个项目之后,我整理了一套常用参数参考值,方便大家起手时有个数:

素材类型SSS颜色SSS PowerSSS StrengthTransmission备注
蜡烛橙红(0.8,0.3,0.1)8-121.0-1.50.3-0.5散射集中边缘
叶片黄绿(0.6,0.9,0.2)1-31.5-2.50.4-0.6配合厚度图
风格化皮肤红(0.7,0.1,0.05)3-60.8-1.20.3-0.5用于耳廓、鼻翼
玉石绿(0.3,0.8,0.4)4-81.0-2.00.5-0.7配合高光滑度
半透明塑料白(0.9,0.9,0.8)2-40.5-1.00.2-0.4漫反射为主

注意:这些参数是“起点”而不是“终点”。不同光照环境、不同模型比例,都需要重新微调。特别是_SSSPower,同一个材质在白天场景和夜晚场景可能要用完全不同的值。

5. 常见问题与排查技巧实录

5.1 散射光完全看不到,是怎么回事

这个坑我踩过很多次,而且多半不是Shader本身的问题。排查顺序如下:

第一步,检查光照方向。散射计算依赖dot(s.Normal, -lightDir),如果物体是正面受光,背面散射基本为零,这时候你会觉得“没效果”。先把灯转到物体侧后方,看边沿有没有亮起来。

第二步,检查材质球_SSSStrength是否设置得太低。如果低于0.3,几乎看不出效果。

第三步,检查模型是不是用了错误的缩放比例。如果模型整体特别大,厚度计算是基于“轮廓接近程度”而非实际物理厚度,模型尺寸会影响厚度。同一个Shader,小模型看起来透光强,大模型看起来透光弱。解决方法是把模型缩放到正常比例,或者给厚度计算加一个基于模型缩放的补偿系数。

第四步,检查Shader里是否有其他代码覆盖了Alpha或颜色输出。特别是很多人会在surf函数里直接给o.Emission赋值,这会把散射效果冲淡。

5.2 散射区域出现脏脏的“条带”或断痕

如果散射光不是连续的一条亮带,而是断断续续的斑块,大概率是模型法线问题。伪SSS对法线极其敏感,因为厚度感完全是靠dot(s.Normal, viewDir)算出来的。

解决方法是:检查模型法线是否平滑,清一下模型上的硬边(或者把光滑组重新算一遍)。对于低模,建议在导入设置里把Normals设为Calculate,并且增加Smoothing Angle。

还有一种情况是使用法线贴图之后散射效果很杂乱。这是因为法线贴图改变了表面法线,导致厚度计算出现高频噪声。如果要用法线贴图,建议把散射计算放到“几何法线”(即未经过法线贴图修改的法线)上:

float thickness = 1.0 - saturate(dot(o.Normal, viewDir));

注意这里的o.Normal是Surface Shader里已经处理过的法线。如果你不想受法线贴图影响,需要在顶点着色器阶段把法线单独传一份。

5.3 透明混合后物体之间排序混乱

这个问题的根源是Unity透明渲染的排序机制。关闭ZWrite后,透明物体之间会按距离排序,但两个交叉的透明物体会出现“忽前忽后”的闪动。

我常用的几个办法:

  • 给同一个模型的不同透明Pass设置不同Queue偏移,比如背面Pass用Queue=Transparent-1,正面Pass用Queue=Transparent。
  • 如果模型内部有自遮挡,用Offset命令调整深度偏移,防止z-fighting。
  • 最省事的办法:进模型内部看的视角不多的话,可以直接给模型分两个子Mesh,内部透光部分用单独的材质球。

5.4 移动端真机闪烁或性能暴跌

性能问题主要出在填充率上。透明度混合的Shader通常意味着Overdraw很高,如果模型占了屏幕很大面积,低端手机会扛不住。

我踩过的一个坑是:给叶子Shader同时开启了双面渲染 + 全屏透明,结果石头一样的老机型直接掉到20帧。后来改成仅在近景LOD级别使用伪SSS材质,远景自动切换成普通不透明材质,问题解决。

如果一定要在移动端全场景使用,建议把散射计算改成“半精度”(half)运算,大幅度减少ALU开销:

half thickness = 1.0 - saturate(dot(half3(s.Normal), half3(viewDir)));

替代方案是做一个“LOD Shader”——距离远了就用简化版,散射范围用固定值,不做逐像素运算。

6. 进阶扩展:让伪SSS更“真”的几个方向

6.1 加入菲涅尔边缘光

伪SSS的散射光集中在轮廓边缘,这本身跟菲涅尔效应有重合之处。我试过在散射计算上叠加菲涅尔:

half fresnel = pow(1.0 - saturate(dot(s.Normal, viewDir)), 3.0); sss += fresnel * _FresnelColor * _FresnelStrength;

这样做的直观效果是:即使没有光源从背面照过来,物体边缘也有一层“空气感”的暖色溢出,更像真实皮肤边缘在环境光下的表现。尤其是在风格化角色上,加一点菲涅尔散射能让人物跟背景分离得更干净。

但要注意别加太多。我之前把菲涅尔强度开到0.8,结果整个角色像披了一层金边,非常塑料。控制在0.2到0.4之间比较合适。

6.2 多光源散射的累加处理

前面的Shader只处理了主光源。如果场景里有点光源、聚光灯,散射也应该跟着响应。

最简单的做法是把LightingFakeSSS改成遍历多个光源,但Surface Shader的自定义光照函数对多光源支持不算友好。我后来改成了Vertex Fragment Shader,用Unity的UNITY_LIGHT_ATTENATION逐光源累加散射。

多光源散射的算法其实跟单光源完全一样,只是多循环几次。关键是控制性能:一个物体同时受5个光源照射,就要跑5次散射计算,移动端可能吃不消。我的优化思路是:只对最亮的一两个光源计算散射,其余光源只走漫反射。

6.3 预烘焙厚度贴图

前文提到的厚度贴图,可以手工画,也可以从3D模型直接烘焙。烘焙的原理是:从模型每个点的法线方向发射一条射线,记录射线在模型内部穿过的距离,这个距离就是“厚度”。

市面上有一些工具可以自动烘焙,实际操作时需要注意:

  • 模型必须是封闭的,开口模型烘焙出来的厚度值会飘。
  • 烘焙分辨率一般512或1024就够,厚度贴图不需要很高的精度。
  • 烘焙结果要尽量平滑,避免出现硬边。如果出现硬边,可以在Photoshop里做一次轻微模糊。

有了厚度贴图之后,散射计算可以升级为:

float thicknessTex = tex2D(_ThicknessMap, IN.uv).r; float thickness = 1.0 - thicknessTex;

用贴图代替几何计算的好处是,厚度感不再依赖视角方向,即使正视物体表面也能看到透光效果。代价是需要额外一张纹理采样,还需要预处理模型。对于做风格化项目的团队,这个成本并不高。

6.4 把透射色放进光照模型

严格来说,真实次表面散射的透射颜色跟光源颜色、材质厚度都有关系,不应该是一个固定常量。一个比较高级的玩法是:把_SSSColor替换成一张“散射颜色渐变图”,横轴是厚度、纵轴是入射角度,查表得到透射色。

我做过一版,用的是2D Ramp Texture:

half2 uv = half2(thickness, NdotL); half3 sssColor = tex2D(_SSSRamp, uv).rgb;

这个方案特别适合风格化项目。美术可以直接在Ramp贴图里画“什么厚度、什么光照角度下呈现什么颜色”,表现力比固定颜色高一个量级。不过它的前提是要正确理解厚度和角度的映射关系,美术需要一些上手时间。

7. 我的最终建议与避坑心得

做完这套伪SSS方案,我在几个项目里反复验证过,最大的感受是:它不是一个“可以随处套用”的万能Shader,而是一套需要针对项目调校的“光影思路”。

如果你想在团队里推广这套方案,我会建议美术和TA先约定清楚资产规范。比如叶子的厚度贴图画到什么程度、蜡烛的散射颜色用哪个色域、角色耳朵的散射范围有多大。这些看似琐碎的约定,决定了最终效果是否统一。

另外我特别想强调一个容易被忽略的细节:Shader参数命名和范围。很多美术同事看到_SSSPower是0到16的范围,会习惯性拖到最大。结果就是一片过曝。后来我把Shader参数范围改成更“直觉化”的0到1,再用内部映射把_SSSPower从1映射到16:

float power = lerp(1.0, 16.0, _SSSPowerNormalized);

美术拖起来直观,代码逻辑也不受影响。

最后,如果你只是做个个人练习或者小Demo,不需要追求真SSS级别的物理正确性。先把这篇文章里的伪SSS方案跑通,理解厚度、角度、颜色这三个变量之间的关系,再决定要不要往更复杂的方案升级。很多情况下,一个调得好的伪SSS已经能撑起整个项目的质感需求了。

相关新闻

STM32+MPU6050六轴姿态解算工程:从I2C驱动到DMP四元数输出

STM32+MPU6050六轴姿态解算工程:从I2C驱动到DMP四元数输出

简介:STM32F103C8T6与MPU6050组合的完整工程,面向物联网、机器人及智能穿戴开发者,提供开箱即用的姿态解算方案。工程基于标准外设库,包含I2C驱动、原始数据读取、姿态解算及串口输出等核心模块,覆盖从底层寄存器配置到…

2026/10/20 5:23:05 阅读更多 →
PHP自建Web应用防护系统:三层架构与实战

PHP自建Web应用防护系统:三层架构与实战

搞安全的这些年,我一直有个看法:真正的Web应用防护,不能光靠买了云清洗和WAF就高枕无忧。流量清洗挡不住业务层的逻辑攻击,传统WAF规则库再全,也识别不了“你自己业务里那个只能输入三位数字的订单号”被塞进了恶意参数…

2026/10/20 5:23:05 阅读更多 →
Blending算法实战:模型融合中的原理、代码与避坑指南

Blending算法实战:模型融合中的原理、代码与避坑指南

堆叠学习(Stacking)和Blending算法,是我在做模型融合时最先认真研究的一对概念。很多人第一次听到Blending,是在某个数据挖掘比赛的Top方案里;等真到自己手上写代码时,往往会发现它对数据划分的要求比想象中…

2026/10/20 5:23:05 阅读更多 →

最新新闻

从单体到弹性扩展:高并发架构改造的完整实战复盘

从单体到弹性扩展:高并发架构改造的完整实战复盘

1. 项目背景与架构需求拆解1.1 最初的系统,和它一步步暴露出的问题先说下背景。这个代号为"arch-system"的架构改造项目,源于团队负责的一条核心业务链路。最初的系统是典型的三层单体:一个应用服务承载所有接口,MySQL …

2026/10/20 6:03:23 阅读更多 →
PPT-Master:用PowerPoint构建业务操作系统的方法论

PPT-Master:用PowerPoint构建业务操作系统的方法论

1. “PPT-Master”不是软件名,而是一类人的生存状态最近在几个技术协作群和设计交流社区里,“PPT-Master”这个词高频出现,但没人把它当产品名说——它更像一句带点自嘲又透着狠劲的行业暗号。我第一次听到是在某次跨部门复盘会上&#xff0c…

2026/10/20 6:03:23 阅读更多 →
图灵奖60年:人机环境系统智能的演进与落地

图灵奖60年:人机环境系统智能的演进与落地

六十年前,那个以一位计算机先驱命名的奖项第一次颁出时,大概没有人想到,它会成为一部无声的“智能观变迁史”。这六十年间,获奖成果背后的工作其实都在回答同一个问题:机器到底怎样才算有智能?答案从“会算…

2026/10/20 6:03:23 阅读更多 →
浙江高考VB排序系列:冒泡与选择排序代码实现及应试技巧

浙江高考VB排序系列:冒泡与选择排序代码实现及应试技巧

1. 从一道排序题说起:为什么VB排序值得单独拎出来讲每年到了技术科目备考的冲刺阶段,总有一批同学在排序算法这块反复栽跟头。选择题里问“冒泡排序第三轮结束后序列长什么样”,填空题里给一段残缺代码让你补全循环边界,上机操作题…

2026/10/20 6:03:23 阅读更多 →
图灵奖六十年:从机器能否思考到人机环境系统智能的跃迁

图灵奖六十年:从机器能否思考到人机环境系统智能的跃迁

图灵奖整整六十年了。作为计算机科学领域最负盛名的荣誉,它这些年一直被当作衡量学术巅峰的标尺。可如果你把六十年来历届获奖者所代表的方向串成一条时间线,会发现一个远比"学术成就"更有意思的东西正在浮现:整个领域对"智能…

2026/10/20 6:03:23 阅读更多 →
主动学习新思路:损失预测模块如何精准筛选高价值样本

主动学习新思路:损失预测模块如何精准筛选高价值样本

1. 为什么主动学习要换一种采样思路做深度学习项目,尤其在数据标注预算有限的时候,大家最先想到的办法多半是“先随便标一部分,训练一版模型,再用模型挑一些‘难样本’送给标注员”。这套逻辑本身没问题,难就难在“难样…

2026/10/20 6:02:23 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →