【问题标题】:opengl shader directional lights specular reflection increasing with distanceopengl shader 定向灯镜面反射随距离增加
【发布时间】:2013-10-06 21:01:13
【问题描述】:

标题说明了一切......使用内置照明系统的opengls,镜面光不会随着与对象的距离而增加或减少,但通过着色器实现会。

顶点着色器:

#version 330

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in vec3 normal;

out vec2 texCoord0;
out vec3 normal0;
out vec3 worldPos0;

uniform mat4 transform;
uniform mat4 normalRotation;
uniform mat4 transformProjected;

void main()
{
    gl_Position = transformProjected * vec4(position, 1.0);
    texCoord0 = texCoord;

    normal0 = normalize((normalRotation * vec4(normal, 0.0))).xyz;
    worldPos0 = (transform * vec4(position, 1.0)).xyz; 
}

片段着色器:

#version 330

in vec2 texCoord0;
in vec3 normal0;
in vec3 worldPos0;

out vec4 fragColor;

struct BaseLight
{
    vec3 colorDiffuse;
    vec3 colorSpecular;
    float intensityDiffuse;
};
struct DirectionalLight
{
    BaseLight base;
    vec3 direction;
};

uniform vec3 tint;
uniform sampler2D sampler;

uniform vec3 eyePos; // camera pos

uniform vec3 ambientLight;
uniform vec3 emissiveLight;

//material 
uniform float specularIntensity;
uniform float specularPower;

uniform DirectionalLight directionalLight;

vec4 calcLight(BaseLight base,vec3 direction, vec3 normal)
{
    float diffuseFactor = dot(normal, -direction);

    vec4 diffuseColorFinal = vec4(0,0,0,0);
    vec4 specularColorFinal = vec4(0,0,0,0);

    if(diffuseFactor > 0)
    {
      diffuseColorFinal =  vec4(base.colorDiffuse,1) * diffuseFactor * base.intensityDiffuse;

      vec3 directionToEye = normalize(eyePos - worldPos0);
      vec3 reflectDirection = normalize(reflect(direction, normal));

      float specularFactor = dot(directionToEye, reflectDirection);
      specularFactor = pow(specularFactor, specularPower);

      if(specularFactor > 0)
          specularColorFinal = vec4(base.colorSpecular,1) * specularFactor   * specularIntensity;
    }
    //
   return diffuseColorFinal + specularColorFinal;
}



void main()
{
    vec4 colorD = texture(sampler, texCoord0.xy) * vec4(tint,1);
    vec3 normal = normal0;
    vec4 totalLight = vec4(ambientLight,1) + vec4(emissiveLight,1); 

     totalLight += calcLight(directionalLight.base,-directionalLight.direction,normal);


    fragColor = colorD * totalLight;
}

正如您从 2 张图像中看到的那样,镜面光占据的表面积越大,相机离飞机越远。在我使用 opengls 内置照明的测试中,这不会发生。有没有办法解决这个问题?我是照明新手,这对于定向光源来说可能是正常的吗?感谢您的帮助!

我还将我的 eyePos 制服设置为我的 cameraPos。我不知道这是否有帮助。

【问题讨论】:

  • 我以前也遇到过这种情况,但我认为是因为表面完全平坦。我可能是错的,但我认为从相机位置到每个片段的角度已经减小,并且片段着色器产生的表面颜色现在几乎完全在镜面反射范围内。我不知道我是否已经解释清楚了。我知道我在脑海中的意思,只是不怎么解释得很好。我发现在网上查看了一些与 BRDF 相关的东西,Real-Time Rendering 这本书有所帮助。

标签: c++ opengl glsl shader specular


【解决方案1】:

基本上你需要在片段和光dist之间保持距离。这对于定向光来说可能是一个问题,因为您只有方向,并且假定距离是无限的。也许切换到点光源?

当你有'dist'时,你会使用公式

att = 1.0 / (Kc + Kl*dist + Kq*dist^2)
Kc - constant attenuation
Kl - linear attenuation
Kq - quadratic attenuation 

更简单的版本(仅使用 Kq,其余设置为 1.0):

float attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));

然后在照明方程中,您基本上将计算出的颜色乘以 att 因子:

vec4 finalColor = ambient + (diffuseColorFinal + specularColorFinal)*att

http://www.ozone3d.net/tutorials/glsl_lighting_phong_p4.php#part_4

http://tomdalling.com/blog/modern-opengl/07-more-lighting-ambient-specular-attenuation-gamma/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 2019-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多