dhui's Blog https://dhui626.github.io/ zh-CN こっちみんな! Tue, 19 Nov 2024 15:32:00 +0000 Tue, 19 Nov 2024 15:32:00 +0000 基于 OpenGL 的 Minecraft 世界渲染器 https://dhui626.github.io/index.php/archives/73/ https://dhui626.github.io/index.php/archives/73/ Tue, 19 Nov 2024 15:32:00 +0000 dhui Minecraft Mini Renderer

本页面用于项目《基于 OpenGL 的 Minecraft 世界渲染器》展示。

渲染器基于 C++ 与 OpenGL,由本人独立完成。(2024.9~至今)

截至目前的最终渲染结果如下

Final
Final

下面按时间顺序来展示各阶段进行的工作与结果。

OpenGL 基础功能

一切的开始!起初这只是一个 OpenGL 学习项目(直到现在项目目录都是LearnOpenGL)

Basic Renderer
Basic Renderer

用 OpenGL 渲染一个草方块,并编写 shader 应用 Blinn-Phong 光照模型。

后面发现了很多问题并修正:

  1. 纹理图案在边界处异常,原因是下载的纹理图案有模糊处理,替换成原图后正常。
  2. 当时实现的实际是 Phong 光照模型,specular 分量的计算未用到半程向量,后修正(顺便一提,GAMES202 的作业框架也存在此错误,且作业1中 specular 颜色值传入了 0,实际计算出的 specular 分量为 0,可能就因此没被助教们发现?)

Chunk Render Test
Chunk Render Test

实现基于 Perlin 噪声的区块生成器,并启用 ImGui 进行调试。场景中只有单个区块(32×32)。

至此性能问题就被充分暴露了:由于我每个方块都调用了一次draw call,因此上面的简单场景也只有10hz,如果场景中有多个区块将是个灾难。

性能优化

主要的优化步骤总结为如下三步:

  1. 每个区块类内维护一个 VAO,在渲染该区块时只执行一次draw call
  2. 只对接触到空气的面加入到 vertices 和 indices 数组,实际很多面不需要绘制(藏在泥土中的,以及两个相邻方块的接触面)。
  3. 启用背面剔除

在解决了以上问题后,可以生成多个区块了,并加入了 GAMES202 中介绍的阴影算法(shadow map, PCF, PCSS)

Shadow Algorithms
Shadow Algorithms

在图下方的方块边缘处阴影缺了一块,这与修复 Shadow Acne 设置的 bias 有关。

Add Grass and Flowers
Add Grass and Flowers

修正世界生成逻辑,改用 Simplex 噪声,并添加了花草,结果如上图。

考虑到花草和方块的渲染逻辑不同,后续也会使用不同的 shader ,本人将代码进行了重构。重构后一个区块可拥有多个 VAOs,且花草、方块以及后面加入的水面可以用不同的 shader 来渲染。

Add Water
Add Water

加入水方块,并对水流使用不同的渲染逻辑(透明物体最后渲染),并在 vertex shader 中模拟水的流动(Gerstner waves)

后处理

后处理主要在屏幕空间完成,即利用 FBO 的渲染结果以及深度进行图像处理。

Screen Space Fog
Screen Space Fog

水上雾化效果和水中漫游效果(Screen Space Fog),利用 FBO 的深度值来计算混合颜色。

Stage3-2
Stage3-2

Bloom效果展示,利用 Gaussion Blur 对一张高亮图模糊化,并加到原图上。

除此之外,还加入了以下调节:亮度、对比度、饱和度、锐度(已移除)、Gamma校正等

Tone Mapping
Tone Mapping

Tone Mapping,实现并比较了各种方法的结果,个人比较喜欢 CE 和 Filmic 。

总结

以上就是本人的 Minecraft Mini Renderer 的暂时进展。后续会加入更多内容,如 Cascade Shadow Map,MSAA,玩家模型等,本页面也将持续更新。

GitHub 链接:https://github.com/dhui626/LearnOpenGL

Commit History
Commit History

]]>
0 https://dhui626.github.io/index.php/archives/73/#comments https://dhui626.github.io/index.php/feed/
Blender 学习记录 https://dhui626.github.io/index.php/archives/71/ https://dhui626.github.io/index.php/archives/71/ Mon, 24 Jun 2024 14:50:00 +0000 dhui 填坑,使用 Blender4.0 官网下载链接,参考Blender Guru 的教程

文章主图是最终渲染图片。

快捷方式

鼠标滚轮按下: 调整视角

Shift + 鼠标滚轮按下: 移动视角

Shift + A: 添加物体

G (grab): 移动物体

G + X/Y/Z: 沿坐标轴X/Y/Z移动物体

G + 鼠标滚轮按下: 沿某一坐标轴移动物体

0: 摄像机视角

N: 选项(常用于关掉那个窗口)

S (scale) + X/Y/Z: 缩放物体

R (rotate) + X/Y/Z: 旋转物体

形状编辑

网格细分:添加修改器 - 生成 - 表面细分 - 调节Catmull-Clark细分的层数

编辑网格细节:选中物体 - 左上角物体模式 - 编辑模式 (快捷键Tab)

衰减编辑:同时改变一系列点。滚轮控制点的范围(P2P变形的参数)

切换透视模式:选框操作时可以选择物体背后的点

解决网格重叠的渲染问题:修改器 - 生成 - 实体化 - 调节偏移量

固定网格的部分点并隐藏:alt + 鼠标点击: 选中 ctrl + : 扩大范围 H: 隐藏

添加新顶点:选中部分点,E + 鼠标拖动

让网格顶点落在另一个网格上,而不重叠:修改器 - 形变 - 缩裹,并指定特定的目标

雕刻模式:左上角切换,常用:膨胀(I) 抓起(G)

遮罩(Mask):快捷键 M,选定不进行雕刻的区域。Ctrl + I:反选。遮罩 - 平滑遮罩:将Mask平滑化。

绑定两个物体:先选子对象(跟着父对象移动的),再选父对象,快捷键 Ctrl + P - 物体(保持变换)

选中面 - Ctrl+B:斜面工具,常用于将尖锐的边光滑化,在编辑时操作滚轮控制层数。

选中顶点 - Ctrl+R:在网格中建立细分

修改器 - 形变 - 简易形变:将网格进行拉伸、缩小

去除网格重复点:A(全选) + M(Merge) - 按距离

移动物体时吸附:G + B,点击对应的点,过程中使用 Alt + 滚轮 调整视角

重新计算法线:选中面 - Shift+N - 勾选向内

材质与渲染

材质 - 添加材质 - 修改颜色、糙度等等。

材质下载:Poliigon,网站有 add-on 安装教程。

Texture Paint:进行网格纹理的绘制,局部视图:快捷键 /

几何节点(Geometry Nodes):对网格进行自定义修改,过于复杂。视频

视图 - 裁剪起始:相机靠近物体太近时会穿过物体,调为最小(0.001m)可解决。

Fly模式:Shift+`,第一人称视角观察,WASD移动/QE上升下降等

更改物体不同部位的材质:建立多个材质

环境光添加:World - 颜色 - 天空纹理

亮度调节:Scene - 胶片 - 曝光度 (也可在环境光设置中调节)

滤镜添加:渲染 - 色彩管理 - 胶片效果()

后处理:Compositing - 勾选“使用节点” - 添加节点(色彩平衡, etc)

开始渲染:渲染 - 渲染动画(Ctrl + F12)

景深设置:选中相机 - 勾选景深,并调节光圈级数

动画

I (insert): 添加关键帧

曲线编辑:Animation - 曲线编辑器 - 编辑Bezier曲线

曲线尺度的调整:HOME键 / Ctrl + 按下鼠标滚轮

输出格式调整:输出 - 文件格式 - PNG(不建议直接生成视频,如果渲染中计算机意外重启可能丢失所有进度)

视频生成

文件 - 新建 - 视频编辑(或在当前项目中添加“视频编辑”工作区)

输出 - 文件格式 - FFmpeg视频 - 编码设置等

输出 - 后期处理 - 勾选序列编辑器(合成处理选项也可以在这里开关)

添加 - 图像序列

视频后处理

Clipchamp : 剪辑视频,提取音频,提取字幕等

分离人声 : https://vocalremover.org/

]]>
0 https://dhui626.github.io/index.php/archives/71/#comments https://dhui626.github.io/index.php/feed/
B-spline 插值 自然边界条件证明 https://dhui626.github.io/index.php/archives/51/ https://dhui626.github.io/index.php/archives/51/ Wed, 01 Nov 2023 06:50:00 +0000 dhui B-spline 插值 自然边界条件证明

定理: 四阶(三次) B-spline 插值 的自然边界条件可以简化成如下方程组:

$$ \frac{\textbf{d}_{2}-\textbf{d}_{1}}{t_{2}-t_{0}} = \frac{\textbf{d}_{1}-\textbf{d}_{0}}{t_{1}-t_{0}} \\ \frac{\textbf{d}_{n+2}-\textbf{d}_{n+1}}{t_{n}-t_{n-1}} = \frac{\textbf{d}_{n+1}-\textbf{d}_{n}}{t_{n}-t_{n-2}} $$

证明:$N_{i,k}(t)$ 参考老师 ppt 的定义,$k$ 是阶数。它的导数为

$$ N'_{i,k}(t) = \frac{k}{t_{i+k}-t_i}N_{i,k-1}(t) - \frac{k}{t_{i+k+1}-t_{i+1}}N_{i+1,k-1}(t) $$

证明见 Reference1 ,使用了数学归纳法。故 B-spline 的一阶导数为:

$$ x(t) = \sum_{i=0}^n N_{i,k}(t) \textbf{d}_i \\ x'(t) = \sum_{i=0}^{n-1} N_{i+1,k-1}(t) \textbf{Q}_i \\ \textbf{Q}_i = \frac{k}{t_{i+k+1}-t_{i+1}}(\textbf{d}_{i+1}-\textbf{d}_{i}) $$

推导见 Reference2 。然后可以写出二阶导数的形式如下。

$$ x''(t) = \sum_{i=0}^{n-2} N_{i+2,k-2}(t) \textbf{R}_i \\ \textbf{R}_i = \frac{k-1}{t_{i+k+1}-t_{i+2}}(\textbf{Q}_{i+1}-\textbf{Q}_{i}) $$

在 B-spline 插值问题中,$k = 4$。指标从 -3 开始。求和范围和 $\textbf{d}_{i}$ 的指标需要相应改变,其他不需要。

$$ x(t) = \sum_{i=-3}^{n-1} N_{i,4}(t) \textbf{d}_{i+3} \\ x'(t) = \sum_{i=-3}^{n-2} N_{i+1,3}(t) \textbf{Q}_{i} \\ x''(t) = \sum_{i=-3}^{n-3} N_{i+2,2}(t) \textbf{R}_{i} \\ $$

因为 $N_{i,2}(t)$ 只在 $(t_i,t_{i+2})$ 区间非零,边界条件 $x''(t_0)=0$ 等价于如下形式。

$$ N_{-1,2}(t_0)\textbf{R}_{-3}=0 $$

根据 $\textbf{R}_{i}$ 的表达式,边界条件等价于

$$ \textbf{Q}_{-2}=\textbf{Q}_{-3} \\ $$

等价于

$$ \frac{\textbf{d}_{2}-\textbf{d}_{1}}{t_{3}-t_{-1}} = \frac{\textbf{d}_{1}-\textbf{d}_{0}}{t_{2}-t_{-2}} $$

由重结点定义,$t_{-1} = t_{-2} = t_{0}$ ,得到所需的边界条件。

在 $t_n$ 处的自然边界条件也能用同样的方法算出。

]]>
0 https://dhui626.github.io/index.php/archives/51/#comments https://dhui626.github.io/index.php/feed/
Linux初上手记录 https://dhui626.github.io/index.php/archives/25/ https://dhui626.github.io/index.php/archives/25/ Sat, 28 Oct 2023 17:19:00 +0000 dhui 当时并没有详细记录的意识,只记录了相关代码,某些步骤现在已经看不懂了x

wsl命令

备份还原

wsl --export Ubuntu C:\OWO\CloudMusic\wslbkp.tar
wsl --import Ubuntu C:\CloudMusic C:\OWO\CloudMusic\wslbkp.tar

卸载子系统

wsl --list --all
wsl --unregister Ubuntu

安装桌面 gnome(失败)

sudo apt-get install ubuntu-desktop gnome

安装 systemd(失败)

git clone https://github.com/DamionGans/ubuntu-wsl2-systemd-script.git
cd ubuntu-wsl2-systemd-script/

修改 enter-systemd-namespace 参考

bash ubuntu-wsl2-systemd-script.sh     //系统会崩溃

设置默认Linux开发版

wslconfig /setdefault Ubuntu-20.04

配置代理(Clash开启允许局域网连接)

export hostip=$(cat /etc/resolv.conf |grep -oP '(?<=nameserver\ ).*');
export https_proxy="http://${hostip}:7890";
export http_proxy="http://${hostip}:7890";
export all_proxy="socks5://${hostip}:7891";

git 通过代理

git clone -c http.proxy="http://127.0.0.1:1080" https://github.com/TIGERB/easy-php.git

apt相关

sudo apt -o Acquire::http::proxy="http://${hostip}:7890" install nvidia-cuda-toolkit
sudo apt search libdc1394
sudo apt install 
sudo apt purge libopencv-dev python3-opencv
sudo apt autoremove

OpenCV(2.4.11 3.2.0均编译失败,而3.4.5可以无错误编译,下载链接
参考

编译用代码

mkdir build && cd build
cmake ..
make -j8
sudo make install
sudo ldconfig

窗口显示
VcXsvr 勾上 Disable access control 选项

nano ~/.bashrc

最后加上

export DISPLAY=`grep -oP "(?<=nameserver ).+" /etc/resolv.conf`:0.0

刷新shell的配置

source ~/.bashrc

Draft

netsh int ipv4 set dynamic tcp start=49152 num=16384

相关教程资料

Ubuntu桌面入门指南

不用装双系统,直接在 Windows 上体验 Linux:Windows Subsystem for Linux - 少数派

快速上手──在 Linux 上游玩 osu!stable | 砂糖砂糖沙

ORB-SLAM2 “工具安装 和 系统运行“ 详细过程

GitHub - DEEPIR/ElasticFusion

ElasticFusion的编译 - CodeAntenna

Windows 10, WSL2 显示 GUI 窗口

]]>
0 https://dhui626.github.io/index.php/archives/25/#comments https://dhui626.github.io/index.php/feed/
Visual Studio 踩坑记录 https://dhui626.github.io/index.php/archives/24/ https://dhui626.github.io/index.php/archives/24/ Sat, 28 Oct 2023 17:04:00 +0000 dhui 运行环境:Windows 10 22H2 x64 + Visual Studio 2022

vcpkg

vcpkg 是 Microsoft 的跨平台开源软件包管理器,极大地简化了 Windows、Linux 和 macOS 上第三方库的配置与安装。官网

配置教程

Step 1: 从 GitHub 克隆 vcpkg

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg

注意vcpkg目录的位置,确保文件路径长度合适以及可以存储较大数据。

Step 2: 运行 bootstrap

./bootstrap-vcpkg.bat

Step 3: 将包自动集成到 vs 的工程中

./vcpkg integrate install

之后缺哪个运行库只需在该文件夹打开 powershell 运行 vcpkg 安装指令即可。

常用命令

搜索包

./vcpkg search [packages]

安装包(输入上面搜出的包名)

./vcpkg install <pkg>

查看已安装包列表

./vcpkg list

删除包

./vcpkg remove <pkg>

帮助

./vcpkg help

卸载 vcpkg(并在之后删除此文件夹)

./vcpkg integrate remove

举例

.\vcpkg install eigen3:x64-windows
.\vcpkg install opencv4[contrib]:x64-windows
.\vcpkg install qt5-base:x64-windows

清理空间

在文档docs/about/faq.md中提到:

## How can I remove temporary files?

You can save some disk space by completely removing the `packages\`, `buildtrees\`, and `downloads\` folders.

​ 参考 @zhc 笔记,删除buildtrees\可能导致静态库无法调试。

网络问题

使用代理服务器进行网络加速时,PowerShell 终端默认不走代理端口。为此可以在 PowerShell 中运行:

$env:HTTP_PROXY="localhost:7890"
$env:HTTPS_PROXY="localhost:7890"

上述代理服务器端口因设备而异,仅改变本次端口设置。

如果需要设置全局代理,可在环境变量中设置

http_proxy         http://127.0.0.1:7890/
https_proxy     http://127.0.0.1:7890/

CMake 时遇到网络问题:在 CMakeLists.txt 的前面添加如下代码

set(ENV{http_proxy} "http://127.0.0.1:7890")
set(ENV{https_proxy} "http://127.0.0.1:7890")

项目配置

CMake

方法一:使用 CMake-GUI

选择源代码位置、build 目录,只需 Configure、Generate、Open Project 三步。

若出错则需要对应报错信息找错。大部分错误是找不到依赖库。

方法二:使用 VS 内置

新建一个空的 VS 项目,文件-打开-CMake,选中 CMakeLists.txt

打开CMake设置-高级-CMake生成器-改为VS2022 Win64

注意点

  1. 请勿新建一个项目,然后将代码文件(.cpp .h等)加入项目,折磨且成功率低
  2. 配置前确认项目可以在win环境生成,如某些依赖库只支持 Linux 系统,需要使用 WSL 生成

字体

YaHei Consolas Hybrid 1.12

Fira Code

命令行参数

项目-属性-配置属性-调试-命令行参数

包含目录出错

无法打开源文件:fstream

包含目录只要有一个错的,后面的包含目录都会出错。

删去不正确的包含目录即可。

Eigen 库使用

svd 分解

Eigen::JacobiSVD<Eigen::Matrix3d> svd(J, Eigen::ComputeFullU| Eigen::ComputeFullV);        Eigen::Matrix3d U = svd.matrixU();
Eigen::Matrix3d S = svd.singularValues();
Eigen::Matrix3d V = svd.matrixV();  //J = U * S * V.T

Learn C++

学习链接:The Cherno的视频系列

C++编程基础

打开debug模式的代码优化:解决方案属性 - C/C++ - 优化 - 最大优化 、 代码生成 - 基本运行时检查 - 默认

输出文件 - 汇编程序输出 - 仅有程序集的列表 (/FA):可在 *.asm 文件查看输出的汇编程序。用这种方法可以查看常量是怎样被优化的。(比如:return 5 * 2 被优化成 mov eax, 10

多行同时输入:alt+鼠标选中位置 或者 alt+shift+方向键

选中当前单词:鼠标双击 或者 ctrl+W

调试 - 窗口 - 内存:查看当前内存的内容。把想查看的变量拖到地址区域。(string 能看到一些有趣的内容)

VS 的输出目录:$(SolutionDir)bin\$(Platform)\$(Configuration)\

VS 多项目 library 使用:解决方案-添加-新建项目(编写lib) 添加附加包含目录 当前项目-添加-引用-选中 library 项目

高级调试:右键添加条件操作,并在输出中查看调试信息。

预编译头:.cpp 属性 - C/C++ - 预编译头 - 创建; 项目属性 - 预编译头 - 使用; 预编译头文件 - .h

VS 编译时间查看:选项 - 项目和解决方案 - 生成计时

C++进阶内容

类中定义的静态变量:就算创建了多个类元素也共享一个存储空间。

C++ 防止创建类的实例:将构造函数写为 private。如 class Log { private:Log(); }; 或将构造函数写为 Log() = delete;

C++ 初始化列表:采用如下写法 Player(const std::string& name) : m_Name(name){} 。这种方法可以避免重复初始化,以及const常量只能这样初始化。

虚函数写法:需要继承的类函数添加 virtual 前缀。纯虚函数:参考视频28

protected : 当前类和派生类可访问到的变量

new 关键词分配的内存:生存周期直到它被 delete 或者程序终止。

static constexpr int size = 5;
int example[size];  // 如果 size 是 const int 会报错

std::string 文档:链接

一些特殊的字符串定义方式:

const wchar_t* chs = L"dhui";
const char16_t* chs2 = u"dhui";
const char32_t* chs3 = U"dhui";
using namespace std::string_literals; //C++14
std::string name0 = "Cherno"s + " hello"; //这种写法允许字符串拼接
const char* name2 = R"(dhui
dhui2)"; //这种写法允许回车

const int 不可以改变指针指向的内存数据。int const 不可以改变指针让它指向其他东西。

mutable 变量:在 const 函数中也可以被更改

explicit 关键字:写在类的构造函数前,不允许隐式类型转换

std::cout << 运算符重载:

std::ostream& operator<<(std::ostream& stream, const Entity& other) {
    stream << other.GetName() << ", " << other.GetAge();
}

智能指针(unique pointer) 与 共享指针(shared pointer) 与 弱指针(weak pointer)

std::unique_ptr<Entity> entity(new Entity());
std::shared_ptr<Entity> shardEntity = std::make_shared<Entity>();
std::weak_ptr<Entity> e0 = shardEntity;

获取类中的变量的offset:(int)&((Vector3*)0)->x;

Templete 写法:template<typename T>

C++ 宏:可让代码在不同配置下执行不同的函数,如只让 Debug 模式输出调试信息。 反斜杠 \ 用于换行。

为类型定义新的名称:

using Devicemap = [type];
typedef [type] Devicemap

auto 关键字:传引用 auto&

函数指针:一种 confusing 的用法

typedef void(*HelloworldFunction)(int); 
HelloworldFunction function = Helloworld;

STL模板库

迭代 vector 元素的方法:for (Vertex& v : vertices); 最好传引用

删除一个 vector 元素:vertices.erase(vertices.begin() + 1);

为 vector 预分配空间 vertices.reserve(3); (有别于resize,之后可以push_back)

使用 vertices.emplace_back(1, 2, 3); 避免类重新被 copy constructor 构建

array: std::array<int,5> data; 可以调用 data.size() 函数。在上开辟内存,而 vector 在上。

Lambda 函数:参考。传入函数可能需要 std::function 。部分代码如下

#include <functional>
void print(int value, const std::function<void(int)>& func) { func(value); }
int a = 5; 
auto lambda = [&](int value) { std::cout << "Value:" << value << "\t a=" << a << std::endl; };
print(9, lambda);

std::find_if 的一个应用示例:

std::vector<int> values = { 1, 5, 4, 2, 3 }; 
auto it = std::find_if(values.begin(), values.end(), [](int value) {return value > 3; });

std::map 与 std::unordered_map:建立两者的关系,类似数组。第一个必须是 hashable 的,如指针,否则要写个 hash 函数。

遍历 std::map :若要有序输出,对于第一个变量要有 operator< 函数重载。视频演示

for (auto& [name, city] : cityMap){}  // C++17
for (auto& kv : cityMap){ kv.first; kv.second; } 

std::thread :分出一个线程干别的事情,并继续后面的代码。

std::thread worker(DoWork);
// Do something
worker.join();

thread_local 关键字:让每个线程中创建一个实例,互不干扰。

计时函数 Chrono

auto start = std::chrono::high_resolution_clock::now();
// Do something
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<float> duration = end - start;
std::cout << "Time = " << duration.count() << std::endl;

或者直接构建结构体,用于计时。在需计时的函数中创建变量 Timer timer; 注意 timer 的生存周期。

struct Timer {
    std::chrono::time_point<std::chrono::steady_clock> start, end;
    std::chrono::duration<float> duration;
    Timer() { 
        start = std::chrono::high_resolution_clock::now(); 
    }
    ~Timer() {
        end = std::chrono::high_resolution_clock::now();
        duration = end - start;
        std::cout << "Timer took = " << duration.count() * 1000.0f << "ms" << std::endl;
    }
};

std::sort 时间复杂度:$O(NlogN)$

static_cast / dynamic_cast :后者会更加安全,涉及类的继承关系时可使用后者。

多返回值: std::tuple / std::pair (后者仅允许双返回值)

std::tuple<std::string, int> person = { "Cherno", 24 }; //初始化
std::string& name = std::get<0>(person); //取元素
std::tie(name, std::ignore) = person; //解包

std::optional (C++17)

std::optional<int> count = {};
if (count.has_value()) {};  // 判断 count 有没有值
int c = count.value_or(100); 

std::variant (C++17)

std::variant<std::string, int> data;
data = "Cherno";
data.index(); // 判断data的类型

std::any (C++17)

std::async 写法较复杂,但可以调试查看每个线程正在执行的任务(调试->窗口->并行堆栈) 视频参考

std::string_view 用于读取string数据,而不用初始化string

benchmarking: 生成 json 文件导入到 chrome://tracing 中, 代码

完结于 2024.6.5,后续教程 (SINGLETON开始) 基本是 C++20 或是更加进阶的 C++ 技巧,需要用到的时候再针对性学习。

]]>
0 https://dhui626.github.io/index.php/archives/24/#comments https://dhui626.github.io/index.php/feed/
Jellyfin 折腾记录 https://dhui626.github.io/index.php/archives/23/ https://dhui626.github.io/index.php/archives/23/ Sat, 28 Oct 2023 16:57:00 +0000 dhui 运行环境:Windows 10 22H2 x64 + Jellyfin Server 10.8.11

介绍

Jellyfin官网 + 文档

查看官网介绍,本应用是一种媒体存储方案,并附加共享功能,可以搭建自己的媒体服务器网络。该应用具有多平台支持,只要有浏览器即可。该软件免费,now and always。

安装

利用 Jellyfin + Bangumi 打造更舒适的动画媒体库

安装后的设置可参考如上文章,笔者在安装结束之后才看到本文。

密码可以留空。

转码设置默认也行,博客作者建议全部勾选。

插件安装:「插件 - 存储库」点击加号,添加如下网址:

https://jellyfin-plugin-bangumi.pages.dev/repository.json

然后在「插件 - 目录 - 元数据」找到 Bangumi 插件安装,重启 Jellyfin

媒体库设置

动画:内容类型选择「节目」

命名规则:将文件名加上 Season 和 Episode 信息。

示例:

Shows
├── Series (2010)
│   ├── Season 00
│   │   ├── Some Special.mkv
│   │   ├── Episode S00E01.mkv
│   │   └── Episode S00E02.mkv
│   ├── Season 01
│   │   ├── Episode S01E01-E02.mkv
│   │   ├── Episode S01E03.mkv
│   │   └── Episode S01E04.mkv
│   └── Season 02
│       ├── Episode S02E01.mkv
│       ├── Episode S02E02.mkv
│       ├── Episode S02E03 Part 1.mkv
│       └── Episode S02E03 Part 2.mkv
└── Series (2018)
    ├── Episode S01E01.mkv
    ├── Episode S01E02.mkv
    ├── Episode S02E01-E02.mkv
    └── Episode S02E03.mkv

重命名教程:

利用 Renamer Pro 的插入 + 序列化功能。

@miracle 的建议:不需要重命名,Jellyfin会自动识别。且若文件夹名和种子文件相同,还可以做种。

但根据测试,季度信息文件夹,如多季度番剧的 S01~S0x 文件夹还是需要创建并拖进相应视频的。

电影:内容类型选择「电影」

三次元电影 bangumi 索引不到,可以提高 tmdb 的优先级。

ass 字幕出现方块字:播放 - 备用字体文件路径

漫画:内容类型选择「照片」

添加相应的文件夹后需要手动扫描媒体库,以获得漫画封面信息。

书籍:内容类型选择「书籍」

能识别 epub 但不能识别 txt 文件,需要手动转换。且 epub 不会生成封面。

音乐:内容类型选择「音乐」

建议按专辑建立文件夹存放。

服务器建立

测试 IPv6 连接

Jellyfin 联网设置中开启 IPv4, IPv6 功能。

如果运气很好,网络环境有公网 IPv4,可以用 http://[IPv4地址]:8096/ 访问。

如果设置得当,网络环境有公网 IPv6,可以用 http://[IPv6地址]:8096/ 访问。

目前大部分网络没有 IPv4,但支持打开 IPv6,需在路由器中设置。

而有些学校的宿舍网络并不支持 IPv6,更别说 IPv4 了,有如下两种解决办法:

  • 使用流量网络(这总支持 IPv6 了吧,不行的话直接 call 运营商总部)
  • 反向代理

反向代理设置教程:

使用 frp:需要有 VPS(没有,遂搁置)

教程:使用frp进行内网穿透 frp 内网穿透神器搭建 萌新也看得懂的教程系列

使用 SakuraFrp

注册登录下载安装,一气呵成。

参考教程:HTTP(S) 协议穿透指南

隧道类型选 TCP,海外节点支持 http 协议,但会经常断线重连,故选择内地节点。

新建穿透隧道 - 输入本地 ip 和端口 - 选择穿透结点(ping一下)- 创建

内地节点 + http 无法正常访问:隧道列表 - 编辑 - 打开自动 HTTPS

Chrome 浏览器会提示连接不安全。

这不对劲,虽然已经实现目标了,但不安全

Jellyfin 开启 https 访问

没有 ssl 证书咋整啊?可以自建。参考

下载 openssl:Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions

若安装步骤中未勾选 Copy OpenSSL DLLs to: The Windows system directory,需要手动添加环境变量。

生成私钥文件

openssl genrsa -des3 -out localhost.key 2048

去除口令

openssl rsa -in localhost.key -out localhost.key

创建请求证书

openssl req -new -key localhost.key -out localhost.csr

生成证书

openssl x509 -req -days 36500 -in localhost.csr -signkey localhost.key -out localhost.crt

这样就生成了三个文件:

localhost.crt
localhost.csr
localhost.key

然后将证书文件转换为 Jellyfin 能读取的 PFX 文件:网站1 网站2

Jellyfin 控制台 - 联网 - 启用 HTTPS + 自定义 SSL证书路径(选择刚才转换完成的 pfx 文件)。

但 Chrome 打开网站还是会显示不安全!但至少能用了。

安全证书颁发方法:使用 Active Directory 证书服务 教程

参考这篇文章?本地安排上HTTPS的最佳途径~ 暂时搁置。

]]>
0 https://dhui626.github.io/index.php/archives/23/#comments https://dhui626.github.io/index.php/feed/
测试数学公式 https://dhui626.github.io/index.php/archives/6/ https://dhui626.github.io/index.php/archives/6/ Sat, 28 Oct 2023 12:49:00 +0000 dhui 行间公式测试:

$$ a + \frac{|ac| \vec{n_1}+|ab| \vec{n_2}}{2 sin\theta} $$

行内公式测试:

其中 $\vec{n_1}$ 和 $\vec{n_2}$ 分别是垂直于 $ab$ 和垂直于 $ac$ 的单位向量,$\theta$ 是 $ab$ 和 $ac$ 的夹角。平移两条垂线组成一个平行四边形易验证外心关系。

]]>
0 https://dhui626.github.io/index.php/archives/6/#comments https://dhui626.github.io/index.php/feed/
个人网站 搭建记录 https://dhui626.github.io/index.php/archives/3/ https://dhui626.github.io/index.php/archives/3/ Thu, 26 Oct 2023 15:11:00 +0000 dhui 个人网站 搭建记录

运行环境:Windows 10 22H2

软件版本:Apache 2.4 + PHP 8.2.12 + MySQL 8.2.0

搭建教程

准备安装 Typecho 进行搭建网页测试。下载下来没有html,诶??? php 是什么啊,打开怎么是源码啊。

此处省略一万字,去学习了静态网页和动态网页的区别。

安装 php 环境

首先安装 php 环境,在 Windows 系统下有集成式安装软件 Wampserver,一键安装。

但是这东西又丑又卡,还不断弹出 cmd 窗口让我觉得是病毒软件,虽然在上面搭建成功了但也反手卸载了。

不如自己动手安装!

参考教程:记一次windows配置PHP环境

难得的优质教程,跟着他的教程来基本没有搜索别的内容了。

1 安装Apache2.4

1.1 Apache 的下载链接 The Apache HTTP Server Project

1.2 点击 a number of third party vendors 下载 windows 版本

1.3 选择 ApacheHaus

1.4 选择 x64 的版本下载

1.5 建立个人主页文件夹 Home,将下载的 apache 解压到其中。

1.6 用记事本打开 conf 中的 httpd.conf,找到如下代码段

Define SRVROOT "/Apache24"
ServerRoot "${SRVROOT}"

将引号内的内容改为 Apache 的路径。

Define SRVROOT "E:/CloudMusic/VSCode/Home/Apache24"
ServerRoot "${SRVROOT}"

1.7 更改端口号

Listen 80

默认端口号是80,浏览器输入 localhost 就能访问,可以改为其他

Listen 9700

1.8 用管理员身份打开 cmd,然后进入 apache 的 bin 路径,用 httpd -k install 进行安装

1.9 安装完成之后在 /Apache24/bin 中打开 ApacheMonitor.exe 并启用服务。

1.10 验证安装,在浏览器输入localhost:9700 如果打开 apache 的首页即为安装成功。

2 安装PHP

2.1 下载 PHP8.2,直接到官网下载即可,笔者选择的版本是 VS16 x64 Thread Safe (2023-Oct-24 21:57:24)

2.2 解压到个人主页文件夹中

2.3 打开PHP的目录将 php.ini-development 先复制一份备份,然后把 php.ini-development 改为 php.ini 保存

2.4 打开 php.ini 修改配置,查找

;extension_dir = "ext"

改为 extension_dir = "ext的目录",比如

extension_dir = "E:/CloudMusic/VSCode/Home/PHP/ext"

2.5 打开 apache/conf 的 httpd.conf,在 DirectoryIndex 后加上 index.php

<IfModule dir_module>
    DirectoryIndex index.html index.php
</IfModule>

2.6 开启 rewrite 功能:将下面这行代码前面的 # 去掉(httpd.conf中)

#LoadModule rewrite_module modules/mod_rewrite.so

2.7 加载PHP模块,在 httpd.conf 中加入以下代码

#php8
LoadModule php_module E:/CloudMusic/VSCode/Home/PHP/php8apache2_4.dll
<IfModule php_module> 
        PHPIniDir "E:/CloudMusic/VSCode/Home/PHP/" 
        AddType application/x-httpd-php .php
        AddType application/x-httpd-php-source .phps
</IfModule>

2.8 验证,注释 apache24/htdocs 中 index.html 的网页代码,输入下边这个输入下边这个 Hello World 代码,然后重命名为 index.php.

<?php
echo"hello world"
?>

在电脑浏览器输入 localhost:9700 , 若能正确显示 hello world , 则 php 网页已经能够显示了。

3 安装mysql

3.1 官网下载链接。笔者选择的是 mysql-8.2.0-winx64.msi

3.2 直接安装的话可能会提示缺少 vs2019 的 redistributable. 到微软官网下载安装 VC_redist.x64.exe

3.3 以管理员身份进入cmd命令行。执行

cd C:\Program Files\MySQL\MySQL Server 8.2\bin
mysqld.exe --install
mysqld --initialize

3.4 在 win+r 之后输入 services.msc 进入本地服务管理,启动 mysql 服务。

3.5 登录需要输入密码。在 C:\Program Files\MySQL\MySQL Server 8.2\data 中后缀名为 err 的文件中找到临时密码,搜索如下字段

A temporary password is generated for root@localhost: &baRyjS-b5mp

3.6 输入 mysql -u root -p 和密码进行登录。登录之后修改密码。

 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';

3.7 输入如下代码创建数据库

create DATABASE home;

4 安装typecho

4.1 进入 /Apache24/htdocs 目录,将 typecho 解压到此处。在浏览器中打开 localhost:9700

4.2 安装提示缺少拓展,需要安装所需拓展。将 php.ini 对应的分号去掉即可。

;extension=mbstring
;extension=openssl
;extension=pdo_mysql

4.3 继续安装,数据库名称填 home,数据库密码填修改后的密码,其余问题不大。

4.4 安装完成后登录控制台,可以进行网页管理等操作。

4.5 第三方主题安装:解压到 /usr/themes ,插件安装:解压到 /usr/plugins ,启用即可。

4.6 若第三方主题启用失败建议查看 github issue 排查问题。

5 网站设置

主题设置可以在 控制台-外观-设置外观 里找到,在此处启用数学公式解析。

设置-基本设置-站点地址,可以更改站点地址。

启用https

如果不关心网站的“不安全”提示,SSL 证书可以暂时不管。

首先登录 Typecho 后台 -> 设置 -> 基本设置 -> 站点地址改成 https 的域名

然后编辑 Typecho 站点根目录下的文件config.inc.php加入下面一行配置。

/** 开启HTTPS */
define('__TYPECHO_SECURE__',true);

然后在站点主题目录下找到comments.php文件,并搜索到$this->commentUrl(),将其修改为:echo str_replace("http","https",$this->commentUrl()),然后点击保存即可。

在开启 https 之后,网站的所有图片外链都需要修改为 https 外链,否则无法正常加载。

内网穿透设置

使用 SakuraFrp,设置本地端口为 443 即可。

在网站未启用 https 的情况下,开启 “强制 https” 会有 bug,会把 http 请求都转换为 https,一些本地的图片资源链接 http://localhost/xxx 也会被强制转换为 https://dhui626.github.io/xxx ,导致无法正常显示。

建议图片外链选择 github.io ,作为免费的图床。

站点地址改成 https://dhui626.github.io 之后,还是会有 bug,在本地能打开网页,但在其他设备打开无法正常显示。需要将站点地址改为内网穿透地址。如笔者的 https://frp-oak.top:56651/。改了之后用 localhost 还是能登陆的,不用担心不小心把内网穿透隧道删除了而再也进不去了的问题。

首页静态Html生成

参考 Typecho生成首页静态HTML数倍提高网站打开速度

在网站根目录创建一个php文件,重命名为static.php

<?php
    $nowtime=time();
    $pastsec = $nowtime - $_GET["t"];
    if($pastsec<600){
      exit; //10分钟更新一次,时间可以自己调整
    }
    ob_start(); //打开缓冲区
    include("index.php");
    $content = ob_get_contents(); //得到缓冲区的内容
    $content .= "\n<script language=javascript src=\"static.php?t=".$nowtime."\"></script>";
    //加上调用更新程序的代码

    file_put_contents("index.html",$content);
    if (!function_exists("file_put_contents")){
      function file_put_contents($fn,$fs){
        $fp=fopen($fn,"w+");
        fputs($fp,$fs);
        fclose($fp);  
      }
    }
?>

设置网站优先打开 index.html 而不是index.php,即可在每次打开 html 提高速度,且会根据设定的时间间隔更新。

全站静态Html生成

参考 typecho全站静态化方案typecho完全静态化

因动态网站部署麻烦,许多站点仅支持静态网站,如 github.io 。本方法可以导出全站的静态html。

创建以下脚本并命名为staticpass.php .

上述参考的代码是 Linux 环境下的代码,笔者已将其转化为 Windows 代码。需要手动安装 wget .

注意 url 是需要爬虫的网页地址,rurl是需要部署静态网页的地址,需要相应修改。

<?php
$url = 'https://dhui626.github.io'; //网址,不能以"/"结尾
$rurl= ''; //要替换成路径或网址,可为空,不能以"/"结尾
$dir = __DIR__ . "/" . str_replace('https://', '', str_replace('http://', "", $url));
exec("cls",$clc);
echo $clc[0];
echo "开始下载文件\r\n";
exec("RMDIR /S /Q {$dir}",$return); //小心调用!
exec("wget --no-check-certificate -r -p -np {$url}",$return);

$dirs = get_filenamesbydir($dir);

//不处理非html文件
for ($i = 0; $i < count($dirs); $i++) {
    $file=str_replace(__DIR__, "", $dirs[$i]['file']);

    if (!preg_match("/html/",$file)  ) {
        //删除对应的元素
        echo "\r\n不处理文件:\r\n";
        echo $file;
        unset($dirs[$i]); 
    }  
}
array_filter($dirs);
sort($dirs);//重新生成索引下标

//网址处理
$count=count($dirs);
for ($i = 0; $i < $count; $i++) {
    // echo $url;
    // echo $rurl;
    $content=str_replace($url,$rurl,file_get_contents($dirs[$i]['file']));
    // echo $dirs[$i]['file'];
    file_put_contents($dirs[$i]['file'],$content);
    $n=$i+1;
    exec("cls",$clc);
    echo $clc[0];
    echo "文件下载完毕\r\n";
    echo "开始处理文件,共{$count}个文件需要处理,已处理{$n}个\r\n";
    
}
echo "处理完毕,文件目录:{$dir}\r\n";

function get_allfiles($path, &$files)
{
    if (is_dir($path)) {
        $dp = dir($path);
        while ($file = $dp->read()) {
            if ($file !== "." && $file !== "..") {
                get_allfiles($path . "/" . $file, $files);
            }
        }
        $dp->close();
    }
    if (is_file($path)) {
        $files[] = ['file' => $path];
    }
}
function get_filenamesbydir($dir)
{
    $files = array();
    get_allfiles($dir, $files);
    return $files;
}

执行

cd E:\CloudMusic\VSCode\Home\Apache24\htdocs
php staticpass.php

注意 "php 绝对目录下的staticpass.php" 代码会在当前目录(如未设置php环境变量就是在php根目录中)创建,而不是站点目录,笔者因为这个愚蠢的问题调试了一个多小时的 bug。

php代码调试

参考 vscode调试php(解决vscode远程调试无效的问题)

但因为静态网站转换的代码无问题,暂时不打算研究 php 调试相关的问题。

参考资料

博客范例参考链接

希卡米 | HiKami:Theme Argon By solstice23

初之音:Powered by Typecho Theme VOID

EdNovas 的小站 :Framework Hexo Theme Butterfly

静态网页模板参考链接(没用上)

FreeHtml5

HTML5 UP

Web开发学习链接

mdn web docs

End

]]>
0 https://dhui626.github.io/index.php/archives/3/#comments https://dhui626.github.io/index.php/feed/
欢迎使用 Typecho https://dhui626.github.io/index.php/archives/1/ https://dhui626.github.io/index.php/archives/1/ Thu, 26 Oct 2023 14:49:00 +0000 dhui 如果您看到这篇文章,表示您的 blog 已经安装成功.

]]>
1 https://dhui626.github.io/index.php/archives/1/#comments https://dhui626.github.io/index.php/feed/