图论的几个经典算法
次小生成树
口述思路:
首先从原图得到最小生成树(这里用的kruskal算法). 显然,
这个最小生成树构成一个新图.
对于原图中的每一个非树边uv, 将其加入新图.
则在新图中会形成环(因为u到v的路径不止一条了).
在新图中, 深度优先搜索从u到v的路径,
用两个变量分别记录最大权值和次大权值.
最后, 对比最大权值和uv路径本身的权值, 如果相等说明MST不唯一.
如果大于说明用uv替换最大权边后总权重增大, 可能为次小生成树.
如果小于则无法替换, 因为会破坏最小生成树.
所以, 判断MST是否唯一的方法已经得到了.
在此基础上, 若想得到严格次小生成树, 有两种情况:
首先是当uv权重等于最大边权. 此时用uv替换次大权边,
然后记录此时的总权重.
其次是当uv权重大于最大边权. 此时直接用uv替换最大权边, 记录总权重.
最后所有替换后总权重取最小.
在实现上依旧有很多细节问题. 首先是最小生成树,
一套连招没什么好说的.
#include <iostream>#include...
用一个函数解决二叉树前中后序的非递归遍历问题
思路就是直接使用二叉树的经典二级结论, 第一次遍历到就输出即为前序,
第二次为中序, 第三次为后序.
#include <iostream>#include <stack>struct Node { Node *lchild, *rchild; int data; int times; Node(int d) : data(d), lchild(nullptr), rchild(nullptr), times(-1){}};void func(Node* root) { std::stack<Node*> s; s.push(root); Node* p = nullptr; while (!s.empty()) { p = s.top(); ++p->times; if (p->times == 2) { s.pop(); } else if (p->times == 1) { if...
[笔记]光线追踪(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的使用很简单, 只需要一行代码, 不过, 在本例中,
实现玻璃效果也属于透明效果的一种,...
[笔记]高级光照
高级光照
冯与布林冯
布林冯模型的原理就是取一个光线方向和视线方向中间的向量, 即为半程向量,
然后计算半程向量与法线的夹角.
布林冯模型与冯模型的区别在于, 前者的计算量更小, 同时通常情况下,
布林冯模型中的半程向量与法线的夹角要小于反射光线与视线的夹角,
因此冯模型是更接近真实情况的.
为了使布林冯模型的结果与冯模型接近, 通常需要让高光次幂为冯模型的 2-4
倍.
伽马校正
CRT显示器与人眼视觉
过去, 大多数监视器是阴极射线管显示器(CRT).
这些监视器有一个物理特性就是两倍的输入电压产生的不是两倍的亮度.
输入电压产生约为输入电压的 2.2 次幂的亮度.
这本质上是一个问题, 但是由于一个神奇的巧合,
CRT显示器的这一特性被保留了下来.
这个神奇的巧合就是: 人类的视觉系统进化出了一个特性,
黑暗环境下的辨识能力要强于明亮环境,
这可能有助于我们及时发现黑暗中隐藏的危险. 如下图所示,
第一行表示的人眼感受到的亮度, 第二行表示实际的物理亮度.
物理亮度基于光子数量,...
[笔记]高级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,...