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

发布于 2024-10-29 18:47:33 字数 3933 浏览 2 评论 0原文

我一直在研究 OpenGL 的 Superbible(第五版)点光源示例。

我发现它们缺少集成到旧照明模型中的恒定、线性和二次衰减值,因此我根据此 食人魔指南

结果非常奇怪。 如何才能在新的 glsl 上获得合理的光衰减?有衰减常数的GLSL表吗?

图片

距离99处的衰减 -球体为黑色,光为蓝色-
在此处输入图像描述

距离 50 处的衰减 - 球体为黑色,光为蓝色 -
在此处输入图像描述

距离 16 处的衰减 - 球体为黑色,光为蓝色 -
在此处输入图像描述

距离 2 处的衰减 - 球体为黑色,光为蓝色 -
在此处输入图像描述

示例顶点和片段程序:

顶点程序:

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

I've been working OpenGL's Superbible (5th Edition) point light examples.

I found them missing the constant, linear and quadratic attenuation values integrated into the old lighting model, so I went and wrote a point light shader with attenuation values based on this ogre guide.

The results have been completely bizarre. What can be done to get a sensible light attenuation on the new glsl? Is there a glsl table for attenuation constants?

Pics

Attenuation at distance 99 -sphere is black, light is blue-
enter image description here

Attenuation at distance 50 -sphere is black, light is blue-
enter image description here

Attenuation at distance 16 -sphere is black, light is blue-
enter image description here

Attenuation at distance 2 -sphere is black, light is blue-
enter image description here

Sample vertex and fragment programs:

Vertex program:

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

Fragment program:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光是把杀猪刀 2024-11-05 18:47:35

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

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

应该改为:

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

这就是为什么当距离增加时球体会变轻的原因。尝试正确的公式并发布结果。

Your attenuation formula is completely incorrect:

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

Should be instead:

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

That's why you are getting the sphere lighter when the distance increases. Try the proper formula and post the result.

泛泛之交 2024-11-05 18:47:35

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

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

衰减除法上也缺少几个括号。

I ended up using just this attenuation values, the thing works acceptably:

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

There a couple of parenthesis missing on the attenuation division too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文