phong着色中的点光镜面反射显示不正确,假设存在一些着色器问题?高光显示旋转并倾斜到渲染目标的中心
以前用几乎相同的着色器代码完成它,找不到问题所在,有人可以调查吗?
#version 450 core
// input
layout (location = 0) in vec4 v_position;
layout (location = 1) in vec4 v_color;
layout (location = 2) in vec4 v_normal;
layout (location = 3) in vec2 v_uv;
// output
out Vertex
{
vec4 position;
vec4 color;
vec4 normal;
vec2 uv;
} f_input;
// uniorm
uniform mat4 u_projection_matrix;
uniform mat4 u_view_matrix;
uniform mat4 u_model_matrix;
//
// main
void main()
{
f_input.position = u_model_matrix * v_position;
f_input.color = v_color;
f_input.normal = transpose(inverse(u_model_matrix)) * v_normal;
f_input.uv = v_uv;
gl_Position = u_projection_matrix * u_view_matrix * f_input.position;
}
在片段着色器中, f_input.position是片段的世界空间位置。 u_view_pos是相机的世界空间原点。
#version 450 core
// input
in Vertex
{
vec4 position;
vec4 color;
vec4 normal;
vec2 uv;
} f_input;
// output
out vec4 color;
// uniform
layout(binding = 0) uniform sampler2D u_texture_unit_0;
layout(binding = 1) uniform sampler2D u_texture_unit_1;
//
struct Material
{
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct DirectionalLight
{
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight
{
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
#define DIRECTIONAL_LIGHT_COUNT 1
#define POINT_LIGHT_COUNT 3
// uniform
uniform vec3 u_view_pos;
uniform Material u_material;
uniform DirectionalLight u_dir_light[DIRECTIONAL_LIGHT_COUNT];
uniform PointLight u_point_light[POINT_LIGHT_COUNT];
// function prototypes
vec3 calc_directional_light(DirectionalLight light, vec3 normal, vec3 viewDir);
vec3 calc_point_light(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
// main
void main()
{
// properties
vec3 norm = normalize(f_input.normal.xyz);
vec3 viewDir = normalize(u_view_pos - f_input.position.xyz);
vec3 fragColor;
// phase 1: directional lighting
for(int i = 0; i < DIRECTIONAL_LIGHT_COUNT; i++)
fragColor += calc_directional_light(u_dir_light[i], norm, viewDir);
// phase 2: point lights
for(int i = 0; i < POINT_LIGHT_COUNT; i++)
fragColor += calc_point_light(u_point_light[i], norm, f_input.position.xyz, viewDir);
color = vec4(fragColor, 1.0f);
}
// calculates the color when using a directional light
vec3 calc_directional_light(DirectionalLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
// lambertian = diff
float diff = max(dot(normal, lightDir), 0.0);
float spec = 0.0;
// specular shading
// phong
//vec3 reflectDir = reflect(-lightDir, normal);
//spec = pow(max(dot(viewDir, reflectDir), 0.0), u_material.shininess);
// blinn-phong
vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(halfwayDir, normal), 0.0), u_material.shininess);
// combine results
vec3 ambient = light.ambient * vec3(texture(u_material.diffuse, f_input.uv));
vec3 diffuse = light.diffuse * diff * vec3(texture(u_material.diffuse, f_input.uv));
vec3 specular = light.specular * spec * vec3(texture(u_material.specular, f_input.uv));
return (ambient + diffuse + specular);
}
// calculates the color when using a point light
vec3 calc_point_light(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
// lambertian = diff
float diff = max(dot(normal, lightDir), 0.0);
float spec = 0.0;
// specular shading
// phong
//vec3 reflectDir = reflect(-lightDir, normal);
//spec = pow(max(dot(viewDir, reflectDir), 0.0), u_material.shininess);
// blinn-phong
vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(halfwayDir, normal), 0.0), u_material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// combine results
vec3 ambient = light.ambient * vec3(texture(u_material.diffuse, f_input.uv));
vec3 diffuse = light.diffuse * diff * vec3(texture(u_material.diffuse, f_input.uv));
vec3 specular = light.specular * spec * vec3(texture(u_material.specular, f_input.uv));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}