首页 > 其他分享 >5、片元着色器之基础光照模型:Phong模型和Blinn-Phong模型

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

时间:2024-10-30 16:46:39浏览次数:5  
标签:direction point 模型 float sdSphere Phong vec3 Blinn

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.);
}

在这里插入图片描述

标签:direction,point,模型,float,sdSphere,Phong,vec3,Blinn
From: https://blog.csdn.net/weixin_41364246/article/details/143368305

相关文章

  • 4、片元着色器之光线步进及其和兰伯特光照模型的结合应用
    1、什么是光线步进?光线步进(RayMarching)是一种用于渲染和追踪的技术,尤其在处理体积数据和隐式表面时非常有效。与传统的光线追踪方法不同,光线步进不直接计算光线与物体的交点,而是通过在光线上逐步前进来寻找相交的表面。这种方法通常用于场景中存在复杂几何体或体积效果......
  • Amphion 推出开源 TTS 模型 MaskGCT,5 秒克隆声音;神秘文生图模型「小熊猫」登顶竞技场
       开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(Real-TimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编......
  • 2024年模型构建、多维空间与几何学国际学术会议(ICMBMSG 2024)
    2024年模型构建、多维空间与几何学国际学术会议(ICMBMSG2024)2024InternationalConferenceonModelBuilding,MultidimensionalSpaceandGeometry(ICMBMSG2024)会议信息大会官网:2024年模型构建、多维空间与几何学国际学术会议(ICMBMSG2024)投稿邮箱:[email protected]【......
  • 大模型提示词简介 举例
    目录大模型提示词(Prompt)详解1.什么是AI提示词(Prompt)2.为什么提示词对AI结果的影响很大3.提示词构成4.提示词举例示例1:生成新闻标题示例2:创作诗歌示例3:撰写电子邮件示例4:解答数学题示例5:翻译句子大模型提示词(Prompt)详解随着人工智能技术的飞速发展,自然语言处......
  • 【JavaScript】之浏览器对象模型(BOM)详解
    浏览器对象模型(BOM:BrowserObjectModel)是JavaScript的一部分,它允许你与浏览器窗口进行交互。不同于DOM(文档对象模型)主要处理网页内容,BOM关注的是浏览器窗口本身及其各种特性,例如导航、窗口大小、浏览器历史记录等等。就是JavaScript将浏览器的各个组成部分封装成了对......
  • OSI模型
    Java复习笔记OSI模型开放式系统互联通信参考模型(英语:OpenSystemInterconnectionReferenceModel,缩写为OSI)1-7物联网叔会使用(资源子网)应用层    为应用程序提供交互服务。    域名系统DNS    文件传输FTP    支持万维网(www)应用的HTTP协议,    ......
  • 掌握机器学习中的偏差与方差:模型性能的关键
    引言在机器学习中,偏差(Bias)和方差(Variance)是两个至关重要的概念,它们共同影响了模型的性能。理解偏差与方差的本质,能够帮助我们找到模型的平衡点,提高模型的泛化能力,避免欠拟合和过拟合。本篇文章将深入探讨机器学习中的偏差与方差,并通过代码示例来演示这些概念。1.偏差与方差......
  • CSS:盒子模型(box-model)
    CSS处理网页时,它认为每个标签都包含在一个不可见的盒子里。如果把所有的标签都想象成盒子,那么我们对网页的布局就相当于是摆放盒子。我们只需要将相应的盒子摆放到网页中相应的位置即可完成网页的布局。盒子模型在网页中的直观表现:(打开方式在上一章节中有详细说明)......
  • 时间序列分析:一种二次指数平滑法构建的纺织生产布料年产量线性预测模型 | 基于SQL语言
    目录0问题描述1 符号规定与基本假设 2模型的分析与建立 3模型的求解【基于SQL语言实现】3.1数据准备3.2问题分析步骤1:计算初始值。步骤2:计算一次平滑值。步骤3:计算二次平滑值 步骤4:计算直线趋势模型的系数 及步骤5:构建线性预测模型进行结果预测3.3结......
  • 多租户系统的核心概念模型
    大家好,我是汤师爷~让我们深入探讨一下多租户系统的概念模型。概念模型是多租户系统的"骨架",帮助我们理解系统各部分的组织和运作方式。多租户的核心概念模型租户:通常指一个企业客户,不同租户之间的数据和行为是相互隔离的。用户:某个租户内的具体使用者,使用账号、密码等信息登......