光照模型:Phong模型

Phong模型

1) 向量定义(对应图中几何关系)

  • P:表面上一点(当前像素/片元的位置)
  • N:该点的单位法线(图中虚线方向),N = normalize(N)
  • L:光照方向(从点 P 指向光源 LightPos)
    L = normalize(LightPos - P)
  • V:视线方向(从点 P 指向相机/眼睛 ViewPos,图中右上)
    V = normalize(ViewPos - P)
  • R:反射方向(镜面反射方向,用于高光)
    R = reflect(-L, N)
    说明:reflect(I, N) 里 I 是"入射方向",这里入射光是从光源打到表面点,方向可写成 -L。

2) Phong 三项:环境光 + 漫反射 + 镜面反射

Phong 模型把最终颜色/亮度写成: I = I_ambient + I_diffuse + I_specular

(1) 环境光 Ambient(不考虑方向,给整体一个底色)

  • I_ambient = Ka * Ia
  • Ka:材质环境系数(可用颜色 vec3)
  • Ia:环境光强/环境光颜色(全局常量或场景参数)

(2) 漫反射 Diffuse(Lambert),取决于入射角(图中箭头与法线夹角)

  • 夹角余弦:NdotL = max(dot(N, L), 0)
  • I_diffuse = Kd * Il * NdotL
  • Kd:材质漫反射系数/底色
  • Il:光源颜色/强度

(3) 镜面反射 Specular(Phong 高光),取决于观察方向与反射方向的接近程度

  • RdotV = max(dot(R, V), 0)
  • I_specular = Ks * Il * (RdotV ^ shininess)
  • Ks:材质镜面系数(高光颜色/强度)
  • shininess:高光指数(越大高光越小越"硬")

常见细节:当 dot(N, L) <= 0 时,镜面项通常也置 0(背光面不产生高光):

  • if (NdotL <= 0) spec = 0

3) 点光源距离衰减(图里像是点光源,更真实)

若光源是点光源,强度随距离减弱:

  • d = length(LightPos - P)
  • atten = 1 / (kc + kl*d + kq*d*d)
  • 把 I_diffuse、I_specular 乘上 atten

4) 最终合成(按颜色通道 vec3 计算)

  • Color = Ka*Ia + atten * (Kd*Il*NdotL + Ks*Il*pow(RdotV, shininess))
  • 最后可 clamp(Color, 0, 1) 或做 HDR/色调映射(看你的渲染管线)
cpp 复制代码
#version 330 core
in vec3 vFragPos;
in vec3 vNormal;
out vec4 FragColor;

uniform vec3 uViewPos;
uniform vec3 uLightPos;
uniform vec3 uLightColor;
uniform vec3 uObjectColor;
uniform float uShininess; // 如 32.0

void main() {
    vec3 N = normalize(vNormal);
    vec3 L = normalize(uLightPos - vFragPos);
    vec3 V = normalize(uViewPos - vFragPos);
    vec3 R = reflect(-L, N);

    float diff = max(dot(N, L), 0.0);
    float spec = pow(max(dot(R, V), 0.0), uShininess);

    vec3 ambient  = 0.1 * uLightColor;
    vec3 diffuse  = diff * uLightColor;
    vec3 specular = 0.3 * spec * uLightColor;

    vec3 color = (ambient + diffuse + specular) * uObjectColor;
    FragColor = vec4(color, 1.0);
}

Blinn-Phong模型

在phong模型的基础上,改变高光的计算,不使用反射向量,取而代之的是半程向量H:H = normalize(L + V)

几何意义:H 是 L 和 V 的角平分方向。当 N 越接近 H,越容易出现高光。

  • 镜面反射(替换为 Half Vector):
    I_specular = Ks * Il * (max(dot(N, H), 0) ^ shininess)

其他项计算和phong模型的计算一致。

cpp 复制代码
#version 330 core
in vec3 vFragPos;
in vec3 vNormal;
out vec4 FragColor;

uniform vec3 uViewPos;
uniform vec3 uLightPos;
uniform vec3 uLightColor;
uniform vec3 uObjectColor;
uniform float uShininess; // 如 32.0

void main() {
    vec3 N = normalize(vNormal);
    vec3 L = normalize(uLightPos - vFragPos);
    vec3 V = normalize(uViewPos - vFragPos);
    vec3 H = normalize(L + V);

    float diff = max(dot(N, L), 0.0);
    float spec = pow(max(dot(N, H), 0.0), uShininess);

    vec3 ambient  = 0.1 * uLightColor;
    vec3 diffuse  = diff * uLightColor;
    vec3 specular = 0.3 * spec * uLightColor;

    vec3 color = (ambient + diffuse + specular) * uObjectColor;
    FragColor = vec4(color, 1.0);
}


相关推荐
余额瞒着我当琳22 分钟前
C++异常,异常的概念,异常抛出与捕获,RAII 和智能指针的设计思路,C++标准库一些指针的使用
java·开发语言·c++·算法
東隅已逝,桑榆非晚23 分钟前
map和set的使用
数据结构·c++·笔记·学习
♡すぎ♡37 分钟前
SWE 的原理解析
算法·计算机图形学·swe
骑着蜗牛撵大象32744 分钟前
大模型 SDK 编译就崩?用 CMakeLists 把 httplib、JSON 与 OpenSSL 装配成可复用的 ChatServer
android·java·c++·http·json·cmake·大模型sdk
码小猿的CPP工坊1 小时前
C++跨平台开发之基于wxWidgets开发GUI程序简介-002
开发语言·c++
chenbingjie_c1 小时前
C++ 继承全解析(从三种继承方式到菱形继承与内存布局)
开发语言·c++
火2251 小时前
# C++ 微服务即时通讯系统(四):MySQL、Redis 与 Elasticsearch——数据分工与一致性
c++·mysql·微服务
xiaoye-duck12 小时前
《C++ 工具库实战》gflags 命令行参数解析库详解
c++·第三方库
狂奔的sherry12 小时前
C++ 宏生成访问函数的代价:访问权限、调试和类型检查
c++·宏·编译·预处理器·类型检查
划破黑暗的第一缕曙光13 小时前
[C++]:5.STL:string(2)
java·c++·redis