[笔记]光线追踪(games101)
Whitted Style Raytracing
从相机出发, 朝某个像素点出射光线, 直到接触到的第一个物体的位置,
从该位置与光源连线, 若连线上没有其他物体, 说明该点可以被照亮.
此时使用布林冯等着色模型进行着色即可.
image
同时考虑折射, 反射, 最后将所有点的贡献叠加,
作为当前像素的着色结果.
image
求光线与表面的交点
在这里说的光线应该指的是从相机射出的光线.
数学上的光线表示为: 从某点延申的一条射线.
球的表面表示为: 表面上的点到圆心的距离等于半径.
注意向量的平方是个标量.
image
代入解出t. 注意t必须是正的. 解的数量决定交点数量.
image
对于一般的隐式表面:
image
解出t之后, 那交点的位置其实就在o + td.
这里说下隐式表面和显示表面的区别. 前者代表满足某个方程的点.
后者则是给定参数, 用参数生成表面方程.
对于显示表面求交,...
随机数与噪声入门
先放链接:
[图形技术科普]
如何以通俗易懂的方式理解柏林噪声的原理?经典柏林噪声算法的探讨与实现 |
Acerola’s Applied Graphics_哔哩哔哩_bilibili
Unity
Pseudorandom Noise Tutorials
前者能够稍微了解噪声原理, 后者则是原理讲解与实现.
本文基于Unity实现噪声可视化. 项目链接: 噪声可视化
项目演示: Unity伪噪声可视化演示[柏林噪声&单形噪声&哈希函数&值噪声]_哔哩哔哩_bilibili
项目代码涉及很多为了手动向量化而做的计算. 可能与文章代码有部分冲突,
但计算逻辑是相同的. 在这篇文章中,
代码更多的是用于帮助理解以及为实现提供参考, 细节上不必太过纠结.
如果在代码上有比较困惑的地方可以在评论区说下, 我会在文章中补充说明.
感谢您!
如果在看完本文后希望亲自实现项目中的效果, 强烈推荐跟一遍catlike
coding的原文.
生成伪随机数 -- 哈希函数
Hash
伪随机数是噪声生成的基础. 而在本文中,...
[UE/动画/ContentExamples]Animation Basics学习笔记
前言
如果你是一位完全没有接触过UE的初学者, 不建议直接上手看示例项目,
因为这种情况下连哪些东西怎么打开都不知道, 是没办法学的.
建议在B站找一个UE蓝图入门教程过一遍, 然后找一个UE角色动画基础教程过一遍.
之后再来上手看项目会好很多. 这里推荐一下我个人看的两个入门教程:
虚幻5基础,虚幻5蓝图基础,虚幻5蓝图零基础入门(已完结)_哔哩哔哩_bilibili
虚幻(UE5)角色动画基础_哔哩哔哩_bilibili
加起来十一个小时. 由于内容非常入门, 肝一点开倍速一两天就能学完.
本文是一位UE初学者的学习笔记, 学习的内容是官方示例项目Content
Example. 不保证没有错误, 仅供参考.
当然, 如果你是因为懒得学这个项目, 来找找有没有文章直接讲解这个项目的,
那应该会比较适合你.
Mirror
概述: 通过一个数据表完成镜像映射, 从而让一个动作镜像播放.
动画蓝图中:
image
如图, 如果从节点1连接至输出, 就会播放镜像后的动画,...
[笔记/入门精要]GrabPass实现玻璃效果
本文文件下载
首先看效果图
image
概述
创建一个充当玻璃的Cube(带有MainTex和BumpTex).
用GrabPass绘制当前屏幕的渲染纹理,
在后续Pass中用采样得到的法线对采样坐标进行偏移, 然后再采样渲染纹理,
此为折射. 反射就没什么好说的了, 用反射光线采样Cubemap即可.
上面提到的"采样坐标"实际上是个二维坐标, 即屏幕坐标.
(NDC坐标根据分辨率大小生成屏幕坐标).
实现
先看需要的properties
image
前三个没什么好说的. distortion控制折射时图像的扭曲程度(与法线相配合).
refraction amount用于控制折射程度. 为1时全折射, 为0时全反射.
GrabPass是一个Pass,
在这个Pass中Unity会为我们生成一张当前屏幕的渲染纹理,
给之后的Pass使用.
GrabPass的使用很简单, 只需要一行代码, 不过, 在本例中,
实现玻璃效果也属于透明效果的一种,...
今天, 焦虑到有点恶心
今天, 焦虑到有点恶心
起因很简单, 早早起来(七点半)开始写代码, 想给渲染器写个"点阴影",
很简单的一个东西, 愣是不知道哪里出了问题, 对着代码捣腾了几个小时,
不但没有任何效果, 反而还把前面的一些东西搞得也有 bug 了, 心态直接崩完了.
现在写这篇博客的时候, 已经是下午五点钟出头了.
我删除了所有点光源相关的东西, 把聚光也删了. 进度回退到了方向光阴影.
我真是服了.
然后就开始焦虑, 看别人写的渲染引擎, 那是真像一个引擎,
我写的就是一坨狗屎. 一千行代码我就有点顶不住了, 纯在搞笑.
一焦虑又开始刷知乎了, 然后就一直在想, 到底要学什么, 到底在学什么,
到底要怎么学. 想做游戏(指渲染/动画/特效), 别的不说,
入个门我都觉得难.
你说做引擎岗吧, 101, 202, 104, rtr4, pbrt, learnOpenGL,
raytracing三部曲, vulkan得学, ue源码得学, 学学hazel, 最后搓个引擎.
面试还得问一堆 cpp 相关的问题,...
[笔记]cpp智能指针
智能指针
来源视频: 独占智能指针unique_ptr使用技巧_哔哩哔哩_bilibili
本文文件下载
这里第三点指的是多线程的情况.
即当多个线程共享一个对象的时候, 程序员难以确定何时释放.
独占指针 unique_ptr
示例
上述程序, 只会调用构造函数. 我们没有手动 delete 的话,
不会调用析构函数. 此时, 我们使用独占指针管理指针 p:
这个语句的意思是: 独占指针的管理的对象的类是 AA, 使用 pu1
管理AA类型指针 p.
这样程序就会在结束的时候执行析构函数.
原理: 独占指针对象 pu1在被销毁的时候会执行自身的析构函数,
而在自身的析构函数中会 delete p. 从而调用了 p 所指对象的析构函数.
使用 pu1 的方式和普通指针基本一样:
实际上, 独占指针有三种初始化方法:
一般使用第一种.
感觉好像有了智能指针,...
[笔记]高级光照
高级光照
冯与布林冯
布林冯模型的原理就是取一个光线方向和视线方向中间的向量, 即为半程向量,
然后计算半程向量与法线的夹角.
布林冯模型与冯模型的区别在于, 前者的计算量更小, 同时通常情况下,
布林冯模型中的半程向量与法线的夹角要小于反射光线与视线的夹角,
因此冯模型是更接近真实情况的.
为了使布林冯模型的结果与冯模型接近, 通常需要让高光次幂为冯模型的 2-4
倍.
伽马校正
CRT显示器与人眼视觉
过去, 大多数监视器是阴极射线管显示器(CRT).
这些监视器有一个物理特性就是两倍的输入电压产生的不是两倍的亮度.
输入电压产生约为输入电压的 2.2 次幂的亮度.
这本质上是一个问题, 但是由于一个神奇的巧合,
CRT显示器的这一特性被保留了下来.
这个神奇的巧合就是: 人类的视觉系统进化出了一个特性,
黑暗环境下的辨识能力要强于明亮环境,
这可能有助于我们及时发现黑暗中隐藏的危险. 如下图所示,
第一行表示的人眼感受到的亮度, 第二行表示实际的物理亮度.
物理亮度基于光子数量,...
[笔记]数据结构题目反思
单词出现次数
难点在他妈的如何正确地输入, 以及处理输入.
int main() { int quesNum = 0; std::cin >> quesNum; std::cin.ignore(); std::vector<int> result; for (int i = 0; i < quesNum; i++) { std::string tmp; std::string text; std::getline(std::cin, text); std::istringstream iss(text); std::string t; std::getline(std::cin, t); int count = 0; while (iss >> tmp) if (tmp == t) count++; ...
[笔记]数据结构
数据结构
绪论
基本概念和术语
数据: 所有能输入到计算机中并被计算机程序处理的符号的总称. (图像,
声音等都算)
数据元素: 数据的基本单位.
有时候一个数据元素可以由若干个数据项组成.
数据项: 数据的不可分割的最小单位.
数据对象: 性质相同的数据元素的集合. 是数据的一个子集.
数据结构: 相互之间存在一种或多种特定关系的数据元素的集合.
数据元素相互之间的关系称为"结构".
数据结构包括逻辑结构和存储结构两个层次.
逻辑结构: 描述的是数据元素之间的逻辑关系. 主要有: 集合, 线性结构,
树结构, 图结构.
存储结构: 数据结构再计算机中的存储称为数据的存储结构, 也称为物理结构.
主要有: 顺序存储结构和链式存储结构.
数据类型:
数据类型是一个值的集合和定义在这个值集上的一组操作的总称.
抽象数据类型( ADT ) : 一般指由用户定义的, 表示应用问题的数学模型,
以及定义在这个模型上的一组操作的总称. 具体包括三个部分:
数据对象, 数据对象上的关系的集合,...
[笔记]高级OpenGL
本文文件下载
Advanced Data (高级数据)
glBufferSubData 及批处理
可以对已通过 glBufferData 创建的内存针对性写入. (这时候只用
glBufferData 创建内存, 传给它的数据可以是 NULL ).
glBufferSubData(GL_ARRAY_BUFFER, 24, sizeof(data), &data); // Range: [24, 24 + sizeof(data)]
先前使用的数据都是123123123这样子排列的,
比如顶点坐标-顶点法线-顶点纹理坐标. 可以通过 glBufferSubData 进行批处理,
使得数据呈现111222333这样的排列顺序.
float positions[] = { ... };float normals[] = { ... };float tex[] = { ... };// fill bufferglBufferSubData(GL_ARRAY_BUFFER, 0,...