Jet README

The project's README from github.com/CubeCoders/Jet. As one markdown file: README.md.

Jet logo

Jet

Jet is a dependency-free, fixed-function 3D software rasteriser written in C++17. It targets embedded hardware with limited CPU and memory, including ESP32 and STM32, and also runs on desktop PCs and Raspberry Pi.

Jet uses integer arithmetic in the rasterisation hot path and native 16-bit RGB565 colour for output to embedded displays. It supports flat-shaded, lit and textured geometry for low-poly games and visualisations.

On an ESP32-S3, Jet reaches a peak throughput of 70,000 triangles/second (flat-shaded). The demo below runs at a 480×320 output resolution and 60 FPS using half-width, interlaced field buffers. Throughput varies with scene complexity, triangle size and enabled rendering features.

Community

Share projects and get help on the Discord server.

Demo

A Wipeout-style game running on an ESP32-S3 at 60 FPS:

Jet on ESP32-S3: 60 FPS Wipeout-style demo

Feature highlights

Compile-time switches in JetConfig.hpp let you disable features to reduce CPU, RAM and flash usage. See src/JetConfig.example.hpp for the available options.

Rendering

Lighting

Post-FX

Tooling

2D Sprites

Sprite2D draws overlays after render(). It supports textured or solid-colour fills, colour-key transparency, alpha and additive blending, integer upscaling, and zOrder-based draw order. On HALF_WIDTH_BUFFERS builds, sprites are composited at full output resolution during display scanout.

Particles

ParticleSystem uses a fixed pool and renders through the rasteriser after scene->render(). It includes spark and water-splash emitters, distance culling, and configurable emitter counts and particle lifetimes.

Lens flare

LensFlare projects a directional light source to screen space and positions a sprite chain along the axis between the sun and screen centre. Fade speed, per-element axis offset (axisT), alpha, blend mode and integer scale are configurable. It can use a pick slot for sun occlusion testing; with MAX_PICK_QUERIES = 0, the sun is treated as unobstructed.

Getting started

Your application provides the framebuffer, display driver and main loop. Add Jet as a CMake subdirectory or ESP-IDF component, provide a JetConfig.hpp on your include path (copy and customise src/JetConfig.example.hpp), then call scene->render() once per frame.

For ESP-IDF, depend on it as you would any other component:

# main/idf_component.yml
dependencies:
  jet: "*"

Minimal example

Allocate colour and depth buffers, add a camera, lights and a cube, then render each frame:

#include "Jet.hpp"
using namespace Renderer;

// 320x240 RGB565 colour buffer + matching Z-buffer.
constexpr int W = 320, H = 240;
uint16_t color[W * H];
uint16_t depth[ZBUFFER_STRIDE(W) * H];

int main() {
    Scene  scene(color, depth, W, H);
    scene.setBackcolor(0x0000);          // RGB565 clear colour (black)
    scene.setClearBuffer(true);

    Camera camera;
    camera.setPosition(0, 0, -500);      // world units
    camera.setFOV(75, W);
    camera.nearPlane = 16;
    camera.farPlane  = 8192;
    scene.setCamera(&camera);

    DirectionalLight sun(Vector3{45, 35, 0}, Color{255, 245, 220}, 220);
    AmbientLight     amb(Color{40, 48, 64});
    scene.setDirectionalLight(&sun);
    scene.setAmbientLight(&amb);

    Material red(0xF800);                // RGB565: bright red
    red.shadingMode = ShadingMode::GOURAUD;

    Object* cube = Primitives::createCube(200, 200, 200, &red);
    cube->setPosition(0, 0, 200);
    scene.addObject(cube);

    // Per-frame: rotate, render, push the buffer to your display.
    for (;;) {
        cube->rotate(0, 1, 0);           // 1 degree per frame around Y
        scene.render();                  // colour buffer now contains the frame
        // pushToDisplay(color, W, H);   // <-- you provide this
    }
}

Documentation

The API reference is generated from the Doxygen comments in src/.

To build the docs locally (requires doxygen and optionally graphviz):

cd components/Jet/src
doxygen Doxyfile
# output: components/Jet/src/docs/html/index.html

GitHub Actions publishes the documentation on pushes to the default branch.

Licensing

Jet is distributed under the MIT License. The full text is in LICENSE.

You can use, modify and distribute Jet in open-source or closed-source projects, including commercial products, without a separate licence or fee. Include the copyright and permission notices as required by the MIT License.

Contributing

Submit bug reports, fixes, examples and documentation improvements through issues or pull requests on the official repository.

Before your first contribution, please read CONTRIBUTING.md. Contributions are accepted under the MIT License; no separate Contributor Licence Agreement is required.


Jet is a CubeCoders project.

Jet (CubeCoders/Jet)

Searching Database…

531 ·GitHub
这是什么?Jet 是一个用 C++17 编写的、无任何依赖的固定功能 3D 软件光栅化器,体积很小,专为 ESP32、STM32 这类 CPU 和内存都很有限的嵌入式芯片打造;它也能在台式电脑和树莓派上运行。
它是一个现成的游戏引擎,还是一个让我自己搭建渲染器的库?它是一个库,不是引擎:由你的应用提供帧缓冲、显示驱动和主循环,每帧只需要调用 scene->render() 来绘制场景。
怎么把它加到我的项目里?把 Jet 作为 CMake 子目录或 ESP-IDF 组件添加进来,把 src/JetConfig.example.hpp 复制到 include 路径下的 JetConfig.hpp 并按需修改,然后在你自己的循环里调用 scene->render()。
有什么限制——它能取代 GPU 吗?不能——Jet 是在 CPU 上通过固定功能管线渲染的,没有任何硬件加速,所以实际性能取决于场景复杂度、三角形大小以及你开启了哪些功能。
我可以在商业项目里使用它吗?可以——Jet 采用 MIT 许可证,无论开源还是闭源项目(包括商业产品)都可以使用,不需要额外授权或付费;只要保留版权和许可声明即可。
为什么用整数运算和 16 位 RGB565,而不用浮点数?因为目标是微控制器和小型嵌入式屏幕:Jet 在光栅化的核心路径中采用整数运算,并直接输出原生的 16 位 RGB565,这正好契合 ESP32 这类芯片有限的 CPU 和内存。
支持后期处理效果吗?支持——CRT 扫描线和卡通着色不需要额外的缓冲就能运行,而 FXAA、泛光(bloom)、运动模糊、色差和像素化则作为需要缓冲的效果,供内存较充裕的目标平台使用。
管线是完全固定的吗,还是我可以添加自己的效果?它是固定功能管线,但提供了自定义着色器入口点用于扩展管线,还有一些特殊模式,比如用于动态水面的 WATERREFLECT,以及用于霓虹灯招牌和爆炸光晕的 ADDITIVE。
能不能把它精简一下,用在特别小的设备上?可以——JetConfig.hpp 里的编译期开关让你可以关闭某些功能,以减少 CPU、内存和 flash 的占用;把 src/JetConfig.example.hpp 复制一份,关掉你的板子负担不起的功能即可。
What are similar projects?NoGraphicsAPI, Marlin, bgfx, raylib, mongoose, coyopedal, assimp, WoWee
Creator
CubeCoders
Size
8.2 MB
Stars
531
Updated
CommitSep 25
Age
5mo
Commits · 90 Days