A from-scratch, CPU-based 3D rendering engine built in Java. This project implements the complete graphics pipeline manually—from parsing raw .obj data to calculating pixel-perfect triangles—without relying on GPU APIs like OpenGL or DirectX.
- Custom 3D Pipeline: Complete implementation of Model-to-World and World-to-Screen transformations.
- Barycentric Rasterization: High-precision pixel filling that uses triangle area ratios for occupancy and depth interpolation.
- Dynamic Z-Buffering: A manual depth-buffer implementation to handle complex object overlapping and occlusion without the need for pre-sorting polygons.
- Optimized Memory Management: Uses a mutation-based approach for vertex transformations to minimize Garbage Collection overhead during high-frequency updates.
- OBJ File Parser: A custom-built parser to load 3D mesh data (vertices and faces) from standard
.objfiles. - Interactive Camera & Transform: Real-time rotation and translation of 3D entities via keyboard input.
| Key | Action |
|---|---|
UP / DOWN |
Rotate object around X-axis |
LEFT / RIGHT |
Rotate object around Y-axis |
W / S |
Translate object along Y-axis |
A / D |
Translate object along X-axis |
The TriangleDrawer uses a bounding-box approach for efficiency. For every triangle, the engine calculates the axis-aligned bounding box and iterates only through those pixels. For each pixel:
- Inside-Outside Test: Checks if the pixel center lies within the triangle boundaries using perpendicular dot products.
-
Depth Interpolation: Uses the areas of sub-triangles (Barycentric coordinates) to find the exact
$Z$ value of that pixel. -
Z-Test: If the pixel is closer than the current value in the
zBuffer, thepixelsarray is updated.
The engine relies on a custom math library (MathFuncs) for:
- Perpendicular Vectors: Used for edge detection during rasterization.
- Cross-Product Area: Efficiently calculates triangle areas to determine Barycentric weights.
- Rotation Matrices: Applied to vertices to simulate 3D movement.
- Java 17+
- Raylib-Java: The project uses Raylib-J for window management and texture blitting.
- Clone the repository.
- Ensure
raylib-javais in your project dependencies. - Update the model path in
Main.java:o = ObjFileParser.converObjFileToRenderObject("C:\\YourPath\\model.obj");
- Run
Main.java.
-
Perspective Projection: Implementing
$W$ -division for realistic "far-away" scaling. - Flat Shading: Using face normals to calculate light intensity per triangle.
- 1D Z-Buffer: Refactoring the 2D depth array into a 1D array for better CPU cache locality.
Developed as a deep-dive into the fundamentals of Computer Graphics.