A.性能优化相关知识

一、综合优化

1、降低屏幕分辨率尤其是在android平台对性能提升很大。可以有效缓解gpu的压力。

  我们在android上分辨率是实际的0.85左右。

2、做好资源异步加载,实现一个实例化队列,可以很大程度上减少卡顿。

3、做好超量的模型和特效屏蔽,可以有效减轻cpu压力。

4、善用工具。比如Unity Profiler、Snapdragon Profiler等,针对性的对性能瓶颈进行优化。

5、玩家头顶血条的HUD要使用3D的,而不是UGUI。否则同屏玩家数量很多的时候Mesh合并开销很大。

6、UI上使用TextMeshPro。可以很大程度上缓解UI打开卡顿的问题。描边、阴影开销很低。

7、控制帧率。现在高刷新率的手机非常多。不要直接使用VSyncCount控制帧率了。否则在120hz刷新率的手机上vSyncCount=1会有120fps的帧率。直接使用targetFrameRate=30来设置帧率。

 

二、优化的经验

(一) UI的性能优化

1、写一个UICollider而不是透明的Image,可以减少overdraw

2、小地图用shader实现指定位置的图片渲染,而不是RectMask2D,可以减少overdraw。因为RectMask2D是使用alpha=0来实现裁剪的。

3、小地图的玩家标识,聊天界面,都添加Canvas,目的是动静分离。

4、使用TextMeshPro。减少GC,减少字体生成的开销。字体放大缩小依然保持锐利清晰。

5、玩家头顶的HUD,比如血条和名字,使用3D的TextMeshPro和SpriteRenderer,目的是避免UGUI的mesh计算开销。MMO中的头顶血条可能会有同屏几百个人。

  血条的减少动画之前是Image和DOTween来实现的。后面修改为shader实现。(坐标计算)

6、战斗飘字,原先是DOTween来实现的,后面修改为直接在Update里面计算坐标。目的是减少DOTween动画初始化的GC开销。自己实现简化版的动画,性能也更好一些。

  战斗飘字还是用UGUI来实现。主要是因为这里还是美术给的艺术字。而且飘字只有玩家自己才会显示,数量不会很多。

7、实现一个高效率的 FindChlid 函数。因为在写UI的时候查询控件对象是非常常见的操作。如果不做优化,使用 gameObject.name == "xxx" 来做比对的话,可能会产生很多的GCAlloc。

8、使用SimpleAnimationComponent 来做UI动画,而不直接使用Animator。因为Animator在动画播放完毕之后,依然会Update。这会导致两个问题,一个是性能隐患,另外一个是被动画控制的控件无法再通过代码设置位置。在动画播放完毕之后再禁用动画组件,实现起来比较复杂。相比而言,直接使用SimpleAnimationComponent就要简单干净很多,也更加高效。

9、禁用不必要的raycastTarget。

10、实现一个UICircleImage来替代用Mask实现的圆形遮罩裁剪。一般64个点就可以形成圆形。外部再罩一个边框图,就可以消除边缘锯齿。

 

(二) 场景的性能优化

1、要勾选StaticBatch,但是不能滥用。有color、uv3的,顶点超过4000个以上的,数量超多,但是同屏显示不多的模型。这些都不应该勾选StaticBatch。否则会导致包体积明显增大。因为StaticBatch会把模型都build到场景的ab包内。

2、注意压缩纹理的使用。法线应该用etc2,ios下用astc6x6,法线需要更高的精度,要避免压缩纹理导致的失真。

3、避免模型和贴图勾选 readable选项。这个可以在模型和纹理导入的时候做设置。

4、光照贴图和shadowmask图的压缩纹理选项。ios下可以统一使用astc6x6。android下shadowmask图使用rgb16,否则阴影会有明显的模糊或者锯齿。lightmap图倒是没有太大限制,尽量使用压缩纹理即可。

(三) 战斗的性能优化

1、设计一套完善的屏蔽规则。保证玩家自己的模型和特效显示。

2、异步加载资源,模型、特效和声音。缓存池的使用。

3、同屏玩家数量很多的时候,屏蔽超额的模型、特效和技能流程。只保留技能数值逻辑即可。

  注意,屏蔽特效要以玩家为单位进行屏蔽。我们之前以特效为单位屏蔽会出现坐骑身上左翅膀有特效,右翅膀没有特效的情况。

4、更多的细节优化。比如lua到C#的调用。一些频繁调用的接口,能用简单类型做参数,就不要弄一个结构体出来。xlua有针对这里做NoGC的性能优化。

5、缓存,预加载特效。两个预加载时机,游戏初始化的时候,或者技能模板初始化的时候。

(四) 内存的性能优化

1、压缩纹理的使用。

2、合理的释放不必要的资源。引用计数。定期UnloadUnusedAssets

3、粒子系统缓存占用的内存。一个ParticleSystem占用8k内存。特效缓存的多了,可能会占用几十兆内存。

4、Shader Lab内存。变体多了,加载的shader多了。这块儿的内存占用可能会比较大。三四十兆都是有可能的。

5、Lua配置的内存优化

5.1、我们业务逻辑都是lua写的,所以配置直接导出为lua文件,而不再需要有额外的解析过程。

5.2、lua中(luajit)没有整型,所有类型都是double。所以与C++相比配置文件超级占内存。我们现在lua占用内存启动游戏后会有40兆左右。其中30兆都是配置文件所占用的内存。

5.3、导出的配置的格式是数组结构,不是key value结构。通过给每个条目设置metatable,业务层同样可以用key来访问对应的数据。这样可以节省一半以上的内存。

5.4、客户端不用的列不用导出。避免浪费。

5.5、超大的配置,可以导出为sqlite。这样只有需要的时候才会加载对应的数据,而不会把整个表格都加载进来。

5.6、C#用到的配置,直接导出为json。不要导出为lua又再设置给C#。

(五) 卡顿的性能优化

1、GCAlloc。可能发生GCAlloc的情景。比如实例化资源,new对象。以及gameObject.SetActive、闭包调用、gameObject.name读写等等。

2、通过Profiler查找热点是什么,针对性的进行优化。

3、不要频繁调用activeSelf=true。要先做好判断,只在需要以及必要的时候调用。

4、特效不用的时候,停掉ParticleSystem,然后把特效丢到很远的地方,而不是active。同样是减少开销大的接口调用。

5、像图片不显示可以把alpha=0,或者文字不显示可以直接设置一个空的字符串。而不是直接active禁用。这样也可以提升效率。

6、lua调用C#的时候尽可能减少字符串的传递。字符串在lua和C#的交互过程中不可避免的会产生多份内存开销,且有可能还会有编码转换的开销。比如lua中获取一个组件,可以用组件Type作为参数传递,而不是组件名。

7、注意字符串比较时的参数传递。一般都是Ordinal。使用Culture的参数会考虑国际化因素,性能较低。同理,可以实现一个 StartWithFast,简单进行字符比对。它会比C#默认的StartWith快很多。

8、使用同一的CoroutineManager而不是直接用MonoBehaviour的StartCoroutine,可以提高性能。

9、尽可能的减少MonoBehaviour的Update的调用。比如我们的Actor,都是通过ObjectManager来驱动Update。

10、Unity的Profiler不会跟踪主线程之外的GCAlloc分配。如果在子线程需要进行分析,可以考虑把子线程切换的主线程进行调试,或者使用功能BeginThreadProfiling API。

11、在每帧执行的代码中,尽可能避免闭包。减少匿名方法。这些可能会产生GCAlloc。

12、避免使用枚举作为字典的key。会有装箱操作。原因是enum为值类型,Dictionary实现会调用Object.getHashCode获取key的哈希代码,这里期望的是引用类型。

  可以考虑强制转换为int即可。或者实现一个 IEqualityComparer。

13、foreach 虽然在5.5的版本以上不再有因为装箱产生的GCalloc的开销。但是与for相比还是有性能差距。所以在调用不频繁的地方,可以使用foreach以提高可读性。频繁调用的地方还是推荐直接用for进行遍历。

14、慎用 mesh.vertices 等接口。它每次调用都会生成一个新的内存副本。同理 Input.touches类似。

15、Physics的接口中也会有对应的NonAlloc版本。

16、C#的string是不可变的,任何SubSting等操作都会产生新的副本。

(六) 一般优化

1、按ID寻址属性。比如 Animator、Shader都有对应的接口。Animator.StringToHash。Shader.PropertyToID。

2、使用非分配物理API。替换Physics.RaycastAll为Physics.RaycastNonAlloc等。

3、UnityEngine.Object == null 比纯C#对象判定成本要高很多。因为它要判定对象(可能是资源)是否存在,是否有被Destroy掉。

4、减少矢量和四元数的数学计算。控制运算顺序。

5、隐形颜色字符串转换的时候 (#RRGGBBAA),使用一个 ColorUtility 的API会更加高效,且可以避免GCAlloc。

6、尽可能避免使用 Find 或者 FindObjectOfType

7、尽可能减少 Camera.,main 的调用。它内部会调用 Object.FindObjectWithTag。在Start中进行缓存。

8、调试代码可以增加 [Conditional("DEBUG")] 这样的标签。防止开发版本的代码或者日志发布出去。频繁打Log会对性能有严重影响。

9、不要用 type[x, y] 这样的多维数组。性能很低。

10、Update统一放到管理器里面进行更新。而不要每个对象一个Update。

11、合理使用C#的委托。每次添加或者删除回调的时候,C#的委托都会执行回调列表的完整拷贝。所以不要在Update中进行委托的添加或者删除回调的操作。如果有频繁添加的需求,可以考虑使用List维护回调数组而不是委托。

12、手工编码的 String.StartsWithFast 会比内置方法快 10~100倍。

13、Vector3.zero 会返回一个新的Vector3对象。虽然因为其是值类型,远比引用类型性能要高。但是频繁调用的地方还是应该维护一个const的对象用来进行比对或者赋值。

14、更新材质属性的时候,使用MaterialPropertyBlock。性能更好。且可以避免实例化一份新的材质对象。

15、AlphaBlend会比AlphaTest性能要好一些。因为移动平台的GPU会有EarlyZ的优化,而AlphaTest会使EarlyZ无效。

16、低版本的Unity上使用的是PhysicX 2的版本,移动没有刚体的静态碰撞体会导致整个物理世界重建,会有较大的开销。在新版本的Unity里面已经升级到 PhysicX 3,解决了这个问题。

17、使用SimpleAnimationComponent来替代Unity的Animator来做UI动画。主要是Animator会一直更新,即便动画已经播放完毕了。这个一方面会有性能问题,另外一方面被动画驱动的控件无法再通过脚本移动。

18、统一封装 Time.deltaTime和 Time.realTimeSinceStartup。因为这个调用是有一定开销的,至少存在C#到C++的调用。统一在入口Update处调用并缓存。在大量业务逻辑调用,直接取缓存的值。

 

(七) Lua的性能优化

1、扩展Unity的API,简化.localPosition等调用的交互次数。

  尽可能的减少lua和C#的参数传递。比如通过扩展Unity接口,实现SetPosition直接给gameObject或者Component设置坐标,而不用 go.transform.position = xxx 这样设置坐标。

2、减少使用 os.date 函数。会有明显的内存分配。

3、在Update中频繁执行的代码,避免各种临时表的分配。

4、配表的内存优化。

5、使用 table.concat 组合字符串,而不是 .. 连接。因为字符串每次 .. 都会产生一份新的字符串内存。

6、尽可能避免数组、字典或者自定义类型的交互参数,这会产生大量的GCAlloc。如果是数组,可以考虑使用一个循环遍历调用。

7、尽可能避免lua到C#传递字符串参数。传递字符串操作不可避免的会有多份内存开销,C#需要把lua的字符串内存拷贝到托管堆中,这是性能低下且有GCAlloc的。

  比如我们GetComponent获取类型,就统一使用type(CS.XXX)这样的类型做参数,而没有使用字符串获取组件。无论从交互的角度考虑,还是在C#内部获取组件的效率考虑,都会获得更好的性能。

 

(八) Shader的性能优化经验

1、使用Mobile版本的shader。比如Particle/Additive中有ColorMask,这个在移动平台比较耗。

2、避免使用昂贵的数学函数。比如 pow exp log cos sin tan 等。

3、尽可能减少纹理采样数目。

4、如果有一些计算比较复杂,可以使用查找纹理(lut)

5、优先使用低精度的数字格式。优先使用half。在现代gpu上fixed等同于half。部分对精度有特殊需求的情况下才使用float。个别情况下,尤其是与法线相关的时候,使用half容易因为精度不足导致渲染结果错误,这个时候还是应该使用float。

(九) 资源规格

1、模型角色高模 6000+面,低模 3000面。顶点数不定,因为顶点存在共用的情况,所以顶点数量可能是面数的两倍,也可能比面数低。纹理使用1024大小的贴图。低模纹理大小减半。主角因为有高低模,所以不开mipmap。个别精度比较高的npc(有UI显示需求)需要开mipmap,否则场景中会有明显的闪烁。

2、场景的drawcall控制在200以下。个别场景因为美术需求,drawcall可能会更高一些,但是SetPassCall也要尽可能保证比较小(材质尽可能共用,可以有效减少SetPassCall)

3、场景的面数在100k~300k之间都是合理的数值。

4、UI的drawcall100以下,一般就是三四十常驻UI Drawcall。

(十) 性能优化的常用工具

1、Unity Profiler。deep profile。

2、Miku-LuaProfiler

3、Frame debugger

4、Snapdragon Profiler或者RenderDoc

5、Xcode的instrument

6、Intel GPA

 

B. 渲染相关知识

一、渲染管线

  输入3D模型,输出2D图片。主要分三个阶段。应用程序阶段、几何阶段、光栅阶段。

1、应用程序阶段:CPU负责。准备场景数据、Culling剔除、设置模型的渲染状态、渲染三角面。

2、几何阶段:GPU负责。顶点变换、光照、裁剪、投影、屏幕映射。简单理解为顶点着色器。

3、光栅化阶段:GPU负责。像素着色器。计算每个像素最终的颜色。

4、GPU流水线:

  4.0 应用程序阶段数据

-------------- 几何阶段

  4.1 顶点着色 (模型变换、视图变换、顶点着色)

  4.2 裁剪 (投影变换、裁剪)

  4.3 屏幕映射 (视口变换)

-------------- 光栅化阶段

  4.4 三角形设置和遍历

  4.5 像素着色

  4.6 混合 (Alpha测试、模板测试、深度测试、Alpha混合)

最终输出到屏幕(帧缓存)

5、如果没有使用AlphaTest。则移动的GPU大多会进行EarlyZ的优化,提前丢弃掉不需要绘制的片元。但是开启AlphaTest之后,就必须执行像素着色器才能知道是否要丢弃掉这个片元。ZTest就只能在像素着色器执行之后再执行。所以AlphaTest性能会比AlphaBlend低。

6、模板测试。比较参考值和模板缓冲区的模板值,决定是否舍弃该片元。

7、深度测试。ZTest。比较当前深度值与深度缓冲区中的深度值,决定是否舍弃该片元。

  通过ZWrite和ZTest的灵活运用,可以实现很多效果。比如某个特效一定要显示在所有模型之前。

8、Alpha Blend。

二、渲染管线、SRP、URP、HDRP

1、SRP。Unity提供了一套C#的API,可以定制渲染管线的内容。

2、URP。通用渲染管线。用于移动平台。

3、HDRP。高清渲染管线,用于主机平台。

三、PBR

1、核心理论是微表面原理。任何一个物体,都处理为无数细分的微平面,然后处理光线反射。

2、遵循能量守恒。即,入射光线能量等于反射光线能量。

3、达到的效果是更加真实的光照表现。且在各个灯光环境下表现都是合理的。极大简化了美术的制作难度,因为只要遵循统一的标准去做,结果就是对的。

4、PBR应该在线性空间制作。这个需要在项目初期就定好。

5、BRDF 双向反射分布函数。给定一个入射角度和观察角度,给出一个最终射向观察角度的光的强度系数。

  我们游戏中使用的是BRDF2。BRDF1开销比较大,BRDF2是lut,效果比较差。

6、直接光照。漫反射+高光(GGX)

7、间接光照(IBL,Image-Based Lighting)。Unity烘焙场景的时候会生成一个ReflectionProbe的CubeMap。通过textureCubeLod对这张cubemap的多个mipmap层级采样,进行差值计算,得出不同粗糙度下的反射。

8、Albedo图是物体基础颜色,不带光照信息

  Normal图是法线图,由高模烘焙出来。

  PAC图,rgb通道分别代表metallic、smoothness和emission。

9、金属工作流和反射工作流

10、高光抗锯齿。有可能我们在屏幕中看高模会有白色噪点闪烁的现象,这个可以用高光抗锯齿来解决。或者降低纹理精度。

 

四、功能的实现

1、平面阴影的推导

2、镜面反射的实现

用一个摄像机在正确的角度绘制场景和角色。输出的RenderTexture作为纹理叠加到目标区域,即可实现目标区域的镜面反射效果。

3、距离雾、高度雾、体积雾

正常Unity是距离雾,根据摄像机远近控制雾的浓度。有的时候我们需要实现根据高度控制浓度的高度雾。比如悬崖或者高山。

4、换色如何实现

5、贴花如何实现

6、流光如何实现

7、死亡溶解效果如何实现

8、角色被遮挡的xray效果如何实现

  主角两个pass。第二个pass被遮挡的时候(zTest的时候当前深度值大于自己)叠加到目标上。

  需要保证场景先画,然后再画主角,最后画其他玩家、怪物等。

9、角色残影效果如何实现

  BakeMesh。缓存。使用Graphic.DrawMesh绘制。也可以实例化GameObject,然后绑定上MeshFilter绘制。

10、屏幕空间扰动效果如何实现

  移动平台不要用GrabPass。开销很大。

  做后处理。特效渲染的时候输出扰动区域到一个纹理上,然后后处理根据这个区域做扰动效果。

 

五、其他

1、菲涅尔效应。边缘光。模拟物体边缘漏光。越靠近边缘的地方越亮。

  游戏中有两个菲涅尔效果。一个是PBR本身的,颜色跟灯光相关。另一个是定死颜色,在程序中控制,用来做高亮选择或者受击闪白这样的特效。

2、GammaSpace、LinnerSpace

  GammaSpace是为了早期为了应对晶体管显示器。

  在Gamma空间下,一旦亮度调高,白色就会爆亮。而在线性空间下,就可以很柔和的进行过度。

3、HDR、Tone Mapping

  HDR渲染出的亮度值可能会超出显示器最大亮度,也就是值会大于1。

  HDR常跟Bloom结合起来使用,HDR大于1的部分就是发光的部分,Bloom会做光晕的溢出。如果没有HDR,就无法很精确的控制哪些区域应该有光晕。效果就是一个全屏幕的泛光。

  为了将光照结果转换为显示器能够正常显示的LDR。就需要通过Tone Mapping将颜色值做个映射。

4、次表面散射(SSS)

5、Depth Buffer 深度缓冲区

6、Stencil Buffer 模板缓冲区

7、CommandBuffer

8、PostProcessing

9、Shadow Mask、Distance Shadow Mask

 

六、数学相关

1、向量点乘 dot 结果是一个值(标量)。

  两个向量点乘等于两个向量的模乘以向量夹角的余弦值。

  几何意义是一条边在另外一条边上的投影,再乘以另一条边的长度。

  两个向量点乘,可以得到两个向量的cosAB。通过这个可以判断两个向量的相似性。

  计算两个向量的夹角:<a,b>= arccos(a·b / (|a|·|b|))

  根据夹角可以判定敌人是在玩家身前(点乘的结果大于0)还是身后(点乘的结果小于0)。

2、向量叉乘 cross

  两个向量叉乘,结果还是个向量,向量垂直于两个向量平面。方向由选用左手坐标系还是右手坐标系而定。Unity是左手坐标系。

  通过叉乘判定a向量到b向量的最小转向角度。

  叉乘可以计算平面的法线向量。

3、总结,点乘可以判定目标是在我的前方还是后方,大于0在前方,小于0在后方

  叉乘可以判定目标是在我的左边还是右边,得到的向量的Y大于0在右方,小于0在左方。

3、矩阵乘法

4、欧拉角和四元数

5、Blinn-Phong的光照公式。L = 漫反射颜色 + 高光反射颜色

6、Unity是左手坐标系,x正方向向右,y正方向向上,z正方向向屏幕里。

 

七、实际项目经验

1、控制矩阵和向量的计算顺序。减少矩阵乘法。

2、尽可能避免if等分支选项。step并不能有效提升性能,跟if差不多。

  这里要说明的是,性能损耗最大的是branch的if。

3、尽可能减少 cos、tan、pow等数学函数。比如我们在模拟线性空间的计算的时候,使用 x*x替代了pow(x, 2.2)

4、尽可能减少纹理采样数量。

5、pow的参数必须是大于0的。如果参数小于0,可能在某些手机上存在问题,显示为黑色。应该使用 saturate 函数括一下,保证其为正数。shader兼容性问题。

图文无关

C. 图形渲染进阶知识

零、前言

  我并不是图形学专业,也不是做引擎开发的,对图形渲染的理解都是工作中零零碎碎学到的碎片化知识。我所理解的东西并不保证准确甚至可能有错误。最近在整理资料的过程中,对之前模糊的概念有了进一步的认识,所以在这里记录下来。期望能对还不了解这些概念的人以帮助。

  有很多东西其实是可以融会贯通的。比如我们常听人说AlphaTest性能低,如果更进一步了解Early-Z、HSR、TBDR之后,就可以理解为什么Unity要先渲染不透明物体,再渲染半透明物体。我们常听人说Drawcall影响性能,更进一步了解渲染管线,知道什么是Drawcall,什么是渲染状态,就会更进一步了解SetPassCalls是什么东东。

  理解本文中列举的几个关键知识点,也就可以对渲染优化有一定的概念了。回过头可以再找几篇显卡厂商的优化相关的文章做参考。

一、渲染管线

(一)、应用程序阶段:

1、粗粒度剔除,把不在屏幕内的模型剔除掉。

2、传递顶点等参数给GPU,即Drawcall。

(二)、几何阶段:顶点着色器

1、计算顶点的世界坐标

  float4 posWorld = mul(unity_ObjectToWorld, v.vertex);

2、得到切线空间到世界空间的转换矩阵

  o.tangentToWorldAndPackedData

3、计算顶点光照

  o.ambientOrLightmapUV = VertexGIForward(v, posWorld, normalWorld);

  场景是使用Lightmap。所以这个参数存放的是lightmap参数

  角色没有使用lightmap,一般都开启顶点光照。所以这里存放的是球谐光照结果。Light Probe。

 

总结,顶点着色器的工作就是根据输入的顶点坐标等参数,转换成世界坐标,求得切线空间到世界空间的转换矩阵,计算顶点光照、顶点雾等参数。输出结果给像素着色器使用。

(三)、光栅化阶段:像素着色器

1、把法线图取到的法线转换成世界法线

  s.normal = TangentToWorld(i, s.normal);

2、得到 albedo、spec和反射率

  half oneMinusReflectivity;s.albedoColor = LIGHTING_SETUP(s, s.specColor, oneMinusReflectivity);

3、GI

3.1、设置光照。

   o_gi.light = data.light;o_gi.light.color *= data.atten;

3.2、间接光的diffuse。静态物体是Lightmap,动态物体是球谐光照。

  Lightmap:

o_gi.indirect.diffuse = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy));

  or 球谐光照:

o_gi.indirect.diffuse = ShadeSHPerPixel(s.normal, data.ambient, data.worldPos);

3.3、间接光的specular。

  对天空球进行采样,根据粗糙度取到不同的mipmap的反射cube。光滑表面取到的图片精度较高,能反射清晰的天空球。粗糙的表面取到的精度比较低,反射看着就比较模糊。

half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflect(s.eyeVec.rgb, s.normal), perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS) * (1-perceptualRoughness*0.5);
o_gi.indirect.specular = DecodeHDR(rgbm, unity_SpecCube0_HDR);

3.4、我们额外做了一个把漫反射的lightmap合并到specular上的操作,防止金属丢失lightmap信息。因为按照计算,金属反馈高光比较强烈,但是完全丢失lightmap效果就不太好。

o_gi.indirect.specular += max(0, o_gi.indirect.diffuse - UNITY_LIGHTMODEL_AMBIENT.rgb * 0.1 - unity_IndirectSpecColor.rgb);   //additive blend

4、PBL

4.1、GGX CookTorrance

  half specularTerm = roughness / (s.eyeVec.a * (1.5h + roughness) * d);

4.2、Diffuse

  half3 color = s.albedoColor * (gi.indirect.diffuse + gi.light.color * diffuseTerm);

4.3、高光

  color += saturate(specularTerm * nl * gi.light.color * s.specColor);

4.4、菲涅尔

 color += surfaceReduction * gi.indirect.specular * lerp(s.specColor, saturate(s.smoothness + (1 - oneMinusReflectivity)), fresnelTerm);

 

总结,像素着色器最终得到的就是一个颜色值,由输入的纹理+光照得来。光照分直接光和间接光。直接光由漫反射(Diffuse)和高光(Specular)组成。间接光由Lightmap、ReflectionProbe得来,这些图都是Unity烘焙场景时得到的,IBL说的就是间接光的处理。最后再加上PBR中常见的菲涅尔效果的计算。

(四)、延迟渲染(Deferred Rendering)和前向渲染(Forward Rendering)

1、延迟渲染会先进行顶点着色,把模型都渲染到屏幕上,然后再进行光照等复杂逻辑的计算。

好处是多光照模型下,性能很好,效果也很好。

2、延迟渲染一般分成两个步骤(2个Pass)

  第一个Pass渲染G-Buffer。正常渲染一遍场景,经过顶点着色器模型坐标变换和片段着色器,计算色彩(diffuse),法线(normal),高光(specular)、深度(depth)、阴影(shadow)等,并把结果缓存到内存中备用。

  第二个Pass利用G-Buffer贴图中的数据重构每个片段的位置信息并进行逐光源的光照计算。最后结果会叠加到光照计算结果和阴影等输出最终的像素颜色。

3、延迟渲染的好处是可以处理多光源的情况。缺点是无法正确处理半透明,且会消耗更多的显存带宽。

4、还有一种 Forward+ 渲染。思路是将屏幕划分为一个一个的块儿,控制每个块儿的影响灯光数量,从而减轻运算压力,让前向渲染也可以处理多光源的情况。不过这个貌似并没有被广泛应用。主流游戏引擎还都是延迟渲染+前向渲染。

5、在移动平台下,我们都是使用前向渲染。因为从需求来说,手机游戏一般只有一个实时方向光,几乎没有或者很少使用实时点光源,有实时动态光照的需求,一般都是使用LightProbe解决。这种情况下因为灯光数量很少,延迟渲染没有应用的意义。另外,移动平台设备基本上都是TBDR架构,这种情况下相当于硬件层面做了延迟渲染的活,我们在软件层面就更加没有使用延迟渲染的必要了。

二、线性空间与Gamma空间的理解

(一)、什么是Gamma校正 (Gamma Correction),为什么要进行Gamma矫正

1、早期CRT显示器,输入的电流和显示的亮度不是线性关系,波形是一个下弦曲线(Gamma2.2,即Pow2.2,颜色值会经过2.2的幂计算)。这个影响参数就是Gamma值。

  为了正确显示颜色,需要对输出给显示器的颜色进行Gamma校正(Gamma1/2.2,一个上弦曲线,Pow0.45)。

2、人眼睛对暗部的分辨程度要明显高于对亮度的分辨程度。进行Gamma校正,可以更好的保存有效颜色信息。

3、现代的液晶显示器虽然没有电流和亮度的问题。但是一方面为了兼容CRT显示器,另外一方面Gamma校正也有显示意义,所以现在的显示器都保留了Gamma校正。

4、如果将来科技进步了,人们以32位去保存颜色信息而不是现在的8位,那么Gamma校正就没有存在的价值了。

(二)、sRGB颜色标准

1、我们通过相机拍摄的图片,或者是ps保存的图片,默认都是以sRGB标准存储的,颜色经过Gamma0.45的校正。颜色值经过 Pow0.45 存储,显示器显示的时候会进行 Pow2.2,那么最终显示的结果就是真实的颜色值。

2、视觉表现上,Gamma0.45 会使图片变亮,Gamma2.2 会使图片变暗。

(三)、Gamma空间下的处理流程

1、输入的图片是sRGB标准的图片,Gamma0.45。

2、直接将采样结果带入光照公式计算。将结果写入FrameBuffer。

3、显示器经过 Gamma2.2,最终显示成正确的颜色。

(四)、线性空间下的处理流程

1、如果图片本身就是线性存储的,那么就直接采样即可。

  如果图片是sRGB存储的,则需要进行 Remove Gamma Correction(Pow 2.2),将颜色转换到线性空间。

  OpenGLES3.0有硬件指令支持,不需要对每个像素执行Pow操作,否则性能太低了。这也是为什么线性空间需要OpenGLES3.0的原因。

2、光照计算在线性空间进行。计算完的颜色进行 Gamma校正(Pow 0.45),转回Gamma空间。这里同样有硬件指令支持。

3、显示器经过 Gamma2.2,最终显示成正确的颜色。

(五)、为什么PBR都应该使用线性空间

1、各种光照公式都是在线性空间进行的。比如,1的亮度就应该是0.5的亮度的2倍。但是在Gamma空间下,图片是 Gamma0.45 处理的。这个系数被带入光照公式中,计算结果显然就不对了。表现结果是亮的地方很容易就曝光严重。

2、选择Gamma空间,则引擎不会对输入和输出做Gamma校正。而因为图片存储时都是经过Gamma校正的,所以光照计算带入了 Gamma0.45,最终得到的颜色就跟实际光照结果有偏差了。

3、选择线性空间,则光照计算都是在线性空间下计算的,输出的时候才进行Gamma校正转回Gamma空间。所以光照结果是准确的。

(六)、Unity中纹理 sRGB 选项

1、Gamma空间下,引擎不会对图片做Gamma校正,是否勾选sRGB选项无影响。

2、线性空间下,勾选sRGB选项,则代表图片是在Gamma空间存储的。引擎在加载这些图片的时候会先执行 Remove Gamma Correction 的操作,恢复到线性空间。

3、线性空间下,如果美术工作流程已经统一,图片输出的时候存储在线性空间,则不需要勾选 sRGB选项。反之,存储在Gamma空间的,则需要勾选。

4、类似的,shader中输入的颜色默认也会被认为是 sRGB 颜色,会自动进行 Remove Gamma Correction 的操作。而如果自己定义的 Float 参数也想 Remove Gamma Correction,则需要在参数前添加 [Gamma] 的前缀。

三、TBDR、Early-Z和渲染顺序

(一)、GPU架构

1、GPU的渲染架构有 IMR(Immediate Mode Rendering,主要用于PC平台),TBR(Tile-Based Rendering,主要用于移动平台)和TBDR(Tile-Based Deferred Rendering,针对TBR做了进一步优化,主要是PowerVR在用)。

2、大部分手机的GPU用的都是手机的System memory和一块容量很小的,带宽比System memory更高的专供OnChip memory。

  SRAM,GPU的OnChip memory。可以理解为小区的便利店。虽然比较小,但是访问速度很快。

  DRAM,显存,离GPU较远,可以理解为市中心的超市。比较大,但是访问速度慢。

  从GPU对FrameBuffer的访问,就相当于一辆货车大量的在家(GPU)和市中心超市(DRAM)之间往返运输。带宽的消耗和发热量之大,是手机上无法接受的。

3、对移动平台而言,功耗是第一位。因为功耗意味着发热量、耗电量、芯片大小等等。

  对功耗影响最大的是带宽。所以对移动芯片而言,第一考虑的不是渲染性能,而是如何通过缓存减少带宽消耗。即,减少对显存的访问。

(二)、IMR、TBR和TBDR

1、IMR(Immediate Mode Rendering),是立即渲染模式。每个像素渲染的时候直接访问DRAM,并写入到FrameBuffer上。PC平台的显卡都是IMR架构。

2、TBR(Tile-Based Rendering),基于Tile渲染。适合移动平台。

  为了减少GPU访问SystemMemory的次数(延迟高、功耗高),将屏幕分成一小块儿一小块儿,确保这一小块渲染所需要的绝大部分数据都能同时装进小小的OnChip memory,从而实现整个渲染大部分操作都可以在带宽较高的OnChip memory上完成。

  TBR是以牺牲执行效率为代价,换来功耗降低。在移动平台直接访问FrameBuffer会有很大的带宽开销,进而影响功耗。所以TBR把屏幕分成格子之后,每个格子可以访问SRAM(OnChip memory),一整块都访问好之后,再整理转移回DRAM。

3、TBDR(Tile-Based Deferred Rendering),基于Tile的延迟渲染。只对玩家能看到的像素做 pixel shader。通过HSR将不可见的点剔除掉。大幅减少对显存带宽的消耗。

  HSR,Hidden Surface Removal,隐藏面消除。在光栅化阶段真正开始前实现像素级裁剪。

4、TBDR,相对于IMR,多了一个FrameData的数据,里面包含了有效信息,可以进行剔除操作。

  TBR架构下,是不能来一个CommandBuffer就处理一个的,因为任何一个CommandBuffer都可能会影响到整个的FrameBuffer,如果来一个就画一个,那么GPU可能会在每一个DrawCall上都来回搬迁所有的Tile。所以TBR的策略一般是对于CPU过来的CommandBuffer,只对他们做VetexProcess,然后对VS产生的结果暂时保存。只有必须刷新整个FrameBuffer的时候(比如Swap Back and Front Buffer、glFluash、glReadPixles等等)才会真正的做光栅化。

  这个暂存的数据就是FrameData。FrameData是TBR特有的在GPU绘制时所需的存储数据。既然TBR是等待所有的FrameData数据一起绘制pixel,那么就可以实现Deffered Rendering。硬件巧妙的利用TBR的FrameData队列实现了一种延迟渲染。即,尽可能只渲染那些最终影响FrameBuffer的像素。

5、为什么PC平台不使用TBR?因为实际上直接对DRAM进行读写速度是最快的。TBR需要一块儿块儿的绘制然后往DRAM拷贝。可以简单理解为TBR是牺牲了执行效率,来解决更重要也更难处理的带宽功耗。

(三)、Early-Z和HSR

1、现代显卡(无论是IMR还是TBR),会在执行像素着色器之前,先进行一轮深度测试,就是EarlyZ。以避免会被深度测试剔除的片元,执行复杂的像素着色器的逻辑。这样可以减少显存带宽的消耗。

  如果没有Early-Z,那么很有可能屏幕上一个像素点会被渲染七八次,显存带宽消耗成倍的增加。

2、AlphaTest在像素着色器才会执行clip操作,才知道会不会剔除这个点。因此使用AlphaTest后,EarlyZ会无效。所以AlphaTest在移动平台性能比较低。

  discard或者clip会导致Early-Z Culling无效。

3、HSR,Hidden Surface Removal,隐面剔除。这个是PowerVR的专利技术,它可以在硬件层面对被遮挡的点进行剔除。它可以保证屏幕上的点不会被重复渲染,比Early-Z更加高效。

  支持HSR的设备(一般是iOS设备),可以不用对物体进行排序,因为HSR已经可以保证裁剪掉被遮挡的片元,也就不依赖Early-Z了。

  对不支持HSR的设备,还是需要对物体进行排序,以尽可能的利用好Early-Z。

4、HSR比Early-Z更加高效。

  一方面不用对物体排序了,省去了软件层面排序的CPU开销。

  另外一方面Early-Z无法有效保证一个点不会被重复渲染。比如一个超大的模型,软件层面排序应该是离摄像机较近的,应该先渲染,但是实际上它的很多点都是被遮挡的,应该被剔除掉。

(四)、渲染顺序

1、不透明物体,离摄像机近的先绘制,这样它会因为ZTest剔除掉后面的渲染内容,性能更好。

2、半透明物体,必须从后往前画,先画离摄像机远的物体,才能保证渲染结果正确。

3、shader非常复杂的模型,尽量后绘制。比如T4M的地表shader,采样了七八张图纹理,那么它最后绘制,更加容易被Z-Culling剔除掉。

4、不透明物体(2000)----AlphaTest物体(2450)----半透明物体(3000),这个渲染顺序有利于HSR或者Early-Z的优化。

  Alpha-Test 在不透明物体绘制完毕之后再绘制,可以避免Alpha-Test导致EarlyZ失效,最后绘制,至少不会影响到之前不透明物体的EarlyZ。

5、RenderQueue2500,区分了不透明和半透明。半透明物体(2500以上)永远在不透明物体(2500以下)后绘制。

  如果物体的RenderQueue在2500的同一侧,则sortingOrder优先级更高:

Camera Depth > Sorting Layer > Order In Layer > RenderQueue > 距离相机的距离

(五)、TBDR的相关优化

1、不使用FrameBuffer的时候及时Clear。在RenderTexture上,当不使用RT之前,调用一次Discard,可以在某些移动设备上提高性能。

2、每帧渲染之前尽量Clear。

3、对于大部分Android设备,预先进行的Early-Z pass可能可以大大减少overdraw。Early-Z发生在整个光栅化之前,因为它处理的是FrameData。

  对于iOS设备(PowerVR),因为它内部有硬件支持去处理FrameData(HSR),所以不需要Early-Z。

4、得益于TBR架构,Blending和MSAA效率很高。

5、避免大量的Drawcall和顶点。在PC上Drawcall和顶点数量对GPU没有太多严重影响。但是对于TBDR,DrawCall过多意味着FrameData数据过多,严重情况下可能会出现内存放不下的情况,这种情况下对FrameData的访问速度奇慢。

  所以对于移动设备,Drawcall不只影响CPU,还会影响到GPU。

  顶点数量在一定范围内影响不大,但是如果达到1M,那么可能就会触发上面提到的极端情况,会大幅影响性能。

6、PowerVR 使用 HSR 进行隐面剔除。不需要对不透明物体进行排序。

  其他Android设备上使用 Early-Z,需要对不透明物体进行排序。从前往后绘制,会更好的利用Early-Z。

四、Drawcall的理解

(一)、Drawcall和渲染状态(RenderState

1、Drawcall就是OpenGL或者DX中的渲染接口。提交顶点给GPU。

  Drawcall过多,CPU传递给GPU的渲染指令就越多。同时一个Drawcall通常还会面临数据拷贝、渲染状态设置等等。如果GPU压力越大,CPU就必须等待GPU执行完毕才能处理下一帧,所以CPU会空置。带来的影响是Profiler中会看到 Gfx.WaitForPresent 或 Graphics.PresentAndSync。

2、SetPassCalls,要渲染一个模型只处理顶点是不够的,还要有材质信息、纹理信息、材质中的开关状态等等。这些就是渲染状态。在渲染队列中,是渲染状态和渲染指令交替进行的。

  如果一批模型材质等都相同,那么就不需要设置渲染状态,只处理渲染指令即可。相对性能会提升很多。在Unity中的表现就是Drawcall很高,但是SetPassCalls比较低。

(二)、StaticBatch和DynamicBatch

1、合批的目的是减少Drawcall。合批是有对应的CPU和内存开销的。大多数时候减少Drawcall有利于提升整体性能。但是如果滥用合批,可能会导致CPU开销更大,产生负优化。

2、动态合批为了平衡CPU消耗和GPU性能优化,将实时合批条件限制在比较狭窄的范围内。静态合批则牺牲了大量的内存和带宽,以使得合批工作能够快速有效的进行。

(三)、GPU Instancing

1、GPU Instancing 没有动态合批那样对网格数量的限制,也没有静态网格那样需要这么大的内存,它很好的弥补了这两者的缺陷。

2、GPU Instancing 并不通过对网格的合并操作来减少Drawcall,GPU Instancing 的处理过程是只提交一个模型网格让GPU绘制很多个地方,这些不同地方绘制的网格可以对缩放大小,旋转角度和坐标有不一样的操作,材质球虽然相同但材质球属性可以不同。

3、GPU Instancing、动态合批、静态合批三者所擅长的各不相同,有互相弥补的地方,各自本身也存在着不同程度的限制和优缺点。从整体上来看,GPU Instancing 更适合同一个模型渲染多次的情况,而动态合批(Dynamic batching)更适合同一个材质球并且模型面数较少的情况,静态合批(Static batching)更适合当我们能容忍内存扩大的情况。

五、其他

(一)、PBR的金属工作流和反射工作流的区别

1、金属工作流和反射工作流的差异在于输入的纹理是什么。正常情况下都是用金属工作流。

1.1、金属工作流的纹理是金属度、光滑度信息。

Albedo Texture的rgb通道为albedo;a通道对应于Alpha;

其Diffuse Color需要通过以下方法来计算:

oneMinusReflectivity = unity_ColorSpaceDielectricSpec.a*(1-metallic);
diffColor = albedo * oneMinusReflectivity;

其Specular Color需要通过以下方法来计算:

specColor = lerp (unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);

注意:unity_ColorSpaceDielectricSpec在unity内部的值为half4(0.04, 0.04, 0.04, 1.0 - 0.04) //linear space。

1.2、反射工作流的纹理是高光信息。

Albedo Texture的rgb通道对应光照运算方程中的diffuse color;a通道对应于Alpha;

Speculer Texture的rgb通道对应光照运算方程的F0;a通道对应光照运算方程的Smoothness;

其oneMinusReflectivity = 1-SpecularStrength(specColor);//SpecularStrength函数是来获取rgb通道最大值;

2、根据输入的 albedoColor和其他参数,获取实际的 diffuseColor、specColor和 oneMinusReflectivity。即diffuse颜色、高光颜色和反射率。用来输入到光照函数中。

(二)、Mipmap的理解

1、Mipmap的优点:

1.1、避免远处物体的锯齿或者闪烁感,效果表现更好。

1.2、Texture Cache,纹理采样的缓存命中率上升,减少对显存的直接访问,减少带宽io,进而提高渲染效率。

2、Mipmap的缺点:多消耗了1/3的内存,增大包体积。

3、渲染时会根据像素点的uv坐标计算,决定取哪个层级的mipmap。多层mipmap之间可以进行插值。所以同一个物体不同的像素点可以是不同的mipmap。也就是说mipmap层级的选择是像素级别的。

  个人理解,mipmap对带宽的优化体现在缓存命中率上,也就是因为不需要访问显存,从而减少了带宽的消耗。而不是因为只传递小图片导致带宽消耗降低。

4、很多时候不开Mipmap效果无法接受,所以对于3D视角的游戏而言,Mipmap是必开的。

5、2D的元素,比如UI图片,是不需要开Mipmap的。

6、Trilinear - 三线性过滤。很多图片尤其是法线,开了mipmap就要选择三线性过滤。默认选择线性过滤,纹理采样是4个点,而三线性过滤会采样8个点,在两级mipmap之间进行混合。如果不使用三线性过滤,可能会导致在视野远方,存在明显的一条分界线,其产生的原因就是分界线前后采样了不同层级的mipmap,导致显示结果产生明显差异。

  没有开启mipmap的图片,线性过滤和三线性过滤结果是一致的。三线性过滤是专门对mipmap进行优化的采样方式。

(三)、显存和显存带宽的理解

1、PC机,CPU和显卡是两个独立的硬件,内存和显存是完全独立的。而对于手机而言,CPU和GPU都在一个SOC上,共用一个物理内存。当然GPU会有逻辑上独立的内存空间,操作系统内核的内存管理不会处理这块儿内存区间。

2、显存带宽的主要消耗不是传输纹理上,只要显存(内存)足够,纹理是一直在显存中的,不存在传输开销。也就是说纹理填充率一般不会形成性能的瓶颈。

  显存带宽的开销主要在GPU对显存数据的访问上。开启Mipmap,纹理采样时Texture Cache(一个存储图片数据的只读cache,在shader processor附近,有高吞吐率和低延迟)容易命中。进而避免GPU对显存的访问,也就可以降低带宽开销。

3、补充下GPU的内存类型,主要是对各级缓存有一些概念。对缓存有一定的 了解,也就可以理解提高缓存命中为什么很重要。比如,减少贴图尺寸不仅仅可以优化内存占用,还会因此提高缓存命中率,进而提高渲染性能。Mipmap对性能的优化也体现在这里。

  PC机的GPU内存跟CPU很像,也是多级缓存机制。包括,Register,Shared Memory,Texture L1 Cache,Instruction Cache,L2 Cache,DRAM。各类存储器容量依次增大,相应的在芯片上的位置也离核心单元越来越远,同时访存延迟也越来越大。

  移动设备的GPU没有专用的显存,而是和CPU共享同一块儿物理内存,缓存机制也是一致的。不同之处在于,GPU上有一块儿On Chip Memory的缓存。这个硬件是TBDR的实现基础。

(四)、Unity下几种Lighting模式

1、Baked Indirect,仅预先计算间接光照,不执行阴影预计算。阴影完全实时生成。所以远处没有阴影,近处是ShadowMap的阴影。

2、Shadowmask,烘焙间接光和阴影。动态模型和场景可以受实时方向光影响。即实时方向光可以改变场景色调。

  当选择为 Distance Shandowmask 之后,阴影光照图可以与实时阴影按照Shadow Distance设置的距离进行混合。近处显示实时阴影,远处显示ShadowMask。实时阴影更加清晰,Shadowmask受精度影响,效果不如实时阴影好。

  Shadowmask模式会将实时光和烘焙的光混合,同样可以混合实时阴影和烘焙的阴影。那么它就需要知道哪里是阴影,这个就需要 ShadowMask 图。

3、Subtractive,烘焙直接光照、间接光照和阴影。改变方向光不能影响场景。在此模式下,参与实时计算的只有动态物体的实时光照和动态物体对静态物体的投影。阴影直接被烘焙在lightmap上,所以不需要ShadowMask图。

(五)、LUT,用贴图缓存中间计算结果。

参考洛城写的文章,因为很多人会对LUT存在误解或误用,所以copy了一段文字在这里。

1、很多时候,我们会把一些数学上的中间计算结果缓存到一张贴图里,这些贴图的数值本身不代表视觉信息,而是纯粹的数字。比如Marschner Hair Mode用LUT去存BRDF;UE4用LUT去存储PBR的环境光BRDF。

2、LUT带来的性能损耗有两点:

2.1、贴图本身是数值,所以只能用无损格式,无法压缩,所以bytes per pixel是比较大的,比一般贴图占用更多读取带宽。

2.2、对于贴图的采样是基于LUT的uv计算的,而相邻像素算出的uv通常都没有空间连续性,这就表示每次LUT的采样几乎都会导致cache miss,所以这类LUT比一般贴图的采样更慢。

3、结论:尽量使用拟合函数去代替LUT采样,对于Mobile GPU来说,永远不要尝试用LUT去优化一段shader;对于Desktop GPU来说,慎重考虑使用LUT。

 

来源知乎专栏:Unity开发启示录

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 拯救xmlrpc.php让WordPress瘫痪的的六种办法

    今天对于我来说 是个战斗的日子,上午发布完文章后,很快360好搜就收录了,但在打开网页的时候,卡主了,没有反应,快速的重启Apache,马上恢复,但过了几分钟,网站又打不开,干脆重启服务器,问题得到解决,过了一会,悲剧再次发生,查看网站防护日志,原来有个IP不停的访问…...

    2024/4/27 6:10:43
  2. 如何提高FPGA工作频率?影响FPGA运行速度的几大因素

    对于设计者来说,我们当然希望我们设计的电路的工作频率(在这里如无特别说明,工作频率指FPGA片内的工作频率)尽量高。我们也经常听说用资源换速度,用流水的方式可以提高工作频率,这确实是一个很重要的办法,今天我想进一步分析该如何提高电路的工作频率。 我们先分析一下是…...

    2024/4/11 16:04:16
  3. 【北京迅为】i.MX6ULL终结者VMware 虚拟机扩展Ubuntu系统磁盘空间

    文章目录1.我们首先需要在VM上进行磁盘扩容2.重新划分磁盘 由于虚拟机下安装软件过多,时不时弹出磁盘空间不足的问题。所以也在这里建议大家,如果需要在虚拟机上搭建比较复杂的环境的话,一般给虚拟机50G的内存空间较合适。以防万一,在操作之前将虚拟机进行了备份。 1.我们首…...

    2024/5/2 10:50:26
  4. 程序员高频英语day14

    Day14vital英[ˈvaɪtl] 美[ˈvaɪtl]释义adj. 维持生命所必需的; 至关重要的; 生死攸关的; 生机勃勃的例句:These matters are vital to the national security. 这些事情对国家安全至关重要.This point is vital to my argument. 这一点对我的论据来说是非常重要的.parallel…...

    2024/4/22 1:53:31
  5. 磁盘管理

    磁盘管理 1. 磁盘结构 1.1 设备文件 设备文件 :关联至一个设备驱动程序,进而能够跟与之对应硬件设备进行通信 设备文件格式块设备 :存取单位“块”,磁盘 字符设备:存取单位“字符”,键盘[root@centos7 ~]#ll /dev/sda brw-rw----. 1 root disk 8, 0 Aug 18 08:59 /dev/sd…...

    2024/4/11 16:04:13
  6. Collection的集合与数组的转换,集合的排序和乱序

    集合转换为数组 public static void main(String[] args) {Collection<String> collection = new ArrayList<String>();collection.add("aaa");collection.add("bbb");collection.add("ccc");collection.add("ddd");colle…...

    2024/4/21 9:14:19
  7. while脚本练习

    1、编写脚本,求100以内所有正奇数之和 [root@centos8 ~]#cat while_sum.sh #!/bin/bash #Version: 1.1 #********************************************************************** sum=0;i=1 while [ ${i} -le 100 ];dolet sum+=ilet i+=2 done echo ${sum}…...

    2024/4/28 8:42:25
  8. JMeter+检查点之响应断言(Response+Assertion)

    JMeter 检查点之响应断言(Response Assertion) JMeter断言用于对sampler(采样器)进行额外检查,且在相同作用域中,每执行完一个sample就会进行一次断言处理,为了确保断言仅作用于某个sample,把该sample添加为子sample。测试环境 apache-jmeter-2.13**1. ** 添加响应断言 右…...

    2024/4/21 6:39:24
  9. 大数据平台架构设计探究

    近年来,随着IT技术与大数据、机器学习、算法方向的不断发展,越来越多的企业都意识到了数据存在的价值,将数据作为自身宝贵的资产进行管理,利用大数据和机器学习能力去挖掘、识别、利用数据资产。如果缺乏有效的数据整体架构设计或者部分能力缺失,会导致业务层难以直接利用…...

    2024/4/27 5:02:26
  10. 微信小程序 showToast 真机下一闪而过 的解决办法(超全)

    wx.showToast()文章目录wx.showToast()前言一、wx.showToast()调用方式二、问题分析1.出现原因2.解决方案总结前言场景一:请求接口需要调用 wx.showLoading(),接口请求结束调用 wx.hideLoading()。如果需要给用户提示错误信息,调用 wx.showToast(),在模拟器上正常显示,但是在…...

    2024/4/11 18:22:20
  11. LVS+keepalived负载均衡+高可用群集

    文章目录LVS+keepalived负载均衡+高可用群集一、概览1、Keepalived案例分析2、Keepalived工具介绍3、Keepalived实现原理剖析二、实验实验介绍1、实验规划2、安装工具包并关闭防火墙(DR1和DR2)3、编辑配置文件(DR1和DR2)4、编辑网卡文件(DR1)5、编辑网卡文件(DR2)6、编…...

    2024/4/24 17:18:35
  12. Centos-7.7 安装 sysbench 压测服务器以及 MySQL

    作者:李红(老李),中国开源协会(oscna.org)数据库分会成员,热衷于数据库集群架构相关方向,上海某企业MySQL数据库负责人。 本文来源:Linux备忘录(iirwt.com)出品,转载请注明来源,谢谢。 备注:数据库自行安装,安装之后数据库的路径 一定要加入变量 一、项目地址 …...

    2024/4/11 18:22:18
  13. springcloud全家桶

    首先介绍一下系统架构演变1.1 系统架构演变随着互联网的发展,网站应用的规模也在不断的扩大,进而导致系统架构也在不断的进行变化。 系统架构大体经历了下面几个过程: 单体应用架构—>垂直应用架构—>分布 式架构—>SOA架构—>微服务架构,当然还有悄然兴起的Ser…...

    2024/4/30 11:08:21
  14. “约见”面试官系列之常见面试题第七篇说说Vue的生命周期(建议收藏)

    目录Vue实例的生命周期全过程(图)在beforeCreate和created钩子函数间的生命周期created钩子函数和beforeMount间的生命周期el选项的有无对生命周期过程的影响template参数选项的有无对生命周期的影响Vue的编译过程——把模板编译成 render 函数beforeMount和mounted钩子函数间…...

    2024/4/29 4:47:52
  15. MySQL约束条件

    sailan1. not null 与 default2. unique3. primary key六、 foreign key 1. not null 与 default 设置插入数据时,是否可为空,not null 为不可空,default设置默认值 当插入数据时如果未主动设置,则自动添加默认值; create table t1 (x int not null); mysql> desc t1; …...

    2024/4/20 22:57:25
  16. 连休8天!关于2020年国庆节、中秋节放假安排的通知!!!

    关于2020年国庆节、中秋节放假安排的通知根据国务院办公厅通知精神,现将2020年国庆节、中秋节放假安排通知如下:10月1日(星期四)至8日(星期四)放假调休,共8天。9月27日(星期日)、10月10日(星期六)上班。请广大市民提前安排好工作生活,节日期间注意安全,度过一个欢…...

    2024/4/21 2:54:22
  17. python SimpleHTTPServer服务相关

    文章目录简单的文件上传下载服务固定用户授权验证:固定用户授权验证文件上传下载服务: 简单的文件上传下载服务 HttpServerWithUpload.py,python2.7 #!/usr/bin/python # -*- coding: UTF-8 -*- __version__ = "0.6" __all__ = ["SimpleHTTPRequestHandler&q…...

    2024/4/11 18:22:13
  18. idea点击setting提示报错Cannot get children Easy Code

    删除C:\Users\[用户名]\AppData\Roaming\JetBrains\IntelliJIdea2020.1\options\easy-code-setting.xml,再重启idea即可...

    2024/4/30 6:20:17
  19. 20道HTML基础面试题(附答案)

    以下是我整理的一些HTML的基础面试体,并自己整理了答案。1 DOCTYPE有什么作用?标准模式与混杂模式如何区分?它们有何意义?告诉浏览器使用哪个版本的HTML规范来渲染文档。DOCTYPE不存在或形式不正确会导致HTML文档以混杂模式呈现。 标准模式(Standards mode)以浏览器支持的…...

    2024/4/24 0:17:36
  20. Git - 详解 - One (精华解析-加粗字体)

    一、版本控制(集中式) 1、什么是版本控制 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。 除了项目源代码,你可以对任何类型的文件进行版本控制。 2、为什么要版本控制 有了它你就可以将某个文件回溯到之前的状态,甚至将整个项目都回退到…...

    2024/4/11 18:22:11

最新文章

  1. 基于EBAZ4205矿板的图像处理:03摄像头采集HDMI输出视频图像

    基于EBAZ4205矿板的图像处理&#xff1a;03摄像头采集HDMI输出视频图像 先看效果 项目简介 我是使用的EBAZ4205矿板&#xff0c;超级大电工的转接板和我自己买的一块没有xclk的ov5640完成的该项目&#xff0c;没有设备需自备。我就是跑通了正点原子的开源代码&#xff08;下文…...

    2024/5/2 12:44:12
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 华为海思2024春招数字芯片岗机试题(共9套)

    huawei海思2024春招数字芯片岗机试题(共9套&#xff0c;有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09;&#xff08;WX:didadidadidida313&#xff0c;加我备注&#xff1a;CSDN huawei数字题目&#xff0c;谢绝白嫖哈&#xff09…...

    2024/5/1 10:20:41
  4. C++ 【原型模式】

    简单介绍 原型模式是一种创建型设计模式 | 它使你能够复制已有对象&#xff0c;客户端不需要知道要复制的对象是哪个类的实例&#xff0c;只需通过原型工厂获取该对象的副本。 以后需要更改具体的类或添加新的原型类&#xff0c;客户端代码无需改变&#xff0c;只需修改原型工…...

    2024/5/1 7:27:36
  5. linuxday05

    1、makedile原理&#xff08;增量编译生成代码&#xff09; # &#xff08;注释符&#xff09; 目标------依赖 目标不存在//目标比依赖旧才会执行命令&#xff1b; makefile的实现 1、命名要求&#xff08;Makefile/makefile&#xff09; 2、规则的集合 目标文件&#…...

    2024/5/1 14:05:41
  6. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/2 11:19:01
  7. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/1 13:20:04
  8. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/5/1 21:18:12
  9. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/5/2 9:47:31
  10. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/5/2 9:47:31
  11. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/2 6:03:07
  12. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/5/2 9:47:30
  13. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/1 11:24:00
  14. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/5/2 5:31:39
  15. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/1 20:22:59
  16. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/2 9:47:28
  17. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/2 9:47:27
  18. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/2 0:07:22
  19. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/5/2 8:37:00
  20. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/5/2 9:47:26
  21. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/5/2 9:47:25
  22. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/5/1 14:33:22
  23. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/5/1 11:51:23
  24. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/5/2 7:30:11
  25. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/1 20:56:20
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57