我们要在非浮点纹理下边实现HDR,需要将所有的浮点数可渲染纹理(前几个例子中的格式都是A16R16G16B16F)修改为A8R8B8G8,修改完之后发现,Exposure_level只能控制图像的亮度,但是Glow效果没有了。
这是因为浮点数纹理在绘制背景及茶壶时使用的如下的语句:
return color * ((1.0+(color.a*64.0))* Exposure_Level);
因为浮点数纹理(A16R16G16B16F存储精度要远远大于常规纹理(A8R8B8G8),我给该颜色乘以一个 Exposure_Level,颜色亮度增加了,后边的Glow效果也增加了,但是还没有达到浮点数可以溢出的值(颜色中会将其CLAMP到最大值),所以Glow效果会随这 Exposure_Level值的变大而越加明显。
反观如果我是用了常规纹理(A8R8B8G8),可能在当前Exposure_Level值下,Glow效果无(或者有,但是十分不明显),我们将Exposure_Level值变大,但是很有可能在Exposure_Level即将变大到Glow效果可以明显显示的时候,常规纹理的存贮精度已经不能够容纳return color * ((1.0+(color.a*64.0))* Exposure_Level)的返回值了,这样即便Exposure_Level增加,可渲染纹理表示解释不了这么大的亮度,只能CLAMP掉,这样,就出现了,无论Exposure_Level如何增加,Glow效果都没不会出现的情况。
书中给出的Solution:
将曝光因子存储在常规可渲染纹理(A8R8B8G8)的α通道,在存储时先除以64然后在最终的Pixel Shader中重新再乘以64。
Vertex Shader Code:
1 sampler Texture0;
2 float Exposure_level;
3
4 float4 ps_main(float2 Tex : TEXCOORD0) : COLOR0
5 {
6 float4 color = float4(tex2D(Texture0,Tex).xyz,0);
7 return float4(color.rgb, ((1 + color.a * 64) * Exposure_level)/64);
8 }
Pixel Shader Code:
1 sampler Texture0;
2 sampler Texture1;
3 sampler Texture2;
4 float Glow_Factor1;
5 float Glow_Factor2;
6 float Glow_Factor3;
7
8 float SourceAlpha;
9
10 float4 ps_main(float2 Tex : TEXCOORD0) : COLOR0
11 {
12 float4 col1 = tex2D(Texture0,Tex);
13 float4 col2 = tex2D(Texture1,Tex);
14 float4 col3 = tex2D(Texture2,Tex);
15
16 return
17 float4((col1.xyz * col1.a * 64 ) * Glow_Factor1,SourceAlpha) +
18 float4((col2.xyz * col2.a * 64 ) * Glow_Factor2,0) +
19 float4((col3.xyz * col3.a * 64 ) * Glow_Factor3,0);
20 }
另外一个问题,本Demo我在实现时碰到的一个问题,最后的图像左侧有几列像素发白:
后来发现是因为每一个小尺寸的Render Target α通道每次清除为255所致,将它设置为0即可。