Yocto/GL: Tiny C++ Libraries for Data-Driven Physically-based Graphics

Yocto/GL: Tiny C++ Libraries for Data-Oriented Physically-based Graphics

windows build badge macos build badge ubuntu build badge

Yocto/GL is a collection of small C++17 libraries for building physically-based graphics algorithms released under the MIT license. Yocto/GL is written in a deliberately data-oriented style for ease of development and use. Yocto/GL is split into small libraries to make code navigation easier. See each header file for documentation.

  • yocto/yocto_math.{h}: fixed-size vectors, matrices, rigid frames, rays, bounding boxes, transforms
  • yocto/yocto_color.{h}: color conversion, color adjustment, tone mapping functions, Perlin noise, shading and integration utilities
  • yocto/yocto_geometry.{h}: geometry functions, ray-primitive intersection, point-primitive overlap
  • yocto/yocto_noise.{h}: Perlin noise
  • yocto/yocto_sampling.{h}: random number generation, generation of points and directions, Monte Carlo utilities
  • yocto/yocto_shading.{h}: evaluation and sampling of fresnel functions, bsdf lobes, transmittance lobes, phase functions
  • yocto/yocto_shape.{h,cpp}: various utilities for manipulating triangle meshes, quads meshes and line sets, computation of normals and tangents, linear and Catmull-Clark subdivision, mesh loading and saving, procedural shapes generation, ray intersection and closest point queries
  • yocto/yocto_mesh.{h,cpp}: computational geometry utilities for triangle meshes, mesh geodesic, mesh cutting, mesh loading and saving
  • yocto/yocto_bvh.{h,cpp}: ray intersection and closest point queries of triangle meshes, quads meshes, line sets and instances scenes using a two-level bounding volume hierarchy
  • yocto/yocto_image.{h,cpp}: simple image data type, image resizing, tone mapping, color correction, image loading and saving, procedural images, procedural sun-sky, advanced color conversion utilities
  • yocto/yocto_sceneio.{h,cpp}: simple scene and scene loading and saving of Ply/Obj/Pbrt/glTF and a custom and scalable Json format
  • yocto/yocto_trace.{h,cpp}: path tracing of surfaces and hairs supporting area and environment illumination, microfacet GGX and subsurface scattering, multiple importance sampling
  • yocto/yocto_modelio.{h,cpp}: parsing and writing for Ply/Obj/Pbrt formats
  • yocto/yocto_commonio.h: printing utilities, file io utilities, command line parsing
  • yocto/yocto_json.h: JSON data type, json io utilities, command line parsing
  • yocto/yocto_common.h: container and iterator utilities
  • yocto/yocto_parallel.h: concurrency utilities

You can see Yocto/GL in action in the following applications written to test the library:

  • apps/yscenetrace.cpp: command-line path-tracer
  • apps/ysceneitrace.cpp: interactive path-tracer
  • apps/ysceneitraces.cpp: simpler version of apps/ysceneitrace.cpp for demos
  • apps/ysceneproc.cpp: command-line scene manipulation and conversion
  • apps/yshapeproc.cpp: command-line mesh manipulation and conversion
  • apps/yimageview.cpp: Hdr/Ldr image viewer with tonemapping and color grading
  • apps/yimageviews.cpp: simpler version of apps/yimageview.cpp for demos
  • apps/yimageproc.cpp: command-line image manipulation
  • apps/yimagedenoise.cpp: command-line image denoiser that uses Intel Open Image Denoise
  • apps/ysceneview.cpp: simple OpenGL viewer

Here are some test images rendered with the path tracer. More images are included in the project site.

Example materials: matte, plastic, metal, glass, subsurface, normal mapping

Example shapes: procedural shapes, Catmull-Clark subdivision, hairs, displacement mapping

Image rendered with Yocto/GL path tracer. Model by Disney Animation Studios.

Design Considerations

Yocto/GL follows a "data-oriented programming model" that makes data explicit. Data is stored in simple structs and accessed with free functions or directly. All data is public, so we make no attempt at encapsulation. Most objects is Yocto/GL have value semantic, while large data structures use reference semnatic with strict ownership. This means that everything can be trivially serialized and there is no need for memory management.

We do this since this makes Yocto/GL easier to extend and quicker to learn, with a more explicit data flow that is easier when writing parallel code. Since Yocto/GL is mainly used for research and teaching, explicit data is both more hackable and easier to understand.

In terms of code style we prefer a functional approach rather than an object oriented one, favoring free functions to class methods. All functions and data are defined in sibling namespaces contained in the yocto namespace so libraries can call all others, but have to do so explicitly.

The use of templates in Yocto was the reason for many refactoring, going from no template to heavy template use. At this point, Yocto uses some templates for readability. In the future, we will increase the use of templates in math code, while keeping many APIs explicitly typed.

We do not use exception for error reporting, but only to report "programmers" errors. For example, IO operations use boolean flags and error strings for human readable errors, while exceptions are used when preconditions or post conditions are violated in functions.

The current version of the library (2.x) is a major refactoring of the previous library versions (1.x) in three main aspects. First, we now allow the use of reference semantic via pointers and adopt it for all large objects, while keeping value semantic for all others. We did this to avoid erroneous copies that cannot detected and avoided at compile time. Second, we had trouble interacting with C libraries that mostly use reference semantic. Third, we reduce the use of exceptions, again for better integration with external code.

Credits

Main contributors:

This library includes code from the PCG random number generator, boost hash_combine, and public domain code from github.com/sgorsten/linalg, gist.github.com/badboy/6267743 and github.com/nothings/stb_perlin.h. Other external libraries are included with their own license.

Compilation

This library requires a C++17 compiler and is know to compiled on OsX (Xcode >= 11), Windows (MSVC 2019) and Linux (gcc >= 9, clang >= 9).

You can build the example applications using CMake with mkdir build; cd build; cmake ..; cmake --build .

Yocto/GL depends on stb_image.h, stb_image_write.h, stb_image_resize.h and tinyexr.h for image loading, saving and resizing, cgltf.h and json.hpp for glTF and JSON support, and filesystem.hpp to support C++17 filesystem API when missing. All dependencies are included in the distribution.

Yocto/GL optionally supports building OpenGL demos, which are handled by including glad, GLFW, ImGui as dependencies in apps. OpenGL support might eventually become part of the Yocto/GL libraries. OpenGL support is enabled by defining the cmake option YOCTO_OPENGL and contained in the yocto_gui library.

Yocto/GL optionally supports the use of Intel's Embree for ray casting. At this point, we rely on prebuilt binaries distributed by Intel. See the main CMake file for how to link to it. Embree support is enabled by defining the cmake option YOCTO_EMBREE.

Yocto/GL optionally supports the use of Intel's Open Image Denoise for denoising renders. At this point, we rely on prebuilt binaries distributed by Intel. See the main CMake file for how to link to it. Open Image Denoise support is enabled by defining the cmake option YOCTO_DENOISE. See apps/yimagedenoise for a demonstration.

Comments
  • Version 4 - Design Documents

    Version 4 - Design Documents

    This issue tracks design consideration for the v4 simplification. Instead of keeping separate design documents for each part of the library, we keep everything into one for simplicity.

  • Compilation error with gcc 8.2.0

    Compilation error with gcc 8.2.0

    I get those errors when I try to compile the code at current version (e155ccb2)

    Tried with: gcc (Ubuntu 8.2.0-7ubuntu1) 8.2.0

    /home/guillaume/src/yocto-gl/yocto/yocto_bvh.cpp: In lambda function:
    /home/guillaume/src/yocto-gl/yocto/yocto_bvh.cpp:1487:69: error: call of overloaded ‘affine(yocto::frame3f&)’ is ambiguous
                                              inverse((affine3f)instance.frame), ray)
                                                                         ^~~~~
    In file included from /home/guillaume/src/yocto-gl/yocto/yocto_bvh.h:91,
                     from /home/guillaume/src/yocto-gl/yocto/yocto_bvh.cpp:29:
    /home/guillaume/src/yocto-gl/yocto/yocto_math.h:1289:24: note: candidate: ‘constexpr yocto::affine<T, 3>::affine(const yocto::mat<T, 4, 4>&) [with T = float]’
         constexpr explicit affine(const mat<T, 4, 4>& m)
                            ^~~~~~
    /home/guillaume/src/yocto-gl/yocto/yocto_math.h:1271:8: note: candidate: ‘constexpr yocto::affine<float, 3>::affine(const yocto::affine<float, 3>&)’
     struct affine<T, 3> {
            ^~~~~~~~~~~~
    /home/guillaume/src/yocto-gl/yocto/yocto_math.h:1271:8: note: candidate: ‘constexpr yocto::affine<float, 3>::affine(yocto::affine<float, 3>&&)’
    
  • Crash in sample_environment_direction_pdf

    Crash in sample_environment_direction_pdf

    The rendering thread sometimes crashes in the function sample_environment_direction_pdf.

    It seems to happen when the texcoord variable gets a y value of exactly 1.0, in that case the idx overflows the elements_cdf size.

  • yocto_cutrace compile errors

    yocto_cutrace compile errors

    Cool project!

    I am getting a lot of compile errors in yocto_cutrace. Most are related to vector functions:

    /tmp/yocto-gl/libs/yocto/yocto_cutrace.cu(173): error: no instance of constructor "yocto::vec2f::vec2f" matches the argument list argument types are: (int, int)

    /tmp/yocto-gl/libs/yocto/yocto_cutrace.cu(376): error: namespace "std" has no member "swap"

    I am compiling with gcc 11.1 and CUDA 11.5 on linux.

  • Split Yocto/Math

    Split Yocto/Math

    This issue track ideas on how to split Yocto/Math. Right now math contains a lot of different functions that are int eh following categories

    • linear algebraic types vec/mat/frame/transforms
    • color manipulation on vec
    • geometry types ray/bbox/intersection/overlap
    • random number generation
    • noise
    • Monte Carlo helpers
    • brdf/phasefunc Monte Carlo helpers

    We probably want to split Math into two or more files. This issue track proposal on how to do this.

  • Error Compiling on VS2017

    Error Compiling on VS2017

    I am getting the following errors when compiling on VS2017:

    Error	C2512	'ym::vec<int,N>': no appropriate default constructor available	yocto	...\yocto-gl\yocto\yocto_gltf.h	1929
    
    Error	C2039	'tolower': is not a member of 'std'	yocto	...\yocto-gl\yocto\yocto_utils.h	620	
    
    Error	C2398	Element '1': conversion from 'double' to 'float' requires a narrowing conversion	yocto	....\yocto-gl\yocto\yocto_trace.cpp	1309	
    

    There are more C2398's at lines 1309 for elements 2 and 3 as well. Ideas?

  • Compilation error at std::array initialization

    Compilation error at std::array initialization

    gcc 5.4 does not accept a = {} initialization for std::array. (and clang will report it as warning when increasing warning level(e.g. -Wall))

    $ g++ -std=c++11 yocto_gltf.h
    yocto_gltf.h:615:55: error: array must be initialized with a brace-enclosed initializer
         std::array<float, 4> baseColorFactor = {1, 1, 1, 1};
    

    More C++11 compliant solution is

    std::array<float, 4> baseColorFactor{{1, 1, 1, 1}}; // OK
    
  • Error with metallic materials ?

    Error with metallic materials ?

    I think there is a bug in the BRDF evaluation of materials with metallic value:

      if (metallic) {
          point.specular = point.specular * (1 - metallic) + metallic * point.diffuse;
          point.diffuse  = metallic * point.diffuse * (1 - metallic);
      }
    

    The multiplication by metallic in point.diffuse computation seems wrong: a material with a very little metallic factor value will have a diffuse value close to zero, while I would expect the opposite. Or am I wrong?

  • Adaptive Sampling.

    Adaptive Sampling.

    Please, take a look at my implementation of 'Adaptive Sampling', using yocto-gl. I do my best to not change too much the original code, just adding a new one. So, the integration may be easy, if you think it is useful.

    https://github.com/mkanada/yocto-gl

  • load_text() fails on Windows

    load_text() fails on Windows

    Thanks for making such a great looking project available!

    I've compiled the latest github version of yocto-gl on Windows 10 using Microsoft Visual Studio Community 2019 Version 16.5.0 and am unable to load any of the json test scenes because of a failure in load_text() on line 949 in yocto_sceneio.cpp

    if (fread(str.data(), 1, length, fs) != length) return read_error();

  • Naming scheme and library content

    Naming scheme and library content

    To freeze version2, we want to adopt a final naming scheme as well as decide about a final library content. This issue is a proposal to track decision in this area.

    Library merges

    To reduce library dependencies, we should merge small libraries into bigger ones if the use makes sense.

    • [x] merge Yocto/Bvh into Yocto/Shape and remove Embree support.
      • this is to shorten code and since the bvh is now only used for other apps
      • Embree support needs to be removed to keep bvhs as values, while Embree is a reference type
      • note that Embree will remain supported in the path tracer
      • in the future, we could have a generic BVH that wraps Embree, but it cannot be a value type, so we need to accept the fact that large data structures in Yocto/Shape need to use pointers
    • [x] Yocto/Ply, Yocto/Bvh, Yocto/Pbrt should eventually be released as separate libraries, since they are already separate now. This is not crucial now.
      • remove dependency on Yocto/Math
    • [x] Yocto/Common is a collection of unrelated utilities like container shortcuts and parallel stuff; it is not used in the rest of Yocto to reduce dependencies. We could remove or keep it.
    • [x] Yocto/Shape contains a lot of functionality that helps everywhere and some more hard functionality. For example compute_normals is helpful everywhere and only a tiny bit of code. While geodesics are more proper in a library for computational geometry. One practical think we could do is to move the small functionality into Yocto/Math and keep the big ones in Yocto/Shape.
    • [x] Yocto/Image contains the image datatype that is used everywhere in yocto. Often the only reason why Yocto/Image is included is to get the image definition and be able to talk to the rest of Yocto. If, and only if, we move small parts of Yocto/Shape into Yocto/Math, we should move small parts of Yocto/Image into Yocto/Math, at least image, tonemap and eval_image.
    • [x] Yocto/Trace contains rendering helpers like fresnel and micro facet functions. We should move them to math. This is similar to render man or osl libraries.

    Library names

    We want to freeze library names to final ones. Also to

    • [x] decide on name for Yocto/Math
      • math seems too generic
      • proposal: Yocto/VecMath
    • [x] decide on name for Yocto/Shape
      • shape makes little sense IMO
      • proposal: not sure yet
    • [x] decide on name for Yocto/OpenGL
      • OpenGL is hidden and should be since it may go away
      • proposal: Yocto/UserInterface
    • [x] decide on name for Yocto/CommonIO
      • Yocto/CommonIO is really library support for quickly writing command line applications
      • proposal: Yocto/CmdLine or Yocto/CommandLine
    • [x] decide on name for Yocto/SceneIO
      • Yocto/SceneIO does mostly scene loading and a few small utilities related to scene validation
      • but in the future we may add a few other small utilities, so maybe a more generic name may be best
      • proposal: either keep the same or Yocto/Scene or Yocto/Model

    Namespace names

    We should decide and update namespace names. The keyword here is consistency in length and meaning. Right now we use 2-5 characters because it just happened that way. But many libraries settle for 3 chars, so maybe that is a good compromised to achieve if it does not break readability too much. Here are some proposal we should vote on. Here I list alternatives of 3 chars or the current ones.

    • [x] Yocto/Math: yvm - ym now
    • [x] Yocto/Shape: ysh - yshp now
      • but really a better library name may be helpful
    • [x] Yocto/Image: yim - yimg now
    • [x] Yocto/OpenGL: yui - yglu now
    • [ ] Yocto/CommonIO: ycl / ycli now
    • [x] Yocto/Trace: ytr - ytrc now
    • [x] Yocto/SceneIO: ysc - yscn now
  • Integrated ply reader in PbrtIo

    Integrated ply reader in PbrtIo

    We should integrate local copy of the ply reader code on the part loader. This would break a dependency and make pbrtio fully self contained, which was an original goal of the low-level refactoring code.

  • Fast float dependency

    Fast float dependency

    We should remove fast float as a dependency.

    While it is faster than charconv, especially when charconv is not supported, it also adds a dependency on the low-level code that we specifically refactored to remove dependencies.

  • CPU raytracing optimization

    CPU raytracing optimization

    Consider optimization found in madmann bvh.

    • [ ] box intersection code
    • [ ] sorted walk, instead of ray direction flags
    • [ ] understand leaf exploration code
    • [ ] use preprocessor for performance comparison
    • [ ] consider binned sah build
  • Rename trace to render

    Rename trace to render

    Consider renaming trace to render, while still maintaining backward compatibility.

    • [ ] make yocto_render, and yocto_curender
    • [ ] rename trace_XXX to render_XXX
    • [ ] rename outrace_XXX to curender_XXX
    • [ ] maintain backward compatibility with typedefs and inline functions
A terminal-based graphics library for both 2D and 3D graphics.
A terminal-based graphics library for both 2D and 3D graphics.

TermGL A terminal-based graphics library for both 2D and 3D graphics. Written in C, created for terminals supporting ANSI escape codes. Table of Conte

May 13, 2022
Vulkan physically based raytracer including denoising
Vulkan physically based raytracer including denoising

VulkanPBRT Vulkan physically based raytracer including denoising. The GPU raytracer is based on Vulkan only, as well as for the denoising only the Vul

Mar 14, 2022
SoL (for Speed of Light, or sun in Spanish) is a Physically-based rendering library written in modern C++

SoL (for Speed of Light, or sun in Spanish) is a small rendering library written in C++20. Its goal is to strike a good balance between performance and usability, and allow easy experimentation for rendering researchers.

Mar 3, 2022
🌞 A physically based monte carlo path tracer written in C++
🌞 A physically based monte carlo path tracer written in C++

Physically Based Path Tracer The below 3D model for the Head of Michelangelo's David bust was taken from this link. Other .obj files taken from The St

May 4, 2022
A modern C++ physically based renderer
A modern C++ physically based renderer

The Dakku Renderer Warning: This project is currently under developing and does not guarantee any consistency. About Dakku is a physically based rende

Apr 15, 2022
A physically based shader for woven cloth
A physically based shader for woven cloth

ThunderLoom A physically based shader for woven cloth This projects consits of three main parts: Irawan shading model At its core is an implementation

Apr 26, 2022
Source code for pbrt, the renderer described in the third edition of "Physically Based Rendering: From Theory To Implementation", by Matt Pharr, Wenzel Jakob, and Greg Humphreys.

pbrt, Version 3 This repository holds the source code to the version of pbrt that is described in the third edition of Physically Based Rendering: Fro

May 11, 2022
appleseed is an open source, physically-based global illumination rendering engine primarily designed for animation and visual effects.
appleseed is an open source, physically-based global illumination rendering engine primarily designed for animation and visual effects.

appleseed is an open source, physically-based global illumination rendering engine primarily designed for animation and visual effects.

May 10, 2022
The tiny C library of 2D computer graphics.
The tiny C library of 2D computer graphics.

libcg The tiny C library of 2D computer graphics. Getting Started The library's .c and .h files can be dropped into a project and compiled along with

May 3, 2022
Low Level Graphics Library (LLGL) is a thin abstraction layer for the modern graphics APIs OpenGL, Direct3D, Vulkan, and Metal
Low Level Graphics Library (LLGL) is a thin abstraction layer for the modern graphics APIs OpenGL, Direct3D, Vulkan, and Metal

Low Level Graphics Library (LLGL) Documentation NOTE: This repository receives bug fixes only, but no major updates. Pull requests may still be accept

May 12, 2022
kaun is a replacement for löve's built-in love.graphics module intended for 3D graphics

kaun kaun is a replacement for löve's built-in love.graphics module intended for 3D graphics. It is a Lua module you can require from a shared library

Apr 5, 2021
This repo contains the DirectX Graphics samples that demonstrate how to build graphics intensive applications on Windows.
This repo contains the DirectX Graphics samples that demonstrate how to build graphics intensive applications on Windows.

DirectX-Graphics-Samples This repo contains the DirectX 12 Graphics samples that demonstrate how to build graphics intensive applications for Windows

May 13, 2022
A community driven OS by the youth
A community driven OS by the youth

Welcome Welcome to the mandelbrot Operating System. This OS is built by a humble group of teenagers over at Discord. We do this solely to have fun and

May 4, 2022
Lightweight and modular C++11 graphics middleware for games and data visualization

Magnum — Lightweight and modular C++11/C++14 graphics middleware for games and data visualization Looking for an open-source library that gives you gr

May 20, 2022
Matplot++: A C++ Graphics Library for Data Visualization 📊🗾
Matplot++: A C++ Graphics Library for Data Visualization 📊🗾

Matplot++ A C++ Graphics Library for Data Visualization Data visualization can help programmers and scientists identify trends in their data and effic

May 13, 2022
This is a openGL cube demo program. It was made as a tech demo using PVR_PSP2 Driver layer GPU libraries.

OpenGL Cube Demo using PVR_PSP2 Driver layer GPU libraries This is a openGL cube demo program. It was made as a tech demo using PVR_PSP2 Driver layer

Oct 31, 2021
Software RayTracing engine written in C++ without the usage of any libraries.
Software RayTracing engine written in C++ without the usage of any libraries.

Software Raytracing Engine This is a software unidirectional raytracing engine, fully written in C++17, with no dependencies or external libraries use

May 4, 2022
Tiny and efficient graph abstractions.
Tiny and efficient graph abstractions.

Tiny and efficient graph abstractions. Usage See tinygraph-example.c Interface See documentation in tinygraph.h Building The tinygraph library require

May 4, 2022