Z-Fighting 深度冲突权威指南

news2024/7/30 4:04:59

Z-Fighting 是渲染管道中深度测试中出现的问题。它是由深度值的有限数值精度引起的。故障将表现为不正确的渲染,即屏幕上错误地显示应该被遮挡在另一个后面的对象。故障主要发生在透视投影变换中,但也可能发生在正交投影变换中。到目前为止,一个众所周知的好的解决方案是使用对数深度测试,但在实施和使用它时必须小心谨慎。无论哪种方式,要处理 Z-Fighting,重要的是正确识别给定条件下的定量限制。

这篇博文旨在成为处理 Z-Fighting 的实用信息来源。它通过简短的理论分析说明了它发生的原因和方式,然后展示了一些使用 OpenGL 实际实现的数值结果。然后,它讨论了有关对数深度测试的一些实现问题。它还附带了三个与 OpenGL 配套的工具。利用这些工具,你可以直观地看到 Z-Fighting 的效果,并通过设置适合你环境的参数来进行实验。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 

1、关键要点

这篇博文有三个要点,对建模者和开发人员设计 3D 模型和场景以及开发渲染系统很有用。如果你还不熟悉坐标变换和深度测试,可以跳过本节。

1.1 一般规则

在对这个主题进行了一些研究并进行了一些分析和实验后,我推荐以下一般规则。

  • 在适用的情况下,在片段着色器中使用 NF 类型的对数深度和 gl_FragDepth
  • 如果片段着色器的 GPU 工作负载成为问题,并且你想要启用早期片段测试,您有两种选择:一种是将对数深度设置为 gl_Position.z,以牺牲扭曲的几何形状为代价。另一种是回到普通的透视投影深度,增加远处物体的 Z 竞争。你可能必须按从后到前的顺序在多个绘制调用中渲染场景,每个绘制调用都使用清除的深度缓冲区。

1.2 避免 Z-Fighting 的最小间隙

本篇博文的共同主题是以下问题:

假设有两个点彼此靠近,在 VCS 中与相机的距离约为 z。视线方向上这两个点之间需要多少间隙 Δz,才能在 SCS 中正确比较它们的深度?

VCS 和 SCS 分别表示视图坐标系和屏幕坐标系。它们将在下文中解释。

首先得出结论,以下是本篇博文中最重要的两个图表。

上面的第一张图表显示了假设深度格式为 OpenGL 中的 GL_DEPTH24_STENCIL8 的理论值。第二张图表显示了从测试程序中获取的采样值,稍后将对其进行描述。每条线或图下方的区域是发生错误比较或 Z-Fighting 的地方。例如,如果两个物体距离相机 10² = 100 [m],如果使用 C=1/10⁶ 的 CF 类型对数深度,则这两个物体在视线上的距离必须至少为 0.1–0.6 [m]。透视(普通)深度类型的最小距离约为 0.01 [m],其他深度类型的最小距离约为 100 [μm]。

1.3 在顶点着色器中将对数深度分配给 gl_Position 的效果

一些实现通过启用早期片段测试将对数深度分配给 gl_Position 以减少片段着色器的调用。然而,它带来了由视锥剔除和光栅化中的线性插值引起的负面影响。这种负面影响扭曲了几何形状。由于很难通过图表显示效果,本博文附带了一个交互式工具,可以实时直观地查看效果。以下是使用 OpenGL 实现的工具的屏幕截图。

左窗格由普通透视投影渲染,没有对数深度测试。右窗格使用片段着色器中设置为 gl_FragDepth 的对数深度进行渲染。中间窗格使用对数深度 gl_Position.z 进行渲染,这会扭曲几何图形,如图所示,遮挡不正确,多边形形状扭曲。

以上就是我在开头想要分享的三个关键点。

2、坐标变换回顾

本节简要介绍图形管道中从 3D 世界坐标系到 2D 屏幕坐标系的变换。它假设 OpenGL 和 GLFW 处于渲染管道的最后阶段,但它也适用于其他技术,例如 Vulkan 和 Metal。

2.1 相机方向

相机在其 LCS 中的方向

按照惯例,相机在其局部坐标系 (LCS) 中的方向是朝向负 Z 方向,垂直向上方向与正 Y 方向对齐。如后所述,它与视图坐标系相同。

2.2 在 WCS 中放置和定位相机

WCS 中相机的平移和方向

相机通过旋转矩阵 R 和平移向量 v_c 放置在世界坐标系或 WCS 中。它们组合成 4x4 模型矩阵,如下所示:

2.3 将世界带入相机的 LCS

要通过相机(也是在 WCS 中放置和定向)查看在 WCS 中放置和定向的物体,你需要将这些物体带入相机的局部坐标系。这是由视图矩阵定义的视图变换,它是相机模型矩阵的逆。结果坐标系是视图坐标系或 VCS。这与相机的 LCS 相同。

2.4 从 VCS 到 NDCS,再到 SCS

通过 NDCS 从 VCS 到 SCS 的变换

VCS 中的坐标被变换到标准化设备坐标系,即 NDCS。在 VCS 的负 Z 区域中定义的视锥体被变换为以 NDCS 中的原点为中心的立方体。VCS 的正 Z 区域(视点后面)被变换为 NDCS 中平面 z=f/(f-n) 后面的区域。在 NDCS 中,VCS 中平面 z=0 的变换未定义。

NDCS 中的坐标最终被变换为屏幕坐标系,即 SCS,其中使用 Z 缓冲区执行深度测试。对于 OpenGL(假设 GL_DEPTH24_STENCIL8),Z 轴上的值范围从 VCS 中的 [-far, -near) 变为 NDCS 中的 [-1.0, 1.0),然后变为 SCS 中的 [0, (2²⁴-1)/2²⁴]。请注意,SCS 是 x 和 y 方向的光栅化整数坐标空间,以及 z 方向的步长为 1/2²⁴ 的定点数空间:

透视矩阵的定义也如上所示。请注意,Z 轴的方向通过透视变换翻转。VCS 是左手坐标系,而 NDCS 是右手坐标系。如果我们关注 Z 轴,则从 VCS 到 NDCS 的变换如下:

对于 OpenGL,SCS 中的 Z 坐标是通过 NDCS 中的 Z 坐标获得的,并进行以下简单的转换:

Z*_ndcs 是 Z_ndcs 的采样和插值。深度测试在 SCS 中使用 Z 缓冲区进行。由于量化,如果 |z_1 - z_2| ≤ 1/2²³,则 NDCS 中的两个不同 Z 坐标 z_1 和 z_2 可以在 SCS 中获得相同的值,从而导致 Z-fighting。

3、使用透视投影进行深度分析

如果我们忽略插值和量化的影响,则 Z 坐标从 VCS 到 SCS 的映射由以下函数给出:

导数为:

假设导数在 z 附近不变,并且考虑到 Z 缓冲区的粒度为 1/2²⁴,则 VCS 中 Z 坐标所需的最小间隙  Δz_vcs 如下所示:

下图显示了 n = 0.1 和 f 在不同位置的这些函数图。0.1 处的近平面可以解释为距离眼睛 0.1 [m] 的取景器:

最后一张图表还显示了使用 OpenGL 实现的批处理测试程序观察到的最小间隙图。它是三个附带工具之一,稍后将在下面描述。

分析

正如最后一张图表所示,所需的最小间隙逐渐增加,深度测试在大约 -z_vcs > near * 1.0E6 时几乎无用。如果两个物体距离相机 1 [km],最小间隙将约为 1 [m]

此外,一些文章建议将近平面和远平面放置得尽可能近,以充分利用 SCS 中的 [0,1.0] 范围,但正如第二张和第三张图表所示,它对最小间隙几乎没有影响,除非视锥体变得像煎饼一样非常浅,但在这种情况下,使用透视投影就没有什么意义了。

4、对数深度的分析:NF 类型

透视投影中的深度值的问题在于它很快趋近于 1.0 并保持相对平坦,即 dF(z)/dz 很快趋近于 0。希望找到一个从 VCS 到 SCS 的映射函数 F(z),其导数 dF(z)/dz 保持相对较高。此外,它必须具有以下特征。

  • F(-near) ≥ 0 且 F(-far) ≤ 1
  • F(z) 是一对一映射。
  • F(z) 单调递减,即 -z1_vcs > -z2_vcs => z1_scs > z2_scs

下面的对数深度就是这样一个函数:

以下3张图表分别显示了函数图、理论最小间隙和测试程序中的观测值:

分析

如第三张图所示,与使用普通透视投影进行映射相比,对数深度的最小间隙更为有利。

对于距离相机约 1 [km] 的两个物体,最小间隙将为 1 [mm](火腿片)。对于距离相机 1 [m] 的两个物体,最小间隙将为 1 [μm](细菌大小)。无论距离(近、远),距离与间隙的比率都保持不变,为 1/10⁶

5、对数深度的分析:CF 类型

这是对数深度映射的参数形式,参数为“c”[Outerra2009]。这似乎是试图进一步改进 NF 类型,将伪近平面拉近到远平面,而不缩小 F(z) 的范围。参数“c”可以被认为是“近”的倒数,即 c=1/n。定义及其导数如下:

下图显示了 f = 10¹⁰ 和 c = 1.0、1/10³ 和 1/10⁶ 的图:

分析

与 NF 类型相比,使用 CF 类型的增益很小。

可以使用以下近似导数分析 NF 和 CF 类型之间的差异。

对于 NF 类型:

对于CF类型:

如果 -z_vcs 足够大,主要区别在于分母。如果我们设置 c=1/n,这两种类型大致相同。如果我们设置 n=1/10¹ 和 c=1/10⁶,那么:

粗略地说,CF 类型所需的最小间隙将比 NF 类型的间隙小 2.75 倍。如果 c=1/10³,则为 11/7 =1.57 如果 c=1.0,则增益为 11/10=1.1

如果 -z_vcs 较小,则 dF(z)/dz 和 CF 类型的最小间隙将变为常数。如果 c=1/10⁶,则 |dF(z)/dz| ≅1.09/10⁷,最小间隙 ≅ 0.55 [m]。如果 c=1/10³,则 |dF(z)/dz| ≅ 6.0/10⁵,最小间隙 ≅ 9.6/10⁴ ≅ 1 [mm]

如上所示,与 NF 类型相比,你必须将 c 设置为明显较低的值,例如 c = 1/10⁶,这样 -z_vcs * c >> 1.0 才能获得一些有意义的增益,但缺点是 -z_vcs * c << 1.0 的最小间隙较大。

对于大多数实际用例, c = 1/10⁶ 是不切实际的,因为对于较小的 Z 坐标,最小间隙较大。如果 c = 1/10³,则对于许多用例而言都是可以接受的,但对于较大的 Z 坐标而言,你获得的增益并不大。

上述论点意味着 NF 类型将适用于大多数用例。深度测试的分析到此结束。让我们继续讨论实施问题。

6、对数深度着色器的实现

本部分给出几种着色器的实现。

6.1 使用 gl_FragDepth 的 NF 类型的示例实现

以下是示例顶点着色器,它将 VCS 的 Z 坐标传递到变量 position_vcs_z 中的片段着色器上:

#version 330 core

in vec4 position_lcs;

uniform mat4 P;
uniform mat4 V;
uniform mat4 M;

out float position_vcs_z;

void main() {

    position_wcs = M * position_lcs;
    vec4 position_vcs = V * position_wcs;
    position_vcs_z = position_vcs.z;
    gl_Position  = P * position_vcs;
}

下面是一个示例片段着色器,它使用 position_vcs_z 中 VCS 中的(插值)Z 坐标设置 NF 类型的对数深度。它将深度值设置为 gl_FragDepth

#version 330 core

in float position_vcs_z;

uniform float log_far;  // = log( 1.0e6  );
uniform float log_near; // = log( 1.0e-1 );

out vec4 color_out;

void main()
{

    float log_z = log( max( 1.0e-30, -1.0 * position_vcs_z ) );
    gl_FragDepth = ( log_z - log_near ) / ( log_far - log_near );

    color_out = vec4( 1.0, 1.0, 1.0, 1.0 );
}
问题:无法应用早期深度测试。

由于在片段着色器中明确为 gl_FragDepth 分配了一个值,因此无法启用早期片段测试。即使使用 GL_ARB_conservative_depth 也是如此,如下所示。

如果启用了 GL_ARB_conservative_depth,你可以重新声明 gl_FragDepth,如下所示:

#extension GL_ARB_conservative_depth : enable
layout(depth_less) out float gl_FragDepth;

属性必须是 depth_less,因为对于域 -far < z < -near, |F(z)| < |gl_Position.z/gl_Position.w|。它不会启用早期深度测试,因为片段着色器可以将像素向前移动,使其在 SCS 中具有较小的 Z 坐标。要在片段着色器中通过显式分配 gl_FragDepth 来启用早期深度测试,属性应该是 depth_greater,假设指定了普通的 glDepthFunc(GL_LESS)

6.2 使用 gl_Position.z 实现 NF 类型的示例

以下代码片段是一个示例顶点着色器,它将对数深度分配给 gl_Position.z。请注意,分配给 gl_Position 的深度值不是在范围为 [0,1) 的 SCS 中,而是在范围为 [-1, 1) 的 NDCS 中。

片段着色器没有任务,因为深度隐式设置为 2.0 * gl_FragCoord.z/gl_FragCoord.w - 1

#version 330 core

in vec4 position_lcs;
uniform mat4 P;
uniform mat4 V;
uniform mat4 M;
uniform float log_far;  // = log( 1.0e6  );
uniform float log_near; // = log( 1.0e-1 );

void main() {
    position_wcs = M * position_lcs;
    vec4 position_vcs = V * position_wcs;
    gl_Position  = P * position_vcs;
    float log_z_vcs = log( max( 1.0e-30, -1.0 * position_vcs.z ) );
    float log_z_ndcs = (log_z_vcs - log_near)/(log_far - log_near) * 2.0 - 1.0;
    gl_Position.z = log_z_ndcs * gl_Position.w;
}
问题:几何失真

在 gl_Position 中分配深度可启用早期片段测试,因此可以通过减少片段着色器的调用次数来减少 GPU 工作量。但是,由于管道中片段着色器之前的采样器和光栅化器的插值取决于 gl_Position 中的值,因此更改其中的 Z 坐标会扭曲几何图形。特别是,如果顶点位于相机后面,即 VCS 中的 Z 坐标为正,则必须将它们限制为某些负值。失真的严重程度很难定量分析,但这里有一个基于一些实验的经验法则。

  • 要渲染的对象的顶点应位于视锥体中。越靠近中心,失真越少。

例如,如果你渲染由靠近屏幕中心的一些细网格组成的 3D 对象,它将相当无失真。但是,你应该避免以下类型的对象:

  • 横跨视锥体或横跨正 Z 区域和负 Z 区域的地板砖。
  • 由长三角形组成或到达视锥体两侧的长梁。
  • 由细长条带组成的网格图案。

一般来说,你应该避免在顶点着色器中分配深度。如果你确实必须使用这种类型,必须始终注意几何图形会被扭曲。

7、工具

本文附带了三种工具。它们位于 Github 存储库中。

7.1 depth_test_interactive

此工具根据当前配置以交互方式可视化 Z-fighting。此工具使用 3 种深度测试渲染以 Z 轴为中心的两个四边形或平面。你可以使用键盘和鼠标滚轮以交互方式更改两个平面的 Z 坐标和对数深度的参数:

上图是该工具的快照,其参数设置如下:

  • 平面 1(红色)放置在 z=-52.104729 处
  • 平面 2(蓝色)放置在 z=-52.104507 处
  • 远平面 = 131954.781250 / 近平面 = 0.1 / C = 0.001

如你所见,使用普通透视投影的深度测试失败,而两个对数深度测试成功。

7.2 depth_test_shader_comparator

此工具可视化了由改变的 gl_Position 引起的几何失真,其中对数深度分配给 Z 坐标。

上图是该工具的快照。它渲染了两个圆柱形多面体的合成图。有三个窗格。左侧窗格使用普通透视深度测试进行渲染。中间窗格使用 NF 类型的对数深度进行渲染,深度值在顶点着色器中分配给 gl_Position。右侧窗格使用 NF 类型进行渲染,但值在片段着色器中分配给 gl_FragDepth。如你所见,中间窗格的渲染存在不正确的遮挡,并且红色多面体的几何形状明显扭曲。

你可以交互地更改以下参数,并实时查看效果:

  • 圆柱形多面体的长度和半径。
  • 圆柱形多面体的位置和方向
  • 相机的位置和方向。

7.3 depth_test_batch

这是一个命令行批处理测试器,通过使用 OpenGL 将渲染四边形实际运行到帧缓冲区来查找最小间隙。对于 VCS 中沿负 Z 轴的每个点 Z_vcs,它通过结合网格搜索和二分搜索来找到两个平面之间的最小间隙 Δz。为了减轻误报的影响,它会执行多次测试(数量由命令行参数 -num_perturbed_samples指定)。对于每次测试,都会向平面的 Z 坐标添加小的随机扰动。如果所有测试都成功,则认为 Z-vcs 和 Δz 通过。

该工具采用以下参数。

  • -depth_type <perspective/logfn/logcf>
  • -near <near(positive)>
  • -far <far(positive)>
  • -c <CF 类型的参数 C>
  • -num_points
  • -num_perturbed_samples

然后,该工具对 VCS 中的 Z 坐标或 Z_vcs 进行 Δz 采样。`Z_vcs` 的数值由参数 -num_points给出,这些点以对数形式均匀分布在 -near 和 -far 之间比例。结果将打印到标准错误输出。

以下是上述图表所用命令的示例调用:

./depth_test_batch -depth_type perspective -near 1.0e-1 -far 1.0e10 -c 1.0 -num_points 100 -num_perturbed_samples 5

8、结束语

这篇博文涵盖了在实际使用中处理 Z-fighting 的要点。处理它最省心的方法是使用 NF 类型的对数深度和 gl_FragDepth。它应该涵盖大多数用例。如果它不能满足你的性能要求,那么你可以使用其他方法,但你应该意识到缺点。无论哪种方式,我希望这篇文章和工具能够帮助你分析 Z-fighting 的问题,并在你必须应对它时做出更好的决策。


原文链接:Z-Fighting 权威指南 - BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1917101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GaussDB关键技术原理:高性能(五)

GaussDB关键技术原理&#xff1a;高性能&#xff08;四&#xff09;从USTORE存储引擎、计划缓存计划技术、数据分区与分区剪枝、列式存储和向量化引擎、SMP并行执行等五方面对高性能关键技术进行解读&#xff0c;本篇将从LLVM动态查询编译执行、SQL-BYPASS执行优化、线程池化、…

threeJS 点击模型出现弹框

前言 需要实现点击模型出现弹框展示模型详细信息 实现代码 // 创建3D渲染器 - 初始化时调用 function createCss3DRender(){labelRenderer new CSS3DRenderer();labelRenderer.setSize(window.innerWidth, window.innerHeight);labelRenderer.domElement.style.position &…

如何将本地仓库中的文件推送到远程git服务器

第一步&#xff1a;进入所在项目&#xff0c;右击打开"Git Bash Here" 第二步&#xff1a;git config --global user.email "18351810763163.com" // 输入你的名称 第三步&#xff1a;git config --global user.name "chenliang-sam&quo…

Mongodb单字段索引详解

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第89篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

Github 2024-07-11 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-11统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10Solidity项目1Python项目1frp: 一个开源的快速反向代理 创建周期:2946 天开发语言:Go协议类型:Apache License 2.0Star数量:75872 …

【文档+源码+调试讲解】冷冻仓储管理系统

摘 要 随着互联网时代的到来&#xff0c;同时计算机网络技术高速发展&#xff0c;网络管理运用也变得越来越广泛。因此&#xff0c;建立一个B/S结构的冷冻仓储管理系统&#xff0c;会使冷冻仓储管理系统工作系统化、规范化&#xff0c;也会提高冷冻仓储管理系统平台形象&#x…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-第十八章 Linux编写第一个自己的命令

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

有哪些媒体适合邀请来报道我们的活动?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 挑选合适的媒体参加活动发布会时&#xff0c;需要考虑活动的主题、目标受众以及预期效果。建议可以考虑邀请以下几类媒体&#xff1a; 行业媒体&#xff1a;专注于您活动所在行业的媒体&…

视图库对接系列(GA-T 1400)十五、视图库对接系列(本级)删除、取消订阅

说明 之前说了订阅和修改订阅,今天我们来实现删除和取消订阅二个接口。删除订阅 逻辑: 请求下级的接口成功我们就删除数据库的对应数据视图库接口定义 实现 service接口层 //删除订阅ResponseStatusListModeObject deleteSubscribes(String idList, HttpServletRequest re…

Python32 极限学习机ELM

极限学习机&#xff08;ELM&#xff09;是一种简单的单层前馈神经网络&#xff08;SLFN&#xff09;学习算法。理论上&#xff0c;极限学习机算法&#xff08;ELM&#xff09;往往以极快的学习速度提供良好的性能&#xff08;属于机器学习算法&#xff09;&#xff0c;由Huang等…

MybatisPlus 使用教程

MyBatisPlus使用教程 文章目录 MyBatisPlus使用教程1、使用方式1.1 引入依赖1.2 构建mapper接口 2、常用注解2.1 TableName2.2 TableId2.3 TableField MyBatisPlus顾名思义便是对MyBatis的加强版&#xff0c;但两者本身并不冲突(只做增强不做改变)&#xff1a; 引入它并不会对原…

krpano开启日志公能

<krpano version"1.21" title"博物馆" debugmode"true" > 之后鼠标右键菜单栏最后一行 点击&#xff08;开启后会发生变化&#xff09;。

【云岚到家】-day05-4-项目迁移-商品搜索

【云岚到家】-day05-4-项目迁移-商品搜索 2 项目迁移-商品搜索2.1 迁移目标2.2 能力基础2.2.1 索引同步方案设计能力2.2.2 Elasticsearch全文检索应用能力 2.3 需求分析2.3.1 界面原型2.3.2 功能列表梳理 2.4 系统设计2.4.1 索引结构2.4.2 索引同步方案2.4.3 搜索自动补全2.4.4…

SpringBoot项目架构实战之“网关zuul搭建“

第三章 网关zuul搭建 前言&#xff1a; 1、主要功能 zuul主要提供动态路由&#xff08;内置ribbon实现&#xff09;和过滤&#xff08;可以做统一鉴权过滤器、灰度发布过滤器、黑白名单IP过滤器、服务限流过滤器&#xff08;可以配合Sentinel实现&#xff09;&#xff09;功能…

【IT领域新生必看】解锁 `final` 关键字的秘密:Java 编程中的终极武器

文章目录 引言什么是 final 关键字&#xff1f;一、 final 变量final 局部变量final 实例变量final 静态变量 二、 final 方法三、 final 类四、 final 关键字的实际应用1. 定义常量2. 防止方法被重写3. 创建不可变类4. 优化性能 五、 final 的一些常见误区1. final 变量不能在…

力扣2356.二维差分模板——子矩阵元素加1

力扣2356.二维差分模板——子矩阵元素加1 模板题 最后将n2*n2的矩阵删去周围一圈变成n*n矩阵的操作 class Solution {public:vector<vector<int>> rangeAddQueries(int n, vector<vector<int>>& queries) {vector<vector<int>> res…

ONLYOFFICE 8.1版本版本桌面编辑器测评

ONLYOFFICE官网链接&#xff1a;ONLYOFFICE - 企业在线办公应用软件 | ONLYOFFICE ONLYOFFICE在线办公套件&#xff1a;在线办公套件 | ONLYOFFICE ONLYOFFICE在线PDF编辑器、阅读器和转换器&#xff1a;在线PDF查看器和转换器 | ONLYOFFICE ONLYOFFICE 8.1版本桌面编辑器是…

【OC】巧用UIStackView简化布局

UIStackView的运用 文章目录 UIStackView的运用引入UIStackView的作用UIStackView的属性compression resistance 和 huggingaxisalignmentDistributionspacing UIStackView的方法UIStackView的示例 引入 在仿写ZARA的过程之中&#xff0c;我看到软件之中是有大量的按钮排列在一…

蓝卓创始人褚健:未来工厂需要一个“工业安卓”

作为国内自动控制的科学家&#xff0c;过去近三十年的时间&#xff0c;褚健教授一直服务于化工行业、炼油石化等流程工业领域。褚健表示&#xff0c;因为涉及到安全生产和环保要求&#xff0c;流程工业企业的自动化水平高一些&#xff0c;但总体来看&#xff0c;目前中国大部分…

【网络安全】SSRF 之 Azure Digital Twins Explorer

未经许可&#xff0c;不得转载。 文章目录 正文 正文 Azure Digital Twins 是一个微软下的平台服务&#xff0c;允许开发者创建和运行数字孪生模型&#xff0c;这些模型能够反映物理世界中的实体及其关系&#xff0c;通过这些模型可以进行监控、分析和预测等操作。 1、进入主…