You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL 添加specular lighting后Mesh变黑问题的修复方案求助

问题原因

从你提供的着色器代码里能找到多个导致镜面光失效、模型变黑的错误:

  • 顶点着色器未给toLightVector和normal两个输出变量赋值,导致片元着色器拿到的是未定义的垃圾值,所有基于光照方向、法向量的计算结果全部错误
  • 片元着色器直接使用了未定义的unitToLightVector、unitNormal、diffuse变量,计算逻辑完全不成立
  • 镜面因子截断行逻辑错误:你写的specular_factor = max(specular, 0.0)错误使用了uniform高光系数specular作为参数,而非点积得到的specular_factor,如果你的高光系数默认值为0或者数值较大,会直接导致镜面项结果为0或者超出颜色取值范围,出现纯黑
  • 最终颜色计算时alpha通道叠加为2,如果开启了alpha混合会出现显示异常

修复方案

修正顶点着色器

#version 330 core

layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 coords;
layout (location = 2) in vec3 normals;

out vec2 Texture_Coords;
out vec3 normal;
out vec3 toLightVector;
out vec3 toCameraVector;

uniform mat4 p;
uniform mat4 m;
uniform mat4 v;
uniform vec3 light_position;

void main(){
    vec4 world_position = m * vec4(pos,1.0);
    gl_Position = p * v * world_position;
    Texture_Coords = coords;
    // 补充法向量、光照方向向量的传递,逆转置矩阵避免非均匀缩放导致法向量偏移
    normal = mat3(transpose(inverse(m))) * normals;
    toLightVector = light_position - world_position.xyz;
    toCameraVector = (inverse(v) * vec4(0,0,0,1)).xyz - world_position.xyz;
}

修正片元着色器

#version 330 core

out vec4 Pixel;

in vec2 Texture_Coords;
in vec3 normal;
in vec3 toLightVector;
in vec3 toCameraVector;

uniform vec4 color;
uniform sampler2D Texture;
uniform float ambient;
uniform vec3 light_color;
uniform float reflective;
uniform float specular; // 建议改名为shininess避免变量名歧义

void main(){
    // 补齐所有单位向量定义
    vec3 unitNormal = normalize(normal);
    vec3 unitToLightVector = normalize(toLightVector);
    vec3 unitToCameraVector = normalize(toCameraVector);

    // 补齐漫反射计算逻辑
    float diffuse_factor = max(dot(unitNormal, unitToLightVector), 0.0);
    vec3 diffuse = ambient * light_color + diffuse_factor * light_color;

    vec3 light_direction = -unitToLightVector;
    vec3 reflection = reflect(light_direction, unitNormal);
    float specular_factor = dot(reflection, unitToCameraVector);
    // 修正max函数参数为计算得到的镜面因子
    specular_factor = max(specular_factor, 0.0);
    float damped_specular = pow(specular_factor, specular);
    vec3 final_specular = damped_specular * light_color * reflective;

    // 修正alpha通道计算,避免叠加后超出取值范围
    vec4 tex_color = texture(Texture, Texture_Coords);
    Pixel = vec4(diffuse * tex_color.rgb + final_specular, tex_color.a);
}

额外校验点

  • CPU端传值时确认specular(高光幂次)取值在2~256的合理区间,不要传0或者过大的数值
  • 确认reflective(高光强度)数值大于0,常规取值在0~1之间
  • 如果模型没有非均匀缩放,可简化法向量计算逻辑提升性能,直接用mat3(m) * normals传递法向量即可

内容的提问来源于stack exchange,提问作者Extorc Productions

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:06:03