您将如何实现色差?


22

如何使用着色器实现色差的效果?

用每种颜色的不同焦距渲染世界是否可以解决问题(也许仅使用一次深度渲染遍历)?


为什么要实现色差?
ashes999

3
您可以按照实现绽放的相同方式进行。您应该将普通场景与其3种模糊版本结合起来;这三种纹理中的每一种都应主要以3种基本颜色进行着色。.当然,如果对3种纹理使用不同的模糊策略(例如,具有不同角度偏移的方向性模糊可能会起作用),则可以进行变化。
teodron

3
@ ashes999-也许是狙击镜或其他长镜头,以增加真实感?色差是许多复合镜片设计的伪影。
KeithS

您可能还希望实现色差,以抵消由观看游戏的镜头引起的任何色差。例如,在使用Oculus Rift进行的游戏中,在视图的边缘具有色差是个好主意。
约瑟夫·曼斯菲尔德

Answers:


22

当镜头无法将每种颜色都聚焦到同一焦点时,就会导致色差。伪造此效果并将其渲染为快速的全屏后处理的一种简单方法是,将偏移量应用于片段着色器中的每个颜色通道。

通过为每个通道使用不同的偏移量,可以合理地复制所需的效果。可以在此处找到此技术的示例;片段着色器看起来像这样:

void main () {
    // Previously, you'd have rendered your complete scene into a texture
    // bound to "fullScreenTexture."
    vec4 rValue = texture2D(fullscreenTexture, gl_TexCoords[0] - rOffset);  
    vec4 gValue = texture2D(fullscreenTexture, gl_TexCoords[0] - gOffset);
    vec4 bValue = texture2D(fullscreenTexture, gl_TexCoords[0] - bOffset);  

    // Combine the offset colors.
    gl_FragColor = vec4(rValue.r, gValue.g, bValue.b, 1.0);
}

但是,这个简单的技巧并没有真正考虑色差是镜头效果的事实:为了获得更好的模拟效果,您实际上想渲染某些东西来充当镜头。这类似于渲染反射或折射对象的方式。因此,典型的反射/折射着色器可以成为实现色差的基础。

通常,您将在顶点着色器中使用GLSL的折射函数,基于视图向量和一些定义的折射率来计算单个折射向量:

void main () {
    // ...

    // RefractionVector is a varying vec3.
    // 'ratio' is the ratio of the two indices of refraction.
    RefractionVector = refract(incidentVector, normalVector, ratio);

    // ...
}

然后,您可以在片段着色器中使用该矢量来执行多维数据集纹理查找(进入环境贴图)。通常,这也与反射效果一起完成,并结合使用计算出的菲涅耳项

为了模拟色差,您可以在顶点着色器中执行三种不同的折射矢量计算,每个计算通过不同的折射率略有偏移:

void main () {
    // ...

    // RefractionVector is a varying vec3, as above.
    // 'ratioR,' et cetera, is the ratio of indices of refraction for
    // the red, green and blue components respectively.
    RedRefractionVector = refract(incidentVector, normalVector, ratioR);
    GreenRefractionVector = refract(incidentVector, normalVector, ratioG);
    BlueRefractionVector = refract(incidentVector, normalVector, ratioB);

    // ...
}

这三个不同的向量可用于执行三个不同的立方体贴图查找,类似于简单示例中的颜色混合方式,它们可以混合在一起:

void main () {
    vec3 color;
    color.r = vec3(textureCube(EnvironmentMap, RedRefractionVector)).r;
    color.g = vec3(textureCube(EnvironmentMap, GreenRefractionVector)).g;
    color.b = vec3(textureCube(EnvironmentMap, BlueRefractionVector)).b;

    gl_FragColor = vec4(color, 1.0);
}

有关更多详细信息,可使用OpenGL橙皮书,其中包含基本反射和折射效果的示例以及色差效果的示例。


有没有一种方法仅使用一个纹理样本并对其进行着色?对于像光线跟踪这样的应用程序来说,这非常有益,因为在这种情况下,跟踪三对一的光线非常昂贵。
塔拉
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.