#Tempest Render Engine (Vulkan 1.3 Render Engine)

1 messages · Page 1 of 1 (latest)

void swift
#

Currently working on a rendering engine to try out various rendering techniques.
Implemented:

  • Buffers
  • Images, Image Views, Samplers
  • Graphics and Compute Shaders
  • Multidraw Indirect
  • Texture and Model Loading (GLTF)
  • ImGUI Integration
#

Currently, trying to work on some water rendering techniques. This is a really early test of some of the abstraction, but the mesh is completely generated in the shader (no vertex buffers needed). Next goals are going to be passing in wave descriptions to do vertex position deformation. Color above is determined by fmod by 1.0 of the time since start.

#
auto state_upload_pass = rgc->add_graph_pass(
    "sim_state_upload", graphics::queue_operation_type::TRANSFER, [&](graphics::graph_pass_builder& bldr) {
        bldr.add_transfer_source_buffer(graphics_device.get_staging_buffer())
            .add_transfer_destination_buffer(wave_data_buffer)
            .on_execute([&](graphics::command_list& cmds) {
                auto sb_ptr = graphics_device.map_buffer_frame(graphics_device.get_staging_buffer());
                std::memcpy(sb_ptr.data(), &sim_state, sizeof(water_sim_state));
                graphics_device.unmap_buffer(graphics_device.get_staging_buffer());
                cmds.copy(graphics_device.get_staging_buffer(), wave_data_buffer, 0, graphics_device.get_buffer_frame_offset(wave_data_buffer, 0));
            });
    });

auto water_sim_pass = rgc->add_graph_pass(
    "water_sim_pass", graphics::queue_operation_type::GRAPHICS, [&](graphics::graph_pass_builder& bldr) {
        bldr.add_color_attachment(color_buffer, graphics::resource_access_type::WRITE, graphics::load_op::CLEAR,
                                    graphics::store_op::STORE, math::vec4<float>(0.0f))
            .add_depth_attachment(depth_buffer, graphics::resource_access_type::READ_WRITE,
                                    graphics::load_op::CLEAR, graphics::store_op::STORE, 1.0f)
            .add_constant_buffer(camera_data_buffer, 0, 0)
            .add_constant_buffer(lighting_data_buffer, 0, 1)
            .add_constant_buffer(wave_data_buffer, 0, 2)
            .depends_on(state_upload_pass)
            .on_execute([&](graphics::command_list& cmds) {
                cmds.set_viewport(0, 0, 1920, 1080)
                    .set_scissor_region(0, 0, 1920, 1080)
                    .use_pipeline(water_pipeline)
                    .draw(8 * 8 * 6);
            });
    });

auto blit_pass =
    rgc->add_graph_pass("swapchain_target_blit_pass", graphics::queue_operation_type::GRAPHICS_AND_TRANSFER,
                        [&](graphics::graph_pass_builder& bldr) {
                            bldr.add_blit_source(color_buffer)
                                .add_external_blit_target(swapchain)
                                .depends_on(water_sim_pass)
                                .on_execute([&](graphics::command_list& cmds) {
                                    cmds.blit(color_buffer, graphics_device.fetch_current_image(swapchain));
                                });
                        });
void swift
void swift
#

For some more context, the periodicity seen here is because this is till using sine waves with FBM. Techniques like this are fine for smaller water sources, but you're going to notice the tiling for large sources quickly. My next steps will be to use FFTs to implement a technique more suitable for large water sources.

void swift
#

Okay, I think before I implemented FFT based water, I'm going to work on implementing ImGUI

void swift
#

Updates! Got ImGUI integrated with this, and now I can tweak parameters on the fly. 256 wave FBM, 2m triangles, running at ~150fps typically (RTX 3090)

void swift
#

Post Christmas Update: I'm currently integrating compute shaders into the render graph. It's going smoothly, and I'll be using them as a test platform for working on an FFT shader for oceans

void swift
#

Working on generating noise for the initial state of the FFT water. This is noise + complex conjugate generated in a compute shader. This will be consumed statically by further steps in the pipeline to generate wave movement and heights

void swift
#

I need to do some mip chain generation on the textures, but it's all there 🙂

void swift
#

Runtime mipmap generation, sponza loading (no lighting, just base textures)

real vortex
#

GET THEE BACK INTO THE TEMPEST AND THE NIGHT'S PLUTONIAN SHORE

void swift
#

PBR sponza

void swift
#

Updates since last post (measurements on RTX 3090 and Intel 10900KF):

  • Implemented a z pre pass (2800 -> 3600 fps)
  • Utilized a dedicated index buffer instead of using a single SSBO for indices and vertices (3600 -> 4000 fps)

Potential Directions for Investigation:

  • Use the same buffer for SSBO (for vertices) and Index Buffer. This would potentially allow memory reads to be more local
void swift
#

Better PBR, merged SSBO and IBO. No improvements to performance.

void swift
#

Update: SSAO

void swift
#

I've significantly simplified the user-code abstractions I present. I can now present sponza with this:

#include <tempest/tempest.hpp>

int main()
{
    auto eng = tempest::engine::initialize();

    auto [win, input_group] = eng.add_window(tempest::graphics::window_factory::create({
        .title = "Tempest",
        .width = 1920,
        .height = 1080,
    }));

    auto camera = eng.get_registry().acquire_entity();
    eng.get_registry().assign(camera, tempest::graphics::camera_component{});

    eng.on_initialize([](tempest::engine& eng) {
        auto sponza = eng.load_asset("assets/glTF-Sample-Assets/Models/Sponza/glTF/Sponza.gltf");
    });

    eng.run();

    return 0;
}
void swift
#

No transmission yet, but progress is getting made on the rendering

void swift
#

Made some progress today:

  • Burley BRDF implemented
  • Emissive texture support
void swift
#

Taking some time to discuss what I've done since the last screenshot:

  • Z Pre Pass - Forward pass to write out a z buffer of opaque and masked geometry to reduce overdraw in future passes. This is also writing out a geometry normal texture for usage in post processing effects later.
  • Hierarchical Z Buffer - Compute shader that consumes the depth buffer built by the depth pre pass to build a mipmapped version of the depth buffer. I plan to use this when implementing TAA and other post processing effects that require depth buffer access.
void swift
#

TAA has been implemented

void swift
#

Doing some editor work

void swift
#

Working a bit on timings and measurement

void swift
void swift
#

Continued work on asset loading and the editor

void swift
#

CSMs with hard edges

#

Only had to add one thing to my abstraction: A mechanism to expose push constants (though I could have just used UBOs instead, this felt more applicable and a good reason to expose them)

void swift
#

Tonemapping

#

I'm no longer blind looking at it

hasty mirage
#

looks sick

void swift
#

I need to get some GI up and going. That'll make it look significantly better