HDR
名词解释
- HDR(High Dynamic Range, 高动态范围),颜色值大于1
- LDR(Low Dynamic Range,低动态范围) ,颜色值[
- 色调映射(Tone Mapping):转换HDR值到LDR值得过程叫做色调映射,一个有趣的色调映射应用是曝光(Exposure)参数的使用
- 浮点帧缓冲:当一个帧缓冲的颜色缓冲的内部格式被设定成了GL_RGB16F, GL_RGBA16F, GL_RGB32F 或者GL_RGBA32F时,这些帧缓冲被叫做浮点帧缓冲(Floating Point Framebuffer),浮点帧缓冲可以存储超过0.0到1.0范围的浮点值
- GL_RGB颜色缓冲的特性:OpenGL会将标准化的定点格式(像GL_RGB)的颜色缓冲这些值存入帧缓冲前自动将其约束到0.0到1.0之间
- MRT:Multiple Render Targets,多渲染目标
色调映射
色调映射(Tone Mapping)是一个损失很小的转换浮点颜色值至我们所需的LDR[0.0, 1.0]范围内的过程,通常会伴有特定的风格的色平衡(Stylistic Color Balance)。
另一个有趣的色调映射应用是曝光(Exposure)参数的使用。
一个简单的曝光色调映射算法会像这样:
uniform float exposure;
void main()
{
const float gamma = 2.2;
vec3 hdrColor = texture(hdrBuffer, TexCoords).rgb;
// 曝光色调映射
vec3 mapped = vec3(1.0) - exp(-hdrColor * exposure);
// Gamma校正
mapped = pow(mapped, vec3(1.0 / gamma));
color = vec4(mapped, 1.0);
}
在这里将exposure定义为默认为1.0的uniform,下面这组图片展示了在不同曝光值下的通道:
泛光(Bloom)
通俗解释就是给发光物体加个光晕,视觉上看起来更亮,如下:
泛光实现
渲染一个有光场景,提取出场景的HDR颜色缓冲以及只有这个场景明亮区域可见的图片。被提取的带有亮度的图片接着被模糊,结果被添加到HDR场景上面。
MRT多渲染目标使用
指定一个颜色附件:除了GL_COLOR_ATTACHMENT0,通过使用GL_COLOR_ATTACHMENT1,可以得到一个附加了两个颜色缓冲的帧缓冲对象:
GLuint colorBuffers[2];
glGenTextures(2, colorBuffers);
for (GLuint i = 0; i < 2; i++)
{
...
// attach texture to framebuffer
glFramebufferTexture2D(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, colorBuffers[i], 0
);
}
显式告知OpenGL我们正在通过glDrawBuffers渲染到多个颜色缓冲,否则OpenGL只会渲染到帧缓冲的第一个颜色附件,而忽略所有其他的。可以通过传递多个颜色附件的枚举来做这件事:
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, attachments);
指定一个布局location标识符,这样我们便可控制一个像素着色器写入到哪个颜色缓冲:
layout (location = 0) out vec4 FragColor;
layout (location = 1) out vec4 BrightColor;