5.1 Shading Models

shading model:决定了渲染管线的功能,也就是渲染的方式,根据不同的光照,视角,来渲染出不同的模型表面颜色

比如:Gooch shading model :根据顶点法线方向和光源的相对位置,来决定模型的表面颜色,法线朝向光源,暖色调,背向光源,冷色调

模型的表面颜色一般受视角方向和光照方向的影响

这就是一个简单的光照模型,其中表示限制值为0-1,这其中出现了两次差值,一次是Ccool和Cwarm的差值,然后是 hightlight 和 diffuse 的差值,可以用 lerp 表示

r 表示反射光,也可以用reflect (-l,n)表示 ,t就是一个半兰伯特模型

5.2 Light Sources

现实生活中的光照计算非常复杂,可能有不同的光源类型,不同的光源形状(shape)、颜色(color)、强度(intensity),还要考虑间接光的影响(PBS)

光照计算复杂的原因还有让shading model 以binary way 的方式,在有光照和没光照两种情况下做出不同的交互,比如阴影的表现

光照从出现到消失,可以用intensity 的差值表示,比如

表示不受光照影响时的表面颜色,根据你想实现的效果,可以赋予它不同的值,比如(0,0,0)表示不受光照时为纯黑色,一般来讲,这部分代表了间接光照的效果,比如天空盒的颜色,或者反射的其它物体的光

如果光源方向l 和表面法线n 的角度超过90度,则该光源就不再影响该表面的颜色

光源到达表面的光线的密度叫做辐射度,它决定了光照的强度(intensity) ,从上图可以看出,辐射度和cos(l 与 n 之间的角度成反比),和 l 与 n  之间的角度成正比

更准确的说 当 n点乘l 为正值,也就是角度小于90度时,辐射度成正比,当点乘为负值时,光照对表面没有任何影响,表现为黑色,所以上面模型使用了半兰伯特模型,提高暗处的亮度

+ 好表示,最小值为0,上式表示多个光照使用了同样的光照模型,所以用了积分

5.2.1 Directional Lights

平行光:光照方向l 和 光源颜色 Clight 都是一个常量,除了Clight 会在阴影处衰减,相对来说  平行光是没有位置属性的,因为它到表面的距离要远远大于场景的大小,它也可以扩展为 Clight 是可变的,根据不同的场景,比如模拟太阳落山

5.2.2 Punctual Lights(point light)

有位置,有方向,向各个方向发射的光强都是一样的,点光源和聚光灯(spot light)是同种类型的光源

光照方向L ,根据表面点的位置不同而不同,计算一个向量的长度,可以用

r表示 表面到光源的距离,除了应用在光照方向上面,它也决定了光照的衰减

Clight 根据r变化而变化,光的辐射度和r的平方成反比,距离越远,光的强度越弱,不像平行光,光强只在一个方向上有变化,点光源是在一个二维的平面上有变化,光的辐射度和R的平方成反比

上式也叫inverse-square light attenuation(平方衰减),r 表示当前的距离光源的距离,R0表示 点光源的半径,虽然从技术上来说,点光源的距离衰减是正确的,但是对于实际的阴影使用来说,有一些问题使得这个方程不那么理想

比如:当r 接近于0时,Clight 就是无限大,当r为0时,除数就为0了,这是不正确的,为了解决这个问题

我们加上了一个常数E,UE引擎中,E =1 cm ,根据不同的引擎,实际的值也不同

也有的引擎使用上述公式,解决r=0的问题,Rmin 表示光源本身的半径,比如一个球是一个光源,光源的辐射半径是R0,球的半径是Rmin

第二个问题就是当r无限大的时候,Clight接近于没有,但是永远不为0,为了渲染的效率,我们希望在超过一个距离是,颜色直接为0 ,而不是继续计算它,但是要避免在该边界处,光照的突变,要有个过渡

还有一些引擎使用

fdist(r) 叫做 distance falloff functions,而不是平方衰减函数,根据引擎的性能做出选择

比如游戏《Just Cause 2》,采用下图的方式,让过渡平滑的同时,节省些性能

Spotlights

聚光灯,光强不仅和光源到表面的距离有关,还和关照方向有关

Fdir(l):表示光照随着光照方向的改变的函数

聚光灯的光照区域是关于中间的光照方向左右对称的,是一个锥体,中间的光照方向我们用向量s 表示,所以 Fdir(l) 可以表示成 光照方向-l 与 s 之间的夹角 和 s 之间的关系,-l 表示指向物体表面的方向,l 表示 点指向光源位置

当然这个夹角也是有范围的,用表示,超过这个角度,值为0 ,也就是不受该聚光灯影响,它可以在计算距离衰减之前,就过滤掉哪些不受光源影响的表面,因为角度超过了限制,就不用再计算距离衰减了

同时也有一个penumbra angle θp 角度,在这个角度内,光照强度为1

不同的引擎,采取的方法也不一样

5.2.3 Other Light Types

Directional and punctual lights 对表面颜色的影响主要受光照方向的影响,不同类型的光源有不同的计算光照方向的方法,除了上述提到的光源类型,游戏《Tomb Raider》还有一个capsule lights 它的光照方向是距离光源最近点的方向

我们现在讨论的光源都是抽象的,在现实当中 light sources 有大小,形状,可以从多个角度照射到表满,在渲染中我们叫 area lights,它们的使用在渐渐增多,  Area-light 的渲染技术大致分为两类,: 由于区域光被遮挡,模拟边缘的阴影是一种,模拟区域光对模型表面的影响是第二种,th. 对于光滑的镜面表面来说,第二种类型的照明是最明显的,在这种表面上,光的形状和大小可以从它的反射中清楚地辨别出来。

5.3 Implementing Shading Models

shading model的实现:就是把我们上述的公式,用代码表示出来

5.3.1 Frequency of Evaluation

在设计 shading 实现的时候, 它的计算能力是根据 frequency of evaluation来划分的,首先,确定该计算的结果,是否在整个draw call当中都是保持不变的,如果是 则这个计算可以由CPU执行(比如顶点数据),然后通过图形API 作为uniform shader inputs传递下去,而GPU来计算哪些更耗费性能的计算.

在这个条件下,也有很大的范围空间,比如 一个常量表达式,在整个draw call 中都是一样的,但是可以通过配置改变,这样的计算在shader 编译的时候,就计算了,根本不需要额外的输入,也就是不是运行时计算的 ,在应用安装时就计算了

另一种就是在应用运行时,计算结果实时改变的,但是计算的频率很低,比如计算一天中的光照,就分为几个阶段

其它的类型包括计算结果实时变化的,且更新频率很高,比如连接视图和透视矩阵,每一帧都在变化等等,根据计算的频率,把uniform shader inputs分组,比如合批,有助于提高性能,也能够降低GPU 更新的频率

如果计算的结果在一个draw call 中会变化,就要通过varying shader inputs 传递给可编程shader 阶段,理论上来讲,shading computations 可以在任何可编程阶段执行,每一个可编程阶段有不同的 evaluation frequency:

现在大部分计算都在片元着色器中执行,顶点着色器只执行一些坐标变换或者顶点扰动,

片元和顶点中计算光照的区别

造成这种错误的原因是在顶点着色器中就进行插值计算了,应该是在片元着色器中差值,虽然这能节省一部分性能,但是插值计算本身的消耗就是非常低的

注意 尽管vertex shader 输出的是单位法线,差值也会更改它们的长度,所以normals需要在 片元着色器中再单位化一次,如果法线长度在顶点之间变化非常大,通常在差值前和差值后进行一次 归一化(normalize),比如在 vertex 和 pixel shaders各进行一次

除了表面法线,视角方向,以及光照方向,也需要在片元着色器中计算,通过向量相减,这个计算非常快,并且在差值之前不要归一化

5.3.2 Implementation Example

比如:

上述式子可以转换成:

Csurface 通常存储在顶点中,或者是贴图中

上面公式实现,需要shader 动态遍历 光源,这是用了shader的动态分支 功能,但是不适用于光源比较多的场景

shader model 不是一个单独的过程,是需要大量的工作要做的

在shader 之前 ,我们需要先定义一些变量

shader inputs 分为两种,一种叫 uniform inputs, 在CPU中计算,在整个draw call 中是常量,比如你定义的一些属性,或者顶点的一些属性,模型坐标,贴图坐标等,另一种叫 varying inputs, 在顶点着色器和片元着色器中是可以改变的,比如世界坐标,世界空间下的法线,这些是通过计算得到的.

注意:在顶点着色器中,法线并没有归一化,因为它在模型中就是已经归一化过得,如果不进行一些操作,比如顶点混合vertex blending ,nonuniform scaling,就不用进行归一化,上面的操作会改变法线的长度

5.3.3 Material Systems

Rendering frameworks 一般很少由一个shader 渲染组成,比如一个模型,可能有多个material,material  system 就是专门来处理多个材质球,多个shading models 的情况。

shader 仅仅是流水线中的可编程阶段,它是最底层的图像API ,所以交互起来可能不太友好,material system 让交互更加的形象,可以在面板上显示出来

material  和shader  不是一对一的关系,有的material 由多个shader 组成,一个shader 也可以在多个material中共享

最通用的就是 parameterized materials,parameterized materials需要两种类型的material entity,material templates 和 material instances,简单来讲就是基类和子类的关系,material templates有一组共同的参数,比如贴图,颜色,instance 在此基础上加上一组特有的参数

这些参数可以在运行时,通过uniform inputs 传入进去,也可以在编译阶段,把值代入

一个比较通用的编译时参数,就是bool 值,用来控制shader分支的,会在编译时就代入进去,从而只编译满足的shader 代码

material 的参数 和 shader的参数并不总是一对一的,比如我们声明了属性,还要在shader中声明对应的变量,从而使用material的参数,这些参数可以保持不变,但也可以在shader中变化,这种变化不会体现到material 中

material system 一个很重要的功能就是:把不同的shader  function 独立出来,然后控制它们的组合,来达到不同的目的

GPU不支持代码在编译后链接(post-compilation linking of code fragments),每一个shader 阶段 都是单独编译的,所以通常通过 #include, #if,  #define 指令来编译不同的代码块

在设计shader variants system的时候,首要问题就是怎么在编译时通过条件判断执行不同的变体,或者在运行时通过动态分支选择不同的变体,在之前硬件不发达的情况下,动态分支判断非常慢,所以都是在编译时判断,在现在,动态分支的判断变得非常快,尤其当所有的pixel 都是走同一个分支时,但是如果判断多了,也就意味着 寄存器多了,则 占有率就下降了,性能也就下降了,所以 编译时判断 也是非常重要的,它避免了一些不必要的变体计算

现在的 material system 同时包含了运行时变体和编译时变体,虽说负担从编译时转向了运行时,但随着变体的增加,编译时的变体仍然很多

material system 通过采取不同的策略,来减少编译的数量了大小,比如:

• Code reuse—把公用的功能写在一个文件中,然后通过 #include 访问

• Subtractive—使用编译时预处理,或者动态分支,来删除掉哪些用不到的变体.

• Additive—通过图形软件

除了上述考虑,还要考虑硬件的适用性,需要支持不同的平台,并且是复制到代码最小化

5.4 Aliasing and Antialiasing

想象一个大的黑色三角形在白色背景上缓慢移动。当一个像素被三角形覆盖时,表示该像素的颜色值,应该平滑的过渡到黑色,但是通常发生的情况是,当像素的中心被覆盖时,像素颜色立即从白色变成黑色。像素的颜色在这种变化中非黑即白的表现就叫锯齿。锯齿是颜色突变造成的

5.4.1 Sampling and Filtering Theory

渲染图片其实就是采样的过程

上图显示了一个连续的信号,每个一段时间采样一次,形成了一个离散的数字信号,然后再通过filtering 重新形成一个(reconstructed)连续的信号

当采样结束时,就会出现锯齿,一个经典的案例就是用电影摄影机拍摄的车轮

因为轮子的转速要远远高于摄像机记录的速度,所以你看起来轮子会出现 倒转,不转  ,或者转的很慢的情况,这是因为车轮的图像是在一系列的时间步骤中拍摄的,这种效果被称为temporal aliasing

在计算机图形中,temporal aliasing常见例子有栅格化线或三角形边缘的“锯齿”、被称为“萤火虫”的闪烁的高光,以及带有格子图案的纹理被缩小

当以很低的频率采样时,锯齿就会出现,源新号被采样之后,形成了一个比原来频率低很多的新的新号,为了让一个新号被正确采样,采样的频率需要是原来信号频率的至少两倍,这个理论叫做  sampling theorem, 这个采样频率叫 Nyquist rate 或者 Nyquist limit,在原理论中,Nyquist limit 被称之为maximum frequency,也就是采样频率也是有上限的,band-limited

也就是说提高采样率,是能够完美重构出原来的信号曲线的

采用点采样,是无论被采样的物体多么小,我们都可以采样成功

Reconstruction

给定一个band-limit采样信号,我们现在将讨论如何从采样信号重建原始信号

为了reconstruction必须使用filter, 请注意,滤波器的值应该始终为1,也就是和原信号的值,保持一致,否则重建信号可能会出现增大或缩小。

上面这个filter 滤波器非常差,因为重构出来的图像是非连续的,使用box filter 的原因是因为它简单,方法就是把滤波器 和 采样后的信号的y值重合

上面的这个叫做 low-pass filter (低通滤波器),它的频率是sin(2πf),f是滤波器的频率,鉴于此,低通滤波器去除所有频率高于滤波器定义的特定频率的频率成分。

为什么叫低通滤波器?它其实是box filter,当它与信号相乘时,它会去除滤波器宽度以上的所有频率

在使用滤波器后,得到了一个连续的信号。然而,在计算机图形学中,我们不能直接显示连续信号,但我们可以对连续信号重新采样到另一个size的信号

Resampling

Resampling 用来放大或者缩小信号,这里的放大或者缩小不是指y值上的放大缩小,而是指采样的间隔,比如原始信号的坐标x 为 (0, 1, 2, . . . ),resample 之后,我们的得到的采样点间隔a, a > 1, 就是downsampling, a < 1, upsampling.

downsample  发生在原始信号的频率非常高,这时我们只能降低采样的频率,结果就是是原来的图像稍微模糊一点

5.4.2 Screen-Based Antialiasing

如果图像的边缘不经过采样和过滤器处理,就会出现锯齿,有一个基于屏幕的通用thread,也就是 对渲染管线输出的结果进行操作.同时需要明确的是 没有一种抗锯齿的方法是十全十美的,都有各自的有点和缺点,根据不同的情形,选择不同的算法

上面讲的黑色三角形在白色背景上缓慢移动的例子,一个原因是采样频率太慢,另一个是采样点只有中心点一处,通用的策略是,多个个采样点,然后共同决定该像素的颜色

n 是采样点的数量,w 是该采样点决定最终颜色的权重,所有点的权重加起来和为1, c(i,x,y)在该位置下的颜色,也就是不同的位置的采样点的颜色是不同的

如果只有一个采样点,那么返回的是该像素中心点的颜色值,w=1

这种计算一个像素中多个采样点的抗锯齿方法,称为 过采样或者超级采样(supersampling (or oversampling)),也叫full-scene antialiasing (FSAA)或者 “supersampling antialiasing” (SSAA)

比如:渲染一个高分辨率的场景图像,然后经过重采样,生成一张屏幕大小的图像,比如 需要一张1280*1024的图像,你先生成了一张2560 × 2048的图像,也就是 原一个像素包含了四个像素的大小,所以每个像素要采样四次,然后通过box filter 过滤,这种方法非常耗性能,因为每次采样都需要重走一遍pass,并且各自包含了z-depth,所以FSAA的优点就是简单

过采样的原理就是利用 accumulation buffer(累计缓存),它的大小和屏幕大小相同,而不是屏幕外的大图像,只不过每一个颜色通道包含了更多的bit,比如一个4个采样点的图像,生成了四张image,这四张图像是在不同的采样点下生成的,需要把这四张图像的数据拷贝到屏幕上,这也是耗费性能的地方。所以这种方式视情况而定,如果性能不是很吃紧,就可以使用

Multisampling antialiasing (MSAA) 通过执行一次shader pass ,然后结果在采样点之间共享,从而减少了性能耗费。

 

同样也是四个采样点,拥有各自的color 和z-depth,但是 shader pass 只执行一次,如果所以的采样点都被颜色覆盖了,则以中间点的数据为准,计算color,如果只是覆盖了一部分,则GPU  会自动调整采样点的位置,这种行为叫做 centroid sampling 或者 centroid interpolation

MSAA 比FSAA 快的地方就是,它只进行一次shader pass,这种思想进一步提升为不需要为每一个采样点都保留color 和 z-depth,只需保存不同的color 和 z-depth,从而脱离的采样点的位置,这种方式叫EQAA , 如果超过存储的颜色数量,则该采样点作废,比如你有一万个采样点,这是不现实的。

当所有的采样点 都计算完毕,就需要计算最终的颜色值了,根据上面的算法,但是如果使用了HDR的颜色时,需要先映射到0-255范围内,这非常耗性能,所以一般是贴图映射

采样之后就需要filter了,之前使用的是box filter,在现代GPU中,你可以使用任意类型的filter,

更好的效果是记录一下上一帧的结果,然后和当前帧进行混合,只不过权重不一样

Sampling Patterns

采样模式,就是我们上图的那样,就是采样点的位置不同,以及数量不同,好的选择是避免两个采样点离得太近,这样意义不大,一般采样模式,内置于硬件当中

5.5 Transparency, Alpha, and Compositing

一种照射半透明物体的方法叫screen-door transparency,这种方法简单,缺点是只能渲染一个半透明物体

另一种更常见的方法是,采用透明度混合的方法

一个像素的 alpha 值不仅仅表示透明度,也可以表示颜色的覆盖度,比如肥皂泡覆盖了四分之三的像素, 也就是0.75的部分接近于透明,能够让十分之九的光线进入眼睛,所以它是十分之一的不透明, 则它的 alpha是 0.75 × 0.1 = 0.075. 但是,当我们使用 MSAA 采样算法时,我们需要考虑采样点本身的透明度, 四分之三的采样点都受泡泡的影响,因此,每一个采样点的透明度都是0.1

5.5.1 Blending Order

Cs 是当前shader计算得到的颜色值,Cd 是color buffer中原来的颜色

当模拟透过玻璃看其他物体的效果是,上述公式就不怎么管用了,在现实世界中,透过红色玻璃观看蓝色物体,蓝色物体通常看起来很暗,因为这个物体反射的光很少、

另一种常用地混合方法,是相加

它适用于发光的物体,能够让颜色更亮更鲜艳

为了时渲染效果正确,我们必须在所有的不透明物体渲染完毕后,再渲染,但是这种问题就是,z-buffer中只能存储一个物体的深度值,当有多个不透明物体时,就不能渲染出正确的结果了

一种方法就是对渲染物体进行排序,但是如果物体穿插,就无法进行排序了,首先要关闭深度写入,因为这种大致的排序比较简单,所有也经常用,还有就是拆分模型,另一个方法就是渲染背面,再渲染前面

上图表示 source alpha 为0.7  destination alpha 为0.6  ,然后这个片元整体的透明度为0.88

5.5.2 Order-Independent Transparency

处理透明度混合的方法有很多种,都有一定的优点和缺点,一种是根据z-depth 剥离层,一个pass可以剥离很多层,然后进行混合,这种方法缺点是性能消耗高,pass数不确定

一种是额外开辟一个缓存,k-buffer,用来存储该像素覆盖的各个片元,相当于一个链表,然后计算平均颜色值,这个不好的地方是需要额外的内存,并且内存上限不可预知

一种是上述方法的改进,对各个fragment 的值进行加权,根据距离加权和根据透明度加权,计算最后的值,但是如果在一个大场景中,距离差不多,透明度也差不多,最后的权值差不多,会和真实场景有点区别

5.6 Display Encoding

当我们计算光照,纹理或者其它颜色操作时,我们需要在 linear  空间下. 为了避免产生不同的效果,display buffers 和 textures 使用 nonlinear encodings 的情况,我们必须考虑进去. 也就是说: shader 输出的color 在 [0, 1] 范围内,然后乘以一个  1/2.2 次幂,也就是大约0.45, 这个叫做 gamma correction(伽马校正).

在最初的CRT阶段,也就是二极管阶段,输出的颜色和输入的电压乘一个幂率的关系,大概是2.2

也就是你的颜色本来是0.5,输出的颜色为0.25左右,

简而言之: 我们sRGB 的图,它是经过display transfer function 的,也就是已经处理过了,要比线性空间要暗一些,我们采样的时候,会把值转换到线性空间,然后当我们最终写入到framebuffer的时候,进行一次伽马校正,让颜色提亮一些,最后,经过屏幕显示出来的,就正常了

Real-Time Rendering 第五章 光照模型相关推荐

  1. 【转载】【《Real-Time Rendering 3rd》 提炼总结】(四) 第五章 · 图形渲染与视觉外观 The Visual Appearance

    本文由@浅墨_毛星云 出品,转载请注明出处.   文章链接: http://blog.csdn.net/poem_qianmo/article/details/72857602 这篇文章将总结和提炼& ...

  2. 【《Real-Time Rendering 3rd》 提炼总结】(四) 第五章 · 图形渲染与视觉外观 The Visual Appearance

    本文由@浅墨_毛星云 出品,转载请注明出处.   文章链接: http://blog.csdn.net/poem_qianmo/article/details/72857602 这篇文章将总结和提炼& ...

  3. 【《Real-Time Rendering 3rd》 提炼总结】(四) 第五章 · 图形渲染与视觉外观

    本文由 @浅墨_毛星云  出品,转载请注明出处.    文章链接:http://blog.csdn.net/poem_qianmo/article/details/72857602 这篇文章将总结和提 ...

  4. 【 Real Time Rendering 3rd 提炼总结】 四 第五章 图形渲染与视觉外观 The Visu

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本文由@ ...

  5. 【 Real-Time Rendering 3rd 提炼总结】 四 第五章 图形渲染与视觉外观 The Visu

    本文由@浅墨_毛星云 出品,转载请注明出处.     文章链接: http://blog.csdn.net/poem_qianmo/article/details/72857602 这篇文章将总结和提 ...

  6. 聚焦3D地形编程第五章GeomipMapping for the CLOD

    第二部分高级地形编程 聚焦3D地形编程第五章GeomipMapping for the CLOD 译者: 神杀中龙 邵小宁 microsoftxiao@163.com 翻译的烂请见谅 原著 <F ...

  7. 交互式计算机图形学总结:第五章 光照和明暗绘制

    第五章 光照和明暗绘制 光照的一些概念 –从光源照射到物体的光传递了反射(Reflective)光[包括漫反射(Diffuse)和镜面(Specular)反射],透明(Transparent)光和吸收 ...

  8. 【Ogre编程入门与进阶】第十五章 Ogre的“二维”与合成特效

    15.1 Ogre中的"二维" 早在第一章,我们就曾经向读者介绍过,Ogre是一个3D图形渲染引擎,通过Ogre可以制作出各种各样的三维动画和游戏.但是,不要以为Ogre中只能渲染 ...

  9. 王道考研 计算机网络笔记 第五章:传输层

    本文基于2019 王道考研 计算机网络: 2019 王道考研 计算机网络 个人笔记总结 第一章:王道考研 计算机网络笔记 第一章:概述&计算机网络体系结构 第二章:王道考研 计算机网络笔记 第 ...

最新文章

  1. 多线程的使用——模拟线程池的实现(2015-12-02 00:14:59)
  2. Sql sever 分组排序
  3. Unity 内建数据索引
  4. can使能上拉 gpio_单片机GPIO输入电压不可过大,最好使能上拉
  5. linux修改文件系统属性,实用技巧:修改Linux操作系统的文件属性
  6. 又一个Python数据分析学习利器!
  7. jeston nano usb转485通信,usb扩展连接多个设备设置固定
  8. 中国行政区划代码(2020年版)附树形sql与excel
  9. 计算机锁屏如何取消密码,笔记本电脑怎么取消锁屏密码
  10. 吴恩达机器学习 编程作业 python 版提交方法以及代码-week2
  11. MonthCalendar上使ToolTip随鼠标位置实时变化
  12. linux最全网络监控命令梳理及评测
  13. win10有一个隐藏的超级管理员帐户,拥有全部权限,如何启用它
  14. 2020年GitHub 上那些优秀Android开源库,这里是Top10!
  15. 咕咕漫画之弹窗破解去除
  16. 记录h5文件数据转为npy和csv格式类型的方法
  17. 爬虫爬取qq看点视频
  18. 如何备份MySQL数据库
  19. HTML5——如何在网页中加入图片和超链接。
  20. 基于JavaEE的大学生公寓管理系统

热门文章

  1. Linux 系统安全检查
  2. 个人计算机市场排行,2017中国市场50款笔记本电脑排行榜
  3. 刀片服务器的故障信息,刀片服务器故障
  4. PDF怎么压缩到最小?有在线压缩的方法吗
  5. wpsppt页面卷曲在哪里_2013版ppt怎么制作页面卷曲动画效果_博客
  6. html实践手机调试
  7. 防火墙阻止了从docker容器到外部的网络连接
  8. vue + sentry监控平台
  9. 【听】特斯拉传,科学超人传奇
  10. 四天搞懂生成对抗网络(一)——通俗理解经典GAN