Skip to content

Commit 608a4a1

Browse files
committed
hidden faces removal (z-buffer)
1 parent 64fe955 commit 608a4a1

File tree

2 files changed

+20
-8
lines changed

2 files changed

+20
-8
lines changed

TinyRenderer.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ public class TinyRenderer extends JPanel {
1515
public static final int width = 800;
1616
public static final int height = 800;
1717

18-
public static double vertices[] = null; // Point cloud. The size equals to the number of vertices*3. E.g: in order to access to the y component of vertex index i, you should write vertices[i*3+1]
19-
public static int triangles[] = null; // Collection of triangles. The size equals to the number of triangles*3. Each triplet references indices in the vertices[] array.
18+
public static double[] vertices = null; // Point cloud. The size equals to the number of vertices*3. E.g: in order to access to the y component of vertex index i, you should write vertices[i*3+1]
19+
public static int[] triangles = null; // Collection of triangles. The size equals to the number of triangles*3. Each triplet references indices in the vertices[] array.
2020
public static BufferedImage framebuffer = null; // this image contains the rendered scene
21+
public static double[][] zbuffer = null; // z-buffer array
2122

2223
// compute the matrix product A*B
2324
public static double[][] matrix_multiply(double[][] A, double[][] B) {
@@ -64,12 +65,11 @@ public static double[][] matrix_inverse(double[][] m) {
6465
return inverse;
6566
}
6667

67-
// verify if the point (x,y) lies inside the triangle [(x0,y0), (x1,y1), (x2,y2)]
68-
public static boolean in_triangle(int x0, int y0, int x1, int y1, int x2, int y2, int x, int y) {
68+
// given a triangle [(x0,y0), (x1,y1), (x2,y2)], compute barycentric coordinates of the point (x,y) w.r.t the triangle
69+
public static double[] barycentric_coords(int x0, int y0, int x1, int y1, int x2, int y2, int x, int y) {
6970
double[][] A = { { x0, x1, x2 }, { y0, y1, y2 }, { 1., 1., 1. } };
7071
double[][] b = { { x }, { y }, { 1. } };
71-
double[][] coord = matrix_multiply(matrix_inverse(A), b);
72-
return coord[0][0]>=0 && coord[1][0]>=0 && coord[2][0]>=0;
72+
return matrix_transpose(matrix_multiply(matrix_inverse(A), b))[0];
7373
}
7474

7575
public void paint(Graphics g) {
@@ -116,15 +116,23 @@ public static void main(String[] args) throws FileNotFoundException, IOException
116116
}
117117

118118
framebuffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
119+
zbuffer = new double[width][height]; // initialize the z-buffer
120+
for (int i=0; i<width; i++) {
121+
for (int j=0; j<height; j++) {
122+
zbuffer[i][j] = -1;
123+
}
124+
}
119125
Random rand = new Random();
120126

121127
for (int t=0; t<triangles.length/3; t++) { // iterate through all triangles
122128
int color = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)).getRGB();
123129
int[] x = new int[3]; // triangle in screen coordinates
124130
int[] y = new int[3];
131+
double[] z = new double[3];
125132
for (int v=0; v<3; v++) {
126133
double xw = vertices[triangles[t*3+v]*3+0]; // world coordinates
127134
double yw = vertices[triangles[t*3+v]*3+1];
135+
z[v] = vertices[triangles[t*3+v]*3+2];
128136
x[v] = (int)( width*(xw+1.)/2.+.5); // world-to-screen transformation
129137
y[v] = (int)(height*(1.-yw)/2.+.5); // y is flipped to get a "natural" y orientation (origin in the bottom left corner)
130138
}
@@ -139,9 +147,13 @@ public static void main(String[] args) throws FileNotFoundException, IOException
139147
bbmaxx = Math.min(width-1, Math.max(bbmaxx, x[v]));
140148
bbmaxy = Math.min(height-1, Math.max(bbmaxy, y[v]));
141149
}
142-
for (int px=bbminx; px<=bbmaxx; px++) {
150+
for (int px=bbminx; px<=bbmaxx; px++) { // rasterize the bounding box
143151
for (int py=bbminy; py<=bbmaxy; py++) {
144-
if (!in_triangle(x[0], y[0], x[1], y[1], x[2], y[2], px, py)) continue;
152+
double[] coord = barycentric_coords(x[0], y[0], x[1], y[1], x[2], y[2], px, py);
153+
if (coord[0]<0 || coord[1]<0 || coord[2]<0) continue; // discard the point outside the triangle
154+
double pz = coord[0]*z[0] + coord[1]*z[1] + coord[2]*z[2]; // compute the depth of the fragment
155+
if (zbuffer[px][py]>pz) continue; // discard the fragment if it lies behind the z-buffer
156+
zbuffer[px][py] = pz;
145157
framebuffer.setRGB(px, py, color);
146158
}
147159
}

drop.png

12.7 KB
Loading

0 commit comments

Comments
 (0)