我在我的引擎中实现了照明。但是有一些问题,物体没有正确点亮
镜面反射照明根本不起作用
下面是顶点着色器:
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 tex_coords;
layout (location = 2) in vec3 normals;
uniform mat4 projectionMatrix;
uniform mat4 worldMatrix;
uniform mat4 viewMatrix;
out vec2 coords;
out vec3 vertexNormals;
out vec3 vertexPos;
void main() {
vec4 mVerPos = worldMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * viewMatrix * worldMatrix * vec4(position, 1.0);
coords = tex_coords;
vertexNormals = normalize(worldMatrix * vec4(normals, 0.0)).xyz;
vertexPos = mVerPos.xyz;
}
字符串
以下是片段着色器:
#version 330
struct Material {
vec4 ambient;
vec4 diffuse;
vec4 specular;
int hasTexture;
float reflectance;
};
struct PointLight {
vec3 color;
vec3 position;
float intensity;
float constant;
float linear;
float exponent;
};
struct DirLight {
vec3 position;
vec3 color;
float intensity;
};
out vec4 fragColor;
in vec2 coords;
in vec3 vertexNormals;
in vec3 vertexPos;
uniform sampler2D sampler;
uniform vec3 ambientColor;
uniform Material material;
uniform PointLight pointLight;
uniform float specularPower;
uniform DirLight dirLight;
vec4 ambientC;
vec4 diffuseC;
vec4 specularC;
void setUpColor(Material material, vec2 coords) {
if (material.hasTexture == 1) {
ambientC = texture(sampler, coords);
diffuseC = ambientC;
specularC = ambientC;
}
else {
ambientC = material.ambient;
diffuseC = material.diffuse;
specularC = material.specular;
}
}
vec4 calcLightColor(vec3 lightColor, float lightIntensity, vec3 position, vec3 to_light_dir, vec3 normal) {
vec4 diffuseColour = vec4(0, 0, 0, 0);
vec4 specColour = vec4(0, 0, 0, 0);
// Diffuse Light
float diffuseFactor = max(dot(normal, to_light_dir ), 0.0);
diffuseColour = diffuseC * vec4(lightColor, 1.0) * lightIntensity * diffuseFactor;
// Specular Light
vec3 camera_direction = normalize(-position);
vec3 from_light_dir = -to_light_dir;
vec3 reflected_light = normalize(reflect(from_light_dir, normal));
float specularFactor = max(dot(camera_direction, reflected_light), 0.0);
specularFactor = pow(specularFactor, specularPower);
specColour = specularC * lightIntensity * specularFactor * material.reflectance * vec4(lightColor, 1.0);
return (diffuseColour + specColour);
};
vec4 calcPointLight(PointLight light, vec3 position, vec3 normal)
{
vec3 light_direction = light.position - position;
vec3 to_light_source = normalize(light_direction);
vec4 lightColor = calcLightColor(light.color, light.intensity, position, to_light_source, normal);
// Attenuation
float distance = length(light_direction);
float attenuationInv = light.constant + light.linear * distance +
light.exponent * distance * distance;
return lightColor / attenuationInv;
}
vec4 calcDirLight(DirLight light, vec3 position, vec3 normal) {
return calcLightColor(light.color, light.intensity, position, normalize(light.position), normal);
}
void main() {
setUpColor(material, coords);
vec4 diffuseSpecularComp = calcDirLight(dirLight, vertexPos, vertexNormals);
diffuseSpecularComp += calcPointLight(pointLight, vertexPos, vertexNormals);
fragColor = ambientC * vec4(ambientColor, 1) + diffuseSpecularComp;
}
型
下面是源代码:https://www.dropbox.com/scl/fo/hwlnz913jm6c9xli2dsb6/h?dl=0&rlkey=b2zj0w6kttwu3b1di9rejwnq3
当我把float diffuseFactor = max(dot(normal, to_light_dir ), 0.0);
和float specularFactor = max(dot(camera_direction, reflected_light), 0.0);
处的零值改变为大于0.1的值时,我得到了
,但高光根本不起作用。
1条答案
按热度按时间w7t8yxp51#
你的代码中有几个问题,但我不完全确定是哪个原因导致了这个问题。
问题
vertexNormals
。在您的特定情况下,这不应该是一个问题,因为看起来您没有不均匀地缩放网格,但值得一提的是,这是一个常见的错误。将对象空间法线与世界矩阵相乘,但应将其与世界矩阵的逆转置相乘。vertexNormals
,但它不正确。虽然你在顶点着色器中规范化了法线,但是片段着色器并没有得到那个特定的向量。它得到3vertexNormals
的线性插值(基本上是加权平均),结果不一定是归一化的。所以你也应该在片段着色器中将其规格化。setUpColor
函数中,为什么给ambientC
、diffuseC
和specularC
赋值相同?通常,这些有不同的纹理,但至少对于漫反射和镜面反射。其他随机观察
position
乘以worldMatrix
两次,但为什么?这看起来像是浪费了性能(也许编译器优化了它)。DirLight
结构体中,您有一个position
成员,但平行光没有位置,它们只有方向。我看到你从位置计算方向,但这似乎不寻常。Material
结构体(以及其他地方)中,您使用vec4
s而不是vec3
s,但我猜,最后一个组件总是1。这是浪费内存,你可以在main
的末尾设置alpha值为1.0f
。Joey de弗里斯有amazing tutorials, including the Phong shading(使用C++)。在 * 最后一件事 * 一节中,他还解释了为什么使用逆转置矩阵来变换法线很重要。