最近准备抽空研究下图形中的光照渲染,先做一个小的demo,然后慢慢加不同的效果
文章来源于 learnOpenGL ,是一个非常好的教程
这篇文章的意义在于将整个过程中的关键点以及遇到的错误心得汇总并记录
UI
这里使用了 Dear Imgui 作为显示组件,用来动态改变渲染的效果,其使用也非常简单,直接将相关的 .h 和 .cpp 文件添加即可,GitHub 上有详细介绍。
当前设置如下:
- rotation 改变模型沿着 y 轴的旋转
- position 改变模型在 x,y 轴上的位移
- scale 改变模型的缩放
- color 用来简单地对模型混合颜色
- rate 控制混合比例
需要的设置 - 设置 imgui 上下文,渲染风格,设置平台并渲染绑定
- 在渲染循环中将渲染 gui,添加需要的组件,赋值
- 将 ui 上的值作为 uniform 传入 shader 中即可
示例如下:
/* imgui 初始化 */
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
const char* glsl_version = "#version 460";
ImGui_ImplOpenGL3_Init(glsl_version);
/* imgui 初始化结束 */
/* 渲染循环 */
while() {
// 将输入给imgui,并开始新的一帧
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
......
// 设置 imgui 的控件
ImGui::Begin("Operations");
static float rate = 0.0;
ImGui::SliderFloat("rate", &rate, 0.0, 1.0);
ImGui::End();
......
shader.setFloat("rate", rate);
......
// 将gui渲染到平面上
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
// 释放imgui的资源
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
transform
这里需要注意的就是矩阵运算的顺序
位移矩阵 · 旋转矩阵 · 缩放矩阵 · 位置
其原因在于如果先计算位移矩阵,在其他矩阵的作用下,位移向量被改变,无法得到正确的组合效果。
例如
当最后计算位移矩阵时,改变 x 轴方向的值效果如下,可以看到模型在世界坐标水平方向上正确的移动(还没加光照,所以黑乎乎的)
但如果将平移矩阵和旋转矩阵交换顺序,模型的平移就会在旋转的基础上进行,就是局部坐标系下的平移
模型
模型加载一直是关键步骤,如果有时间还是建议自己实现下 obj 格式的读写,会有很大帮助。
由于模型不是关注的重点,这里直接使用 assimp 库来用于模型的加载, 其格式如下。
由于 mesh 中包含了渲染所有的数据,所以节点直接以 mesh 为单位存储,这样也可以方便后期动画的生成。
为了方便使用,需要将 assimp 的模型数据转换为我们定义的 mesh 格式,这一步 learnopengl 中提供了详细的源码。
在这个过程中遇到了一个 cmake 问题,编译后只能找到 .lib 文件,无法找到 .dll 文件,如果有知道原因的希望在评论区留言
笔记
- 图片长宽需要是2的幂才行,不然 stb_image 会报错
- 如果三个维度的缩放系数相同时,缩放矩阵和旋转矩阵顺序可以互换