gamma correction

 

http://www.cambridgeincolour.com/tutorials/gamma-correction.htm

 

gamma needs more to describe darkness less bits for brighter range

因为只有8bits 我们眼睛感知颜色不是线性感知的 如果颜色线性过来 我们感受到的暗部会丧失细节 所以需要更多位来描述暗部 所以需要input gamma encode一下

 用gamma encode存储图片是为了有效利用更多bit存储我们眼睛更为敏感的暗部

即使最后会被dispaly gamma pow回线性 图片细节 暗部细节

 

gamma correction 是指pow0.45  即encode

之后还有个display gamma 叫decode 是pow2.2 这个是显示器做的 可以从显示器的设置里改  我们就当成显示器不改设置的话 默认会做pow2.2

 

正确的流程是这样的

1.Texture 通常都是gamm space 的所以不用软件特殊处理,打开看颜色正常的就是gamma space  (encoding gamma 1/2.2) 

raw texture 颜色有些暗 (既没有encdoe又没有decode的val) (http://www.cambridgeincolour.com/tutorials/gamma-correction.htm)这里有例子

0.5 pow2.2 =0.21 pow0.45 =0.73 所以encode变亮 

 读入的时候 把srv tex设置成srgb格式,这样就会被从gamma space 转入linear space(pow2.2一次) 这样用于光照计算那步就是对的 就不用再转了 

(此pass的destination format如果设置为srgb 结果就会再被pow0.45 为了给之后display pow2.2用 或者不指定dest srgb在第三步那里统一做p0.45

(前面pass不要指定srgb destion 第三步那里做因为你要确保display的输入是gamma p0.45压过的  

(如果你为了去band artifacts可以把前面指定srgb 那种错误叫roping 但之后的采样要接着srv srgb通常用于pp里面

2.光照需要在线性空间计算  realtime rendering Page143 有sample 这里不做修改

3.最终颜色校正加个后处理 pow(1/2.2) (display gamma p2.2 by device realtime rendering Page143)

 

为什么需要这步转换呢

因为人眼感知的颜色是非线性空间的 gamma space 

power law encoding--percepual uniformity 感知一致

 

为什么又要转线性空间

 8bit的srv 值在0-1 minimizes banding artifacts, 会有roping 指定srv有助于改善这一点 反走样。。

mipmap light calculate这两步线形颜色空间计算结果 开了gammacorrect(p0.45)是不对的

gamma涉及所有要把values加减乘除运算的地方

 

http://www.cnblogs.com/minggoddess/p/4277680.html

hdr不是8bit存储所以不需要srgb dest

如果没有hdr 后处理需要srgb unity既然这么说 说明在没有hdr的情况下 它把pp前面的pass用了srgb//这个周一去确认一下

在支持此功能的平台opengles3.0 metal unity 用了srgbtarget会主动处理blend和msaa的 看起来就像realtimer3说的dx10的行为 dx9据说blend和msaa是错的

hdr的流程就是srgb srv 之后都不设置srgb target 因为float已经是线性空间了 在最后做一次gamma correction就可以了 转到gammaspace p0.45

 

Conversion to or from sRGB space is automatically done by D3DX10 or D3DX9 texture-load functions.

If a format with _SRGB has an A channel, the A channel is stored in Gamma 1.0f data; the R, G, and B channels in the format are stored in Gamma 2.2f data.

alpha 通道不参与encode decode

------------------------------

又过了一个项目

通常拿到的未经处理的texture是gamma空间的(p0.45 亮) ,需要转到线性空间 (p2.2)(diffuse 转normal不转),用这种贴图做 linear space的颜色计算。

这样光照+就不会过亮,锯齿会少,mipmap我记得也是要做的 还有msaa的什么问题

============

之后需要确认下unity linearspace都做了什么操作 把那些rt设置成srgb了 难道是所有。。。

================

我感觉 我做了这么多项目 到现在gammacorrection还是没弄对 这次一定不能再错了

========

这个项目的gamma做对了

包括ui 这个项目ui是在线性空间做的 没有encode了 这样的缺点就是 暗部细节丢失

如果用srp 能把unity linear space的最后一张rt 不用srgb format

ui的tex用srgb 在gamma 空间做blend 虽然数学上不太好 也许可以和ps里结果一直 这样的好处是 暗部细节在 gamma一变 混合出来的结果就不是美术在ps里调的结果了(这句不对 因为powervr的onchip mem的精度是32bits)

综上还是觉得前者比较好

======

由于后者仍然无法重现 ps混合结果

所以我选ps工作空间gamma1.0 游戏ui写到srgb(省带宽 

转载于:https://www.cnblogs.com/minggoddess/p/5888808.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要编写正伽马校正(Positive Gamma Correction),需要进行以下步骤: 1. 设置伽马值:正伽马校正是一种非线性的校正方法,通过将像素值的平方根或其它次方应用于原始像素值来调整图像亮度。伽马值通常在1.8到2.5之间,可以根据实际需要进行调整。 2. 计算伽马校正表:将每个像素值进行伽马校正,生成一个伽马校正表。可以使用以下公式进行计算:Gamma-corrected value = Original value^(1/Gamma)。 3. 应用伽马校正:将伽马校正表应用于图像中的所有像素,以生成正伽马校正的图像。 下面是一个使用ESP32和libili9341库的示例代码,用于进行正伽马校正: ```c++ #include <Adafruit_GFX.h> #include <Adafruit_ILI9341.h> #define TFT_CS 10 #define TFT_DC 9 #define TFT_RST 8 // Create a new instance of the display library Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); float gammaValue = 2.2; // Set gamma value for positive gamma correction void setup() { // Initialize the display tft.begin(); } void loop() { // Load image data into a buffer uint16_t buffer[320 * 240]; for (int i = 0; i < 320 * 240; i++) { buffer[i] = /* load pixel data */; } // Generate gamma correction table uint8_t gammaTable[256]; for (int i = 0; i < 256; i++) { gammaTable[i] = pow(i / 255.0, gammaValue) * 255.0 + 0.5; } // Apply gamma correction to image data for (int i = 0; i < 320 * 240; i++) { uint16_t pixel = buffer[i]; uint8_t r = (pixel & 0xF800) >> 11; uint8_t g = (pixel & 0x07E0) >> 5; uint8_t b = pixel & 0x001F; r = gammaTable[r]; g = gammaTable[g]; b = gammaTable[b]; buffer[i] = (r << 11) | (g << 5) | b; } // Display the image tft.startWrite(); tft.setAddrWindow(0, 0, 319, 239); tft.pushColors(buffer, 320 * 240); tft.endWrite(); } ``` 在这个示例中,我们使用了ESP32和libili9341库来控制显示屏。我们首先加载图像数据到一个缓冲区中,然后使用伽马值计算一个伽马校正表。最后,我们将伽马校正表应用于图像数据,并将结果显示在显示屏上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值