GAMES101作业5及框架梳理

news2025/1/11 11:15:38

闲言碎语

emmm,上一次写还是2022年4月份的事情了,真的有点恍如隔世,4月到9月主要是在准备保研的事情,然后10月到12月基本上是在适应实习生活(没错,保完研之后因为种种原因就直接开始实习了,害,好吧,其实基本上就是奢靡的摆烂生活==,因为压力忽然没了,基本就是在公司混日子,没干啥事),就有很多事情本来早就该弄了,但是自己一直拖拖拉拉,最近慢慢适应了工作节奏,就陆陆续续开始搞一些曾经想搞但一直没时间搞的东西,由于本科毕设是做渲染相关的,所以games101渲染部分的作业得好好做一做,争取在年前能够入个门。

好了回归正题,作业5总体来说不是很难,主要是把整个框架看懂花了点时间,实际上敲代码的话是比较容易的,感觉核心还是看懂整个框架,收获的东西相较于作业会更多

目录

    • 闲言碎语
    • 框架梳理
    • 任务一:生成光线
    • 任务二:光线与三角形求交
    • 最终效果
    • 感悟
    • 参考链接

框架梳理

这个作业框架实际上是实现了简单的光线追踪流程(无加速算法),从全局来看就是先往scene里面添加物体(包括物体本身的材质信息和各种属性)和光源,其中物体既可以是显示表示(三角网格),也可以是隐式表示(球,用方程)。添加完之后就调用Render函数进行渲染以上就是对应图形学两个环节,建模和渲染,如果要让他们动起来的话就是还要加个模拟。

渲染流程大概就是先生成光线(视点与屏幕像素中心点的连线),然后光线与场景相交找到第一个与之相交的点(这里相交的方法是遍历空间中所有物体,依次与光线相交求出相交点,然后找到最近的相交点返回。其中,对于不同物体的求交方法是不一样的,比如对于球这种隐式表示的,就用解析解的方法直接求交点,对于三角网格这种显示表示的,就依次遍历其所有三角形,用线和三角形求交的方法求交点),之后根据各种渲染的方法对该点着色(不同材质的着色方法不一样,代码里面写了三种材质,对应三种不同的着色方法,并且这里还需要判断点是否处在阴影中,若在阴影中,则不需要着色),然后该点的颜色就会最终返回,作为最终渲染图像的一个像素值。射出全部光线就能得到全部像素值,最终得到渲染图像。

由于这次框架比较简单,这次就不一边梳理框架一边看代码了,因为我觉得代码千变万化,不同场景都会有变化,但是光线追踪核心的思想和流程是不变的,只要核心的思想懂了,代码怎么变都是可以看懂的。而且我觉得看框架的代码也是一个自主学习的过程,如果讲的太透,也没有什么意思,还是自主学习更加有趣,也会有更多的收获,我相信只要坚持看下去,每个人肯定是能把代码框架看懂的,遇到看不懂的地方可以再回来看一下我上面的思路,希望对你有一定帮助。

当你看懂框架的代码后,一定是能看懂我上面的这段话的

如果实在看不懂框架,可以参考:https://blog.csdn.net/qq_41835314/article/details/124969379(这位老哥可以说是讲的相当的细了==

任务一:生成光线

这个不难,本质上就是坐标转换,算出屏幕像素中心点在世界坐标系的坐标,与视点相减,就是光线方向。实际上可以这么理解,这里坐标转化的过程与透视投影那一部分几乎是一模一样的思路,可以把屏幕像素看作视锥的一个底面,脑子里要有一张图,然后视点就是视锥的尖端,按照这种角度去理解应该会更好理解一点,scale和imageAspectRatio的意义也容易明白。

可以参考:https://blog.csdn.net/Q_pril/article/details/123825665,已经讲的比较透彻了。

void Renderer::Render(const Scene& scene)
{
    std::vector<Vector3f> framebuffer(scene.width * scene.height);

    float scale = std::tan(deg2rad(scene.fov * 0.5f));
    float imageAspectRatio = scene.width / (float)scene.height;
                                                                                                 
    // Use this variable as the eye position to start your rays.
    Vector3f eye_pos(0);
    int m = 0;
    for (int j = 0; j < scene.height; ++j)
    {
        for (int i = 0; i < scene.width; ++i)
        {
            // generate primary ray direction
            // TODO: Find the x and y positions of the current pixel to get the direction
            // vector that passes through it.
            // Also, don't forget to multiply both of them with the variable *scale*, and
            // x (horizontal) variable with the *imageAspectRatio* 
            float x,world_scene_width;
            float y, world_scene_height;
            //世界坐标下屏幕的真实长度和宽度
            world_scene_width = 1 * scale * 2 * imageAspectRatio;
            world_scene_height = 1 * scale * 2;
            //x范围从  0-(scene.width-1) 转换为 0-1
            x = (i + 0.5) / (scene.width - 1);
            //x范围从  0-1 转换为 -1-1
            x = x * 2 - 1;
            //x范围从  -1-1 转换为 -world_scene_width/2-world_scene_width/2
            x = x * world_scene_width / 2;
            //y同理,其范围从0-(scene.height-1)最终转换为world_scene_height/2-(-world_scene_height/2)
            y= (-2 * (j + 0.5) / (scene.height-1) + 1)* world_scene_height/2;

            Vector3f dir = Vector3f(x, y, -1); // Don't forget to normalize this direction!
            dir = normalize(dir);
            framebuffer[m++] = castRay(eye_pos, dir, scene, 0);
        }
        UpdateProgress(j / (float)scene.height);
    }

    // save framebuffer to file
    FILE* fp = fopen("binary.ppm", "wb");
    (void)fprintf(fp, "P6\n%d %d\n255\n", scene.width, scene.height);
    for (auto i = 0; i < scene.height * scene.width; ++i) {
        static unsigned char color[3];
        color[0] = (char)(255 * clamp(0, 1, framebuffer[i].x));
        color[1] = (char)(255 * clamp(0, 1, framebuffer[i].y));
        color[2] = (char)(255 * clamp(0, 1, framebuffer[i].z));
        fwrite(color, 1, 3, fp);
    }
    fclose(fp);    
}

任务二:光线与三角形求交

这个也很简单,就是把老师ppt上面的Moller Trumbore求交算法实现出来,实际上老师上课讲了两种方法,另外一种是解析几何的方法,这种算是一种直接求解法,本质上是通过重心坐标构造一个线性方程进行求解。按老师说法是比解析几何的方法要快的。个人理解就是解析几何的过程是先求平面和光线的交点,然后再通过叉乘判断交点是否在三角形内部。而Moller Trumbore算法是直接求出交点的重心坐标,通过简单的逻辑判断是否在三角形内部,相较于解析几何方法,不需要再进行一次叉乘计算判断,一步到位

bool rayTriangleIntersect(const Vector3f& v0, const Vector3f& v1, const Vector3f& v2, const Vector3f& orig,
    const Vector3f& dir, float& tnear, float& u, float& v)
{
    // TODO: Implement this function that tests whether the triangle
    // that's specified bt v0, v1 and v2 intersects with the ray (whose
    // origin is *orig* and direction is *dir*)
    // Also don't forget to update tnear, u and v.

    //这里也不难,说白了就是把ppt上的Moller-Trumbore算法写出来就行
    Vector3f E1 = v1 - v0,
             E2 = v2 - v0,
             S = orig - v0,
             S1 = crossProduct(dir, E2),
             S2 = crossProduct(S, E1);

    float S1E1 = dotProduct(S1, E1);
    tnear  = dotProduct(S2, E2) / S1E1;
    u= dotProduct(S1, S) / S1E1;
    v= dotProduct(S2, dir) / S1E1;
    if (tnear < 0) return false;
    if ((1 - u - v) > 0 && u > 0 && v > 0) return true;

    return false;
}

最终效果

由于这次作业比较简单,没遇到bug,一次就出来了,最后效果看上去和老师给的差不多,还有点小激动==

在这里插入图片描述

感悟

好久没写算法了,前段时间都在写工程的一些东西,现在写这些简单的都有点生疏,慢慢拾起来吧,然后的话作业做完,看懂框架之后,感觉自己对光线追踪的过程有了进一步的理解,编程实践真的很重要==

参考链接

1.https://blog.csdn.net/Q_pril/article/details/123825665
2.https://blog.csdn.net/ycrsw/article/details/124199544
3.https://blog.csdn.net/qq_41835314/article/details/124969379

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/137488.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Vue]Vue3学习笔记(尚硅谷)

文章目录&#x1f97d; 创建Vue3项目&#x1f30a; vue-cli&#x1f30a; vite&#x1f97d; 项目结构&#x1f97d; Vue3开发者工具的安装&#x1f97d; 初识setup&#x1f97d; ref 函数&#x1f97d; reactive函数&#x1f97d;Vue3.0中的响应式原理&#x1f30a; vue2.x的响…

微服务架构解决方案介绍

1、微服务架构 目前微服务是非常火的架构或者说概念&#xff0c;也是在构建大型互联网项目时采用的架构方式。 1.1 单体架构 在软件设计中&#xff0c;经常提及和使用经典的3层模型&#xff0c;即表示层、业务逻辑层和数据访问层。 表示层&#xff1a;用于直接和用户交互&a…

内网穿透(mac,window,linux通用)1分钟实现外网访问电脑本地服务器

我们在做开发时&#xff0c;不想购买服务器&#xff0c;只想搭建我们本地的服务器&#xff0c;我们搭建的本地服务器只能供我们自己电脑的浏览器访问&#xff0c;或者处于同一个wifi下的手机访问&#xff0c;但是我们如果想让别人访问到我们的本地服务器&#xff0c;尤其做微信…

共享模型之管程(三)

1.Synchronized优化原理 1.1.轻量级锁(Lock Record) 1.1.1.简介 1>.轻量级锁的使用场景:如果一个对象虽然有多个线程访问,但是多个线程访问的时间是错开的(即没有竞争),那么可以使用轻量级锁来进行优化; 2>.轻量级锁对使用者是透明的,即语法仍然是"synchronized…

docker减少构建镜像大小

目录 1.原镜像大小 1.1 Dockerfile文件 1.2 hello文件 1.3 进入文件夹myprojecthello打包镜像 1.4查看打包的镜像 2.通过拆分文件夹减少镜像大小 2.1 创建两个文件夹 2.2 移动文件 2.3 打包镜像 3. 通过 .dockerignore 文件的方式 3.1 创建 world.txt文件 3.2 创建 …

【Spring(三)】DI入门案例(XML版)

文章目录前言DI入门案例总结前言 前面我们已经演示了IOC入门案例的介绍&#xff0c;里边还有一些东西是耦合的&#xff0c;接下来我们就来学习DI的入门案例来解决这个问题&#x1f4aa;&#x1f4aa;。 DI入门案例 我们先来想一下&#xff0c;你做DI这个首先得先让IOC容器管着b…

STM32 TIM PWM中阶操作:互补PWM输出

STM32 TIM PWM中阶操作详解&#xff1a;互补PWM输出 STM32 TIM可以输出管脚PWM信号适合多种场景使用&#xff0c;功能包括单线/非互补PWM输出&#xff0c;双线/互补PWM输出&#xff0c;以及死区时间和刹车控制等。 实际上&#xff0c;因为早期IP Core的缺陷&#xff0c;早期的…

万应低代码12月重点更新内容速递

速览版 详情版 低代码开发效率升级 01 动作流 动作编排过程中涉及到多条件判断时使用&#xff0c;即&#xff1a;满足某条件可执行一条分支&#xff0c;不满足则执行“其他”分支。 【使用场景】 ● 以“个人所得税计算”场景为例&#xff0c;不同收入水平的人输入不同的收…

人工智能对联生成 API 数据接口

人工智能对联生成 API 数据接口 基于百万数据训练&#xff0c;AI 训练与应答&#xff0c;多结果返回。 1. 产品功能 AI 基于百万历史对联数据训练应答模型&#xff1b;机器学习持续训练学习&#xff1b;一个上联可返回多个下联应答&#xff1b;毫秒级响应性能&#xff1b;数据…

关键字:final

文章目录一、final修饰类修饰方法修饰变量修饰属性修饰局部变量static final练习每日一考一、final final&#xff1a;最终的 final可以修饰的结构&#xff1a;类、方法、变量 修饰类 此类不能被其他类所继承 修饰方法 此方法不可以被重写 修饰变量 此时的“变量”就称为…

ACL论文总结

「博士毕业一年&#xff0c;我拿下 ACL Best Paper」 在不久前结束的自然语言处理NLP&#xff0c;领域顶级学术会议ACL2021上&#xff0c;字节跳动AL lab研究院许晶晶&#xff0c;完成了他的演讲。 在全球顶会做完分享后&#xff0c;许晶晶感到很欣慰&#xff0c;没想到&#…

自然语言处理重点 第11章 机器阅读理解 复习

机器阅读理解复习机器阅读理解概述机器阅读(MRC)理解与问答系统(QA)的区别:本章内容&#xff1a;MRC 任务分类&#xff1a;完形填空形式&#xff08;cloze-style&#xff09;选项形式片段抽取形式&#xff08;span extraction&#xff09;文本生成形式&#xff08;free-answer/…

uCharts柱状图横向排列及不同条件下得数据颜色不同,雷达图的使用及各个参数的配置讲解

一:雷达图 1,建立一个盒子,内部存放uCharts图表 在data数据中return内部配置如下数据: chartData: {},//您可以通过修改 config-ucharts.js 文件中下标为 [radar] 的节点来配置全局默认参数,如都是默认参数,此处可以不传 opts 。实际应用过程中 opts 只需传入与全局默认…

【台式机DIY】我的第一台台式机电脑配置清单

文章目录[toc]【第一台台式机】一、电脑配置清单【电脑小白我科普】一.CPU1.选购&#xff1a;主流品牌2.选购&#xff1a;如何选择3.参数&#xff1a;接口4.参数&#xff1a;频率5.参数&#xff1a;核心和线程6.参数&#xff1a;功耗7.参数&#xff1a;缓存二.主板1.选购&#…

Django开发员工管理系统(Part I)

文章目录1. 准备工作1.1 创建django项目1.2 创建app1.3 配置settings.py文件&#xff0c;完成app注册2. 设计数据库表结构3. 在MySQL中生成表3.1 创建数据库3.2 修改配置文件&#xff0c;连接MySQL数据库3.3 通过django命令生成数据库表4. 编写部门列表4.1 &#xff08;前段页面…

报表开发工具FastReport.NET的十大常见问题及解决方法(二)

Fastreport是目前世界上主流的图表控件&#xff0c;具有超高性价比&#xff0c;以更具成本优势的价格&#xff0c;便能提供功能齐全的报表解决方案&#xff0c;连续三年蝉联全球文档创建组件和库的“ Top 50 Publishers”奖。慧都科技是Fast Reports在中国区十余年的友好合作伙…

php宝塔搭建部署实战海洋cms视频内容管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的海洋cms视频内容管理系统源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&#…

在动态规划的海洋中遨游(一)

前言&#xff1a;\textcolor{Green}{前言&#xff1a;}前言&#xff1a; &#x1f49e;本专栏用于本人刷算法的过程。主要包含刷题中的感受以及知识点缺陷。对于学习者来说可以作为参考。 目前更新的算法内容会比较多&#xff0c;很多都是通过刷题来进行知识点的总结&#xff0…

计算机SCI论文,很难发表吗?应该如何发表? - 易智编译EaseEditing

首先&#xff0c;找题目需要符合国际标准&#xff0c;但不要缺少创新的探究题目。这个题目可以是最新的技术&#xff0c;也可以是最新的领域&#xff1b; 也可以是探索过很多次的课题。但是如果我们想成功交付&#xff0c;如何创新是我们需要思考的。 其次&#xff0c;因为英语…

为什么有的电源不是从0V开始上电的

大家可以看下&#xff0c;这张图片是测试XILINX 的FPGA 325T的上电时序图&#xff0c;其中绿色的线是FPGA 核心电源VCCINT 1.0V的波形&#xff0c;黄色的是BANK的电源2.5V的波形&#xff0c;蓝色的是辅助电源1.8V 的波形大家有没有发现这个时序图中黄色的波形&#xff0c;也就是…