A tiny soft-renderer built from scratch using C++ 11
View Demo
Report Bug
The original intention of building such a 3D rendering system from scratch without any help of graphics library is to get a thorough understanding of the three-dimensional rendering process.
This project was totally refactored based on previous naive version I built 2 years ago. Now, I utilize the following third-party libraries to build this renderer. Please note that SDL2 is just for displaying the rendered results as well as handling mouse and key events.
I build this project on Windows platform. Please make sure your system is equipped with the following softwares.
- cmake:at least version 3.5
- Microsoft visual studio 2017 or 2019
Please compile the project for x64 platform.
-
Clone the repo
git clone https://github.com/ZeusYang/TinySoftRenderer.git
-
Use cmake to build the project:
cd build cmake .. make
or using cmake-gui is ok.
Please note that copy external/dlls/*.dll (for example: SDL2.dll) to the corresponding example binary directory for execution (like build/Release
). Release mode is much more efficient than debug mode.
Please check out examples/
for more details.
int main(int argc, char* args[])
{
constexpr int width = 666;
constexpr int height = 500;
TRWindowsApp::ptr winApp = TRWindowsApp::getInstance(width, height, "TinySoftRenderer-By yangwc");
if (winApp == nullptr)
{
return -1;
}
bool generatedMipmap = true;
TRRenderer::ptr renderer = std::make_shared<TRRenderer>(width, height);
//Load scene
TRSceneParser parser;
parser.parse("../../scenes/complicatedscene.scene", renderer, generatedMipmap);
renderer->setViewMatrix(TRMathUtils::calcViewMatrix(parser.m_scene.m_cameraPos,
parser.m_scene.m_cameraFocus, parser.m_scene.m_cameraUp));
renderer->setProjectMatrix(TRMathUtils::calcPerspProjectMatrix(parser.m_scene.m_frustumFovy,
static_cast<float>(width) / height, parser.m_scene.m_frustumNear, parser.m_scene.m_frustumFar),
parser.m_scene.m_frustumNear, parser.m_scene.m_frustumFar);
winApp->readyToStart();
//Blinn-Phong lighting
renderer->setShaderPipeline(std::make_shared<TRBlinnPhongShadingPipeline>());
glm::vec3 cameraPos = parser.m_scene.m_cameraPos;
glm::vec3 lookAtTarget = parser.m_scene.m_cameraFocus;
//Rendering loop
while (!winApp->shouldWindowClose())
{
//Process event
winApp->processEvent();
//Clear frame buffer (both color buffer and depth buffer)
renderer->clearColorAndDepth(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 0.0f);
//Draw call
renderer->setViewerPos(cameraPos);
auto numTriangles = renderer->renderAllDrawableMeshes();
//Display to screen
double deltaTime = winApp->updateScreenSurface(renderer->commitRenderedColorBuffer(),
width, height, 3, numTriangles);
}
renderer->unloadDrawableMesh();
return 0;
}
-
Affine and perspective correct per vertex parameter interpolation.
-
Screen space back face culling (more robust compared to implementation in ndc space).
-
Z-buffering (reversed z) and depth testing for 3D rendering.
-
Accelerated edge function-based triangle rasterization (Implement top left fill rule). Refs: link
-
Texture mapping, nearest texture sampling, and bilinear texture sampling.
-
Tiling and morton curve memory layout for accessing to texture. (But it turns out that high-frequency address mapping is also time-consuming...) Refs: link1, link2
-
Implement Phong/Blinn-Phong illumination algorithm.
-
Regular light source for lighting: point light source, spot light source, and direcitonal light source.
- Tangent space normal mapping.
- Reinhard tone mapping (from HDR -> LDR).
- Multi sampling anti-aliasing (MSAA 4X, and MSAA 8X)
- Alpha blending, and alpha to coverage algorithm based on MSAA (order independent transparency).
- Multi-thread parallelization using tbb as backend. The cpu usage could reach to 100%.
Distributed under the MIT License. See LICENSE
for more information.