照明问题,可能正常相关?

时间:2014-03-08 21:17:30

标签: opengl shader lighting normals

我使用的是OpenGL 3.3并且有一些奇怪的灯光问题,我首先会以不同的角度显示两个截图,然后给出着色器代码。

第一个角度:

first angle

第二个角度:

second angle

你在这里看到的是:

  • 一个立方体,其中间位于原点;
  • 一个定向光源,来自黄点通过原点;
  • 在青色中,您会看到顶点的法线。

我知道顶点的法线是"错误",但我正在尝试调试它们。

我的期望是:A(从上到下)各种颜色的变化,取决于" sun"的位置。和相机。

但我得到的是立方体的两个部分(上部和下部)都有不同的颜色,但不符合我的预期。

着色器中有阴影代码,但我故意在这里禁用它们以避免混淆。

顶点着色器:

#version 430 core

layout(location = 0) in vec4 position;
layout(location = 1) in vec3 normal;

layout(location = 0) uniform mat4 model_matrix;
layout(location = 1) uniform mat4 view_matrix;
layout(location = 2) uniform mat4 proj_matrix;
layout(location = 3) uniform mat4 shadow_matrix;

out VS_OUT {
    vec3 N;
    vec3 L;
    vec3 V;
    vec4 shadow_coord;
} vs_out;

uniform vec4 light_pos = vec4(-20.0, 7.5, -20.0, 1.0);

void main(void) {
    vec4 local_light_pos = view_matrix * light_pos;
    vec4 p = view_matrix * model_matrix * position;

    //normal
    vs_out.N = normalize(normal);

    //light vector
    vs_out.L = local_light_pos.xyz - p.xyz;

    //view vector
    vs_out.V = -p.xyz;

    //light space coordinates
    vs_out.shadow_coord = shadow_matrix * position;

    gl_Position = proj_matrix * p;
}

片段着色器:

#version 430 core

out vec4 color;

in VS_OUT {
    vec3 N;
    vec3 L;
    vec3 V;
    vec4 shadow_coord;
} fs_in;

layout(binding = 0) uniform sampler2DShadow shadow_tex;

uniform vec3 light_ambient_albedo = vec3(1.0);
uniform vec3 light_diffuse_albedo = vec3(1.0);
uniform vec3 light_specular_albedo = vec3(1.0);

uniform vec3 ambient_albedo = vec3(0.0, 0.2, 0.0);
uniform vec3 diffuse_albedo = vec3(0.2, 0.7, 0.2);
uniform vec3 specular_albedo = vec3(0.0, 0.0, 0.0);
uniform float specular_power = 128.0;

vec3 rgb_to_grayscale_luminosity(vec3 color) {
    float value = color.r * 0.21 + color.g * 0.71 + color.b * 0.07;
    return vec3(value);
}

void main(void) {
    //normalize
    vec3 N = normalize(fs_in.N);
    vec3 L = normalize(fs_in.L);
    vec3 V = normalize(fs_in.V);

    //calculate R
    vec3 R = reflect(-L, N);

    //calcualte ambient
    vec3 ambient = ambient_albedo * light_ambient_albedo;

    //calculate diffuse
    vec3 diffuse = max(dot(N, L), 0.0) * diffuse_albedo * light_diffuse_albedo;

    //calcualte spcular
    vec3 specular = pow(max(dot(R, V), 0.0), specular_power) * specular_albedo * light_specular_albedo;

    //apply shadow and write color
    float shadow_value = textureProj(shadow_tex, fs_in.shadow_coord);
    if (shadow_value > 0.0001 || true) {
        //no shadow
        color = vec4(ambient + diffuse + specular, 1.0);
    }
    else {
        //in shadow
        //color = vec4(rgb_to_grayscale_luminosity((ambient + diffuse) * (1 - shadow_value)), 0.5);
        //color = vec4(vec3(shadow_value), 0.5);
        color = vec4((ambient + diffuse) * (1 - shadow_value) * 0.5, 1.0);
    }
}

这里可能出现什么问题?

1 个答案:

答案 0 :(得分:0)

假设您的法线仅指向上/下(在OpenGL坐标系中x = 0且z = 0),您看到的应该是预期的行为(没有关于着色器/图形管道的错误)。

在图形管道的光栅化阶段,属性在顶点(重心坐标)之间进行插值。 假设平面“y = 0”以上的所有法线都是

  • “vec3(0,1,0)”

此平面下方的所有法线均为

  • “vec3(0,-1,0)”

然后对于每个像素,插值法线将为

  • “vec3(0,*,0)”其中*在“y = 0”平面上方> 0且在该平面下方<0。

在片段着色器中,您将所有法线标准化,因此它们将再次成为

  • “vec3(0,1,0)”如果相应的顶点位于“y = 0”平面上方且
  • “vec3(0,-1,0)”,如果相应的顶点位于该平面下方。

这将为“y = 0”平面下方和上方的所有顶点产生相同的颜色。

如果您要删除片段着色器中的正常“标准化”,或者如果您向某些法线的x或z坐标添加最小偏移,则可以检查此项,例如

  • vec3(0.0000001,+ / - 1,0)