LLGL Low-Level Graphics Abstraction Library

repository·master·Indexed 25 days ago

https://github.com/lukasbanana/llgl

A high-performance, thin graphics abstraction library providing a unified interface for modern APIs (Vulkan, D3D12, Metal) and legacy APIs (OpenGL, D3D11). LLGL supports desktop, mobile, and web platforms, including Windows, macOS, iOS, Android, and WebAssembly. It features a C99 wrapper for language bindings, C# support, and integration capabilities with Dear ImGui.

Tokens
30.5K
Snippets
80
Records
166
Agent score
83%

What's inside LLGL

  1. Overview of LLGL capabilities and language support

    master

    LLGL (Low Level Graphics Library) is a thin abstraction layer for modern and legacy rendering APIs across desktop and mobile platforms. It provides close coupling with underlying APIs to maintain a rich feature set while simplifying architectural hurdles.

    Supported Languages:

    • C++11 (Primary)
    • C99
    • C# 6.0
    • Go
    • WebGL
  2. Explore C99 LLGL examples

    master

    The examples/C99 directory contains several reference implementations for using LLGL in ISO-C99:

    • Hello Triangle: A basic example illustrating fundamental interaction with the LLGL API in C.
    • Texturing: Demonstrates image loading from file (utilizing the STB library), indexed-drawing, and management of dynamic resources.
    • Offscreen: Demonstrates offscreen rendering where the output is rendered into a texture and saved to disk instead of being displayed on the screen.
  3. LLGL C++ Tutorials and Examples Overview

    master

    The LLGL repository includes several tutorials and examples covering core graphics concepts:

    Tutorials

    • Hello Triangle: A getting started tutorial for rendering a single multi-colored triangle.
    • Tessellation: Demonstrates hardware tessellation for high-detail geometry.
    • ImGui Integration: A guide on how to integrate ImGui into an LLGL project for UI rendering and event handling.

    Advanced Examples

    • Texturing: Simple texturing and sampler state usage.
    • Fonts: Efficient font rendering using batched draw calls.
    • Queries: Using Query objects and conditional rendering for occlusion culling.
    • Render Target: Using render targets with optional multi-sample textures (Texture2DMS/sampler2DMS).
    • Multi Context: Demonstrates multiple render contexts (one per window), simultaneous rendering into multiple viewports, and geometry shaders.
    • Indirect Draw: Uses a compute shader and a storage buffer for indirect draw commands.
    • Instancing: Hardware instancing for rendering large numbers of textured instances.
    • Post-Processing: Implementing glow effects using shaders, render targets, and graphics pipelines.
    • Shadow Mapping: Standard shadow-mapping techniques.
    • Stencil Buffer: Using the stencil buffer for effects like portal rendering.
    • Volume Rendering: Generating Perlin noise into 3D textures for volume rendering.
    • Cloth Physics: Using multiple compute shaders for position-based dynamics.
    • OpenXR: A small VR application example using OpenXR.
  4. Run LLGL C++ Examples

    master

    To run the C++ examples provided in the repository, you must set the working directory of your executable to the specific example folder.

    For example, if your LLGL repository is located at /Users/JohnDoe/LLGL, the working directory for the HelloTriangle example should be set to: /Users/JohnDoe/LLGL/examples/Cpp/HelloTriangle.

  5. Create Pipeline States without ShaderProgram (v0.03 migration)

    master

    In version 0.03, the ShaderProgram interface was removed. Instead of creating a shader program and then a pipeline state, you now provide individual shaders directly to the GraphicsPipelineDescriptor and create the pipeline state using CreatePipelineState. Error reporting is now handled via the GetReport() method on the PipelineState object.

    // Usage:
    LLGL::GraphicsPipelineDescriptor myPSODesc;
    myPSODesc.pipelineLayout = myPipelineLayout;
    myPSODesc.renderPass = mySwapChain->GetRenderPass();
    myPSODesc.vertexShader = myVertexShader;
    myPSODesc.fragmentShader = myFragmentShader;
    LLGL::PipelineState* myGraphicsPSO = myRenderer->CreatePipelineState(myPSODesc);
    if (const LLGL::Report* myReport = myGraphicsPSO->GetReport())
    {
        if (myReport->HasErrors())
            std::cerr << myReport->GetText() << std::endl;
    }
  6. Integrate Dear ImGui with LLGL

    master

    To integrate Dear ImGui into an LLGL application, you must bridge the LLGL abstraction layer with the underlying rendering API (e.g., Direct3D 11) by extracting native handles.

    Note: This tutorial is for Microsoft Windows using Direct3D 11. For a more modern example, refer to the LLGL-Example-ImGui repository.

    Setup Steps:

    1. ImGui Source: Download the ImGui source from GitHub and include the main source files and the backend files for your specific rendering API (e.g., imgui_impl_dx11.cpp/.h and imgui_impl_win32.cpp/.h for D3D11 on Windows).
    2. LLGL Headers: Include <LLGL/LLGL.h>, <LLGL/Platform/LLGL.h>, and the backend-specific native handle header (e.g., <LLGL/Backend/Direct3D11/NativeHandle.h>).
    3. Linking: Link your project against LLGL.dll. Ensure the backend DLL (e.g., LLGL_Direct3D11.dll) is in the same directory as your executable. For debug builds, use LLGLD.dll and LLGL_Direct3D11D.dll.
  7. Handle Binding Model changes and ResetResourceSlots (v0.04)

    master

    The LLGL binding model is now fully abstracted; binding slots are defined exclusively in the PipelineLayout.

    • ResetResourceSlots is deprecated: You can simply remove calls to this function.
    • Automatic Unbinding: For the D3D11 backend, LLGL now automatically manages unbinding resources to prevent overlapping read-only and read-write resource views, making manual resets unnecessary.
  8. Perform Shader Reflection (v0.03 migration)

    master

    In version 0.03, shader reflection has been updated. The ShaderReflectionDescriptor and its nested types have been renamed and moved to the LLGL namespace. Specifically:

    • ShaderReflectionDescriptor $\rightarrow$ LLGL::ShaderReflection
    • ShaderReflectionDescriptor::ResourceView $\rightarrow$ LLGL::ShaderResource
    • ShaderReflectionDescriptor::Uniform $\rightarrow$ LLGL::ShaderUniform

    Binding attributes in ShaderResource are now contained within a BindingDescriptor structure. Reflection no longer throws exceptions; instead, Shader::Reflect returns a bool indicating success.

    LLGL::ShaderReflection reflection;
    if (myShader->Reflect(reflection)) {
        /* Evaluate ... */
    } else {
        /* Error ... */
    }
  9. Render tessellated geometry

    master

    When rendering tessellated geometry using an index buffer:

    1. Clear Buffers: Use myCmdBuffer->Clear(LLGL::ClearFlags::ColorDepth) to clear both color and depth buffers simultaneously.
    2. Bind Resources: Bind your vertex buffer, index buffer, and the ResourceHeap associated with your pipeline.
    3. Draw: Use DrawIndexed instead of Draw. The number of indices must account for all control points in the patches (e.g., 6 patches with 4 control points each requires 24 indices).
    myCmdBuffer->Clear(LLGL::ClearFlags::ColorDepth);
    
    myCmdBuffer->SetVertexBuffer(*myVertexBuffer);
    myCmdBuffer->SetIndexBuffer(*myIndexBuffer);
    myCmdBuffer->SetResourceHeap(*myResourceHeap);
    
    // Draw 6 patches with 4 control points each (24 indices)
    myCmdBuffer->DrawIndexed(24, 0);
  10. Implement a custom renderer using Backend include files

    master

    To implement your own renderer interface in LLGL, use the provided backend include files (*.inl). These files contain the declarations for all required functions for a specific interface. You must include the relevant .inl file inside your class definition to satisfy the interface requirements.

    Note: These headers are only required when implementing a custom backend; they are not needed for standard LLGL usage.

    #include <LLGL/CommandBuffer.h>
    
    class MyOwnRenderer : public LLGL::CommandBuffer {
    public:
        #include <LLGL/Backend/CommandBuffer.inl>
    public:
        MyOwnRenderer();
        ~MyOwnRenderer();
    private:
        MyRendererData privateData;
    };