Last active
March 15, 2022 14:31
-
-
Save pekkavaa/4b170e21ccd3aa12e747b7702464a727 to your computer and use it in GitHub Desktop.
NumPy triangle rasterizer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import matplotlib.pyplot as plt | |
from numpy import array | |
width = 100 | |
height = 80 | |
# The triangle | |
d = np.array([ [ [0.9, 0.5], [0.5, 0.8], [0.1, 0.15] ] ]) | |
# Calculates the distance from the edge v0-v1 to point p | |
def edgefunc(v0, v1, p): | |
px = p[:, 1] | |
py = p[:, 0] | |
return (v0[:,0] - v1[:,0])*px + (v1[:,1] - v0[:,1])*py + (v0[:,1]*v1[:,0] - v0[:,0]*v1[:,1]) | |
# Calculate the area of the parallelogram formed by the triangle | |
area = edgefunc(d[:, 2, :], d[:, 1, :], d[:, 0, :]) | |
# Create a grid of sampling positions | |
ys = np.linspace(0, 1, height, endpoint=False) | |
xs = np.linspace(0, 1, width, endpoint=False) | |
xpos = np.tile(xs, (height, 1)) | |
ypos = np.tile(ys, (width, 1)).transpose() | |
# Reshape the sampling positions to a H x W x 2 tensor | |
pos = np.moveaxis(array(list(zip(ypos, xpos))), 1, 2) | |
pos = np.reshape(pos, (height*width, 2)) | |
# Evaluate the edge functions at every position | |
w0 = edgefunc(d[:, 2, :], d[:, 1, :], pos) | |
w1 = edgefunc(d[:, 0, :], d[:, 2, :], pos) | |
w2 = edgefunc(d[:, 1, :], d[:, 0, :], pos) | |
# Only pixels inside the triangle will have color | |
mask = (w0 > 0) & (w1 > 0) & (w2 > 0) | |
data = np.zeros((height * width, 3), dtype=np.uint8) | |
data[:,0] = (w0 / area[0])*255*mask | |
data[:,1] = (w1 / area[0])*255*mask | |
data[:,2] = (w2 / area[0])*255*mask | |
plt.imshow(np.reshape(data, (height, width, 3)), interpolation='nearest') | |
plt.show() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment