2011-03-04 2 views
0
#version 150 
uniform float shade; 
in vec3 cshade; 
in vec3 v_o; 
in vec3 locallight_o; 
in vec3 n; 
in float shadescale_o; 
out vec4 pixelcolour; 
void main() 
{ 
    float shadescale; 
    shadescale=shadescale_o; 
    vec3 vn,l,ln,nn,h,hh; 
    vec3 ambient = vec3(0.4,0.4,0.4);  // ambient light  

    vn=normalize(v_o); 
    ln=normalize(locallight_o); 
    if (dot(ln,n)<0) 
    { 
     h=vn-ln;//light direction shines from source to object 
     hh=h; 
     h=normalize(h); 
     nn=normalize(n); 
     shadescale= dot(h,nn);//inward normal 
     if (shadescale<0) 
      shadescale=0; 
     shadescale*=shadescale; 
     shadescale*=shadescale; 
    } 
    else 
    shadescale=0; 

    // Get pixel colour from input shade 
    if (shade>=0.5) 
    {  
     pixelcolour = vec4((cshade * shadescale) + (ambient * cshade), 1.0); // ambient lighting  

     //pixelcolour = vec4((cshade*ambient)+ambient, 1.0); 
     //pixelcolour += vec4(ambient, 1.0); 
    } 
    else 
    { 
     pixelcolour = vec4((cshade * shadescale_o) + (ambient * cshade), 1.0); 

     //pixelcolour = vec4((cshade*ambient)+ambient, 1.0);  
     //pixelcolour += vec4(ambient, 1.0); 

    }    

} 

Le code ci-dessus est un pixel shader direct, utilisé dans un framework openGL qui montre un cube. Actuellement l'éclairage ambiant a été mis en place, mais comment faire pour ajouter une réflexion diffuse et spéculaire (pas simultanément!) À ce code? Je comprends que j'aurai besoin d'uniformes supplémentaires, c'est-à-dire de vec3 appelés diffus et spéculaires, mais quelles opérations précises dois-je effectuer?Réflexion diffuse et spéculaire dans ce pixelhader

Répondre

1

Je ne vais pas coller le code ici, mais la réponse à toutes vos questions est http://www.lighthouse3d.com/opengl/glsl/index.php?lights. En résumé, diffuse = -dot (normal, lightDir). Pourquoi? Eh bien, le produit scalaire évalue la "similitude" de deux vecteurs, en estimant 1 s'ils sont identiques, 0 s'ils sont à angle droit et -1 s'ils sont opposés. Si la normale de la face pointe directement dans la lumière (normal et lightDir sont opposés), elle devrait prendre la valeur maximale. Si la lumière brille sur un angle, le produit scalaire renvoie une valeur plus proche de 0, ce qui donne la valeur finale de l'éclairage.

Il convient de noter que lightDir et normal doivent être normalisés.

+0

Grand lien merci pour cela, a aidé à l'équation. Je n'utilise pas strictement OpenGL dans cette édition im littérale du code donné, et ne pas utiliser les commandes GL qui rendent probablement la vie plus facile. –

0

Autant que je peux voir à partir de votre code, je suppose que les choses suivantes:

  • v_o ist position fragment
  • locallight_o est le poasition d'une source de lumière locale
  • n est normal vecteur à la position du fragment

En outre, je suppose que ces points et vecteurs ont le même système de référence et sont dans l'espace des yeux. Avec cette information, vous pouvez mettre en œuvre un modèle de lumière simple Blinn Phong avec une lumière ambiante constante.

Calcualte la lumière ambiante:

vec3 ambient = vec3(0.2, 0.2, 0.2); 
pixelcolour = ambient; 

Calcualte vers la lumière et la Labertian diffuse terme et l'ajouter au résultat:

vec3 diffuse = vec3(0.6, 0.6, 0.6); 
vec3 normalV = normalize(n); 
vec3 lightV = normalize(locallight_o - v_o); 
float NdotL = max(0.0, dot(normalV, lightV)); 
pixelcolour += NdotL * diffuse; 

Calcualete le vecteur demi-Way et la Blinn- Phong reflets spéculaires et l'ajouter au résultat:

vec3 specular = diffuse; 
float shininess = 20.0; 
vec3 eyeV = normalize(-v_o); 
vec3 halfV = normalize(eyeV + lightV); 
float NdotH = max(0.0, dot(normalV, halfV)); 
pixelcolour += (shininess + 2.0) * pow(NdotH, shininess)/(2.0 * 3.14159265); 

Voir aussi les réponses à cela remet en question

How does this faking the light work on aerotwist?

GLSL fixed function fragment program replacement