Games101作业5
1.实现Renderer.cpp 中的 Render():为每个像素生成光线
这里你需要为每个像素生成一条对应的光 线,然后调用函数 castRay() 来得到颜色,最后将颜色存储在帧缓冲区的相 应像素中。
我们要做的就是将屏幕空间下的坐标最后转换到世界空间的坐标
这里一开始是处于屏幕空间坐标下的,如下图,这里假设原点在左上角,opengl原点在左下角,dx原点在左上角,那么首先想到的是将i,j分别加0.5取得像素中心坐标

接着将坐标变换到NDC空间,NDC空间是一个长宽高取值范围为[-1,1]的立方体,超过这个范围的顶点,会被GPU剪裁。注:在DirectX里面,NDC的z方向取值范围是[0,1]
DX下的NDC空间如下图,要转换到NDC空间下,首先要用x,y分别除以屏幕的宽度贺高度。然后NDC空间需要将坐标轴原点变回到屏幕中间位置。
i方向即宽方向,[0,1]->[-1,1],因为变化是线性的,很容易得到 i = 2*i-1。
j方向即高方向,[0,1]->[1,-1],因为变化是线性的,很容易得到 i = -2*i+1


最后要将坐标转换到世界空间,要解决两个问题:
①横纵方向的长度并不是1:1的;
②物体本身并不是在[-1,1]的,[-1,1]是缩放后的范围。
解决办法:
①imageAspectRatio即宽高比,是原本scene的宽高比,所以要想恢复原始的比例需要用 宽 * 宽高比,即 x * imageAspectRatio。
②scale为一半可看角度(fov/2)的tan值,即下图tan(α/2),它代表了原本图像屏幕高度与图像到X-Y平面距离的比值,又由代码已给出的 Vector3f dir = Vector3f(x, y, -1) ,可以知道原本的图像屏幕距离X-Y平面为1,所以scale即为原本的图像高度,而现在的图像高度为1,所以令x,y同时乘以scale即可得到原始世界坐标下的坐标。

综上所述,最后直接给出代码计算
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 = (float)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 directionfloat x = (2 * (((float)i + 0.5) / scene.width) - 1)* imageAspectRatio * scale;float y = (1.0 - 2 * ((float)j + 0.5) / scene.height) * scale;// 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* //vector = op,说明scene在z=-1,故znear距离人眼距离=1 Vector3f dir = normalize(Vector3f(x, y, -1)); // Don't forget to normalize this direction!framebuffer[m++] = castRay(eye_pos, dir, scene, 0);}UpdateProgress(j / (float)scene.height);}// save framebuffer to fileFILE* 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);
}
到这一步输出的结果:
window下查看ppm图片貌似需要用到第三方软件,这里给出我用的一个网站:
在线查看 PPM 文件的免费在线工具 - ImageToStl

2.Triangle.hpp 中的 rayTriangleIntersect():实现视射线与三角形相交
主要就是根据这个公式分别带入不同的参数就可以

origin是相机的位置,dir是射出的方向
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.Vector3f E1 = v1 - v0, E2 = v2 - v0 ;Vector3f S = orig - v0,S1 = crossProduct(dir, E2), S2 = crossProduct(S, E1);if (dotProduct(S1, E1) <= 0) return false;tnear = dotProduct(S2, E2) / dotProduct(S1, E1);u = dotProduct(S1, S) / dotProduct(S1, E1);v = dotProduct(S2, dir) / dotProduct(S1, E1);if (tnear >= 0 && u >= 0 && v >= 0 && (1 - u - v) >= 0) return true;return false;
}
最后的结果

相关文章:
Games101作业5
1.实现Renderer.cpp 中的 Render():为每个像素生成光线 这里你需要为每个像素生成一条对应的光 线,然后调用函数 castRay() 来得到颜色,最后将颜色存储在帧缓冲区的相 应像素中。 我们要做的就是将屏幕空间下的坐标最后转换到世界空间的坐标…...
Golang解决跨域问题【OPTIONS预处理请求】
Golang解决跨域问题 前置知识:跨域问题产生条件及原因 跨域是是因为浏览器的同源策略限制,是浏览器的一种安全机制,服务端之间是不存在跨域的。 所谓同源指的是两个页面具有相同的协议、主机和端口,三者有任一不相同即会产生跨域…...
复试 || 就业day05(2023.12.31)算法篇
文章目录 前言找不同最长回文串找到所有数组中消失的数字下一个更大元素 I键盘行 前言 💫你好,我是辰chen,本文旨在准备考研复试或就业 💫文章题目大多来自于 leetcode,当然也可能来自洛谷或其他刷题平台 💫…...
Spring-4-代理
前面提到过,在Spring中有两种类型的代理:使用JDK Proxy类创建的JDK代理以及使用CGLIB Enhancer类创建的基于CGLIB的代理。 你可能想知道这两种代理之间有什么区别,以及为什么 Spring需要两种代理类型。 在本节中,将详细研究代理…...
设计模式:抽象工厂模式(讲故事易懂)
抽象工厂模式 定义:将有关联关系的系列产品放到一个工厂里,通过该工厂生产一系列产品。 设计模式有三大分类:创建型模式、结构型模式、行为型模式 抽象工厂模式属于创建型模式 上篇 工厂方法模式 提到工厂方法模式中每个工厂只生产一种特定…...
C语言中的Strict Aliasing Rule
文章目录 前言没有警告不代表没有问题目前的应对方法 前言 很久没写了,水一篇。 最近有个代码在gcc 4.8.5上编译失败。编译失败的提示是: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werrorstrict-aliasing]查了下…...
单字符检测模型charnet使用方法,极简
Git链接 安装按照上面的说明,说下使用。 把tools下面的test做了一点修改,可以读取一张图片,把里面的单个字符都检测和识别出来。 然后绘制到屏幕上。 import torch from charnet.modeling.model import CharNet import cv2, os import num…...
Erlang、RabbitMQ下载与安装教程(windows超详细)
目录 安装Erlang 1.首先安装RabbitMQ需要安装Erlang环境 2.点击下载好的.exe文件进行傻瓜式安装,一直next即可 3.配置Erlang环境变量 安装RabbitMQ 1.给出RabbitMQ官网下载址:Installing on Windows — RabbitMQ,找到 2.配置RabbitMQ环境变量࿰…...
2023年终总结丨很苦,很酷!
文章目录 个人简介丨了解博主写在前面丨博主介绍年终总结丨博主成就年终总结丨博主想说年终总结丨学习芝士年终总结丨未来展望写在后面丨新年快乐 个人简介丨了解博主 主页地址:https://blog.csdn.net/m0_68111267 荣誉身份 ⭐2022年度CSDN 社区之星 Top6 ⭐2023年…...
鸿蒙 DevEco Studio 3.1 入门指南
本文主要记录开发者入门,从软件安装到项目运行,以及后续的学习 1,配置开发环境 1.1 下载安装包 官网下载链接 点击立即下载找到对应版版本 下载完成,按照提示默认安装即可 1.2 下载SDK及工具链 运行已安装的DevEco Studio&…...
ubuntu多用户环境dockerbug,卸载重装docker流程
之前不小心误操作删除重装docker,结果删除没成功,更没法重装,每次apt install都会报一个docker错误,虽然不影响软件的常规安装~但是现在还是需要装一个完整docker,还是选择删除一下,重点是关闭服…...
微信小程序开发系列-09自定义组件样式特性
微信小程序开发系列目录 《微信小程序开发系列-01创建一个最小的小程序项目》《微信小程序开发系列-02注册小程序》《微信小程序开发系列-03全局配置中的“window”和“tabBar”》《微信小程序开发系列-04获取用户图像和昵称》《微信小程序开发系列-05登录小程序》《微信小程序…...
数据结构 模拟实现LinkedList单向不循环链表
目录 一、链表的简单介绍 二、链表的接口 三、链表的方法实现 (1)display方法 (2)size得到单链表的长度方法 (3)addFirst头插方法 (4)addLast尾插方法 (5…...
2023-12-24 LeetCode每日一题(收集足够苹果的最小花园周长)
2023-12-24每日一题 一、题目编号 1954. 收集足够苹果的最小花园周长二、题目链接 点击跳转到题目位置 三、题目描述 给你一个用无限二维网格表示的花园,每一个 整数坐标处都有一棵苹果树。整数坐标 (i, j) 处的苹果树有 |i| |j| 个苹果。 你将会买下正中心坐…...
Oracle 19c OCP 1z0 082考场真题解析第17题
考试科目:1Z0-082 考试题量:90 通过分数:60% 考试时间:150min 本文为云贝教育郭一军guoyJoe原创,请尊重知识产权,转发请注明出处,不接受任何抄袭、演绎和未经注明出处的转载。 17. Which three …...
掌握这十几个Python库才是爬虫界的天花板,没有你搞不定的网站!实战案例:Python全网最强电影搜索工具,自动生成播放链接
掌握这十几个Python库才是爬虫界的天花板,没有你搞不定的网站!实战案例:Python全网最强电影搜索工具,自动生成播放链接。 用来爬虫的十几个Python库。只要正确选择适合自己的Python库才能真正提高爬虫效率,到达高效爬虫目的。 1.PyQuery from pyquery import PyQuery as …...
模型 KANO卡诺模型
本系列文章 主要是 分享 思维模型,涉及各个领域,重在提升认知。需求分析。 1 卡诺模型的应用 1.1 餐厅需求分析故事 假设你经营一家餐厅,你想了解客户对你的服务质量的满意度。你可以使用卡诺模型来收集客户的反馈,并分析客户的…...
启明智显开源项目分享|基于Model 3c芯片的86中控面板ZX3D95CM20S-V11项目软硬件全开源
前言: 本文为4寸 480*480 RGB接口IPS全面触屏的86中控面板(RT-ThreadLVGL)软硬件开源干货内容,该项目是综合性非常强的RTOS系列项目!项目主控芯片使用 Model 3c,整体实现了简化版本的86中控面板的功能需求…...
Kind创建k8s - JAVA操作控制
kind 简介kind 架构安装 Kind (必备工具)docker官网kubectl官网kind官网校验安装结果 关于kind 命令 安装一个集群查看当前 Kubernetes 集群中的节点信息。查看当前命名空间下中的Pod(容器实例)的信息。使用 kind create cluster 安装,关于安…...
Qt sender()函数
sender函数原型: QObject *sender() const; 如果在由信号激活的插槽中调用该函数,返回指向发送信号的对象的指针,否则返回0,该指针仅在从该对象的线程上下文调用此函数的槽执行期间有效。 主要代码如下: 其中运用了Q…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
