{"id":16443010,"url":"https://github.com/skyzh/raytracer-tutorial","last_synced_at":"2025-06-14T07:02:26.936Z","repository":{"id":39334190,"uuid":"280326668","full_name":"skyzh/raytracer-tutorial","owner":"skyzh","description":"raytracer project for PPCA 2020","archived":false,"fork":false,"pushed_at":"2021-11-20T05:06:29.000Z","size":263,"stargazers_count":63,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-17T21:42:37.638Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skyzh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-17T04:32:44.000Z","updated_at":"2025-02-07T10:37:40.000Z","dependencies_parsed_at":"2022-08-09T14:48:14.011Z","dependency_job_id":null,"html_url":"https://github.com/skyzh/raytracer-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skyzh%2Fraytracer-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skyzh%2Fraytracer-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skyzh%2Fraytracer-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skyzh%2Fraytracer-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skyzh","download_url":"https://codeload.github.com/skyzh/raytracer-tutorial/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244745618,"owners_count":20503042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T09:19:16.103Z","updated_at":"2025-03-21T05:30:29.505Z","avatar_url":"https://github.com/skyzh.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"![banner](https://user-images.githubusercontent.com/4198311/89027545-461dd180-d35d-11ea-9972-7bf1b07f942d.png)\n\n# PPCA raytracer\n\n**UPDATE** 工科 PPCA 已结课。我们在[这里](https://github.com/skyzh/raytracer-tutorial/issues/9)保存了同学们的作品。\n\n**UPDATE** 2021 年的 PPCA raytracer-tutorial 可以在 [aik2mlj/raytracer-tutorial](https://github.com/aik2mlj/raytracer-tutorial) 查看。\n\nWelcome! 你可以直接点击右上角的“Use this template”将这个项目复制到自己的 GitHub Profile 中。接下来，你需要做一些准备工作。\n\n## Task 0: Preparation\n\n* 在 `Cargo.toml` 中，修改作者信息。\n* 在 `LICENSE` 中，将作者修改为自己。你也可以换成其他许可证。\n* 使用 [rustup 安装 Rust](https://doc.rust-lang.org/book/ch01-01-installation.html)。如果下载速度很慢，可以考虑使用 [SJTUG Mirror](https://mirrors.sjtug.sjtu.edu.cn) 的 rust-static 和 crates.io 镜像。\n* 之后，你需要安装一些工具。首先，你需要定位到项目目录。而后，运行 `rustup component add clippy rustfmt`\n* 接着，运行 `make ci`。如果程序可以正常运行，那么环境就已经配置成功了。\n* 将这些更改 push 到 GitHub 上。在 GitHub Action 中，“Lint and Test”和“Build and Upload”都应当通过。\n* 程序生成的结果会出现在 GitHub Action 的 artifacts 中。output 文件夹下的内容应当是程序运行时生成的。\n  对 output 文件夹的修改不应该被同步到 GitHub 上（这个文件夹在 `.gitignore` 中有设置，会被 git 忽略）。\n* 最后，你可以把 README.md 的教程部分删除，换成自己程序的描述、运行方法等信息。\n\n## Task 1: Ray-tracer From Scratch\n\nTA Wenxin Zheng 会有更详细的说明。\n\n## Task 2: Advanced Ray-tracer\n\n在完成 Cornell Box 的重要性采样渲染后，你可以挑选下面的任务完成。（8选3，8月5日上午及之前完成的内容不算。）\n\n* **Track 1: New Features** 完成 Rest of Your Life 的剩余部分，重构代码并渲染带玻璃球的 Cornell Box。\n* **Track 2: More Features** 完成 Next Week 中除 Motion Blur 外的部分，渲染噪点较少的最终场景。\n* **Track 3: Reduce Contention** 此项工作的前提条件是完成多线程渲染。在多线程环境中，clone / drop Arc 可能会导致性能下降。因此，我们要尽量减少 Arc 的使用。这项任务的目标是，仅在线程创建的时候 clone Arc；其他地方不出现 Arc，将 Arc 改为引用。\n* **Track 4: Static Dispatch** 调用 `Box\u003cdyn trait\u003e` / `Arc\u003cdyn trait\u003e` / `\u0026dyn trait` 中的函数时会产生额外的开销。我们可以通过泛型来解决这个问题。\n  * 这个任务的目标是，通过定义新的泛型材质、变换和物体，比如 `LambertianStatic\u003cT\u003e`，并在场景中使用他们，从而减少动态调用的开销。你也可以另开一个模块定义和之前的材质同名的 struct。\n  * 你可以在 `material.rs` 里找到泛型的相关用法。\n  * 仅在 `HitRecord`, `ScatterRecord` (这个在 Rest of Your Life 的剩余部分中出现), `HittableList` 和 `BVHNode` 中使用 `dyn`。\n  * 如果感兴趣，可以探索如何使用 `macro_rules` 来减少几乎相同的代码写两遍的冗余。\n* **Track 5: Code Generation** 此项工作的前提条件是完成 BVH。\n  * 目前，`BVHNode` 是在运行时构造的。这个过程其实可以在编译期完成。我们可以通过过程宏生成所有的物体，并构造静态的 `BVHNode`，从而提升渲染效率。\n  * 为了使用过程宏，在这个工程中，我们已经重新组织了目录结构。请参考[这个 PR](https://github.com/skyzh/raytracer-tutorial/pull/14)进行修改。\n  * 你可以使用 `cargo expand` 来查看过程宏处理过后的代码。你也可以在编译过程中直接输出过程宏生成的代码。\n  * `codegen` 部分不需要通过 clippy。\n  * 如果感兴趣，你也可以探索给过程宏传参的方法。e.g. 通过 `make_spheres_impl! { 100 }` 生成可以产生 100 个球的函数。\n* **Track 6: PDF Static Dispatch** 此项工作的前提条件是完成 Rest of your Life 的剩余部分。PDF 中需要处理的物体使用泛型完成，去除代码路径中的 `\u0026dyn`。\n* **Track 7: More Code Generation** 在过程宏中，读取文件，直接从 yaml 或 JSON 文件（选择一种即可）生成场景对应的程序。\n  * 在 `data` 文件夹中给出了一些例子。\n  * 例子中 `BVHNode` 里的 `bounding_box` 是冗余数据。你可以不使用这个数据。\n  * 读 JSON / yaml 可以调包。\n* **Track 8: Advanced Features** 增加对 Transform 的 PDF 支持。\n* 如果你有多余的时间，你可以通过 benchmark 来测试实现功能前后的区别。\n  * 完成 Track 3 前请备份代码 (比如记录 git 的 commit id)。完成 Track 4, 5, 6 时请保留原先的场景和程序，在此基础上添加新的内容。\n  * 你可以使用 `criterion` crate 做 benchmark。benchmark 的内容可以是往构造好的场景中随机打光线，记录打一条光线所需的时间。\n\n## More Information\n\n### Makefile\n\n`Makefile` 中包含了运行 raytracer 的常用指令。如果没有安装 `make`，你也可以直接运行 `cargo balahbalah`。\n\n* `make fmt` 会自动格式化所有的 Rust 代码。\n* `make clippy` 会对代码风格做进一步约束。\n* `make test` 会运行程序中的单元测试。你编写的 `Vec3` 需要通过所有测试。\n* `make run_release` 会运行优化后的程序。通常来说，你需要用这个选项运行 raytracer。否则，渲染会非常慢。\n* `make run` 以 debug 模式运行程序。\n* `make ci` = `fmt + clippy + test + run_release`。建议在把代码 push 到远程仓库之前运行一下 `make ci`。\n\n### GitHub Action\n\n这个仓库已经配置好了 GitHub Action。只要把代码 push 到远程仓库，GitHub 就会进行下面两个检查。\n\n* **Lint and Test** 会运行所有单元测试，并检查代码风格。\n* **Build and Upload** 会运行优化后的程序，并将 output 目录下生成的文件传到 build artifacts 中。\n\n## Reference\n\n* [The Rust Programming Language](https://doc.rust-lang.org/book/title-page.html) \n  * 通常来说，你只需要用到前 6 章和第 10.2 节的内容。\n  * 如果碰到了 lifetime 相关的问题，请仔细阅读第 4 章，特别是 4.2 的例子。\n  * 当然，你也可以通过第 15 章中的智能指针解决一部分 lifetime 导致的问题。\n  * Rust 的面向对象特性（trait，对应 C++ 的类）可以在 10.2 中找到。\n  * 如果你希望编写一个多线程的渲染器，可以阅读第 15、16 章的内容。\n* [rustlings](https://github.com/rust-lang/rustlings) 包含许多 Rust 小练习。如果你希望通过练习来学习 Rust 语言，可以尝试一下这个参考资料。\n* [Ray Tracing in One Weekend](https://raytracing.github.io/books/RayTracingInOneWeekend.html)\n* 过程宏相关\n  * [Procedural Macros](https://doc.rust-lang.org/reference/procedural-macros.html) (关注 Function-like procedural macros 即可)\n  * [quote crate](https://crates.io/crates/quote)\n* JSON / yaml 读取\n  * [serde-json](https://docs.serde.rs/serde_json/)，只需要关注其中的 untyped 部分。\n  * [yaml-rust](https://docs.rs/yaml-rust/0.4.4/yaml_rust/)\n  * 通常来说，你并不需要使用到下面这个序列化/反序列化的包。\n  * [serde](https://serde.rs)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskyzh%2Fraytracer-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskyzh%2Fraytracer-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskyzh%2Fraytracer-tutorial/lists"}