我一直在使用OpenGL的Superbible(第5版)点光源示例。
我发现它们缺少集成到旧照明模型中的常数,线性和二次衰减值,所以我去写了一个基于此ogre guide的衰减值的点光着色器。
结果完全奇怪。 可以做些什么来在新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
}
}
答案 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;
衰减区也有一些括号缺失。