Blinn-Phong Reflectance Model 光照反射模型

Blinn-Phong Reflectance Model

Blinn-Phong反射模型简介

Blinn-Phong反射模型的三种光照

在这里插入图片描述

  • Specular highlights 镜面高光
    • 镜面反射光,只有与镜面反射光角度接近才可以观察到,与观察角度有关。
  • Diffuse reflection 漫反射
    • 光线会被均匀的反射到各个方向去,在不同方向观测结果一致,与观测角度无关。
  • Ambient lighting 环境光
    • 在此简化模型中,默认一般假设环境光为常数。
Blinn-Phong反射模型的变量定义

三个方向向量,着色点记录的属性,光源的属性

在这里插入图片描述

  • 三个方向向量 : 一定要是单位向量,否则光会产生偏移
    • l , 着色点指向光源的单位方向向量
    • n, 着色点处的法线单位方向向量
    • v, 着色点指向观测点的单位方向向量
  • 若干着色点(片元 fragment)记录的属性
    • 颜色值(可能直接给出color)
    • 纹理/纹理坐标,texture/texture coordinate
      • 纹理内可以存各种各样的属性,可以是用于做凹凸效果的相对高度,可以是纹理的颜色值,最常用的是颜色值。
    • 着色点的坐标位置(point position)
    • 法线方向向量(normal)
  • 光源的属性
    • 光照强度 I (注意区分字母,这里是i - identity 光照是l - light)
      • 单位面积的光照能量
    • 光源距离着色点的距离 r
着色的局部性

在这里插入图片描述

在着色环节,不会考虑阴影等遮挡问题,也就是只考虑当前的着色点,不考虑其它模型对此的作用。

Diffuse Reflection 漫反射

漫反射理论基础
  • 漫反射的现象
    在这里插入图片描述

    • 当一个光线射到某个点,光线会被均匀的反射到各个方向上去
    • 在任意方向观察漫反射造成的表面颜色都是相同的。
  • 光照能量接收的损失问题

    • 光照传播距离所造成的单位面积下能量的损失
      • 在这里插入图片描述

      • 假设光的能量都均匀分布在以光源为球心,半径为1的球壳上。在此球壳上的单位面积的光照能量为 I , I就称为光照强度。

      • 球壳上的能量就为4πI , 这时考虑距离光源距离为r的点,其处的能量应该均匀的分布在一个更大的球壳上。

      • 通过能量守恒定律可以知道此球壳上的能量也为4πI,单位面积的光照能量就是4πI / 4πr^2 = I / r^2 即在距离光源为r处所接收到的光照强度为 I / r^2

    • 非直射情况下所造成的单位面积下能量的损失
      • 在这里插入图片描述

      • 物体表面在被光照直射的情况下,单位面积下能接受所有的光线带来的能量,但在被斜射的情况下单位面积并不能接收所有的光线所带来的能量,如上图所示。

      • 单位面积所接收到的光照能量 = 此点下的光照强度 * cosθ;θ就是光照方向和法线方向的夹角。

      • 由于光照方向I和法线方向n都是单位向量,cosθ也可以用l·n的点乘形式来计算余弦夹角。

      • 公式:(I / r^2)cosθ = (I/r^2)n·l

漫反射公式推导

在这里插入图片描述

  • kd
    • 漫反射系数 Vector3f 三维向量
    • 一般用于控制反射光的颜色,例如(1,1,1),所有的光都反射出去,看到的也就是白色RGB(255,255,255),例如(0,0,0),所有的光都被吸收不反射,看到的也就是黑色RGB(0,0,0)。
    • 一般由纹理的颜色进行赋值
  • (I/r^2)
    • 前面介绍的 I 光照强度和 光源到着色点的距离r,此公式代表的就是在着色点处的单位面积光照所能达到的能量。
    • 注意 I也是 Vector3f 三维向量代表分解到xyz方向的光照强度,在算数乘后的结果与kd三维向量相乘时,是两个三维向量对应位置相乘,不是点乘或叉乘!
  • max(0,n·l)
    • n·l就是法线和光照方向夹角的余弦值cosθ,也就是着色点单位面积所能接收到的光照能量的比例。
    • 这里用max的意义是为了不取到负数,可以想到只有投射到物体表面的另一侧才会出现法向量和光照方向夹角为负数的情况如下图
      • 在这里插入图片描述

      • 这种情况显然是无意义的,所以当出现这种情况直接置0,不加考虑。

  • Ld 漫反射光照的结果,也就是漫反射在此着色点产生的颜色 Vector3f

Specular highLights 镜面高光

镜面高光理论基础

在这里插入图片描述

  • 根据材质光滑程度的不同,反射光的出射方向是一个范围分布,越集中范围小亮度越高,越分散范围大亮度越低。若是磨砂材质,范围大,高光效果也就不明显了。
  • 只有观察方向和反射方向接近的时候才可以观察到高光的现象
镜面高光公式推导

在这里插入图片描述

  • 利用半程向量h和法向量n的夹角等效替换观测向量和反射向量的夹角,夹角余弦值反映了接近程度
    • 求反射光方向的计算复杂,而求半程向量只需要平行四边形法则后除以模长单位化即可
  • 省略斜照造成的单位面积光照能量的损失
    • 经验模型,这里更关注高光,无需关注接收能量的损失
  • 镜面反射系数 ks
    • 一般根据材质的光滑程度所定义
  • 高光系数p
    • 在这里插入图片描述

    • 第一个图在45度虽然高光衰减了一部分,但仍能清晰看到高光,而最后一个图衰减迅速,超过20度左右就看不见高光了。

    • 正常情况下高光系数取100-200之间,一般3度-5度就看不见高光了

    • 一般根据材质的光泽度定p , 金属材质光泽度更高,p就更高,高光更加集中。

  • Ls:,镜面反射高光的结果,颜色值

Ambient Light 环境光

环境光理论基础

环境光在Blinn-Phong Reflectance模型处进行简化,认为其是一个常驻的常数向量。

环境光推导公式

在这里插入图片描述

  • Ka 环境光系数 视具体情况给定
  • Ia 环境光强度 常数,视具体情况给定即可
  • La 环境反射光结果,颜色值

模型结果,三个光的叠加

在这里插入图片描述

对于每个着色点都进行一次漫反射,环境光照,镜面高光反射,将三个光照结果相加就能得到Blinn-Phong Reflectance Model的结果,最后将这个结果的颜色值作用于此着色点即可。

以下是使用OpenGL实现Blinn-Phong光照模型的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <GL/glut.h> // 材质参数 GLfloat mat_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; // 光源参数 GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; // 窗口大小 int window_width = 800; int window_height = 600; void init(void) { // 初始化材质参数 glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); // 初始化光源参数 glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); // 启用光照和深度测试 glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); } void display(void) { // 清除颜色缓冲区和深度缓冲区 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 绘制一个立方体 glutSolidCube(2.0); // 交换前后缓冲区 glutSwapBuffers(); } void reshape(int width, int height) { // 设置视口大小 glViewport(0, 0, (GLsizei)width, (GLsizei)height); // 设置投影矩阵 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // 设置模型视图矩阵 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // 更新窗口大小变量 window_width = width; window_height = height; } int main(int argc, char** argv) { // 初始化GLUT库 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(window_width, window_height); glutInitWindowPosition(100, 100); glutCreateWindow("Blinn-Phong Lighting Model"); // 调用初始化函数 init(); // 注册回调函数 glutDisplayFunc(display); glutReshapeFunc(reshape); // 进入主循环 glutMainLoop(); return 0; } ``` 此代码实现了一个简单的立方体和Blinn-Phong光照模型。其中,材质参数和光源参数可以根据需要进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值