Custom renderer in PythonΒΆ
This test demostrates how to create an custom renderer using component extension in Python.
[1]:
%load_ext autoreload
%autoreload 2
[2]:
import os
import imageio
import pandas as pd
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import lmfunctest as ft
import lmscene
import lightmetrica as lm
[3]:
os.getpid()
[3]:
659
[4]:
%load_ext lightmetrica_jupyter
[5]:
@lm.pylm_component('renderer::ao')
class Renderer_AO(lm.Renderer):
"""Simple ambient occlusion renderer"""
def construct(self, prop):
self.film = lm.Film.castFrom(lm.comp.get(prop['output']))
if self.film is None:
return False
self.spp = prop['spp']
return True
def render(self, scene):
w = self.film.size().w
h = self.film.size().h
rng = lm.Rng(42)
lm.progress.start(w*h)
def process(index, threadid):
x = index % w
y = int(index / w)
rp = np.array([(x+.5)/w, (y+.5)/h])
ray = scene.primaryRay(rp, self.film.aspectRatio())
hit = scene.intersect(ray)
if hit is None:
return
V = 0
for i in range(self.spp):
n, u, v = hit.geom.orthonormalBasis(-ray.d)
d = lm.math.sampleCosineWeighted(rng)
r = lm.Ray(hit.geom.p, np.dot(d, [u,v,n]))
if scene.intersect(r, lm.Eps, .2) is None:
V += 1
V /= self.spp
self.film.setPixel(x, y, np.full(3, V))
lm.progress.update(y*w+x)
lm.parallel.foreach(w*h, process)
lm.progress.end()
[6]:
lm.init('user::default', {})
[7]:
lm.parallel.init('parallel::openmp', {
'numThreads': 1
})
[8]:
lm.log.init('logger::jupyter', {})
[9]:
lm.progress.init('progress::jupyter', {})
[10]:
lm.info()
[I|0.032|114@user ] Lightmetrica -- Version 3.0.0 (rev. fe30e7c) Linux x64
[11]:
# Scene
lm.asset('film_output', 'film::bitmap', {
'w': 640,
'h': 360
})
lmscene.load(ft.env.scene_path, 'fireplace_room')
[I|0.050|48@assets ] Loading asset [name='film_output']
[I|0.060|48@assets ] Loading asset [name='camera_main']
[I|0.061|48@assets ] Loading asset [name='model_obj']
[I|0.061|29@objload] Loading OBJ file [path='fireplace_room.obj']
[I|0.061|169@objloa] Loading MTL file [path='fireplace_room.mtl']
[I|0.061|44@texture] Loading texture [path='wood.ppm']
[I|0.165|44@texture] Loading texture [path='leaf.ppm']
[I|0.168|44@texture] Loading texture [path='picture8.ppm']
[I|0.208|44@texture] Loading texture [path='wood5.ppm']
[12]:
lm.build('accel::sahbvh', {})
[I|0.666|246@scene ] Building acceleration structure [name='accel::sahbvh']
[I|0.666|131@accel_] Flattening scene
[I|0.695|261@accel_] Building
[13]:
lm.render('renderer::ao', {
'output': lm.asset('film_output'),
'spp': 5
})
[I|1.475|151@user ] Starting render [name='renderer::ao']
[14]:
img = np.flip(np.copy(lm.buffer(lm.asset('film_output'))), axis=0)
[15]:
f = plt.figure(figsize=(15,15))
ax = f.add_subplot(111)
ax.imshow(np.clip(np.power(img,1/2.2),0,1))
plt.show()