glsl 1.3+中的点光源/聚光灯衰减?

时间:2011-04-03 01:46:35

标签: glsl

我一直在使用OpenGL的Superbible(第5版)点光源示例。

我发现它们缺少集成到旧照明模型中的常数,线性和二次衰减值,所以我去写了一个基于此ogre guide的衰减值的点光着色器。

结果完全奇怪。 可以做些什么来在新glsl上获得合理的光衰减?是否有用于衰减常数的glsl表?

照片管理

距离99处的衰减 - 球体为黑色,光线为蓝色 -
  enter image description here

距离50处的衰减 - 球体为黑色,光线为蓝色 -
enter image description here

距离16处的衰减 - 球体为黑色,光线为蓝色 -
enter image description here

距离2处的衰减 - 球体为黑色,光线为蓝色 -
enter image description here

示例顶点和片段程序:

顶点程序:

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

片段计划:

//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
        }
    }

2 个答案:

答案 0 :(得分:1)

您的衰减公式完全不正确:

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

应该是:

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

这就是为什么你在距离增加时让球体更亮。尝试正确的公式并发布结果。

答案 1 :(得分:0)

我最终只使用了这个衰减值,事情可以接受:

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

衰减区也有一些括号缺失。