当前位置: 首页 > news >正文

5、片元着色器之基础光照模型:Phong模型和Blinn-Phong模型

1、什么是Phong光照模型?
Phong模型就是在兰伯特模型的基础上增加了镜面反射光的计算。具体来说,兰伯特模型只考虑漫反射光,而Phong模型在此基础上引入了镜面反射光的概念,以模拟光线在光滑表面反射时产生的高光效果。镜面反射光的计算考虑了观察者的视角和光源的方向,能够产生更加逼真的高光效果。
2、示例

//限制光线步进的范围,防止计算过长的距离。
const float maxDistance=40.;
// 球心在原点,半径为1.0的球体
float sdSphere(vec3 point)
{return length(point)-1.;
}
// 光线步进,start指的是相机(视点)位置;direction表示从相机(视点)发出的光线的方向
float rayMarching(vec3 start,vec3 direction)
{float d=0.;for(int i=0;i<9999;i++){vec3 point=start+d*direction;// 像素点到球体表面的距离float d0=sdSphere(point);// 当d0小于0.001时认为射线和球体表面相交了if(d0<.001||d>maxDistance)break;d+=d0;}return d;
}vec3 getNormal(vec3 p)
{float d=sdSphere(p);vec2 e=vec2(.001,.0);float fdx=d-sdSphere(p-e.xyy);float fdy=d-sdSphere(p-e.yxy);float fdz=d-sdSphere(p-e.yyx);return normalize(vec3(fdx,fdy,fdz));
}
// 构建绕y轴旋转的旋转矩阵
mat2 rot(float angle){float c=cos(angle);float s=sin(angle);return mat2(c,-s,s,c);
}
void mainImage(out vec4 fragColor,in vec2 fragCoord){// 将像素坐标标准化为 [-1, 1] 的范围vec2 uv=(fragCoord-iResolution.xy*.5)/iResolution.y;vec3 color=vec3(0.);// 视点在z轴正方向上,渲染结果就是相机在该位置看到的结果vec3 cameraPosition=vec3(0.,0.,5.);// 改变direction的z分量实际上相当于修改了fov的大小,fov越小,物体看起来越大(前提是其他参数不变)//vec3 direction=normalize(vec3(uv,-1.0));// fov是90°vec3 direction=normalize(vec3(uv,-2.));// fov是53.13°float d=rayMarching(cameraPosition,direction);if(d<maxDistance){vec3 point=cameraPosition+d*direction;vec3 normal=getNormal(point);// 定义光源位置,在xoy坐标系的第一象限vec3 lightPosition=vec3(5.,5.,0.);// 相机绕着y轴转lightPosition.xz*=rot(iTime);// 定义光源方向vec3 lightDir=normalize(lightPosition-point);// 光源的强度float lightIntensity=1.;// 漫反射系数float kd=1.;// 漫反射光强(兰伯特模型)float diffuseIntensity=kd*lightIntensity*max(dot(normal,lightDir),0.);//镜面反射vec3 reflectDir=reflect(-lightDir,normal);//reflect函数:提供入射光线和法线,返回反射向量//视线向量:从表面指向观察者vec3 viewDir=normalize(cameraPosition-point);// 镜面反射系数float ks=1.;//控制高光区域大小的系数。数值越大,光斑越小且越亮float shininess=8.0;//通过点乘来衡量反射光线是否接近视线方向;pow用于实现高光的集中度float specular=pow(max(dot(reflectDir,viewDir),0.0),shininess);// 灯光颜色vec3 lightColor=vec3(1.,.5,.3);// 设置球体颜色color+=lightColor*(diffuseIntensity+specular);}fragColor=vec4(color,1.);
}

在这里插入图片描述

3、Blinn-Phong模型
Blinn-Phong光照模型是Phong光照模型的一种改进,主要用于计算镜面反射光的强度。相较于Phong模型,Blinn-Phong模型在计算上更加高效,并且能够更好地模拟光照效果。Phong模型需要计算反射光线,是有一定计算量的,Blinn-Phong使用半角向量来简化计算。
4、示例

//限制光线步进的范围,防止计算过长的距离。
const float maxDistance=40.;
// 球心在原点,半径为1.0的球体
float sdSphere(vec3 point)
{return length(point)-1.;
}
// 光线步进,start指的是相机(视点)位置;direction表示从相机(视点)发出的光线的方向
float rayMarching(vec3 start,vec3 direction)
{float d=0.;for(int i=0;i<9999;i++){vec3 point=start+d*direction;// 像素点到球体表面的距离float d0=sdSphere(point);// 当d0小于0.001时认为射线和球体表面相交了if(d0<.001||d>maxDistance)break;d+=d0;}return d;
}vec3 getNormal(vec3 p)
{float d=sdSphere(p);vec2 e=vec2(.001,.0);float fdx=d-sdSphere(p-e.xyy);float fdy=d-sdSphere(p-e.yxy);float fdz=d-sdSphere(p-e.yyx);return normalize(vec3(fdx,fdy,fdz));
}
// 构建绕y轴旋转的旋转矩阵
mat2 rot(float angle){float c=cos(angle);float s=sin(angle);return mat2(c,-s,s,c);
}
void mainImage(out vec4 fragColor,in vec2 fragCoord){// 将像素坐标标准化为 [-1, 1] 的范围vec2 uv=(fragCoord-iResolution.xy*.5)/iResolution.y;vec3 color=vec3(0.);// 视点在z轴正方向上,渲染结果就是相机在该位置看到的结果vec3 cameraPosition=vec3(0.,0.,5.);// 改变direction的z分量实际上相当于修改了fov的大小,fov越小,物体看起来越大(前提是其他参数不变)//vec3 direction=normalize(vec3(uv,-1.0));// fov是90°vec3 direction=normalize(vec3(uv,-2.));// fov是53.13°float d=rayMarching(cameraPosition,direction);if(d<maxDistance){vec3 point=cameraPosition+d*direction;vec3 normal=getNormal(point);// 定义光源位置,在xoy坐标系的第一象限vec3 lightPosition=vec3(5.,5.,0.);// 相机绕着y轴转lightPosition.xz*=rot(iTime);// 定义光源方向vec3 lightDir=normalize(lightPosition-point);// 光源的强度float lightIntensity=1.;// 漫反射系数float kd=1.;// 漫反射光强(兰伯特模型)float diffuseIntensity=kd*lightIntensity*max(dot(normal,lightDir),0.);//视线向量:从表面指向观察者vec3 viewDir=normalize(cameraPosition-point);// 半角向量vec3 halfVector=normalize(lightDir+viewDir);// 镜面反射系数float ks=1.;//控制高光区域大小的系数。数值越大,光斑越小且越亮float shininess=8.0;//通过点乘来衡量半角向量是否接近法线方向;pow用于实现高光的集中度float specular=pow(max(dot(halfVector,normal),0.0),shininess);// 灯光颜色vec3 lightColor=vec3(1.,.5,.3);// 设置球体颜色color+=lightColor*(diffuseIntensity+specular);}fragColor=vec4(color,1.);
}

在这里插入图片描述


http://www.mrgr.cn/news/61999.html

相关文章:

  • 【Linux】Redis 部署
  • [产品管理-51]:产品经理:塑造未来的多面手,道、法、术、器的全面掌控
  • 时间数据处理
  • 全桥PFC电路及MATLAB仿真
  • 【Mybatis】动态SQL+配置文件+数据库连接池+企业规范(10)
  • 订购 Claude AI 的第二天 它独自完成 文字转语音 flask应用
  • 【Linux】进程间通信
  • iOS18 取消/适配TabbarController缩放动画
  • Vue CLI: 安装、项目创建及基本概念指南,vue生命周期
  • C++:输入和输出
  • 《Linux系统编程篇》exec族函数——基础篇
  • MATLAB——入门知识
  • Vue3 学习笔记(十三)Vue组件详解
  • Windows高级技巧:轻松实现多进程窗口的连接与管理
  • 轻松实现金蝶与旺店通数据无缝对接的完整解决方案
  • Linux文件系统_inode
  • 兽音译器的编码原理
  • 真香!Python十大文件操作整理,收藏起来以后有用!!
  • 为什么不建议使用黑帽SEO手法?
  • 阿里云VPC机器如何访问公网
  • 【总目录】
  • 浏览器指纹:了解这个神秘的技术
  • node学习记录-process
  • 【flink】之kafka到kafka
  • Flask
  • Python 中 jieba 模块详解