GraphicsLab Project之Color Processing
来源:互联网 发布:文网文添加域名 编辑:程序博客网 时间:2024/06/05 23:45
作者:i_dovelemon
日期:2016 / 09 / 15
来源:CSDN
主题:Post-processing, Gamma correction, Color Grading
引言
今天来和大家分享下一种在屏幕空间对整体的画面进行(Color Grading)颜色调制的一种简单方法。这些方法在成熟的引擎中,都有运用。比如CryEngine中使用的大量滤镜,还有Unreal中Post-processing中的Color Grading就是实现这样的功能。
Color Grading
熟悉PS的同学应该都知道,在PS中,如果我们需要对一张图片进行颜色,饱和度,对比度和曝光度这样的整体调节就是Color Grading。举个例来说,比如现在我们想要下面的效果:
我们只要对原有的图像进行黑白滤镜处理就能够得到。上面仅仅是通过滤镜能够实现的其中一种效果,通过对PS中各个参数的调节,我们能够实现很多不同的效果,这些效果能够很容易的让美工对画面的整体风格进行把控,是一种很好的控制画面风格,实现各种特殊效果的方法。
如何在渲染中实现?
首先,我们要知道Color Grading是对图片中的每一个像素的颜色进行操作,即仅仅与像素的颜色有关系,而与像素所处的位置,附近的颜色等等没有关系。读者请注意,这里说的是最终进行Color Grading时进行的操作对象,而操作中各个参数的来源是需要考虑整幅图片的属性的。比如说,我要调节一下整个场景中的颜色亮度,那么我需要先计算一下场景的平均亮度值,然后根据这个值对每一个像素进行操作。
从上面的描述中,大家可能也看到了,我在这里提出的实现,仅仅是对每一个像素进行最终的Color Grading操作,而操作的来源却没有实现。那么我该怎么得到这个操作的来源了?这个问题就是我们Color Grading实现的核心。
在Unreal中,提供了一个内置的编辑器,能够实时的调整例如颜色,对比度,饱和度这样的参数,然后使用这些参数去进行Color Grading操作。也就是说,我们需要一种手段,能够得到这些参数,然后在我们的Shader中进行计算。但是,同学们,这里的计算方法多种多样,看看PS里面提供的各种效果你就知道了。我们不太可能把每一种计算方式编码到shader中去。
在了解了上面的困境之后,我们该怎么解决这个问题了?上面说了,计算的过程不太可能放在shader中,那么我们直接将计算的结果放在shader中如何?前面讨论过,最终的操作是对每一个像素进行,所以也就是说,RGB(0-255,0-255,0-255)这个范围里面的所有颜色,都能够在最终的结果里面找到对应的颜色值。那么,我们为什么不构造一张最终结果的查找表了?然后通过源颜色值,从查找表中查找到最终进行Color Grading之后的颜色。这样不就是把所有的计算操作放在了外部,比如PS软件中,我们在渲染的时候,仅仅需要查询下最终的结果就可以了。
从上面的讨论,大家应该就大致的了解到了如何使用这样的方式进行Color Grading了吧?
Color Grading的步骤
为了让大家更清楚明白,这里详细的列举进行Color Grading的步骤。
1.首先你得将RGB(0-255,0-255,0-255)颜色做成一张查找表,便于我们进行查找。由于最终的查找操作是在shader中进行的,所以这张查找表最好的方式还是使用贴图。这里提出两中方法供大家参考。在说明之前,我们先来看看如果将所有的颜色都保存下来,大概需要多大的空间:
Mem = 256 * 256 * 256 * 4 / 1024 / 1024 = 64MB
可以看出,将所有的颜色保存下来需要64MB的一张贴图,先不说支不支持这么大的贴图,单单这个内存就吃不消。(当然,如果你只要一种Color Grading效果的话,又很土豪的话,保持精度,也可以这么做。)所以在实际开发中,我们往往选择16*16*16的图,或者32*32*32的图。虽然颜色损失了一点,但是通过线性插值也能够逼近实际的效果。下面列举构建查找表的两中方式(以下示例,都以16×16×16的尺寸进行描述)
a.将所有的颜色保存在一个2D纹理中,保存的最终图像如下所示:
b.将所有颜色保存在一个3D纹理中,保存的最终图像如下所示:
2.截取游戏中的一张图片,然后将你所使用的查找表和游戏截图放在一起,通过PS软件更改两个图层的颜色,对比度等等属性,达到你想要的效果。
3.通过上面的操作,你原来的查找表,就变成了进行Color Grading之后的查找表。然后使用这张查找表到Shader中进行实际的计算。计算方法很简单,只要在显示画面之前,添加一个最后的render pass,在这个pass中使用你计算好的颜色值,以这个值为坐标,查找纹理中对应的颜色就可以了。
OpenGL实现
上面的理论知识讲解完毕之后,我们来点实际的代码。首先,我选择的是16×16×16的3D纹理。选择的原因,一方面是因为我渲染出来的画面大小容纳不下32*32*32的贴图,所以没有办法很好的在PS中进行调色,另外一方面,3D纹理查找更加的直接,如果使用2D纹理,还需要对纹理坐标进行一些计算,比较麻烦。
在OpenGL中创建3D纹理的方法,如下所示:
glBindTexture(GL_TEXTURE_3D, tex_obj);glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, texture_width, texture_width, texture_width, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);glGenerateMipmap(GL_TEXTURE_3D);glBindTexture(GL_TEXTURE_3D, 0);
这里需要注意几个地方:
1.OpenGL的纹理坐标是u向右为正方向,v向上为正方向,和DX是有区别的,所以在构建查找表的时候,需要注意
2.OpenGL中3D纹理创建,需要构建slice数组,然后传递到glTexImage3D中去。也就是说后面的texture_data实际上是3D纹理贴图里面的每一个小的2D纹理贴图的数组。
3.OpenGL中在shader设置3D纹理坐标的时候,需要注意一些东西。下面给出的Shader中有一个链接,详细的讲解了这个知识。
对应的shader文件:
//------------------------------------------------------------// Declaration: Copyright (c), by i_dovelemon, 2016. All right reserved.// Author: i_dovelemom[1322600812@qq.com]// Date: 2016 / 09 / 12// Brief: Color process will do color correction and color grading//------------------------------------------------------------in vec2 glb_ps_tex_coord;out vec3 glb_color;uniform sampler2D glb_scene_tex;uniform sampler3D glb_lut32_tex;const float glb_gamma = 2.2;const float glb_lut_size = 16.0;void main() {vec3 src_color = texture2D(glb_scene_tex, glb_ps_tex_coord).xyz;// Color correction (aka Gamma correction)float gamma = 1.0 / glb_gamma;src_color.x = pow(src_color.x, gamma);src_color.y = pow(src_color.y, gamma);//----------------------------------------------------------------------// The z value is a little tricky.// If the 3D texture is 16*16*16,// then the first slice's z coordinate is defined as 0.5 * 1.0 / 16.0.// This means if you don't specific the z coordinate as center the slice,// it will sample two nearest slice and blend the result value.// For more detail, look at this page:// http://stackoverflow.com/questions/31810822/opengl-3d-texture-shine-through//----------------------------------------------------------------------src_color.z = pow(src_color.z, gamma);src_color.z = src_color.z / (1.0 / glb_lut_size);src_color.z = floor(src_color.z) * 1.0 / glb_lut_size + 0.5 * 1.0 / glb_lut_size;// Color gradingglb_color = texture3D(glb_lut32_tex, src_color).xyz;}
这个shader做了两件事。第一件事是进行Gamma correction,这样能够让我们的计算在线性空间中进行。关于这方面的内容,可以参考之前博客中的介绍。第二件事就是进行Color Grading。这个操作很简单,就是对3D纹理,进行一下查找,然后使用对应的颜色来替换就可以了。
总结
这种方法具有很大的取巧性,如果想要深入的了解Color Grading的实质,可以自己在shader中实现各种各样的算法,加强自己的能力。
参考文献
[1] http://www.kpulv.com/359/Dev_Log__Color_Grading_Shader/ Dev_Log: Color Grading Shader
[2] http://the-witness.net/news/2012/08/fun-with-in-engine-color-grading/ Fun with in-engine Color Grading
[3] http://renderwonk.com/publications/s2010-color-course/hoffman/hoffman_course_notes_intro.pdf Color Enhancement and Rendering in Film and Game Production
0 0
- GraphicsLab Project之Color Processing
- GraphicsLab Project之HDR渲染
- GraphicsLab Project之Normal Mapping
- GraphicsLab Project学习项目
- GraphicsLab Project之辉光(Glare,Glow)效果
- GraphicsLab Project之Screen Space Ambient Occlusion(SSAO)
- GraphicsLab Project之Parallel Split Shadow Map(PSSM)
- 数字图像处理实验(15):PROJECT 06-02,Pseudo-Color Image Processing
- 数字图像处理实验(16):PROJECT 06-03,Color Image Enhancement by Histogram Processing
- Color Image Processing
- Color Image Processing: Methods and Applications
- Processing 主题(21)color关键字
- Processing 之 基础知识
- Opencv 颜色空间处理(Color space processing)
- 资源文件之Color
- android 资源之 color
- values资源之color
- Lombok Requires Annotation Processing Annotation processing seems to be disabled for the project "xx
- selenium+python环境搭建
- 使用fresco遇到的坑-SimpleDraweeView
- 上传本地代码到github上
- 数据结构实验之栈四:括号匹配
- Vue.js——60分钟browserify项目模板快速入门【7】
- GraphicsLab Project之Color Processing
- ArrayAdapter,SimpleAdapter的基本使用
- Sicily 1001.Alphacode | 动态规划
- python堆排序
- 暑期社会实践心得
- java字符串分解 StringTokenizer用法
- java各大排序算法总结
- Vue.js——60分钟webpack项目模板快速入门【8】
- 二叉树的非递归遍历