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

4、片元着色器之光线步进及其和兰伯特光照模型的结合应用

1、什么是光线步进?
光线步进(Ray Marching)是一种用于渲染和追踪的技术,尤其在处理体积数据和隐式表面时非常有效。与传统的光线追踪方法不同,光线步进不直接计算光线与物体的交点,而是通过在光线上逐步前进来寻找相交的表面。这种方法通常用于场景中存在复杂几何体或体积效果的情况。
2、基本步骤

  1. 光线发射:从相机位置发射光线,通常在场景中每个像素位置发射一条光线。
  2. 步进前进:在光线上以固定的步长逐步前进,每一步都计算当前位置的场景信息。
  3. 场景求值:在每一步中,使用一个场景描述函数(如距离场)来判断当前点距离最近表面的距离。如果距离小于某个阈值,则认为光线和物体相交。
  4. 交点判断:一旦光线与物体相交,计算交点的颜色和光照,并将结果返回。
  5. 重复步骤:如果没有找到交点,继续前进,直到光线超出场景的边界。

3、应用场景:

  1. 体积渲染:适用于模拟云、烟、雾等体积效果。
  2. 复杂几何体:处理复杂的隐式曲面,特别是无法直接通过多边形网格表示的几何体。
  3. 效果优化:在某些情况下,光线步进可以提供更高的渲染灵活性和表现力,尤其是在实时渲染和着色器编程中。

4、优缺点
灵活性高,可以处理复杂场景;
适合动态场景的渲染;
性能开销大,尤其是在高分辨率和复杂场景中;
需要精心调整步长,以平衡渲染质量和性能。

5、示例

//限制光线步进的范围,防止计算过长的距离。
const float maxDistance=40.0;
// 球心在原点,半径为1.0的球体
float sdSphere(vec3 point)
{
    return length(point)-1.0;
}
// 光线步进,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.0);
    // 视点在z轴正方向上,渲染结果就是相机在该位置看到的结果
    vec3 cameraPosition=vec3(0.,0.,5.0);

    // 改变direction的z分量实际上相当于修改了fov的大小,fov越小,物体看起来越大(前提是其他参数不变)
    //vec3 direction=normalize(vec3(uv,-1.0));// fov是90°
    vec3 direction=normalize(vec3(uv,-2.0));// 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 kd=1.;
        // 光源的强度
        float lightIntensity=1.;
        
        // 使用Lambert光照模型计算亮度
        // float intensity = kd * lightIntensity * (0.5*dot(normal, lightDir)+0.5);//半兰伯特模型
        float intensity=kd*lightIntensity*max(dot(normal,lightDir),0.);//兰伯特模型
        
        // 设置球体颜色
        color+=vec3(1.0, 0.5, 0.3)*intensity;
    }
    fragColor=vec4(color,1.0);
}

光线步进+兰伯特(gif经过压缩,质量有点不好)
光线步进+兰伯特(gif经过压缩,质量有点不好)
光线步进+半兰伯特(gif经过压缩,质量有点不好)
光线步进+半兰伯特(gif经过压缩,质量有点不好)


http://www.kler.cn/a/375718.html

相关文章:

  • Docker篇(安装容器)
  • 【搜索引擎】俄罗斯搜索引擎yandex
  • 如何解决mingw64安装后配置完环境变量仍然执行不了gcc命令以及Vscode中的环境路径配置中找不到gcc
  • Qt指定程序编译生成文件的位置
  • 使用Scrapy框架爬取博客信息
  • 数据库管理系统的ACID都各自是什么?
  • ChatGPT网页正式上线搜索聊天记录功能!埃隆马斯克的xAI正试图筹集数十亿美元|AI日报
  • ctfshow--xss靶场web327-web333(一命速通不了的靶场)
  • 小程序与服务器通信webSocket和UDPSocket
  • 【Java】异常处理见解,了解,进阶到熟练掌握
  • Github上的十大RAG(信息检索增强生成)框架
  • web——upload1——攻防世界
  • JBoss 6.x中间件监控指标详解
  • 《Python游戏编程入门》注-第4章6
  • C# 图片工具类,缩略图、加水印、调整光暗和灰度、翻转图片等...
  • npm入门教程1:npm简介
  • django重写响应对象
  • 基于随机森林的智能手机用户行为分类及流量预测分析
  • 【Axure原型分享】颜色选择器——填充颜色
  • 数据采集-Kepware 安装证书异常处理
  • ElementUI el-form表单多层数组的校验
  • C9800 bundle转换为install
  • 测试外包服务 | 从人员外包到测试工具、测试平台,提供全方位的测试解决方案~
  • 如何面对鸿蒙系统
  • Vite学习之模式
  • Edge-labeling graph neural network for few-shot learning in CVPR论文笔记