Code Monkey home page Code Monkey logo

software-rasterizer's Introduction

CPU Software Rasterizer

A software-rasterizer in C++, that I wrote to get a basic understanding of the OpenGL graphics pipeline.

alt l.t.r. "Sad toaster" by tasha.lime, "Coatlicue" by aptass, "Gameboy Cartridge" by Karolina D, "Demon Skull" by Auxiar Molkhun

Features

  • C++ implementation
    • generic vertex and fragment attributes
    • programmable vertex and fragment shader (functors)
    • generic framebuffer targets (for "offscreen" rendering)
    • small math library (2D, 3D, 4D vectors and 2x2, 3x3, 4x4 matrices)
    • .obj and .mat loading
    • GLFW/OpenGL viewer (uploads framebuffer each frame)
  • Rasterizer
    • perspective-correct attribute interpolation
    • z-buffering
    • texture sampler filter (nearest, linear)
    • texture sampler wrapping (repeat, edge)
    • face culling
    • custom framebuffer
    • line rendering (wireframe rendering)
    • mip map generation
    • mip map level computation
    • anisotropic filtering
    • cubemap
  • Examples
    • minimal examples
      • colored triangle
      • index buffer
      • texture and sampler
      • custom framebuffer
      • glfw/gl viewer
      • model loading
    • Blinn-Phong illumination
    • Cel Shading with depth buffer edge detection
    • Normal Mapping
    • Shadow Mapping
    • Screen Space Ambient Occlusion
    • Physically-based rendering + offline pre-integration

Examples

Minimal setup (colored triangle)

Similar to traditional Graphic APIs we define the input and output of the shader stages, i.e. the data passing through the rasterization pipeline.

All members from Varying contained in the VARYING(...) macro are interpolated per fragment by the rasterizer. Note, that it is mandatory to have a Vec4 position interpolated attribute.

/* vertex data -> input to draw call (via Buffer) */
struct Vertex
{
    Vec3 pos;
    Vec3 color;
};

/*
 * Output of vertex stage, Input to fragment stage
 * -> position is mandatory
 * -> members to interpolate are declared by VARYING macro (member need scalar multiplication, and addition)
*/
struct Varying
{
    Vec4 position;
    Vec3 color;

    VARYING(position, color);
};

/* uniform struct accessable from both "shaders" */
struct Uniforms {};

Vertex and fragment shaders are written as function objects which need to be set accordingly with onVertex and onFragment (currently no default shader).

Program<Vertex, Varying, Uniforms> program;
program.onVertex([](const Uniforms& uniform, const Vertex& in, Varying& out)
{
    out.position = Vec4(in.pos, 1.0f);
    out.color = in.color;
});

program.onFragment([](const Uniforms& uniform, const Varying& in, Vec4& out)
{
    out = Vec4(in.color, 1.0f);
});

Mesh data is provided to the renderer with a Buffer object.

Buffer<Vertex> buffer;
buffer.primitive = ePrimitive::TRIANGLES;
buffer.vertices = { { {-0.5, -0.5, 0.5}, {1.0, 0.0, 0.0} },
                    { { 0.5, -0.5, 0.5}, {0.0, 1.0, 0.0} },
                    { { 0.0,  0.5, 0.5}, {0.0, 0.0, 1.0} } };

An instance of Renderer contains a default framebuffer with a color and depth target.

After clearing the framebuffer, a draw call can be submitted with the previously defined shader program and vertex buffer.

/* rasterizer with framebuffer size */
Renderer rasterizer(480, 480);

/* clear framebuffer */
rasterizer.framebuffer().clear(Vec4(0, 0, 0, 1));

/* submit draw call */
rasterizer.draw(program, buffer);

/* save framebuffer as .png */
rasterizer.framebuffer().color().save("00_triangle.png");

Results

Model Loading and Texture Mapping ("Sad toaster" Link by tasha.lime.) alt

Blinn-Phong Illumination with diffuse, normal and ambient occlusion map ("Demon Skull" Link by Auxiar Molkhun) alt

Physically-based rendering with pre-integrated irradiance and radiance maps ("Bilora Bella 46 Camera" Link by Martijn Vaes licensed under CC-BY-4.0) alt

Cel-Shading with post-process edge detection on the depth buffer ("Bird" Link by Václav Pleticha licensed under CC-BY-4.0) alt

Shadow Mapping (based on "low poly house" Link by cofitelle licensed under CC-BY-4.0 CC-BY-4.0) alt

Screen-space ambient occlussion ("Pokemon FireRed - Player's Room" Link by Wesai licensed under CC-BY-4.0) alt

📚 Useful Resources

Tiny Renderer
Scratchpixel Lesson Rasterator
SRPBR
Stack Overflow Perspective Interpolation
learnopengl Tutorials
IBL Blogpost by Bruno Opsenica

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.