2012-03-23 13 views
6

Estoy escribiendo un sombreador GLSL que simula la aberración cromática para objetos simples. Me mantengo compatible con OpenGL 2.0, así que uso la pila de matriz OpenGL integrada. Este es el simple vertex shader:Reflexión/refracción con aberración cromática - corrección de ojos

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(); 
} 

El cameraPos uniforme es la posición de la cámara en el espacio modelo, como uno podría imaginar. Aquí está el fragment shader:

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); 
} 

El environment es un mapa de cubo que se representa en vivo desde el entorno del objeto dibujado.

En circunstancias normales, el sombreado se comporta (creo), como se esperaba, dando el siguiente resultado:

correct shader behavior

Sin embargo, cuando la cámara se gira 180 grados alrededor de su objetivo, de modo que ahora apunta a el objeto desde el otro lado, la imagen refractada/reflejada se combado como tal (Esto ocurre gradualmente para ángulos entre 0 y 180 grados, por supuesto):

incorrect shader behavior

Aparecen artefactos similares cuando la cámara se baja/levanta; solo parece comportarse al 100% correctamente cuando la cámara está directamente sobre el objeto objetivo (apuntando hacia la Z negativa, en este caso).

Tengo problemas para determinar qué transformación en el sombreador es responsable de esta imagen deformada, pero debería ser algo obvio relacionado con cómo se maneja cameraPos. ¿Qué está causando que la imagen se combe de esta manera?

Respuesta

2

esto parece sospechoso a mí:

vec4 position = gl_ModelViewMatrix * gl_Vertex; 
incident = position.xyz/position.w - cameraPos; 

Está su cameraPos definido en el espacio mundo? Estás restando un vector de espacio de vista (position), de un espacio supuestamente mundial cameraPos. O necesita hacer el cálculo en el espacio mundial o ver el espacio, pero no puede mezclarlos.

Para hacer esto correctamente en el espacio mundial, tendrá que cargar la matriz del modelo por separado para obtener el vector de incidentes del espacio mundial.

+0

¡Esto fue todo! También tuve que reemplazar el 'gl_NormalMatrix' por' mat3 (modelMatrix) 'por razones obvias. Simplemente nunca me di cuenta de que debería considerar el espacio de la variable 'position', parecía ser trivialmente correcto de alguna manera. ¡Gracias! – dflemstr

Cuestiones relacionadas