Software RayTracing engine written in C++ without the usage of any libraries.

Overview

Software Raytracing Engine

This is a software unidirectional raytracing engine, fully written in C++17, with no dependencies or external libraries used.

How to launch it

If you are using MSVS, you can launch it from the project file. Alternatively, you can build it with CMake

cmake -H. -Bbuild
cmake --build build
./bin/RayTracing

Input

As input, the program uses a scene file, where all properties are listed. Depending on the scene, object files, textures, and skyboxes might also be loaded. Scene path can be passed as an argument value at program start.

Output

The output of the program is a single bpm file, containing a rendered image of a given resolution. BMP image format was chosen because of its simplicity.

Scene loader

In order to render something, we need information about scene. Those are stored in scene file. It is a text file that has several blocks:

  • Options: Here all types of settings are store as a pair of =
  • Object/Light: Each light or object block represents a single entity in the scene.
  • End block: The scene file ends with an end block to indicate that all data has been read.

Features

Multithreading

Ray tracing process for each pixel is a task that can be easily paralleled, so the program splits a scene into a set of 128x128 tiles and then renders them with a number of threads that equals to system thread count.

Anti-Aliasing

After scene was rendered, anti-aliasing may be applied. The process consists of 2 steps: running Sobel filter on rendered image to detect edges. And then launch tile renderer that will rewrite image pixel with color of 4 new rays launched for that pixel.

Sobel filter result 8x zoomed image comparison

Basic shapes

The simplest scene that can be rendered is a scene consisting of base shapes, like Sphere and Plane, and Point or Distant light sources. Here is an example of such a scene.

Here you can see all 4 types of surfaces:

  • Diffuse - Collects info from all visible light sources
  • Phong - Combines three components: ambient, diffuse, specular
  • Reflective - Casts reflected ray for every ray fallen on it
  • Transparent - Using Fresnel model: combines refracted and reflected rays

How Phong illumination system works:

Ambient Diffuse Specular Final

Skybox

On the image below you can see the application of the skyboxes. Skybox is composed of 6 cube textures, and each time ray leaves the scene - we get color from one of those textures

Polygon Meshe

In order to use Polygon Mesh, we have to first load it. There are a lot of object types that can store 3d object data, but the type of my choice was .obj file. It is relatively simple yet powerful enough to implement a full specter of features.

Mesh features

Backface culling

Backface culling is a simple technique that can give a little performance boost at the ray-triangle intersection test. If ray faces 'another side' of triangles, the intersection will not be fully computed. However, if the model has some holes in it, it may give visual artifacts:

Backface culling on (2.1 s) Backface culling off (2.7s)

Acceleration Structures

They do not change anything in visual appearance, however, they can boost performance up to tens of times. It does so by creating a hierarchy of bounding boxes, which allows saving a lot of ray-triangle intersections. Each box may have two ancestor boxes, or store a set of triangles. This way we may text triangles only when the ray intersects the box. Left and Right boxes are separated by SAH - Surface Area Heuristic. This program has an option to visualise those bounding boxes:

Rendered object Low penalty (1) Higher penalty (10)

The only parameter determining AC construction is a penalty. The deeper AC is in the hierarchy, the bigger the minimum amount of triangles it can store. Therefore the total amount of AC will change. However, it doesn't have much impact on performance.
Model above containes 250'000 triangles. Without usage of AC render time was 356 seconds. With AC - only 6 seconds.

Basic Shaders

Mesh consists of polygons (triangles), and if we will draw them as they are we will receive an image that doesn't look nice. To fix it, we may use shaders. The most basic one will smoothen the surface by extrapolating the normal triangle vertices.

Flat shading Vertex shading

Texture maps

The plain object is not very interesting and useful, so we can use texture maps to fix it. A texture map (sometimes called diffuse map) is an image storing information about objects' color. We can get them from texture coordinates, which are associated with each triangle. Also, those coordinates are normalized (from 0 to 1), therefore texture itself can have any size. The bigger the size - the better the quality.

Texture file Render without texture Render with texture

Normal maps

Another tecnique similar to texture map is normal map. It can add to object more small details, without increasing the complexity of geometry. To use the tangent normal map we have to calculate tangent and bitangent for each triangle, and each time we'll need a normal we will transform the vector from the map into world space. In each pixel of such a map 3d vector is encoded, which shows direction of normal in tangent space.
Following 2 images show normal view of object, which means that color of surface shows direction of normal in world space. In upper image we can see that object is smooth, while on picture below surface has much more details in it. It is the effect of normal map.

Specular map

We can add one more map to the object, which is specular map. This map is used for Phong shaded objects and can determine how reflective surface will be.

All 3 maps of the following model:

Texture (diffuse) map Normal map Specular map

And with those 3 image we managed to enhance view of our model without significant performance loss.

Area light

The area light is the thing that can make a scene look much more plausible, but it also makes it much slower. In this engine, every area light source is parallelogram defined by its center position and sides vectors. Light quality is described by the number of samples per side of the parallelogram. So, the bigger the source - the more samples should be used and slower it will run.

Original model Low resolution of light source
Small light source Large light source

Also, if you are additionally interested in code and wish to expore it more, output folder has the call tree generated by Doxygen

Issues
  • Use of atomics

    Use of atomics

    In several places atomics are incremented with code like this:

    finishedPixels.store(finishedPixels.load() + 1);
    

    This is not atomic, it's three separate statements (read, modify, write). Consider what happens if you have two threads modifying the same variable:

    1. Thread 1 calls finishedPixels.load() and reads (for example) the value 2
    2. Thread 2 also calls finishedPixels.load() and also reads 2
    3. Thread 1 increments the value to 3 and calls finishedPixels.store(3)
    4. Thread 2 increments the value to 3 and also calls finishedPixels.store(3).

    The value is now 3 instead of the expected 4, just as if you had used a plain non-atomic variable - this is what atomic operations exist to avoid.

    std::atomic overloads the ++ and -- operators, so you can increment/decrement your values as one unsplittable (-> atomic) operation.

    opened by Kantaja 1
  • Fixed problem with absolute paths. More Linux (NixOS) support

    Fixed problem with absolute paths. More Linux (NixOS) support

    • Using relative paths now (relative to the scene file, not the working directory)
    • Linux support: default.nix file for nix-shell and xdg-open opens default image viewer on Linux for output file
    opened by codefionn 0
Owner
Makar Ivashko
Makar Ivashko
Minimal pathtracer using Vulkan RayTracing

Single File Vulkan Pathtracing Minimal pathtracer using Vulkan RayTracing Environment Vulkan SDK 1.2.162.0 GPU / Driver that support Vulkan Ray Tracin

Yuki Nishidate 23 Nov 15, 2021
Minimal raytracing example with a combination of embree and tinyobjloader

embree-tinyobj-example minimal raytracing example with a combination of embree and tinyobjloader Requirements CMake (>=3.20) Embree (>=3) OpenMP (Opti

yumcyawiz 1 Nov 21, 2021
PainterEngine is a application/game engine with software renderer,PainterEngine can be transplanted to any platform that supports C

PainterEngine is a application/game engine with software renderer,PainterEngine can be transplanted to any platform that supports C

DBinary 1.2k Jan 17, 2022
Horde3D is a small 3D rendering and animation engine. It is written in an effort to create an engine being as lightweight and conceptually clean as possible.

Horde3D Horde3D is a 3D rendering engine written in C++ with an effort being as lightweight and conceptually clean as possible. Horde3D requires a ful

Volker Vogelhuber 1.2k Jan 19, 2022
Software ray tracer written from scratch in C that can run on CPU or GPU with emphasis on ease of use and trivial setup

A minimalist and platform-agnostic interactive/real-time raytracer. Strong emphasis on simplicity, ease of use and almost no setup to get started with

Arnon Marcus 36 Dec 21, 2021
Yocto/GL: Tiny C++ Libraries for Data-Driven Physically-based Graphics

Yocto/GL: Tiny C++ Libraries for Data-Oriented Physically-based Graphics Yocto/GL is a collection of small C++17 libraries for building physically-bas

Fabio Pellacini 2.2k Jan 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

David Cantu 5 Oct 31, 2021
Open 3D Engine (O3DE) is an Apache 2.0-licensed multi-platform AAA Open 3D Engine

Open 3D Engine (O3DE) is an Apache 2.0-licensed multi-platform 3D engine that enables developers and content creators to build AAA games, cinema-quality 3D worlds, and high-fidelity simulations without any fees or commercial obligations.

O3DE 4.3k Jan 17, 2022
Brand new engine with new and QoL features. Grafex is Psych engine with some additions and Better graphics

Friday Night Funkin' - Graphex Engine Credits: Grafex Mod aka Psych Graphic Rework: Xale - Lead Coding, Artist PurpleSnake - Second Coder Psych Engine

Xale 4 Jan 8, 2022
ORE (OpenGL Rendering Engine) is a rendering engine developed for my college minor project assessment.

ORE (OPENGL RENDERING ENGINE) What is ORE? ORE(OpenGL Rendering Engine) is a rendering engine with great and easy to use UI that allows the user to lo

HARSHIT BARGUJAR 4 Dec 20, 2021
OpenGL Object Loading can load virtually every 3d.obj file you can find on the internet, without using another object loading library

OpenGL Object Loading can load virtually every 3d.obj file you can find on the internet, without using another object loading library (assimp for example). The program can load Object with 12M+ triangles and more

Phan Sang 1 Dec 25, 2021
Plugin implementing Kirchhoff rods to simulate any 1D flexible structure

BeamAdapter plugin This SOFA plugin implements a 1-dimensional Finite Element Method (FEM) in the context of coil embolization in neurology. The metho

SOFA Framework 5 Dec 20, 2021
A C++ commandline for use in servers and chat software. Provides very simple asynchronous input/output.

commandline A C++ commandline for use in servers and terminal chat software. Provides very simple asynchronous input/output. Supports reading and writ

Lion 24 Dec 19, 2021
Pencil2D is an animation/drawing software for Windows, macOS, Linux, and FreeBSD.

Pencil2D is an animation/drawing software for Windows, macOS, Linux, and FreeBSD. It lets you create traditional hand-drawn animation (cartoon) using both bitmap and vector graphics. Pencil2D is free and open source.

Pencil2D 1.1k Jan 17, 2022
ZBar Bar Code Reader is an open source software suite for reading bar codes from various sources

ZBar Bar Code Reader is an open source software suite for reading bar codes from various sources

null 2.3k Jan 18, 2022
Dust3D is a cross-platform open-source 3D modeling software

Dust3D is a cross-platform open-source 3D modeling software. Auto UV unwrapping, auto rigging with PBR Material support, pose and motion authoring all in one.

Jeremy HU 2.3k Jan 14, 2022
Lightweight OpenCL-Wrapper to greatly simplify OpenCL software development with C++ while keeping functionality and performance

OpenCL-Wrapper OpenCL is the most powerful programming language ever created. Yet the OpenCL C++ bindings are very cumbersome and the code overhead pr

Moritz Lehmann 2 Jan 23, 2022
Cross-platform, graphics API agnostic, "Bring Your Own Engine/Framework" style rendering library.

bgfx - Cross-platform rendering library GitHub Discussions Discord Chat What is it? Cross-platform, graphics API agnostic, "Bring Your Own Engine/Fram

Бранимир Караџић 10.9k Jan 24, 2022
2D Vector Graphics Engine Powered by a JIT Compiler

Blend2D 2D Vector Graphics Powered by a JIT Compiler. Official Home Page (blend2d.com) Official Repository (blend2d/blend2d) Public Chat Channel Zlib

Blend2D 987 Jan 22, 2022