具有色差的反射/折射 - 眼睛矫正

dfl*_*str 6 opengl glsl matrix

我正在编写一个模拟简单物体色差的GLSL着色器.我保持OpenGL 2.0兼容,所以我使用内置的OpenGL矩阵堆栈.这是简单的顶点着色器:

uniform vec3 cameraPos;

varying vec3 incident;
varying vec3 normal;

void main(void) {
    vec4 position = gl_ModelViewMatrix * gl_Vertex;
    incident = position.xyz / position.w - cameraPos;
    normal   = gl_NormalMatrix * gl_Normal;

    gl_Position = ftransform();
}
Run Code Online (Sandbox Code Playgroud)

cameraPos正如人们可能想象的那样,制服是相机在模型空间中的位置.这是片段着色器:

const float etaR = 1.14;
const float etaG = 1.12;
const float etaB = 1.10;
const float fresnelPower = 2.0;
const float F = ((1.0 - etaG) * (1.0 - etaG)) / ((1.0 + etaG) * (1.0 + etaG));

uniform samplerCube environment;

varying vec3 incident;
varying vec3 normal;

void main(void) {
    vec3 i = normalize(incident);
    vec3 n = normalize(normal);

    float ratio = F + (1.0 - F) * pow(1.0 - dot(-i, n), fresnelPower);

    vec3 refractR = vec3(gl_TextureMatrix[0] * vec4(refract(i, n, etaR), 1.0));
    vec3 refractG = vec3(gl_TextureMatrix[0] * vec4(refract(i, n, etaG), 1.0));
    vec3 refractB = vec3(gl_TextureMatrix[0] * vec4(refract(i, n, etaB), 1.0));

    vec3 reflectDir = vec3(gl_TextureMatrix[0] * vec4(reflect(i, n), 1.0));

    vec4 refractColor;
    refractColor.ra = textureCube(environment, refractR).ra;
    refractColor.g  = textureCube(environment, refractG).g;
    refractColor.b  = textureCube(environment, refractB).b;

    vec4 reflectColor;
    reflectColor    = textureCube(environment, reflectDir);

    vec3 combinedColor = mix(refractColor, reflectColor, ratio);

    gl_FragColor = vec4(combinedColor, 1.0);
}
Run Code Online (Sandbox Code Playgroud)

environment是一个立方体贴图,可以从绘制对象的环境中实时渲染.

在正常情况下,着色器表现(我认为)就像预期的那样,产生了这样的结果:

正确的着色器行为

但是,当相机绕其目标旋转180度,使其现在指向另一侧的物体时,折射/反射的图像会像这样翘曲(当然,这种情况会逐渐发生在0到180度之间的角度) :

不正确的着色器行为

降低/升高相机时会出现类似的瑕疵; 当相机直接在目标物体上方时(在这种情况下指向负Z),它似乎只能正确地表现100%.

我无法确定着色器中哪个转换负责这个扭曲的图像,但它应该是明显与cameraPos处理方式有关的东西.是什么导致图像以这种方式扭曲?

Tim*_*Tim 2

这对我来说看起来很可疑:

vec4 position = gl_ModelViewMatrix * gl_Vertex;
incident = position.xyz / position.w - cameraPos;
Run Code Online (Sandbox Code Playgroud)

你是cameraPos在世界空间中定义的吗?position您正在从所谓的世界空间向量中减去视图空间向量 ( ) cameraPos。您需要在世界空间或视图空间中进行计算,但不能混合使用它们。

要在世界空间中正确执行此操作,您必须单独上传模型矩阵以获得世界空间入射矢量。