当前位置: 首页 > news >正文

[总结] 漫谈HDR和色彩管理(四)HDR标准和ACES

[总结] 漫谈HDR和色彩管理(四)HDR标准和ACES

https://zhuanlan.zhihu.com/p/144775352

上一节讲到了上古时代的SDR Color Pipeline以及最常见的两种SDR显示及其颜色空间标准(sRGB和Rec. 709)。然而,SDR显示在色彩管理和显示上有着天然的缺陷,随着对色彩显示和存储的更高需求,我们迎来了HDR显示的时代。这些纷繁复杂的显示器和颜色标准给整个pipeline增加了非常大的管理挑战,ACES横空出世来帮助我们在各个阶段都能获取一致的显示结果。

# SDR的缺陷

SDR最明显的缺点就是它覆盖的色域范围太小,只占了CIE 1931颜色空间的大约35.9%区域:

来源:https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html

一些饱和度非常高的颜色无法在这样的低色域下表现出来,影响色彩表现的丰富度。同时,在低色域下计算光照和渲染会导致颜色值被clip掉,影响色彩的准确性。

其次,从SDR的OETF函数到最终显示器亮度之间存在一条不确定的鸿沟。这是因为,SRD OETF的输出范围为0到1,而显示器的最大亮度是不确定的,这和具体的显示器型号相关,例如HDTV显示的亮度峰值通常要大于PC显示器。我们使用的SDR Tonemapping曲线在较低亮度的PC显示器上可能效果更好,而在有着更高亮度峰值的HDTV上显示就显得缺少细节,我们当然可以为更高亮度的显示器使用一条不同的Tonemapper曲线来增加高亮区域的细节,但这也会增加色彩管理的复杂性。

为了解决这些问题,我们引入了HDR颜色空间标准。

# HDR颜色空间标准

最常见的HDR颜色空间标准是ITU-R Recommendation BT.2020(简称Rec. 2020或BT.2020)。Rec. 2020定义了一个HDR颜色空间的三原色(R (0.708, 0.292), G (0.170, 0.797), B (0.131, 0.046))和白点(D65),它的色域范围可覆盖CIE 1931颜色空间的75.8%:

来源:https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html

和Rec. 709类似,Rec. 2020标准也指定了一个精确的OETF传递函数:

其中,α和β在32位全精度下的值为1.09929682680944和0.018053968510807 ,在12位精度下的值为1.0993和0.0181,在10位精度下的值为1.099和0.018。

Rec. 2020标准定义了在SDR显示下其使用的EOTF函数,这个EOTF函数和Rec. 709一样,即是由BT.1886定义的EOFT函数。而配合Rec. 2020使用的更常见的传递函数是在HDR显示下使用的EOTF函数,这是由ITU-R BT.2100定义的ST 2084或HLG传递函数。

## ST 2084 / PQ传递函数

ST 2084全称为SMPTE ST 2084(Society of Motion Picture and Television Engineers, 2014),它是一个配合Rec. 2020三原色使用的EOTF函数(即output-referred encoding function)。它最早是由杜比(Dolby)定义的一个名为PQ(Perceptual Quantizer)的编码函数,最大可编码高达10000 cd/m²(尼特)的高动态亮度值。PQ传递函数的本质是根据人眼视觉系统对亮度的感知对比度来最大限度地利用编码空间对数字信号进行量化,简单来说,就是在尽量避免出现人眼可察觉的亮度色阶(banding)的情况下对数据进行量化和编码。

下面是由人眼视觉系统衍生出来的Barten Ramp模型,它描述了在当前亮度值(横坐标)下,两个亮度值之间的差别达到多大百分比时可以被人眼所察觉到。亮度差处于虚线上方时,人眼就可以察觉到亮度对比从而出现所谓的banding现象;当亮度差处于虚线下面时,在人眼看来它们就是没有区别的是平滑渐变的:

来源:HDR in Call of Duty

依靠Barten Ramp模型,我们可以评估一条亮度编码曲线对数据的利用率。例如,下面绿线表示用16位精度(如OpenEXR格式)直接存储亮度值所产生的亮度精度差,可见它的差值全在曲线以下因此在视觉上不会产生banding:

来源:HDR in Call of Duty

下面橙线和蓝线分别表示15位和10位精度下使用伽马编码后的曲线。10位精度的伽马编码在0到1亮度范围内的亮度差都在曲线以上,这意味着会出现人眼可见的色阶问题。而15位精度的伽马编码虽然都在曲线以下,但它在高亮区域的编码是一种数据浪费,也就是说在这些区域它存储的大量不同亮度值在人眼看来其实是没有差别的。紫线表示了13位精度的Log编码,相比15位伽马编码来说它虽然更加充分地利用了高亮区域的数据编码,但在低亮区域却会造成数据浪费:

来源:HDR in Call of Duty

下面就是使用Dolby提出的PQ传递函数在12位精度下所得到的亮度差曲线,可见PQ传递函数的编码方式在各个亮度区间范围内都可以更加充分地利用编码数据:

来源:HDR in Call of Duty

ITU-R BT.2100为PQ定义了它具体的EOTF传递函数。这个ST 2084 EOTF传递函数如下:

其中各常量数值如下:

其曲线表示如下:

来源:https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html

可以看出,PQ OETF函数与之前见到的sRGB或Rec. 709的EOTF函数有很大不同。首先PQ传递函数输出的是一个范围在0到10000 cd/m²的绝对亮度值,而SDR输出的则是一个在0到1范围内的相对亮度值,SDR显示器显示的真正亮度值是未知的。这种确定性在我们debug时也很有帮助,例如PQ值为0.5时对应的亮度值大约为100尼特,它是老的LCD显示器常见的亮度峰值;PQ为0.75时对应的亮度值大约为1000尼特,它是一部分HDR TV显示器的亮度峰值。

PQ传递函数的视觉一致性使得它很适合作为output-referred image的工作空间,可以最大限度地利用编码数据减少视觉错误。事实上,很多游戏引擎在HDR显示时都会先使用PQ传递函数把场景线性亮度值转换成0到1的编码值并以此来采样一张3D LUT做Color Grading和Tonemapping的操作。例如,UE4在为HDR显示计算3D LUT时会使用ST2084ToLinear进行解码来得到线性亮度值,并在此亮度值上做后续的颜色操作:

// Since ST2084 returns linear values in nits, divide by a scale factor to convert 
// the reference nit result to be 1.0 in linear. 
// (for efficiency multiply by precomputed inverse) 
LinearColor = ST2084ToLinear(LUTEncodedColor) * LinearToNitsScaleInverse;

在采样这张3D LUT时,会进行上述计算的反函数来把线性亮度值转换成0到1的纹理采样坐标:

// ST2084 expects to receive linear values 0-10000 in nits. 
// So the linear value must be multiplied by a scale factor to convert to nits. 
float3 LUTEncodedColor = LinearToST2084(LinearColor * LinearToNitsScale);  

float3 UVW = LUTEncodedColor * ((LUTSize - 1) / LUTSize) + (0.5f / LUTSize); 
float3 OutDeviceColor = Texture3DSample( ColorGradingLUT, ColorGradingLUTSampler, UVW ).rgb; 

上述PQ传递函数需要两次pow计算和一次rcp计算,在计算时要小心它的指令消耗:

// 
// Dolby PQ transforms 
// 
float3 ST2084ToLinear(float3 pq) 
{
     const float m1 = 0.1593017578125; // = 2610. / 4096. * .25;
     const float m2 = 78.84375; // = 2523. / 4096. *  128;
     const float c1 = 0.8359375; // = 2392. / 4096. * 32 - 2413./4096.*32 + 1;
     const float c2 = 18.8515625; // = 2413. / 4096. * 32;
     const float c3 = 18.6875; // = 2392. / 4096. * 32;
     const float C = 10000.;
     float3 Np = pow( pq, 1./m2 );
     float3 L = Np - c1;
     L = max(0., L);
     L = L / (c2 - c3 * Np);
     L = pow( L, 1./m1 );
     float3 P = L * C;

     return P;
} 

值得注意的是,尽管PQ传递函数最大可支持高达10000尼特的绝对亮度值,但大多数显示器的亮度峰值不会超过2000尼特,甚至很多HDR显示器的亮度峰值大约在1000尼特。最简单的做法当然就是直接对场景亮度值进行线性缩放使其对应某个特定显示器的亮度值,再使用ST 2084 OETF函数进行编码并发送给显示器。但正如我们之前在SDR显示里看到的那样,这种线性到线性的对应关系并不满足视觉上的线性关系,这会造成高亮和较暗区域都缺少细节。因此,我们仍然需要某种Tonemapping操作来把我们场景里高动态亮度值重新映射到显示设备可支持的亮度范围内,在这个映射过程中可以适当提高高亮和阴影区域的对比度来得到更好的视觉效果。ACES中就提供了几种最常见也是最通用的HDR曲线映射(View Transform),它们被分别用于1000 cd/m²、2000 cd/m²和4000 cd/m²标准的HDR显示。这些映射函数的设计初衷是为了让HDR显示可以得到和SDR显示在视觉上尽可能一致的画面效果。在后面讲到ACES时我们会具体看到这些映射函数。

## HLG传递函数

HLG传递函数在游戏引擎的HDR显示管线中并不常用,在此为了完整性我们也简单描述一下。HLG全称是Hybrid Log Gamma,它是由BBC与NHK电视台合作设计的一个编码函数。HLG传递函数的设计初衷主要是为了兼容那些没有能力进行HDR显示的SDR显示器,也就是说,如果我们把HLG信号发送给一台常规使用BT 1886 EOTF的SDR显示器,也可以得到一个合理的显示效果。

HLG编码函数同样是由ITU-R BT.2100定义的,这里仅给出HLG EOTF的函数曲线:

来源:https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html

# 世界主宰:ACES

由于存在大量不同型号的摄影设备及其特定的编码和显示标准,加上制作流程中各个阶段(如合成、CG、VFX等)数据输入输出的复杂性,影视制作中的色彩管理是一项非常容易出现问题的环节,很容易出现大量的猜测和瞎蒙的情况。ACES就是为了解决这个问题而存在的一套管理系统。

ACES的基本定义如下:

The Academy Color Encoding System (ACES) is a set of components that facilitates a wide range of motion picture and television workflows while eliminating the ambiguity of legacy file formats. The system is designed to support both all-digital and hybrid film-digital motion picture workflows.
—— From github

这个系统的核心组成部分包括如下几个部分:

  • 若干规范
    • 颜色编码和度量规范
    • 文件格式规范
    • 颜色转换,并为其提供了一个开源版本(使用CTL语言)的代码实现
  • 一组参考图像和校准目标图像,每个图像对应了使用ACES里某个颜色变换对参考图像进行处理后的结果,以此来帮助用户验证他们对ACES系统实现的准确性
  • 对系统和软件工具的说明文档

ACES的文档非常详尽,其命名和用处都有非常严格的说明。如果要详细了解ACES的各个标准和实现细节,这些文档是最好的参考。例如,TB-2014-001是综述性文档,它提供了对其他各个文档大致使用说明;TB-2014-002提供了一份用户产品体验指南,来指导那些需要把ACES集成到软件中的开发人员如何更好地向用户呈现ACES接口和概念;TB-2014-012给出了ACES各个组件(包括颜色空间,颜色转换,文件格式)的详细名称。

对实时渲染来说,与我们关系最为密切的是ACES系统规范中关于颜色编码和颜色转换的部分。

## 颜色编码

ACES系统定义了若干颜色空间,分别用于影视制作流程中的各个阶段。这些颜色空间的三原色和转换函数的定义都是为其应用场景而特别规定的,它们包括:

  • ACES2065-1:一个使用线性转换函数编码的scene-referred颜色空间,它主要用于ACES流程中的图像交换工作
    • 三原色:使用名为AP0(ACES Primaries 0)的三原色值,在1931 CIE xy色度图中其值分别为R(0.7347, 0.2653)、G(0.0, 1.0)、B(0.0001, -0.077)。
    • 白点:与D60值类似但不完全一样的一个白点值(0.32168, 0.33767),一些资料里甚至直接将其说成是D60,这其实是不准确的。
  • ACEScg:也是一个使用线性转换函数编码的scene-referred颜色空间,它主要用于CG、VFX和合成阶段的working space
    • 三原色:使用名为AP1(ACES Primaries 1)的三原色值,在1931 CIE xy色度图中其值分别为R(0.713, 0.293)、G(0.165, 0.830)、B(0.128, 0.044)。
    • 白点:白点值与ACES2065-1一样,即(0.32168, 0.33767)。
  • ACESproxy、ACEScc、ACEScct:这三个空间的三原色和白点值与ACEScg一样,但使用了不同的编码深度和传递函数。例如ACESproxy使用10-bit或12bit整型数据编码、使用log作为传递函数的颜色空间。这几个颜色空间主要用于影视制作流程,游戏实时渲染里很少接触。

AP0和AP1三原色的值是一大批专家们为了它们的应用场景而严格设计和定义的。AP0的三个顶点所围成的区域包含了整个光谱轨迹:

来源:https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html

AP0的定义是为了能够在AP0线性颜色空间下使用正值来编码所有人眼可见的颜色值。尽管AP0对应的三原色颜色值在物理上是无法实现的,也就是说我们无法在真正的现实世界中创造出这样的三种颜色(类似1931 CIE XYZ三原色),但这与它的应用场景有关,由于其色域之广使得它非常适合作为各个制作流程之间图像传递的中间颜色空间,可以最大程度地减少信息丢失。

与AP0相比,AP1的色域范围就显得“保守”许多,它所围成的色域范围与Rec. 2020非常接近,虽然仍然略微越过了光谱轨迹:

来源:https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html

与AP0为了最大限度保存和编码颜色信息的目的不同,AP1更适合用于CG和VFX里的渲染和光照计算工作。渲染使用的颜色空间选择是非常重要的,这会影响光照的计算方式从而影响我们最终的渲染结果,尤其是间接光照的计算。可以说,尽管大家都是平等的,但某些颜色空间就是比其他颜色空间算出来的颜色更好更正确。

这就不得不提到颜色空间的比较了。在计算机渲染领域,我们任何的计算都是要基于颜色空间的三原色,也就是这个颜色空间在三维空间里的三个基向量。考虑以下情况,我们在sRGB空间使用某些颜色进行一定光照计算后,将结果再转换到CIE XYZ空间得到结果A;再把这些sRGB空间的颜色先转换到ACEScg空间进行同样的光照计算后,将结果也转换到CIE XYZ空间得到结果B;令人警惕的是,结果A和结果B往往并不是等价的。在数学上我们可以更容易理解这个现象,各种颜色空间的三个基向量在XYZ空间下都不是正交基,在这些非正交基下做的计算,除了加法和减法等操作以外,乘除和取幂等常见的光照计算都不是等价的。那么如何对比这些结果哪一种是更正确的呢?我们一般认为使用光谱渲染器(例如Mitsuba,使用波长进行颜色计算)得到的结果是ground truth,Ward and Eydelberg-Vileshin (2002)、Langlands and Mansencal (2014)、Mansencal (2014)等人分别做了若干颜色空间的对比试验,Anders Langlands和Thomas Mansencal在Computer Graphics的一篇帖子里对这些试验结果进行了简单的解释,以下是他们的对比结果:

来源:https://chrisbrejon.com/cg-cinematography/chapter-1-5-academy-color-encoding-system-aces/

上述前三行分别是Rec. 709、Mitsuba、Rec. 2020对同一目标的渲染结果,后两行是用Mitsuba减去Rec. 709和Rec. 2020得到的差值,颜色越暗表示差值越小也就意味着结果更接近ground truth更正确。可以看到,整体而言Rec. 2020的表现更接近光谱渲染的结果,但也可以看到在某些情况下,Rec. 709的表现的确更好。实际上,我们仍然无法拍胸部说存在一个颜色空间是最最合适用于计算机渲染的,但正如Thomas Mansencal说到的:

Some RGB colourspaces have gamuts that are better suited for CG rendering and will get results that overall will be closer to a ground truth full spectral rendering. ACEScg / BT.2020 have been shown to produce more faithful results in that regard.
—— From this article

前人的研究表明,那些三原色越接近光谱轨迹的色域空间渲染出来的结果往往更接近光谱渲染的正确结果,ACEScg就是这样一个颜色空间,它的三原色AP1在光谱轨迹附近,且包含了Rec. 2020等常见的广色域空间,因此它非常适合作为CG和VFX等计算机渲染的工作空间。


在十几年前sRGB和Rec. 709是行业最通用的标准,但随着技术发展,Rec. 2020等HDR广色域颜色标准大行其道,老的SDR色域空间退出历史舞台是早晚的事。AP0和AP1的这些特性,使得即便在未来有更多广色域的新颜色空间被提出来,它们也仍然具有非常强的兼容性,短时间内不会被历史淘汰,这也体现了ACES系统的强大之处。

## 颜色转换

ACES还为影视制作的各个阶段定义了一套完整而强大的颜色转换。这些转换包括:

  • Input Transform:之前也被称为Input Device Transform(IDT)。ACES 1.0里的正式名称是ACES Input Transform,简称Input Transform。它负责把输入数据转换到scene-referred颜色空间。例如,各种不同的摄影设备采集到的相片都需要使用其专有的IDT来进行转换。
  • Look Transform:之前也被称为Look Modification Transform(LMT)。ACES 1.0里的正式名称是ACES Look Transform,简称Look Transform。LMT提供了一个位于正式调色步骤之前的整体图像外观的变换,它的输入输出空间是一样的,都是scene-referred图像空间。
  • Output Transform:之前也被称为RRT(Reference Rendering Transform) + ODT(Output Device Transform),也就是ACES Viewing Transform。ACES 1.0里的正式名称是ACES Output Transform,简称Output Transform。其中,RRT负责把图像从scene-referred空间转换到high dynamic range output-referred空间,而ODT负责继续把RRT的结果转换到特定的输出设备的颜色空间下。RRT + ODT是一次把scene-referred图像完整地呈现到特定显示设备的转换操作,因此它被称为Viewing Transform/Output Transform。

在影视制作领域,IDT的特别之处在于它们是由各个摄像设备生产商提供的。RED、Alexa、Canon、Panasonic、Sony等各大厂商都有各自的颜色空间和编码标准,在ACES工作流下,这些厂商无需公开自己秘方而只需按照SMPTE里的ACES标准制作它们各自的IDT,将其图像数据统一转换到ACES颜色空间下即可。这移除了影视制作流程中输入数据的不确定性,这也是ACES的魅力所在。当然,在游戏渲染里,我们使用的IDT通常就是把sRGB图像从伽马空间转换到线性空间。

LMT是一个由用户定义的LUT转换阶段,它的输入输入空间都是scene-referred线性场景空间。它的作用很容易和调色混淆,与调色这种需要针对图像不同区域进行不同类型的颜色操作不同,LMT是一种对图像整体的改观变换操作,起到一个“定基调”的作用。之所以要把它单独分成一个特定的转换,是因为某些整体的图像操作是比较复杂的,LMT提供了这样一个在影视各个制作流程之间共享的LUT转换。在游戏渲染里,LMT的存在感就比较低了。

RRT是由ACES委员会制定的,它的来源可以通俗地理解成一个问句,“我们想要让一张未经调色的图像呈现出什么样子?”ACES收集一大批行业专家对这个问题的答案最终得到了这个RRT变换,它的具体实现可以参考ACES在github上给出的CTL实现版本。同样类似的还有ODT的具体定义。可以看出,ODT和RRT的定义是有一定的主观成分在的,是这些行业专家们认为的如何在各个显示器上让图像呈现最好结果的变换。在游戏渲染领域,我们最常打交道的就是sRGB和Rec. 709的ODT,这些ODT里包含了一个类似tonemapping的操作来让图像变得视觉上“更好看”,虽然带有一定主观性,但这个tonemapp曲线里的参数都是由行业里那些最挑剔的眼睛验证过的,是不应该被轻易更改的。我们应该使用前期调色,而不是直接更改RRT + ODT来达到我们对图像画面的外观要求。

在ACES 1.0中,RRT和ODT是两个独立的阶段,这两个阶段各存在一个Tone Scale操作(具体实现可参考github上给出的RRT源码ODT源码部分):

这种Two Stage Tone Scale的模式非常具有迷惑性,实现上也不太直观,不利于从中制定HDR Output Device Transform的相关标准。因此,ACES委员会提出了ACES ODT改进计划,选择使用一个统一的Single Stage Tone Scale(SSTS)算法作为替代。统一后的流程管线如下所示:

新的Output Transform源码实现里可以发现,它保留了原先RRT阶段的色彩计算,同时使用一条SSTS曲线来完成Tonemapping操作。在命名上,新的Output Transform使用RRTODT作为前缀,来区别于之前单独的Output Transform(ODT)阶段。


以下是影视领域使用ACES的一个较为完整的流程:

来源:https://z-fx.nl/ColorspACES.pdf

影视制作流程中的CG和VFX阶段里对ACES的应用和游戏渲染很类似:

来源:https://z-fx.nl/ColorspACES.pdf

 


Christophe Brejon在他的书里是这么总结ACES在影视制作中的地位:

Everyone should work with ACES...I never had a case where ACES would not make something look better. It is such an improvement of quality: everything looks more real and behaves more correctly.

ACES是当之无愧的色彩管理之主宰。

## DCC里的ACES

目前,在各个软件里使用ACES工作流最方便的途径就是使用OpenColorIO。OpenColorIO是一个Sony Pictures Imageworks开发的开源颜色管理系统。诸如Nuke、Fusion、Maya等软件都已支持OpenColorIO,我们可以使用OCIO配置文件来进行色彩管理,最新的ACES OCIO文件可以在github上下载,这些配置文件可以帮助我们对图像做各种ACES颜色转换。

可惜的是,一些软件仍然不支持OpenColorIO,例如Substance Painter(Substance Designer在2019年末已宣布支持)。但这些软件通常允许使用自定义的LUT进行颜色转换,我们可以针对这些软件需要的LUT格式为其生成特定的LUT文件即可。例如,在Substance Painter里我们可以使用一张LUT图像完成从sRGB linear到ACES sRGB显示的转换。这张LUT可由Nuke制作,或者直接代码生成也行。

Christophe Brejon在他的书里给出了各个软件使用ACES的流程和参考。使用OpenColorIO和自定义LUT也基本可以满足我们在各个DCC软件里的颜色校准工作。


影视制作流程里的ACES和游戏里的还是有些区别,要在游戏里实现HDR显示需要在ACES流程上进行一些修改,并针对游戏做一些特定的开发工作,下一节我们会看其他游戏和引擎是怎么完成这件事的。

# 参考文献

1. Digital Dragons 2018: HDR in Call of Duty

2. https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html

3. https://nick-shaw.github.io/cinematiccolor/academy-color-encoding-system-aces.html

4. https://nick-shaw.github.io/cinematiccolor/visual-effects-animation-and-games.html

5. https://www.oscars.org/science-technology/aces/aces-documentation

6. https://chrisbrejon.com/cg-cinematography/chapter-1-5-academy-color-encoding-system-aces/

编辑于 2020-06-27

 

 

 

 

相关文章:

  • 视频名词浅析——HDR
  • 虚幻引擎学习之路:渲染模块之全局光照明
  • 我所理解的DirectX Ray Tracing
  • Unity 曲线插值(Hermite插值和Catmull_Rom插值)
  • 参数化曲线:Hermite Catmull-Rom Bezier
  • 贝塞尔曲线原理(简单阐述)
  • 插值与样条
  • Unity 打包因为资源没有 meta ,打包 assetbundle 的时候,导致资源没有打包进去
  • 深入理解color model(颜色模型)
  • LMS色彩空间
  • 计算机图形中的色彩概念
  • 网游帧同步的分析与设计
  • UE4网络同步思考(一)---经典同步方案
  • UE4网络同步(二)——深入同步细节
  • 2021-03-13
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • 2018一半小结一波
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Elasticsearch 参考指南(升级前重新索引)
  • Invalidate和postInvalidate的区别
  • iOS 颜色设置看我就够了
  • Java方法详解
  • Promise面试题2实现异步串行执行
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • 初识 beanstalkd
  • 从重复到重用
  • 多线程 start 和 run 方法到底有什么区别?
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 记一次和乔布斯合作最难忘的经历
  • 坑!为什么View.startAnimation不起作用?
  • 理解在java “”i=i++;”所发生的事情
  • 免费小说阅读小程序
  • 前端
  • 一份游戏开发学习路线
  • elasticsearch-head插件安装
  • 树莓派用上kodexplorer也能玩成私有网盘
  • # 数据结构
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • #pragma预处理命令
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (二)JAVA使用POI操作excel
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)springboot教学评价 毕业设计 641310
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (简单) HDU 2612 Find a way,BFS。
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (译)计算距离、方位和更多经纬度之间的点
  • (转)用.Net的File控件上传文件的解决方案
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况