2012-03-23 3 views
6

Sto scrivendo uno shader GLSL che simula l'aberrazione cromatica per oggetti semplici. Sono compatibile con OpenGL 2.0, quindi utilizzo lo stack matrix OpenGL integrato. Questa è la semplice vertex:Riflessione/rifrazione con aberrazione cromatica - correzione dell'occhio

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

Il cameraPos uniforme è la posizione della fotocamera nello spazio modello, come si potrebbe immaginare. Qui è lo shader frammento:

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

Il environment è una mappa del cubo che è resa dal vivo l'ambiente del oggetto disegnato.

In circostanze normali, lo shader comporta (Credo) come previsto, ottenendo questo risultato:

correct shader behavior

Tuttavia, quando la telecamera viene ruotata di 180 ° attorno al suo bersaglio, in modo che ora punta a l'oggetto dall'altro lato, l'immagine rifratto/riflessa deformarlo in questo modo (Ciò avviene gradualmente per angoli tra 0 e 180 gradi, ovviamente):

incorrect shader behavior

Manufatti simili appaiono quando la fotocamera viene abbassata/sollevata; sembra solo comportarsi correttamente al 100% quando la telecamera è direttamente sopra l'oggetto target (puntando verso Z negativo, in questo caso).

Non riesco a capire quale trasformazione nello shader è responsabile di questa immagine deformata, ma dovrebbe essere qualcosa di ovvio in relazione a come viene gestito cameraPos. In che modo l'immagine si deforma in questo modo?

risposta

2

Questo sembra sospetto a me:

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

È il vostro cameraPos definito nello spazio mondo? Stai sottraendo un vettore di spazio di visualizzazione (position) da un vettore presunto di spazio cameraPos. È necessario eseguire il calcolo nello spazio mondiale o visualizzare lo spazio, ma non è possibile combinarli.

Per fare ciò correttamente nello spazio mondiale è necessario caricare separatamente la matrice del modello per ottenere il vettore di incidente spaziale mondiale.

+0

Questo era! Ho dovuto anche sostituire il 'gl_NormalMatrix' di' mat3 (modelMatrix) 'per ovvi motivi. Non mi ha mai colpito il fatto che dovrei considerare lo spazio della variabile 'position', sembrava in qualche modo banalmente corretto. Grazie! – dflemstr