I’m trying to make a simple Raytracer with Numba, but I have this error and can’t find the specific line that is causing it or how to solve it:
Traceback (most recent call last):
File "C:\Users\Yoyo\projects\experiments\nrt.py", line 123, in <module>
main()
File "C:\Users\Yoyo\projects\experiments\nrt.py", line 115, in main
render(arr, SX, SY, PROJ_DIST, CAM_POS, CAM_COORDS, RADIUS)
File "C:\Users\Yoyo\projects\experiments\venv\lib\site-packages\numba\core\dispatcher.py", line 468, in _compile_for_args
error_rewrite(e, 'typing')
File "C:\Users\Yoyo\projects\experiments\venv\lib\site-packages\numba\core\dispatcher.py", line 409, in error_rewrite
raise e.with_traceback(None)
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Cannot unify int64 and array(float64, 1d, C) for 'n.2', defined at C:\Users\Yoyo\projects\experiments\nrt.py (81)
File "nrt.py", line 81:
def render(arr, sx, sy, proj_dist, cam_pos, cam_coords, radius):
<source elided>
for n in range(AA_V_SAMPLES):
for m in range(AA_H_SAMPLES):
^
During: typing of assignment at C:\Users\Yoyo\projects\experiments\nrt.py (81)
File "nrt.py", line 81:
def render(arr, sx, sy, proj_dist, cam_pos, cam_coords, radius):
<source elided>
for n in range(AA_V_SAMPLES):
for m in range(AA_H_SAMPLES):
^
You can see my source code here: experiments/nrt.py at main · HenrYxZ/experiments · GitHub
Or here:
from math import sqrt
from numba import njit
import numpy as np
from PIL import Image
import utils
SCREEN_WIDTH = 280
SCREEN_HEIGHT = 210
COLOR_CHANNELS = 3
AA_H_SAMPLES = 1
AA_V_SAMPLES = 1
AA_SAMPLES = AA_V_SAMPLES * AA_H_SAMPLES
RADIUS = 0.5
SPHERE_POS = np.array((0.0, 0.0, 0.0))
SX = 2.0
SY = 1.5
PROJ_DIST = 2.0
CAM_POS = np.array((0.0, 0.0, -2.0))
CAM_COORDS = np.array((
(1.0, 0.0, 0.0), # n0
(0.0, 1.0, 0.0), # n1
(0.0, 0.0, 1.0) # n2
))
MAT_COL = np.array((128 / 255.0, 0.0, 128 / 255.0))
C0 = MAT_COL * 0.2 # Lowest possible material color
BG_COLOR = np.zeros(COLOR_CHANNELS)
LIGHT_DIR = utils.normalize(np.array([-0.3, 1.0, -0.5]))
rng = np.random.default_rng()
@njit
def project_pixel(sx, sy, n0, n1, h, w, pixel_coords, p00):
"""
Get the projection point for a given screen pixel
Args:
sx:
sy:
n0:
n1:
h:
w:
pixel_coords (tuple[float]):
p00 (ndarray):
Returns:
ndarray: The projection point in 3D coordinates
"""
xp = (pixel_coords[0] / w) * sx
yp = ((h - pixel_coords[1]) / h) * sy
pp = p00 + n0 * xp + n1 * yp
return pp
@njit
def intersect(pp, nr, pos, radius) -> float:
diff = pp - pos
b = np.dot(nr, diff)
c = np.dot(diff, diff) - radius ** 2
discriminant = b ** 2 - c
if b > 0 or discriminant < 0:
return -1.0
t = -b - sqrt(discriminant)
return t
@njit
def render(arr, sx, sy, proj_dist, cam_pos, cam_coords, radius):
h, w, _ = arr.shape
n0, n1, n2 = cam_coords
p00 = cam_pos + (n0 * (-sx / 2) + n1 * (-sy / 2) + n2 * proj_dist)
for j in range(h):
for i in range(w):
color = np.zeros(COLOR_CHANNELS)
for n in range(AA_V_SAMPLES):
for m in range(AA_H_SAMPLES):
offsets = rng.random(2)
pixel_coords = (
i + (m + offsets[0]) / AA_H_SAMPLES,
j + (n + offsets[1]) / AA_V_SAMPLES
)
# Project pixel to point in 3D coordinates
pp = project_pixel(
sx, sy, n0, n1, h, w, pixel_coords, p00
)
# Shoot ray
nr = utils.normalize(pp - cam_pos)
t = intersect(cam_pos, nr, SPHERE_POS, radius)
# print(t)
if t > 0:
p_hit = cam_pos + nr * t
n = utils.normalize(p_hit - SPHERE_POS)
color += np.maximum(np.dot(n, LIGHT_DIR) * MAT_COL, C0)
else:
color += BG_COLOR
color = color / AA_SAMPLES
final_color = np.empty_like(color)
np.round(color * 255, 0, final_color)
arr[j, i, 0] = int(final_color[0])
arr[j, i, 1] = int(final_color[1])
arr[j, i, 2] = int(final_color[2])
def main():
arr = np.zeros(
(SCREEN_HEIGHT, SCREEN_WIDTH, COLOR_CHANNELS), dtype=np.uint8
)
timer = utils.Timer()
with timer:
render(arr, SX, SY, PROJ_DIST, CAM_POS, CAM_COORDS, RADIUS)
img = Image.fromarray(arr)
img_path = "docs/nrt_output.png"
img.save(img_path)
print(f"Finished rendering and saved image in {img_path}")
if __name__ == '__main__':
main()
I guess it could be the last line of the render function where I try to cast a float 3D array to a 3D uint8 array (RGB)