Skip to content

Self made monte carlo raytracer created from scratch

Notifications You must be signed in to change notification settings

flarive/Cortex-Raytracer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cortex-Raytracer

Cortex RT is a self made CPU based monte carlo path tracer created from scratch in C++.

Screenshot

Primitives

Cortex supports an extended list of builtin uv mapped primitives mostly for testing purposes :

  • Plane
  • Cylinder
  • Disk
  • Cone
  • Box
  • Torus
  • Sphere
Primitives with test UV texture Primitives with stone texture
Screenshot of all builtin primitives Screenshot of all builtin primitives

extended_primitives.scene

Meshes

Cortex RT supports loading Wavefront .obj files.

obj is a kind of old legacy plain text 3D file format but it is still widely used by 3D software (blender, 3ds max, maya...) as an export file format.

  • .obj file contains vertex, faces, normals, uv mapping and smmothing groups definition
  • .mtl (Material template library) additional file contains materials definition (color, textures, ambient, diffuse, specular, bump...)

If you want to knowm more about obj and mtl files : https://en.wikipedia.org/wiki/Wavefront_.obj_file

teapot.obj solid color teapot.obj textured 3ds max obj exporter
Screenshot of 3ds max OBJ file exporter

Scenes

Cortex RT comes with a convenient .scene configuration file system to describe the scene to be rendered (primitives, meshes, camera, lights, materials, textures, rendering quality...)

# teapot_mesh.scene

image:
{
    width = 512;
    height = 388;
    maxDepth = 100;
    samplesPerPixel = 100;
    background = 
    {
        color = { r = 0.0; g = 0.0; b = 0.0; };
    };
};

# Configuration of the camera
camera:
{
    aspectRatio = "16:9";
    lookFrom = { x = 0.0; y = 4.0; z = 9.0; };
    lookAt = { x = 0.0; y = 0.0; z = 0.0; };
    upAxis = { x = 0.0; y = 1.0; z = 0.0; };
    fov = 18.0;
};

# Lights in the scene
lights:
{
    sphereLights: (
        {
            name = "MySphereLight";
            position = { x = 0.0; y = 8.0; z = 5.0; };
            radius = 3.0;
            intensity = 3.0;
            color = { r = 1.0; g = 1.0; b = 1.0; };
            invisible = true;
        }
    )
}

textures:
{
    solidColor: (
        {
            name = "ground_texture";
            color = { r = 0.7; g = 0.8; b = 1.0; };
        },
    ),
    image: (
        {
            name = "teapot_diffuse_texture";
            filepath = "../../data/models/rusted_metal1.jpg";
        }
    )
}

materials:
{
    lambertian: (
        {
            name = "ground_material";
            texture = "ground_texture";
        }
    ),
    phong: (
        {
            name = "teapot_material";
            diffuseTexture = "teapot_diffuse_texture";
            ambientColor = { r = 0.0; g = 0.0; b = 0.0; };
            shininess = 0.9;
        }
    )
}

# Meshes in the scene
meshes:
{
    obj: (
        {
            name = "MyTeapotModel"
            filepath = "../../data/models/teapot.obj";
            position = { x = 0.0; y = 0.0; z = 0.0; };
            material = "teapot_material"
            use_mtl = false;
            use_smoothing = true;
            transform =
            {
                translate = { x = 0.0; y = 0.0; z = 0.0; };
                rotate = { x = 0.0; y = 0.0; z = 0.0; };
                scale = { x = 0.02; y = 0.02; z = 0.02; };
            };
        }
    );
};

# Primitives in the scene
primitives:
{
    # List of boxes
    boxes: (
        {
            name = "MyGround";
            position = { x = 0.0; y = -1.0; z = 0.0; };
            size = { x = 40.0; y = 0.5; z = 40.0; };
            material = "ground_material";
            uvmapping = { scale_u = 1.0; scale_v = 1.0; offset_u = 0.0; offset_v = 0.0; repeat_u = 2.0; repeat_v = 2.0; };
        }
    );
};

Materials

Screenshot of all suported materials

Cortex RT mostly support following materials :

  • Phong
  • Oren Nayar
  • Anisotropic (for wood, slate, ice, velvet...)
  • Isotropic (for glass, crystals with cubic symmetry, diamonds, plastic, metal...)
  • Dielectric (for water, glass, diamond...)
  • Lambertian (simple diffuse material without any specular relection)
  • Metal (for metals, mirrors...)
  • Emissive (WIP)
crate.obj (diffuse + specular + bump textures) cushion.obj (diffuse + specular + normal textures)
Screenshot of phong crate model with diffuse + specular + bump textures Screenshot of phong cushion model with diffuse + specular + normal textures
Screenshot of crate textures Screenshot of cushion textures

The phong reflection model is a full featured material that combines ambient + diffuse + specular. https://en.wikipedia.org/wiki/Phong_reflection_model

On top of that, Cortex RT phong material also support a lot of possible textures (solid color, gradient, image, bump, normal, displacement, alpha...)

# Sample materials section in scene file
materials:
{
    lambertian: (
        {
            name = "ground_material";
            texture = "ground_texture";
        }
    ),
    phong: (
        {
            name = "crate_material";
            diffuseTexture = "crate_diffuse_texture";
            specularTexture = "crate_specular_texture";
            #bumpTexture = "crate_bump_texture";
            normalTexture = "crate_normal_texture";
            ambientColor = { r = 0.0; g = 0.0; b = 0.0; };
            shininess = 0.0;
        }
    )
}

all_materials_spheres.scene

Textures

Screenshot of all suported materials

Cortex RT supports quite a lot of textures you can combine in a material :

  • Solid color texture
  • Gradient color texture
  • Image texture
  • Bump texture
  • Normal texture
  • Displacement texture (WIP)
  • Alpha texture (transparency texture)
  • Perlin texture (procedural noise)
  • Checker (procedural checkboard pattern texture)
  • Emissive texture (WIP)
# Sample textures section in scene file
textures:
{
    image: (
        {
            name = "ground_texture";
            filepath = "../../data/textures/scifi_floor2.png";
        },
        {
            name = "crate_diffuse_texture";
            filepath = "../../data/models/crate_diffuse.jpg";
        },
        {
            name = "crate_specular_texture";
            filepath = "../../data/models/crate_specular.jpg";
        },
        {
            name = "crate_bump_texture";
            filepath = "../../data/models/crate_bump.jpg";
        }
    ),
    normal: (
        {
            name = "crate_normal_texture";
            filepath = "../../data/models/crate_normal.jpg";
            strength = 0.005;
        }
    )
}

all_textures_spheres.scene

Bump texture Normal texture
Screenshot of bump texture Screenshot of normal texture

Camera

Cortex RT provides 2 kinds of camera : perspective (default) and orthographic (no perception of depth)

Perspective camera Orthographic camera
# Configuration of a perspective camera
camera:
{
    aspectRatio = "16:9";
    lookFrom = { x = 0.0; y = 2.0; z = 9.0; };
    lookAt = { x = 0.0; y = 0.6; z = 0.0; };
    upAxis = { x = 0.0; y = 1.0; z = 0.0; };
    fov = 18.0; // Field Of View (zoom level in degrees)
};
# Configuration of an orthographic camera
camera:
{
    aspectRatio = "16:9";
    lookFrom = { x = 0.0; y = 2.0; z = 9.0; };
    lookAt = { x = 0.0; y = 0.6; z = 0.0; };
    upAxis = { x = 0.0; y = 1.0; z = 0.0; };
    orthographic = true;
    orthoHeight = 2.0; // Orthographic viewport height (height of the viewport in world space units)
};

Rendering parameters

The image section in .scene files defines some usefull render settings :

  • width/height : The size in pixels of the final rendered image (according to the camera aspect ratio)
  • maxDepth : The max number of ray bounces (50 should be more than enough)
  • samplesPerPixel (spp) : The max number of samples calculated to generate each pixel of the rendered image (50 is very fast but very noisy, 500-1000 is high quality, 5000+ is extra high quality but very slow)
  • background : The background to use while rendering the scene (color, simple image or hdr skybox image)
# Configuration of the rendered image quality
image:
{
    width = 512;
    height = 388;
    maxDepth = 50;
    samplesPerPixel = 500;
    background = 
    {
        #color = { r = 0.1; g = 0.1; b = 0.1; };
        filepath = "../../data/backgrounds/hdr/christmas_photo_studio_02_2k.hdr";
        is_skybox = true;
    };
};
50 spp 500 spp 1000 spp 5000 spp 10000 spp

Lights

Cortex RT supports 3 different kinds of lights :

  • Omni light : Also known as a point light, an omni light emits light equally in all directions from a single point in space, similar to a light bulb.

  • Directional light : Simulates light coming from a specific direction, as if it were emitted from an infinitely large source, such as the sun.

  • Spot light : More focused light source that emits light in a specific direction within a cone.

Lights are produced by hidden objects (quad or sphere) with an emissive material.
Such objects can be displayed for debug lightning purpose.

Omni light Omni light debug (emissive sphere)
Directional light Directional light debug (emissive quad)
Spot light Spot light debug (emissive sphere)

all_lights_types.scene

Transforms and groups

Cortex RT supports applying transforms to primitives and meshes (translate, rotate, scale). Transform attribute overrides the object position and size already defined.

# Transform applied on a box primitive
primitives:
{
    boxes: (
        {
            name = "MyGround";
            position = { x = 0.0; y = -0.28; z = 0.0; };
            size = { x = 10.0; y = 0.5; z = 40.0; };
            material = "ground_material";
        },
        {
            name = "MyBox"
            position = { x = 0.0; y = 0.35; z = 0.0; };
            size = { x = 0.7; y = 0.7; z = 0.7; };
            material = "uvmapper_material";
            uvmapping = { scale_u = 0.5; scale_v = 0.5; offset_u = 0.0; offset_v = 0.0; };
            transform =
            {
                translate = { x = 0.0; y = 0.0; z = 0.0; };
                rotate = { x = 0.0; y = 45.0; z = 0.0; };
                scale = { x = 2.0; y = 2.0; z = 2.0; };
            };
        }
    );
};

# Transform applied on a custom mesh
meshes:
{
    obj: (
        {
            name = "MyMesh"
            filepath = "../../data/models/smooth_sphere.obj";
            use_mtl = true;
            use_smoothing = true;
            transform =
            {
                translate = { x = -1.3; y = 0.0; z = 0.0; };
                rotate = { x = 0.0; y = 45.0; z = 0.0; };
                scale = { x = 1.2; y = 1.2; z = 1.2; };
            };
        }
    );
};

In a scene objects (primitives and meshes) can be grouped by using groups. A transform can also be applied to a group.

primitives:
{
    boxes: (
        {
            name = "MyBox1"
            position = { x = 0.0; y = 0.0; z = 0.0; };
            size = { x = 0.7; y = 0.7; z = 0.7; };
            material = "uvmapper_material";
            group = "MyGroup";
        },
        {
            name = "MyBox2"
            position = { x = 0.0; y = 0.0; z = 0.0; };
            size = { x = 0.7; y = 0.7; z = 0.7; };
            material = "uvmapper_material";
            group = "MyGroup";
        }
    );
};

# Definition of groups
groups: (
    {
        name = "MyGroup";
        transform =
        {
            translate = { x = -100.0; y = 270.0; z = 395.0; };
            rotate = { x = 0.0; y = 15.0; z = 0.0; };
            scale = { x = 2.0; y = 2.0; z = 2.0; };
        };
    }
);

transforms.scene

Anti aliasing

Performances and optimizations

Command line exe

Graphical User Interface

Dependencies

Thanks to

What's next ?

About

Self made monte carlo raytracer created from scratch

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published