// shaders/phong.frag #version 330 core // 从顶点着色器插值传入的变量 in vec3 Position_worldspace; in vec3 Normal_cameraspace; in vec3 EyeDirection_cameraspace; in vec3 LightDirection_cameraspace; in vec2 UV; // 输出颜色 out vec3 color; // Uniform 变量 uniform sampler2D myTextureSampler; // 纹理采样器 uniform vec3 lightColor; // 光源颜色 uniform float lightPower; // 光照强度 uniform vec3 viewPos_worldspace; // 观察者位置(世界空间) uniform vec3 lightPos_worldspace; // 光源位置(世界空间) // 材质属性 (可以作为uniform传入,这里为了简单硬编码) vec3 materialDiffuseColor = vec3(1.0, 1.0, 1.0); // 从纹理获取 vec3 materialAmbientColor = vec3(0.1, 0.1, 0.1); vec3 materialSpecularColor = vec3(0.5, 0.5, 0.5); float materialShininess = 32.0; void main(){ // 环境光 vec3 AmbientLighting = materialAmbientColor * lightColor * 0.2; // 环境光强度通常较低 // 漫反射光 vec3 Normal_normalized = normalize(Normal_cameraspace); vec3 LightDirection_normalized = normalize(LightDirection_cameraspace); float cosTheta = clamp(dot(Normal_normalized, LightDirection_normalized), 0, 1); // clamp 避免负值 vec3 DiffuseLighting = materialDiffuseColor * lightColor * cosTheta; // 镜面反射光 vec3 EyeDirection_normalized = normalize(EyeDirection_cameraspace); vec3 ReflectionDirection = reflect(-LightDirection_normalized, Normal_normalized); float cosAlpha = clamp(dot(EyeDirection_normalized, ReflectionDirection), 0, 1); vec3 SpecularLighting = materialSpecularColor * lightColor * pow(cosAlpha, materialShininess); // 如果法线和光线方向相反(背面),则不应有镜面反射和漫反射 if(dot(Normal_normalized, LightDirection_normalized) < 0.0){ SpecularLighting = vec3(0,0,0); DiffuseLighting = vec3(0,0,0); // 可选,取决于是否做双面光照 } // 从纹理采样颜色,并与漫反射材质颜色混合 (这里直接用纹理作为漫反射颜色) vec3 textureColor = texture(myTextureSampler, UV).rgb; DiffuseLighting = textureColor * lightColor * cosTheta; // 最终颜色 (光照强度衰减) float distance = length(lightPos_worldspace - Position_worldspace); // 实际光源与片元距离 float attenuation = lightPower / (distance * distance); // 简单平方反比衰减 color = AmbientLighting + (DiffuseLighting + SpecularLighting) * attenuation; // 不带衰减的简单版本(如果上面的衰减不工作,可以尝试这个) //color = AmbientLighting + DiffuseLighting + SpecularLighting; }