unity 烘焙参数 设置_Unity通用渲染管线(URP)系列(九)——点光源和聚光灯

28ba7fd6f96c243cf854a0e04f801566.png

a1292a3298ae34ae1f6390bdcbcf7b1d.png

200+篇教程总入口,欢迎收藏:

放牛的星星:[教程汇总+持续更新]Unity从入门到入坟——收藏这一篇就够了​zhuanlan.zhihu.com
cf7a8f762ff46591bb1729adb4a7287b.png
本文重点内容:
1、支持更多类型的灯光
2、包含实时的点光源和聚光灯
3、为点光源和聚光灯烘焙阴影
4、每个物体限制最多8个其他光源

这是有关创建自定义脚本渲染管道的系列教程的第九部分。它增加了对点光源和聚光灯的实时和烘焙支持,但还没有实时阴影。

本教程是CatLikeCoding系列的一部分,原文地址见文章底部。

本教程使用Unity 2019.2.21f1制作。

c13543da3338ecd42f94cd6e3f7daad3.png
点光源和聚光灯的派对

1 点光源

到目前为止,我们仅使用了定向光,因为这些光会影响所有事物并且具有无限范围。而其他光源类型则不同,不会假定它们无限远,因此它们具有位置并且强度会变化。这需要额外的工作来设置和呈现,这就是我们为此创建单独代码的原因。我们从点光源开始,点光源是无限小的点,可以均匀地向所有方向发光。

1.1 其他的灯光数据

与定向灯一样,我们只能支持有限数量的其他灯光。场景通常包含很多不定向的灯光,因为它们的有效范围有限。通常,对于任何给定的帧,所有其他光的子集都是可见的。因此,我们可以支持的最大值适用于单个帧,而不适用于整个场景。如果最终我们看到的可见光比最大数量更多,则将被忽略掉。Unity会根据重要性对可见光列表进行排序,因此只要可见光不发生变化,哪些灯被忽略就是一致的。但是,如果确实发生变化(由于相机移动或其他更改),则可能会导致明显的光过爆的情况。因此,我们不能使用太低的最大值。现在,让我们同时允许多达64个的其他光源,设置为Lighting中的另一个常量。

676a5090729c50f568c391309d90c4de.png

就像方向光一样,我们需要为其他类型的光发送光的数量和光颜色到GPU。而同时,我们还需要发送光的位置。添加着色器属性名称和向量数组字段来实现。

f4b65c4013a56926cb208ef8b8178e95.png

在SetupLights中,追踪其他光数量以及定向光数量。遍历可见光后,将所有数据发送到GPU。但是,如果我们最终得到零个其他光源,则无需发送数组。而且,现在只包含其他光源而没有定向光源也很有意义,因此我们也可以跳过发送定向光数组的操作。但不管是不是有光源,我们总是需要将光源数发送出去。

e3a47becc2054232600944c6215bfb0f.png

在着色器这边,定义另一个最大光照值和新的光照数据。

db1ede58968022c9ecc3a949daffcecb.png

然后定义一个GetOtherLightCount函数,稍后我们将使用它。

9187817ee985ec641e7d7b095e00c6b8.png

1.2 设置点光源

在Lighting中创建一个SetupPointLight方法来设置点光源的颜色和位置。给它与SetupDirectionalLight相同的参数。颜色的设置也是相同的。位置的工作原理类似于方向光的方向,但我们需要本地到世界矩阵的最后一列而不是第三列。

88bb9a579ee24a2dba20bbec03b7d644.png

现在,我们还需要调整SetupLights中的循环,以便区分方向光和点光源。一旦达到最大数量的方向光,我们不是像以前一样再结束循环。相反,我们会跳过方向光继续循环。对点光源执行相同的操作,同时要考虑其他光源的最大值。让我们使用switch语句对此进行编程。

d60556159cbf2aed525a962385fe509f.png

1.3 着色

现在,着色器可以使用支持点光源所需的所有数据。要使用它,我们向Light添加一个GetOtherLight函数,其参数与GetDirectionalLight相同。这时,光线的方向会随每个片元而变化。我们通过将从表面位置到光线的光线归一化来找到它。因为目前不支持阴影,因此衰减为1。

dd2f5cc69765a46691a2772a1c00a051.png

要应用新的灯光,请在GetLighting中为方向光添加一个循环,然后为所有其他光添加一个循环。尽管循环是分开的,但我们需要为其迭代器变量使用不同的名称,否则在某些情况下,我们将获得着色器的编译器警告。所以我用j代替i作为第二个。

fcd1c1b0cbfe5fe056a2409b9f98a67f.png

58cd998437d021017b1c82cf8e82fa32.png
只有点光源,没有环境光

1.4 距离衰减

我们的点光源现在可以工作了,但是它们太亮了。现实中,随着光远离其源传播之后,它会散布开来,变得越来越不集中,因此光越远,亮度就越低。光线的强度是其中i 为配置强度,d 为距离。

这被称为平方反比定律。请注意,这意味着在小于1的距离处,强度会变为大于配置的强度。也就是说非常接近灯光的位置变得非常明亮。早先我们推断,最终使用的光色代表的是从正面照亮的完美白色漫射表面碎片反射时观察到的光量。对于方向光来说确实如此,但对于其他类型的光,它也专门用于与光之间距离为1的片元。

4933d129ba1b95485c787f6e939552dc.png
距离衰减曲线

通过计算光的平方来应用距离衰减,并将其倒数用作衰减。为防止潜在的除0操作,请将平方距离的最小值设置为很小的正值。

aeda192348b1ac6abe76c2918a922809.png

ac697e4651ce99858f8babe97565d995.png
光随距离淡化

1.5 光范围

尽管点光源强度现在会迅速衰减,但理论上它们的光仍然会影响所有对象,只是正常时候无法感知。漫反射很快变得不明显,而镜面反射在更远的距离仍然可见。

为了使渲染更真实,我们将使用最大照明范围参数,超过此范围我们将使照明强度强制为零。这是不符合现实的,但是这样设定之后,所有灯光无论距离多远都总是可视为可见。在增加范围的情况下,点光源包含在边界球中,边界球由其位置和范围定义。

我们不会突然切断球体边界处的光,而是通过应用距离衰减来平滑地将其淡出。Unity的Universal RP和lightmapper的使用

c9bf58337d275d0a800a685a15dbe8bc.png

公式,r是光的范围,所以我们也会使用相同的函数。

a108df20aec8bb13a11c88adee318821.png
距离衰减曲线

我们可以将范围存储在Light Position的第四个分量位置。以减少着色器的工作量。直接存储,同样要避免除0操作。

691651a9ce110189fa0f08c61c1d5b90.png

然后在GetOtherLight中考虑距离衰减。

f6627caf3cfd76d934129c2a83e64903.png

7f65a5f75f94aa80dae412a39a172c82.png
范围和距离衰减

2 聚光灯

现在,我们来支持聚光灯。点光和聚光灯之间的区别在于,聚光灯的光被限制为圆锥形。实际上,它是一个点光源,该点光源被一个有孔的封闭球包围。孔的大小决定了光锥的大小。

2.1 方向

聚光灯具有方向和位置,因此向Lighting添加着色器属性名称和其他光源方向的数组。

96c9e60cb78430569ec6b15b93a6762c.png

在SetupLights中将新数据发送给GPU。

984bae59a2230897012a03507afb9922.png

创建一个SetupSpotLight方法,该方法是SetupPointLight的副本,但它也存储光的方向。我们可以使用本地到世界矩阵的第三列的求反,类似于定向光。

3db5ca4a82dfe894762f31946ec41e7a.png

然后在SetupLights循环中包括一个聚光灯的Case。

f3a1e0f18af0f6fb46d75e9b61b6fe16.png

在着色器端,将新数据添加到Light中的缓冲区。

060e16da2e6bce21ea57990104a5f3ef.png

并在GetOtherLight中应用spot衰减。我们从简单地使用spot和光方向的饱和点积开始。这将使光衰减,使其在90°的光点角处达到零,然后照亮所有在灯光前方的物体。

3838eec3abbd5cccc6a91fd3029c47ec.png

0bf394f026e6c3dedf0758f9b492a46f.png
聚光灯

2.2 角度

聚光灯有一个角度来控制其光锥的宽度。该角度是从中间开始测量的,因此90°的角度看起来像我们现在的角度。除此之外,还有一个单独的内角控制光何时开始衰减。Universal RP和lightmapper通过在饱和之前缩放并在点积中添加一些东西来完成此操作,然后对结果求平方。公式大概如下:

165c624a5feefb074a0cb555e52aa437.png

,其中d是点乘。

2fa7ce3d14af95881d2df9eed8358397.png

并且

366b8cdb7ea7c5dd8d1ebe7ceb680bcb.png

41b0af0242af8e7683156e63b4a3f5f9.png

则分别为它们的内角和外角弧度。

0e36762af52c967e25c6b2dcd7f42210.png
角度衰减,内角为0°, 20°, 45°, 70°,外角为90°

该函数也可以写成

e093b45fdf21e9a7730a1ab9b84fa01a.png

,但是通过上面的方式分解,我们可以计算Lighting中的a和b,并通过一个新的点角度数组将它们发送到着色器中。定义数组及其属性名。

6a63351cdc76eab6908caefced5659cd.png

在SetupLights中将数组复制到GPU。

023479e1d22f77930ad3b884ce8dfaa5.png

然后在SetupSpotLight中计算值,并将它们存储在spot angles数组的X和Y分量中。通过VisibleLight结构的spotAngle属性可以使用外角。但是,对于内角,我们首先需要通过其light属性检索Light游戏对象,该对象又具有innerSpotAngle属性。

3f51c64925b1a3679d0c3801f71a6690.png
为什么内角不存储在VisibleLight中?
可配置的内角是Unity的新增功能。VisibleLight结构可能没有它,因为它会更改其大小并需要重构Unity内部代码。

回到着色器,在Light中添加新的数组。

dda50da524a6f3a153504713ed8b231b.png

并在GetOtherLight中调整spot衰减。

190a3b41a44947b4311f05dd49a1bc30.png

05995e939a068589072912fee4bd2db0.png
当前使用的衰减

最后,为确保点光源不受角度衰减计算的影响,请将其点角值设置为0和1。

2699b99c63d10fc981fc926f9a57670d.png

2.3 配置内角角度

聚光灯始终具有可配置的外角,但是在引入Universal RP之前,不存在单独的内角。结果,默认的灯光检查器不会暴露内角参数。RP可以进一步修改灯光,因此可以覆盖灯光的默认检查器。这是通过创建扩展LightEditor的编辑器脚本并将其赋予CustomEditorForRenderPipeline属性来完成的。此属性的第一个参数必须是Light类型。第二个参数必须是我们要覆盖检查器的RP资产的类型。让我们创建一个这样的脚本,将其命名为CustomLightEditor,并将其放在Custom RP / Editor文件夹中。还给它提供CanEditMultipleObjects,以便它与选定的多个光源一起使用。

09617395a7e158ed19856742971c0e7d.png

要替换检查器,我们需要重写OnInspectorGUI方法。但是我们将做最少的工作以暴露内角,因此我们首先调用base方法以正常绘制默认检查器。

65e1a3b805e058a262670a24db042df0.png

之后,我们检查是否仅选择了聚光灯。可以通过一个方便的名为settings的子类属性来做到这一点,该属性提供对编辑器选择的序列化属性的访问。用它来检查我们没有多种不同的光源类型,并且类型是LightType.Spot。如果是的话,在设置上调用DrawInnerAndOuterSpotAngle以在默认检查器下方添加一个inner-outer spot angle滑块。然后,调用ApplyModifiedProperties以应用对该滑块所做的任何更改。

4258166fbab5cf2be7eb3f8f0a50e59d.png

ba2e47325c6e1365e567b64ff0e10b6f.png

a5e8b34556aceea3b43c5f137b1a0f6d.png
不同的内角度

3 烘焙光和阴影

在本教程中,我们不会涵盖点光源和聚光灯的实时阴影,但是现在我们先支持烘焙这些光源类型。

3.1 全烘焙

完全烘焙点和聚光灯只需将其Mode设置为Baked即可。请注意,默认情况下,它们的Shadow Type设置为None,因此,如果要将它们与阴影一起烘焙,请将其更改为其他内容。

10f4ecdf17a79eab942bced3dcc0b883.png

e36e61c8a071648e2091076f9615c9ae.png
实时光和烘焙光,只有点光源和聚光灯生效

尽管现在已经足以烘焙这些光源,但事实证明它们在烘焙后太亮了。发生这种情况的原因是,默认情况下Unity使用不正确的光衰减,与传统RP的结果相匹配。

3.2 灯光代理

通过提供一个方法的委托,可以告诉Unity使用不同的衰减,该方法应在Unity在编辑器中执行光照映射之前被调用。为此,请将CustomRenderPipeline转换为局部类,并在其构造函数的末尾调用当前不存在的InitializeForEditor方法。

116886cfd85391df3de9757000a74d1f.png

然后为它创建另一个特定于编辑器的局部类(就像CameraRenderer一样),该类为新方法定义了一个默认的模板。除了UnityEngine命名空间外,我们还需要使用Unity.Collections和UnityEngine.Experimental.GlobalIllumination。这将导致LightType发生类型冲突,因此请为其明确使用UnityEngine.LightType。

d075496ebf83f33204e17fee8257d1f3.png

针对编辑器,我们需要重写光照贴图器以解决如何设置其光照数据。通过为它提供方法的委托来完成,该方法将数据从输入Light数组传输到NativeArray

我们还需要为每个光源配置一个LightDataGI结构,并将其添加到output中。我们需要为每种光源类型使用特殊的代码,因此需要在循环中使用switch语句。默认情况下,我们在灯光数据上调用带有灯光实例ID的InitNoBake,这指示Unity不烘焙灯光。

076ffd28604a15f98e182e772c90d637.png

接下来,对于每种受支持的光源类型,我们需要构造一个专用的light结构,调用LightmapperUtils.Extract,以light和对该结构的引用作为参数,然后在光源数据上调用Init,并通过引用传递该结构。对方向光,点光源,聚光灯和区域光执行此操作。

40d256efa21ef78c8f29d024398f9620.png

因为我们尚不支持实时区域光,因此,如果存在,请强制将其light模式设置为烘焙。

e6eeb5bcae08b4d63a028fed5f37453b.png

现在只是我们必须包含的模板代码。所有这些的重点是,我们现在可以对所有的灯光设置光数据的falloff类型为 FalloffType.InverseSquared。

3f8ce878bd13d3b3cf1733b5c57eb746.png

要让Unity调用我们的代码,请创建一个InitializeForEditor的编辑器版本,该编辑器以我们的委托作为参数来调用Lightmapping.SetDelegate。

e013f4234b62cb9494b4398805e67398.png

当我们的管道被处理时,我们还需要清理并重置委托。这是通过重写Dispose方法,让其调用其基本实现以及Lightmapping.ResetDelegate来完成的。

ae7047b5e7abee0b7cc8e03961d83856.png

9567ce748f8eb15e2ee8faaff08c490f.png
正确的衰减烘焙

不幸的是,Unity 2019.2光照贴图器不支持聚光灯的自定义内衰减角度。可以设置内spot角度,但它会被忽略。

光照贴图程序可以在更高版本的Unity中使用内Spot角度吗?
是的,从Unity 2019.3开始,AngularFalloffType存在,你可以执行以下操作:

7be66244d04f8935e73c0a23297d2588.png

3.3 阴影遮罩

通过将点光源和聚光灯的Mode设置为Mixed,也可以将它们的阴影烘焙到Mask中。就像方向光一样,每个光都有一个通道。但是因为它们的范围有限,所以只要它们不重叠,就有可能多个光源使用相同的通道。因此,Mask可以支持任意数量的光,但每个纹理像素最多只能支持四个。如果在尝试声明同一通道时多个光最终重叠,则最不重要的光将被强制为Baked模式,直到不再有冲突为止。

fd13995841a835b5c11ccef38b084f9c.png
一个点光源和一个聚光灯的阴影遮罩

要将阴影遮罩用于点光源和聚光灯,请向Shadows添加ReserveOtherShadows方法。它的工作方式与ReserveDirectionalShadows相似,只是我们只关心阴影遮罩的模式,只需要配置阴影强度和Mask通道。

9b425f3308a541883f91a87a355663c9.png

将阴影数据的着色器属性名称和数组添加到Lighting。

6a1349a1d96f8576ef43522e29cae41e.png

在SetupLights中将它发送给GPU。

73b394f6575b6164390fb64d1205c82a.png

并在SetupPointLight和SetupSpotLight中配置数据。

a79828b22333e922cd6fdabfb0f535ab.png

在着色器端,向阴影添加一个OtherShadowData结构和GetOtherShadowAttenuation函数。再次,我们使用与定向阴影相同的方法,只是我们只有强度和遮罩通道。如果强度为正,则我们总是调用GetBakedShadow,否则没有阴影。

164e16420effe37382b0ba57d0ad9618.png

在Light中,添加阴影数据并将其分解为GetOtherLight中的衰减。

e59c70b22a0004c0b2ef72508c4cc4b5.png

c655c1166792fc0a0aad7cd29b21894a.png
点光源和聚光灯 烘焙了阴影

4 逐物体的光源

当前,将对每个渲染的片元评估所有可见光。这对于方向光源很好,但是对于超出片元范围的其他光源则是不必要的工作。通常,每个点光或聚光灯只会影响所有片元的一小部分,因此,许多工作都是徒劳无功的,这可能会严重影响性能。为了支持许多性能良好的灯光,我们需要以某种方式减少每个片元评估的灯光数量。为此,有多种方法,其中最简单的方法是使用Unity的per-object光照索引。

这个想法是由Unity确定哪些灯光会影响哪些对象并将此信息发送到GPU。然后,我们可以在渲染每个对象时仅评估相关的灯光,而忽略其余的灯光。因此,灯光是基于每个对象而不是每个片元确定的。通常,这对于小型物体而言效果很好,但对于大型物体而言并不理想,因为如果光线仅影响物体的一小部分,则仍然需要对其整个表面进行评估。另外,可以影响每个物体的光线数量是有限制的,因此大型物体更容易缺少灯光。

由于per-object的光线指标不是理想的,可能会错过一些灯光,因此我们将其设为可选。这样,还可以轻松比较视觉效果和性能。

Unity的基于对象的灯光索引代码是不是中断过很多次?
是的,自Unity 2018以来,它已经被中断过了好几次,有时几个月了,它导致了很多错误。这是使其成为可选的另一个原因。

4.1 逐物体的灯光数据

向CameraRenderer.DrawVisibleGeometry添加一个布尔参数,以指示是否应使用lights-per-object模式。如果是,请为图形设置的每个对象数据启用PerObjectData.LightData和PerObjectData.LightIndices标志。

a947e11a70b0e3e4696bb88268398fa3.png

必须将相同的参数添加到Render,以便可以将其传递到DrawVisibleGeometry。

3eeee2a2836f3877d2b7364950e265f0.png

而且,我们还需要追踪和传递CustomRenderPipeline中的模式,就像其他布尔选项一样。

b1cb1e711d80ddd129db7b529d737530.png

最后,将切换选项添加到CustomRenderPipelineAsset。

354620385dadc9e2f574b3ebea7bdc0d.png

3ba434db0ec29be2b83c47866e2b4290.png
Lights per object 开启

4.2 过滤灯光索引

Unity只是创建每个对象所有活动光源的列表,并按其重要性大致排序。此列表包括所有灯光,无论它们是否可见,当然包含方向灯光。我们需要清理这些列表,以便仅保留可见的非方向光的索引。我们在Lighting.SetupLights中执行此操作,因此向该方法中添加一个lights-per-object参数,并向Lighting.Setup添加该参数。

78972e2c56e8e23d114cb6922314c559.png


然后在camerarder . render中添加模式作为设置参数。

8b3619ca926bb0829f5febf92c3aa7d3.png

在Lighting.SetupLights中,在循环到可见光之前,请从剔除结果中检索光索引图。这是通过使用Allocator.Temp作为参数调用GetLightIndexMap来完成的,这为我们提供了一个临时的NativeArray

我们仅在使用lights per object时才需要检索此数据。由于NativeArray是一个结构,因此我们将其初始化为默认值,否则它将不分配任何内容。

e24574acf835f9128763966a84e96749.png

我们只需要包含的点光源和聚光灯的索引,应该跳过所有其他类型的光源。通过将所有其他灯光的索引设置为-1来传达给Unity。我们还需要更改其余灯光的索引以匹配我们的索引。仅在我们检索Map时设置新索引。

b457729c5929011975ede3912417c2cd.png

我们还需要消除所有不可见光的索引。如果我们使用lights per object,请执行第二个循环,该循环在第一个循环之后继续进行。

49d47c8000717552be5366811f1e75ba.png


完成后,我们必须通过在剔除结果上调用SetLightIndexMap将调整后的索引Map发送回Unity。此后不再需要IndexMap,因此我们应该通过在其上调用Dispose来对其进行释放。

60c6a86ee64c4ca04d370ba050fa6580.png

最后,当使用lights per object时,我们将使用不同的着色器变体。通过适当地启用或禁用_LIGHTS_PER_OBJECT着色器关键字来决定。

6f1c0388dc5f89a96b59f30bc1bd88f8.png

4.3 使用索引

要使用灯光索引,请将相关的多编译编译指示添加到我们的Lit着色器的CustomLit的Pass中。

010bc5287c13d1f972ec9a4ce37a8ea3.png

所需数据是UnityPerDraw缓冲区的一部分,由必须在unity_WorldTransformParams之后直接定义的两个real4值组成。首先是unity_LightData,它包含其Y分量中的灯光量。之后是unity_LightIndices,它是长度为2的数组。两个向量的每个通道都包含一个光索引,因此每个对象最多支持八个。

1bda6bb53c3a30b4bb6b7888e459231e.png

如果定义了_LIGHTS_PER_OBJECT,则对GetLighting中的其他灯光使用替代循环。在这种情况下,可以通过unity_LightData.y找到灯光量,并且必须从unity_LightIndices的适当元素和组件中检索灯光索引。可以通过将迭代器除以4并通过取模4得到正确的分量来获得正确的向量。

a68554a5ed72adebf49de48f5c6ceaf0.png

但是,尽管最多只有8个光索引可用,但是提供的光计数并未考虑此限制。因此,我们必须将循环明确地限制为八个迭代。

f1c85fcfe768f3faa2bf7396a3df147d.png
是否有缓冲方法不限于每个对象八个灯?
曾经有,但是该代码自Unity 2018.3起已被禁用,并且已从Universal RP中部分删除。死代码已经有一年多了,所以我不会再依赖它了。

65c9f1f650b98d82cb1b298663761815.png

331cb4c7c5e60f5141326ecdfa77c686.png
Lights-per-object 没有开启和开启

请注意,启用Lights-per-object后,GPU实例化效率较低,因为灯光计数和索引列表匹配的对象才会分组。SRP批处理程序不受影响,因为每个对象仍然获得自己的优化后的DrawCall。

下一章,点光和聚光灯阴影。

本文翻译自 Jasper Flick的系列教程

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

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

相关文章

c#日期转换周几_Java时间与日期

只有把眼前的事情做好,才能考虑其他的问题。众所周知,全世界在同一时刻看手表肯定不会看到同一个时间,因为地球是圆的,面对太阳的角度是不一样的,我们一般说时间几点几点,是指的本地时间,比如国…

Python开发之--前端 HTML基础

一:HTML介绍 HTML:超文本标记语言,标准通用标记语言下的一个应用。包括“头”部分(英语:Head)、和“主体”部分(英语:Body),其中“头”部提供关于网页的信息&…

给与用户建立dblink的权限_网络安全 之 NTFS安全权限

NTFS安全权限一、NTFS权限概述1、通过设置NTFS权限,实现不同的用户访问不同的权限2、分配了正确的访问权限后,用户才能访问其资源3、设置权限防止资源被篡改、删除二、文件系统概述 文件系统即在外部存储设备上组织文件的方法常用的文件系统:…

TCP 连接中的TIME_WAIT

原文:http://blog.csdn.net/wangpengqi/article/details/17245349 这就有个细节,一次http请求,谁会先断开TCP连接?什么情况下客户端先断,什么情况下服务端先断? 百度后,找到原因,主要…

丁丁打折网卷能用吗_微信群控还能用吗?现在什么群控还能使用吗?

微信群控系统还能用吗?为什么现在微信群控系统越来越被限制了呢?其实,微信群控我想在生活中占据着很大的位置!因为微信这么多的使用,现在微信使用人数都是几十亿了,所以很多人看重微信群控系统的市场&#…

错题整理

1.JAVA语言的下面几种数组复制方法中,哪个效率最高? A for循环逐一复制 B System.arraycopy C System.copyof D 使用clone方法 答案:B A、for循环的话,很灵活,但是代码不够简洁. for循环为什么慢,java中所…

xpath中两个冒号_爬虫学习(5)—XPath

之前我们写了一个简单的爬虫,在提取页面信息时我们使用正则表达式来匹配内容,但是正则表达式的书写比较繁琐,而且一旦错误就可能导致匹配失败。对于网页的节点来说,它可以定义id,class或其他的属性,而且节点…

canny算法的实现(android加载图片,数组写入文件换行)

Canny边缘检测首先要对图像进行高斯去噪,前面讲到了高斯去噪处理,这里从对图像灰度进行微分运算讲起吧。微分运算常用的方法是利用模板算子,把模板中心对应到图像的每一个像素位置,然后按照模板对应的公式对中心像素和它周围的像素…

【VirtualBox】VirtualBox的桥接网络模式,为啥网络不稳定?

网桥模式访问外网非常慢,经常卡死,ping时断时续 七搞八搞,反复重启了几次 TMD 就好了,也不知道什么情况,VirtualBox还是不太好使啊。。。。。 网桥模式 设置 如下: 参考资料: http://blog.csdn…

白盒基本路径发测试实验报告_软件生命周期、白盒测试、黑盒测试

继上一讲:隅巳毕月:达摩克里斯之——排序与查找技术​zhuanlan.zhihu.com我们今天来讲一下软件周期与两种软件测试方法软件开发应遵循一个软件的生命周期,通常把软件产品从提出、实现、使用、维护到停止使用、退役的过程称为软件生命周期。软…

Windows7睡眠后自动唤醒

笔者的电脑(Windows7 64位旗舰版)睡眠后,隔段时间后会自动唤醒。经两项配置后,解决了该问题。 1 禁用唤醒定时器 控制面板里进入"电源选项""更改计划设置"界面,如下图所示 单击上图的"更改高…

bootstrap 两个轮播图冲突_为什么使用bootstrap在一个页面同时做两个轮播效果时,只有第一个有效??...

我们都知道使用bootstrap做轮播效果非常快,但是有时候一个页面会需要两个轮播;但这个时候再次使用bootstrap做轮播效果时就会失效;原因在于bootstrap的Carousel问题,只要修改一下id,就好了~~这是第一个轮播&#xff1a…

Ajax的用法

1 Ajax是什么 1.1 Asynchronous JavaScript and XML(异步的javascript和xml) 实质为:使用浏览器内置的一个对象(XmlHttpRequest)向服务器发送请求,服务器返回xml数据或文本数据给浏览器,然后在浏…

Node.js server使用

一、创建项目 #创建项目目录 cd /data mkdir webroot cd webroot#初始化git git init vim .gitignore 输入: node_modules/ 保存: :wq#初始化npm,生成package.json npm init#安装express npm install -D express#创建入口文件 vim app.js输入: var expr…

模仿Linux内核kfifo实现的循环缓存

想实现个循环缓冲区(Circular Buffer),搜了些资料多数是基于循环队列的实现方式。使用一个变量存放缓冲区中的数据长度或者空出来一个空间来判断缓冲区是否满了。偶然间看到分析Linux内核的循环缓冲队列kfifo的实现,确实极其巧妙。…

领域模型(domain model)贫血模型(anaemic domain model)充血模型(rich domain model)

领域模型是领域内的概念类或现实世界中对象的可视化表示,又称为概念模型或分析对象模型,它专注于分析问题领域本身,发掘重要的业务领域概念,并建立业务领域概念之间的关系。 贫血模型是指使用的领域对象中只有setter和getter方法&…

datagrid显示mysql_WPF DataGrid显示MySQL查询信息,且可删除、修改、插入 (原发布 csdn 2018-10-13 20:07:28)...

1、入行好几年了,工作中使用数据库几率很小(传统行业)。借着十一假期回家机会,学习下数据库。2、初次了解数据库相关知识,如果本文有误,还望告知。3、本文主要目的,记录下wpf界面显示数据库信息,且可进行删…

mysql 集群 qps_MySQL Cluster:如何通过扩展为MySQL带来2亿QPS

本篇文章的目的在于介绍MySQL Cluster——也就是MySQL的一套内存内、实时、可扩展且具备高可用性的版本。在解决标题中所提到的每秒2亿查询处理能力问题之前,我们先对MySQL集群的背景信息及其架构进行一番回顾,这将有助于大家理解上述目标的实现过程。My…

测试题的答案(技术博客)

根据老师的要求,我把上次测试的答案汇总了下,将程序写的得到满分的答案给挑了出来,希望大家不要追究版权问题,若有问题,我们私下武力解决问题。 第一题:从键盘输入一个大写字母,要求改用小写字母…

history模式监听_面试题:VueRouter中的 hash 模式和 history 模式有什么区别

面试题:VueRouter中的 hash 模式和 history 模式有什么区别hash模式hash 模式的路由中带有 # 号hash 模式通过 window.onhashchange 方法监听路由的修改hash 模式在页面刷新的时候,发送的请求 url 是不带 # 后面的内容的hash 模式可以兼容部分低版本的浏…