2011-04-03 2 views
1

J'ai travaillé sur les exemples de points lumineux d'OpenGL Superbible (5ème édition). Je les ai trouvés sans les valeurs d'atténuation constante, linéaire et quadratique intégrées dans l'ancien modèle d'éclairage, donc je suis allé écrire un point de lumière avec des valeurs d'atténuation basées sur ogre guide.Atténuation de lumière ponctuelle/spotlight dans glsl 1.3+?

Les résultats ont été complètement bizarres. Que peut-on faire pour obtenir une atténuation de la lumière sensible sur le nouveau glsl? Existe-t-il une table glsl pour les constantes d'atténuation?

Pics

Affaiblissement à la distance 99 -sphere est noir, bleu-lumière est
enter image description here

Attenuation à une distance de 50 -sphere est noir, bleu-clair est
enter image description here

Affaiblissement à la distance 16 -sphere est noir, la lumière est bleu-
enter image description here

Affaiblissement à la distance 2 -sphere est noir, la lumière est bleu-
enter image description here

sommet de l'échantillon et des programmes de fragments :

programme Vertex:

//point light per pixel vertex program 
#version 130 

// Incoming per vertex... position and normal 
in vec4 vVertex; 
in vec3 vNormal; 


uniform mat4 mvpMatrix; 
uniform mat4 mvMatrix; 
uniform mat3 normalMatrix; 
uniform vec3 vLightPosition; 

// Color to fragment program 
smooth out vec3 vVaryingNormal; 
smooth out vec3 vVaryingLightDir; 

out float dist; 
out float constantAttenuation; 
out float linearAttenuation; 
out float quadraticAttenuation; 

void main(void) 
    { 
    // Get surface normal in eye coordinates 
    vVaryingNormal = normalMatrix * vNormal; 

    // Get vertex position in eye coordinates 
    vec4 vPosition4 = mvMatrix * vVertex; 
    vec3 vPosition3 = vPosition4.xyz/vPosition4.w; 

    //get distance to light source 
    dist=length(vLightPosition-vPosition3); 

    //write proper attenuation values 

    if (dist<7.0){ 
     constantAttenuation=1.0; 
     linearAttenuation=0.7; 
     quadraticAttenuation=1.8; 
    } 

    else if (dist<13.0){ 
     constantAttenuation=1.0; 
     linearAttenuation=0.35; 
     quadraticAttenuation=0.44; 
    } 

    else if (dist<20.0){ 
     constantAttenuation=1.0; 
     linearAttenuation=0.22; 
     quadraticAttenuation=0.20; 
    } 

    if (dist<32.0){ 
     constantAttenuation=1.0; 
     linearAttenuation=0.14; 
     quadraticAttenuation=0.07; 
    } 
    if (dist<50.0){ 
     constantAttenuation=1.0; 
     linearAttenuation=0.09; 
     quadraticAttenuation=0.32; 
    } 

    if (dist<65.0){ 
     constantAttenuation=1.0; 
     linearAttenuation=0.07; 
     quadraticAttenuation=0.017; 
    } 

    if (dist<100.0){ 
     constantAttenuation=1.0; 
     linearAttenuation=0.045; 
     quadraticAttenuation=0.0075; 
    } 



    // Get vector to light source 
    vVaryingLightDir = normalize(vLightPosition - vPosition3); 

    // Don't forget to transform the geometry! 
    gl_Position = mvpMatrix * vVertex; 
    } 

programme Fragment:

//point light per pixel fragment program 

#version 130 

out vec4 vFragColor; 

uniform vec4 ambientColor; 
uniform vec4 diffuseColor; 
uniform vec4 specularColor; 

smooth in vec3 vVaryingNormal; 
smooth in vec3 vVaryingLightDir; 

in float dist; 
in float constantAttenuation; 
in float linearAttenuation; 
in float quadraticAttenuation; 

void main(void){ 

    float att; 

    att = 1.0/constantAttenuation + linearAttenuation*dist +quadraticAttenuation*dist*dist; 

    // Dot product gives us diffuse intensity 
    float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir))); 

    // Multiply intensity by diffuse color, force alpha to 1.0 
    vFragColor = att*(diff * diffuseColor +ambientColor); // attenuation affects the diffuse component 

    // Specular Light 
    vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal))); 

    float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection)); 
    if(diff != 0) { 
     float fSpec = pow(spec, 128.0); 
     vFragColor.rgb += (att*vec3 (fSpec, fSpec, fSpec)); // attenuation affects the specular component 
     } 
    } 
+0

Toute chance d'images pour aider à clarifier "bizarre"? – ssube

+0

@peachykeen: Bien sûr, mon pote. – andandandand

Répondre

0

J'ai fini en utilisant seulement ces valeurs d'atténuation, la chose fonctionne acceptablement:

 constantAttenuation=1.0; 
     linearAttenuation=0.22; 
     quadraticAttenuation=0.20; 

Il a deux parenthèses manquante sur la division d'atténuation trop.

1

Votre formule d'atténuation est complètement incorrecte:

att = 1.0/constantAttenuation + linearAttenuation*dist +quadraticAttenuation*dist*dist; 

devrait être à la place:

att = constantAttenuation/((1+linearAttenuation*dist)*(1+quadraticAttenuation*dist*dist)). 

C'est la raison pour laquelle vous obtenez la sphère plus légère lorsque la distance augmente. Essayez la bonne formule et publiez le résultat.

+0

ouais, j'ai remarqué ça aussi. Merci. – andandandand

+0

Où est la formule documentée dans les documents? J'ai trouvé "son intensité est atténuée par la réciproque de la somme du facteur constant, le facteur linéaire fois la distance entre la lumière et le sommet étant éclairé" à https://www.opengl.org/sdk/docs/man2/ xhtml/glLight.xml qui ressemble à la première formule. –