def create_mesh(indices, vertices, normals, uvs): indices = torch.tensor(indices, dtype = torch.int32, device = pyredner.get_device()) vertices = torch.tensor(vertices, device = pyredner.get_device()) if len(uvs) == 0: uvs = None else: uvs = torch.tensor(uvs, device = pyredner.get_device()) if len(normals) == 0: normals = None else: normals = torch.tensor(normals, device = pyredner.get_device()) return TriangleMesh(vertices, indices, uvs, normals)
def __init__(self, diffuse_reflectance, specular_reflectance = None, roughness = None, two_sided = False): if specular_reflectance is None: specular_reflectance = pyredner.Texture(\ torch.tensor([0.0,0.0,0.0], device = pyredner.get_device())) if roughness is None: roughness = pyredner.Texture(\ torch.tensor([1.0], device = pyredner.get_device())) # Convert to constant texture if necessary if isinstance(diffuse_reflectance, torch.Tensor): diffuse_reflectance = pyredner.Texture(diffuse_reflectance) if isinstance(specular_reflectance, torch.Tensor): specular_reflectance = pyredner.Texture(specular_reflectance) if isinstance(roughness, torch.Tensor): roughness = pyredner.Texture(roughness) assert(diffuse_reflectance.texels.is_contiguous()) assert(diffuse_reflectance.texels.dtype == torch.float32) assert(specular_reflectance.texels.is_contiguous()) assert(specular_reflectance.texels.dtype == torch.float32) assert(roughness.texels.is_contiguous()) assert(roughness.texels.dtype == torch.float32) if pyredner.get_use_gpu(): assert(diffuse_reflectance.texels.is_cuda) assert(specular_reflectance.texels.is_cuda) assert(roughness.texels.is_cuda) else: assert(not diffuse_reflectance.texels.is_cuda) assert(not specular_reflectance.texels.is_cuda) assert(not roughness.texels.is_cuda) self.diffuse_reflectance = diffuse_reflectance self.specular_reflectance = specular_reflectance self.roughness = roughness self.two_sided = two_sided
# randomly generate distortion parameters torch.manual_seed(1234) target_distort_params = (torch.rand(8) - 0.5) * 0.05 resolution = (256, 256) cam = pyredner.Camera(position = position, look_at = look_at, up = up, fov = fov, clip_near = clip_near, resolution = resolution, distortion_params = target_distort_params) checkerboard_texture = pyredner.imread('scenes/teapot.png') if pyredner.get_use_gpu(): checkerboard_texture = checkerboard_texture.cuda(device = pyredner.get_device()) mat_checkerboard = pyredner.Material(\ diffuse_reflectance = checkerboard_texture) mat_black = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device())) plane = pyredner.Object(vertices = torch.tensor([[-1.0,-1.0, 0.0], [-1.0, 1.0, 0.0], [ 1.0,-1.0, 0.0], [ 1.0, 1.0, 0.0]], device = pyredner.get_device()), indices = torch.tensor([[0, 1, 2], [1, 3, 2]], dtype = torch.int32, device = pyredner.get_device()),
def load_obj(filename, obj_group = True): """ Load from a Wavefront obj file as PyTorch tensors. XXX: this is slow, maybe move to C++? """ vertices_pool = [] uvs_pool = [] normals_pool = [] indices = [] vertices = [] normals = [] uvs = [] vertices_map = {} material_map = {} current_mtllib = {} current_material_name = None def create_mesh(indices, vertices, normals, uvs): indices = torch.tensor(indices, dtype = torch.int32, device = pyredner.get_device()) vertices = torch.tensor(vertices, device = pyredner.get_device()) if len(uvs) == 0: uvs = None else: uvs = torch.tensor(uvs, device = pyredner.get_device()) if len(normals) == 0: normals = None else: normals = torch.tensor(normals, device = pyredner.get_device()) return TriangleMesh(vertices, indices, uvs, normals) mesh_list = [] light_map = {} f = open(filename, 'r') d = os.path.dirname(filename) cwd = os.getcwd() if d != '': os.chdir(d) for line in f: line = line.strip() splitted = re.split('\ +', line) if splitted[0] == 'mtllib': current_mtllib = load_mtl(splitted[1]) elif splitted[0] == 'usemtl': if len(indices) > 0 and obj_group is True: # Flush mesh_list.append((current_material_name, create_mesh(indices, vertices, normals, uvs))) indices = [] vertices = [] normals = [] uvs = [] vertices_map = {} mtl_name = splitted[1] current_material_name = mtl_name if mtl_name not in material_map: m = current_mtllib[mtl_name] if m.map_Kd is None: diffuse_reflectance = torch.tensor(m.Kd, dtype = torch.float32, device = pyredner.get_device()) else: diffuse_reflectance = pyredner.imread(m.map_Kd) if pyredner.get_use_gpu(): diffuse_reflectance = diffuse_reflectance.cuda(device = pyredner.get_device()) if m.map_Ks is None: specular_reflectance = torch.tensor(m.Ks, dtype = torch.float32, device = pyredner.get_device()) else: specular_reflectance = pyredner.imread(m.map_Ks) if pyredner.get_use_gpu(): specular_reflectance = specular_reflectance.cuda(device = pyredner.get_device()) if m.map_Ns is None: roughness = torch.tensor([2.0 / (m.Ns + 2.0)], dtype = torch.float32, device = pyredner.get_device()) else: roughness = 2.0 / (pyredner.imread(m.map_Ks) + 2.0) if pyredner.get_use_gpu(): roughness = roughness.cuda(device = pyredner.get_device()) if m.Ke != (0.0, 0.0, 0.0): light_map[mtl_name] = torch.tensor(m.Ke, dtype = torch.float32) material_map[mtl_name] = pyredner.Material(\ diffuse_reflectance, specular_reflectance, roughness) elif splitted[0] == 'v': vertices_pool.append([float(splitted[1]), float(splitted[2]), float(splitted[3])]) elif splitted[0] == 'vt': uvs_pool.append([float(splitted[1]), float(splitted[2])]) elif splitted[0] == 'vn': normals_pool.append([float(splitted[1]), float(splitted[2]), float(splitted[3])]) elif splitted[0] == 'f': def num_indices(x): return len(re.split('/', x)) def get_index(x, i): return int(re.split('/', x)[i]) def parse_face_index(x, i): f = get_index(x, i) if f < 0: if (i == 0): f += len(vertices) if (i == 1): f += len(uvs) else: f -= 1 return f assert(len(splitted) <= 5) def get_vertex_id(indices): pi = parse_face_index(indices, 0) uvi = None if (num_indices(indices) > 1 and re.split('/', indices)[1] != ''): uvi = parse_face_index(indices, 1) ni = None if (num_indices(indices) > 2 and re.split('/', indices)[2] != ''): ni = parse_face_index(indices, 2) key = (pi, uvi, ni) if key in vertices_map: return vertices_map[key] vertex_id = len(vertices) vertices_map[key] = vertex_id vertices.append(vertices_pool[pi]) if uvi is not None: uvs.append(uvs_pool[uvi]) if ni is not None: normals.append(normals_pool[ni]) return vertex_id vid0 = get_vertex_id(splitted[1]) vid1 = get_vertex_id(splitted[2]) vid2 = get_vertex_id(splitted[3]) indices.append([vid0, vid1, vid2]) if (len(splitted) == 5): vid3 = get_vertex_id(splitted[4]) indices.append([vid0, vid2, vid3]) mesh_list.append((current_material_name, create_mesh(indices, vertices, normals, uvs))) if d != '': os.chdir(cwd) return material_map, mesh_list, light_map
look_at = torch.tensor([0.0, 0.0, 0.0]) up = torch.tensor([0.0, 1.0, 0.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position = position, look_at = look_at, up = up, fov = fov, clip_near = clip_near, resolution = resolution) mat_green = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.35, 0.75, 0.35], device = pyredner.get_device())) mat_red = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.75, 0.35, 0.35], device = pyredner.get_device())) mat_black = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device())) materials = [mat_green,mat_red,mat_black] tri0_vertices = torch.tensor(\ [[-1.7,1.0,0.0], [1.0,1.0,0.0], [-0.5,-1.0,0.0]], device = pyredner.get_device()) tri1_vertices = torch.tensor(\ [[-1.0,1.5,1.0], [0.2,1.5,1.0], [0.2,-1.5,1.0]], device = pyredner.get_device()) tri0_indices = torch.tensor([[0, 1, 2]], dtype = torch.int32, device = pyredner.get_device()) tri1_indices = torch.tensor([[0, 1, 2]], dtype = torch.int32, device = pyredner.get_device())
render = pyredner.RenderFunction.apply img = render(0, *scene_args) pyredner.imwrite(img.cpu(), 'results/pose_estimation/target.exr') pyredner.imwrite(img.cpu(), 'results/pose_estimation/target.png') target = pyredner.imread('results/pose_estimation/target.exr') if pyredner.get_use_gpu(): target = target.cuda() # Now we want to generate the initial guess. # We want to rotate and translate the teapot. We do this by declaring # PyTorch tensors of translation and rotation parameters, # then apply them to all teapot vertices. # The translation and rotation parameters have very different ranges, so we normalize them # by multiplying the translation parameters 100 to map to the actual translation amounts. translation_params = torch.tensor([0.1, -0.1, 0.1], device = pyredner.get_device(), requires_grad=True) translation = translation_params * 100.0 euler_angles = torch.tensor([0.1, -0.1, 0.1], requires_grad=True) # We obtain the teapot vertices we want to apply the transformation on. shape0_vertices = shapes[0].vertices.clone() shape1_vertices = shapes[1].vertices.clone() # We can use pyredner.gen_rotate_matrix to generate 3x3 rotation matrices rotation_matrix = pyredner.gen_rotate_matrix(euler_angles) if pyredner.get_use_gpu(): rotation_matrix = rotation_matrix.cuda() center = torch.mean(torch.cat([shape0_vertices, shape1_vertices]), 0) # We shift the vertices to the center, apply rotation matrix, # then shift back to the original space. shapes[0].vertices = \ (shape0_vertices - center) @ torch.t(rotation_matrix) + \ center + translation
max_bounces = 5) # Set max_bounces = 5 for global illumination render = pyredner.RenderFunction.apply img = render(0, *scene_args) pyredner.imwrite(img.cpu(), 'results/coarse_to_fine_estimation/target.exr') pyredner.imwrite(img.cpu(), 'results/coarse_to_fine_estimation/target.png') target = pyredner.imread('results/coarse_to_fine_estimation/target.exr') if pyredner.get_use_gpu(): target = target.cuda() # Now let's generate an initial guess by perturbing the reference. # Let's set all the diffuse color to gray by manipulating material.diffuse_reflectance. # We also store all the material variables to optimize in a list. material_vars = [] for mi, m in enumerate(scene.materials): var = torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device(), requires_grad = True) material_vars.append(var) m.diffuse_reflectance = pyredner.Texture(var) # And let's also slightly perturb the camera up vector and field of view a bit up = torch.tensor([0.2, 0.8, -0.2], requires_grad = True) fov = torch.tensor([41.0], requires_grad = True) cam_vars = [up, fov] scene.camera = pyredner.Camera(\ position = scene.camera.position, look_at = scene.camera.look_at, up = up, fov = fov, clip_near = scene.camera.clip_near, resolution = scene.camera.resolution)
position = torch.tensor([0.0, 2.0, -4.0]) look_at = torch.tensor([0.0, -2.0, 0.0]) up = torch.tensor([0.0, 1.0, 0.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position = position, look_at = look_at, up = up, fov = fov, clip_near = clip_near, resolution = resolution) mat_shiny = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device()), specular_reflectance = torch.tensor([1.0, 1.0, 1.0], device = pyredner.get_device()), roughness = torch.tensor([0.0005], device = pyredner.get_device())) mat_grey = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device())) mat_black = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device())) materials = [mat_shiny, mat_grey, mat_black] floor_vertices = torch.tensor([[-4.0,0.0,-4.0],[-4.0,0.0,4.0],[4.0,0.0,-4.0],[4.0,0.0,4.0]], device = pyredner.get_device()) floor_indices = torch.tensor([[0,1,2], [1,3,2]], device = pyredner.get_device(), dtype = torch.int32) shape_floor = pyredner.Shape(floor_vertices, floor_indices, None, None, 0)
look_at = torch.tensor([0.0, 0.0, 0.0]) up = torch.tensor([0.0, 0.0, 1.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position=position, look_at=look_at, up=up, fov=fov, clip_near=clip_near, resolution=resolution) mat_grey = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device())) mat_black = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device())) materials = [mat_grey, mat_black] floor_vertices = torch.tensor([[-20.0, 0.0, -20.0], [-20.0, 0.0, 20.0], [20.0, 0.0, -20.0], [20.0, 0.0, 20.0]], device=pyredner.get_device()) floor_indices = torch.tensor([[0, 1, 2], [1, 3, 2]], device=pyredner.get_device(), dtype=torch.int32) shape_floor = pyredner.Shape(floor_vertices, floor_indices, None, None, 0) blocker_vertices = torch.tensor(\ [[-0.5,10.0,-0.5],[-0.5,10.0,0.5],[0.5,10.0,-0.5],[0.5,10.0,0.5]], device = pyredner.get_device())
def load_obj(filename: str, obj_group: bool = True, flip_tex_coords: bool = True, use_common_indices: bool = False, return_objects: bool = False, device: Optional[torch.device] = None): """ Load from a Wavefront obj file as PyTorch tensors. Args ==== filename: str Path to the obj file. obj_group: bool Split the meshes based on materials. flip_tex_coords: bool Flip the v coordinate of uv by applying v' = 1 - v. use_common_indices: bool Use the same indices for position, uvs, normals. Not recommended since texture seams in the objects sharing. The same positions would cause the optimization to "tear" the object. return_objects: bool Output list of Object instead. If there is no corresponding material for a shape, assign a grey material. device: Optional[torch.device] Which device should we store the data in. If set to None, use the device from pyredner.get_device(). Returns ======= if return_objects == True, return a list of Object if return_objects == False, return (material_map, mesh_list, light_map), material_map -> Map[mtl_name, WavefrontMaterial] mesh_list -> List[TriangleMesh] light_map -> Map[mtl_name, torch.Tensor] """ if device is None: device = pyredner.get_device() vertices_pool = [] uvs_pool = [] normals_pool = [] indices = [] uv_indices = [] normal_indices = [] vertices = [] uvs = [] normals = [] vertices_map = {} uvs_map = {} normals_map = {} material_map = {} current_mtllib = {} current_material_name = None def create_mesh(indices, uv_indices, normal_indices, vertices, uvs, normals): indices = torch.tensor(indices, dtype = torch.int32, device = device) if len(uv_indices) == 0: uv_indices = None else: uv_indices = torch.tensor(uv_indices, dtype = torch.int32, device = device) if len(normal_indices) == 0: normal_indices = None else: normal_indices = torch.tensor(normal_indices, dtype = torch.int32, device = device) vertices = torch.tensor(vertices, device = device) if len(uvs) == 0: uvs = None else: uvs = torch.tensor(uvs, device = device) if len(normals) == 0: normals = None else: normals = torch.tensor(normals, device = device) return TriangleMesh(indices, uv_indices, normal_indices, vertices, uvs, normals) mesh_list = [] light_map = {} with open(filename, 'r') as f: d = os.path.dirname(filename) cwd = os.getcwd() if d != '': os.chdir(d) for line in f: line = line.strip() splitted = re.split('\ +', line) if splitted[0] == 'mtllib': current_mtllib = load_mtl(splitted[1]) elif splitted[0] == 'usemtl': if len(indices) > 0 and obj_group is True: # Flush mesh_list.append((current_material_name, create_mesh(indices, uv_indices, normal_indices, vertices, uvs, normals))) indices = [] uv_indices = [] normal_indices = [] vertices = [] normals = [] uvs = [] vertices_map = {} uvs_map = {} normals_map = {} mtl_name = splitted[1] current_material_name = mtl_name if mtl_name not in material_map: m = current_mtllib[mtl_name] if m.map_Kd is None: diffuse_reflectance = torch.tensor(m.Kd, dtype = torch.float32, device = device) else: diffuse_reflectance = pyredner.imread(m.map_Kd).to(device) if m.map_Ks is None: specular_reflectance = torch.tensor(m.Ks, dtype = torch.float32, device = device) else: specular_reflectance = pyredner.imread(m.map_Ks).to(device) if m.map_Ns is None: roughness = torch.tensor([2.0 / (m.Ns + 2.0)], dtype = torch.float32, device = device) else: roughness = 2.0 / (pyredner.imread(m.map_Ns) + 2.0) roughness = roughness.to(device) if m.Ke != (0.0, 0.0, 0.0): light_map[mtl_name] = torch.tensor(m.Ke, dtype = torch.float32) material_map[mtl_name] = pyredner.Material(\ diffuse_reflectance, specular_reflectance, roughness) elif splitted[0] == 'v': vertices_pool.append([float(splitted[1]), float(splitted[2]), float(splitted[3])]) elif splitted[0] == 'vt': u = float(splitted[1]) v = float(splitted[2]) if flip_tex_coords: v = 1 - v uvs_pool.append([u, v]) elif splitted[0] == 'vn': normals_pool.append([float(splitted[1]), float(splitted[2]), float(splitted[3])]) elif splitted[0] == 'f': def num_indices(x): return len(re.split('/', x)) def get_index(x, i): return int(re.split('/', x)[i]) def parse_face_index(x, i): f = get_index(x, i) if f > 0: f -= 1 return f assert(len(splitted) <= 5) def get_vertex_id(indices): pi = parse_face_index(indices, 0) uvi = None if (num_indices(indices) > 1 and re.split('/', indices)[1] != ''): uvi = parse_face_index(indices, 1) ni = None if (num_indices(indices) > 2 and re.split('/', indices)[2] != ''): ni = parse_face_index(indices, 2) if use_common_indices: # vertex, uv, normals share the same indexing key = (pi, uvi, ni) if key in vertices_map: vertex_id = vertices_map[key] return vertex_id, vertex_id, vertex_id vertex_id = len(vertices) vertices_map[key] = vertex_id vertices.append(vertices_pool[pi]) if uvi is not None: uvs.append(uvs_pool[uvi]) if ni is not None: normals.append(normals_pool[ni]) return vertex_id, vertex_id, vertex_id else: # vertex, uv, normals use separate indexing vertex_id = None uv_id = None normal_id = None if pi in vertices_map: vertex_id = vertices_map[pi] else: vertex_id = len(vertices) vertices.append(vertices_pool[pi]) vertices_map[pi] = vertex_id if uvi is not None: if uvi in uvs_map: uv_id = uvs_map[uvi] else: uv_id = len(uvs) uvs.append(uvs_pool[uvi]) uvs_map[uvi] = uv_id if ni is not None: if ni in normals_map: normal_id = normals_map[ni] else: normal_id = len(normals) normals.append(normals_pool[ni]) normals_map[ni] = normal_id return vertex_id, uv_id, normal_id vid0, uv_id0, n_id0 = get_vertex_id(splitted[1]) vid1, uv_id1, n_id1 = get_vertex_id(splitted[2]) vid2, uv_id2, n_id2 = get_vertex_id(splitted[3]) indices.append([vid0, vid1, vid2]) if uv_id0 is not None: assert(uv_id1 is not None and uv_id2 is not None) uv_indices.append([uv_id0, uv_id1, uv_id2]) if n_id0 is not None: assert(n_id1 is not None and n_id2 is not None) normal_indices.append([n_id0, n_id1, n_id2]) if (len(splitted) == 5): vid3, uv_id3, n_id3 = get_vertex_id(splitted[4]) indices.append([vid0, vid2, vid3]) if uv_id0 is not None: assert(uv_id3 is not None) uv_indices.append([uv_id0, uv_id2, uv_id3]) if n_id0 is not None: assert(n_id3 is not None) normal_indices.append([n_id0, n_id2, n_id3]) mesh_list.append((current_material_name, create_mesh(indices, uv_indices, normal_indices, vertices, uvs, normals))) if d != '': os.chdir(cwd) if return_objects: objects = [] for mtl_name, mesh in mesh_list: if mtl_name in material_map: m = material_map[mtl_name] else: m = pyredner.Material(diffuse_reflectance = \ torch.tensor((0.5, 0.5, 0.5), device = device)) if mtl_name in light_map: l = light_map[mtl_name] else: l = None objects.append(pyredner.Object(\ vertices = mesh.vertices, indices = mesh.indices, material = m, light_intensity = l, uvs = mesh.uvs, normals = mesh.normals, uv_indices = mesh.uv_indices, normal_indices = mesh.normal_indices)) return objects else: return material_map, mesh_list, light_map
def backward(ctx, grad_img): if not grad_img.is_contiguous(): grad_img = grad_img.contiguous() scene = ctx.scene options = ctx.options d_cam_position = torch.zeros(3) d_cam_look = torch.zeros(3) d_cam_up = torch.zeros(3) d_ndc_to_cam = torch.zeros(3, 3) d_cam_to_ndc = torch.zeros(3, 3) d_camera = redner.DCamera(redner.float_ptr(d_cam_position.data_ptr()), redner.float_ptr(d_cam_look.data_ptr()), redner.float_ptr(d_cam_up.data_ptr()), redner.float_ptr(d_ndc_to_cam.data_ptr()), redner.float_ptr(d_cam_to_ndc.data_ptr())) d_vertices_list = [] d_uvs_list = [] d_normals_list = [] d_shapes = [] for shape in ctx.shapes: num_vertices = shape.num_vertices d_vertices = torch.zeros(num_vertices, 3, device = pyredner.get_device()) d_uvs = torch.zeros(num_vertices, 2, device = pyredner.get_device()) if shape.has_uvs() else None d_normals = torch.zeros(num_vertices, 3, device = pyredner.get_device()) if shape.has_normals() else None d_vertices_list.append(d_vertices) d_uvs_list.append(d_uvs) d_normals_list.append(d_normals) d_shapes.append(redner.DShape(\ redner.float_ptr(d_vertices.data_ptr()), redner.float_ptr(d_uvs.data_ptr() if d_uvs is not None else 0), redner.float_ptr(d_normals.data_ptr() if d_normals is not None else 0))) d_diffuse_list = [] d_specular_list = [] d_roughness_list = [] d_materials = [] for material in ctx.materials: diffuse_size = material.get_diffuse_size() specular_size = material.get_specular_size() roughness_size = material.get_roughness_size() if diffuse_size[0] == 0: d_diffuse = torch.zeros(3, device = pyredner.get_device()) else: d_diffuse = torch.zeros(diffuse_size[2], diffuse_size[1], diffuse_size[0], 3, device = pyredner.get_device()) if specular_size[0] == 0: d_specular = torch.zeros(3, device = pyredner.get_device()) else: d_specular = torch.zeros(specular_size[2], specular_size[1], specular_size[0], 3, device = pyredner.get_device()) if roughness_size[0] == 0: d_roughness = torch.zeros(1, device = pyredner.get_device()) else: d_roughness = torch.zeros(roughness_size[2], roughness_size[1], roughness_size[0], 1, device = pyredner.get_device()) d_diffuse_list.append(d_diffuse) d_specular_list.append(d_specular) d_roughness_list.append(d_roughness) d_diffuse_uv_scale = torch.zeros(2) d_specular_uv_scale = torch.zeros(2) d_roughness_uv_scale = torch.zeros(2) d_diffuse_tex = redner.Texture3(\ redner.float_ptr(d_diffuse.data_ptr()), diffuse_size[0], diffuse_size[1], diffuse_size[2], redner.float_ptr(d_diffuse_uv_scale.data_ptr())) d_specular_tex = redner.Texture3(\ redner.float_ptr(d_specular.data_ptr()), specular_size[0], specular_size[1], specular_size[2], redner.float_ptr(d_specular_uv_scale.data_ptr())) d_roughness_tex = redner.Texture1(\ redner.float_ptr(d_roughness.data_ptr()), roughness_size[0], roughness_size[1], roughness_size[2], redner.float_ptr(d_roughness_uv_scale.data_ptr())) d_materials.append(redner.DMaterial(\ d_diffuse_tex, d_specular_tex, d_roughness_tex)) d_intensity_list = [] d_area_lights = [] for light in ctx.area_lights: d_intensity = torch.zeros(3, device = pyredner.get_device()) d_intensity_list.append(d_intensity) d_area_lights.append(\ redner.DAreaLight(redner.float_ptr(d_intensity.data_ptr()))) d_envmap = None if ctx.envmap is not None: envmap = ctx.envmap size = envmap.get_size() d_envmap_values = \ torch.zeros(size[2], size[1], size[0], 3, device = pyredner.get_device()) d_envmap_uv_scale = torch.zeros(2) d_envmap_tex = redner.Texture3(\ redner.float_ptr(d_envmap_values.data_ptr()), size[0], size[1], size[2], redner.float_ptr(d_envmap_uv_scale.data_ptr())) d_world_to_env = torch.zeros(4, 4) d_envmap = redner.DEnvironmentMap(\ d_envmap_tex, redner.float_ptr(d_world_to_env.data_ptr())) d_scene = redner.DScene(d_camera, d_shapes, d_materials, d_area_lights, d_envmap, pyredner.get_use_gpu(), pyredner.get_device().index if pyredner.get_device().index is not None else -1) if not get_use_correlated_random_number(): # Decouple the forward/backward random numbers by adding a big prime number options.seed += 1000003 options.num_samples = ctx.num_samples[1] start = time.time() redner.render(scene, options, redner.float_ptr(0), redner.float_ptr(grad_img.data_ptr()), d_scene, redner.float_ptr(0)) time_elapsed = time.time() - start if print_timing: print('Backward pass, time: %.5f s' % time_elapsed) # # For debugging # # pyredner.imwrite(grad_img, 'grad_img.exr') # # grad_img = torch.ones(256, 256, 3, device = pyredner.get_device()) # debug_img = torch.zeros(256, 256, 3) # start = time.time() # redner.render(scene, options, # redner.float_ptr(0), # redner.float_ptr(grad_img.data_ptr()), # d_scene, # redner.float_ptr(debug_img.data_ptr())) # time_elapsed = time.time() - start # if print_timing: # print('Backward pass, time: %.5f s' % time_elapsed) # pyredner.imwrite(debug_img, 'debug.exr') # pyredner.imwrite(-debug_img, 'debug_.exr') # debug_img = debug_img.numpy() # print(np.max(debug_img)) # print(np.unravel_index(np.argmax(debug_img), debug_img.shape)) # print(np.min(debug_img)) # print(np.unravel_index(np.argmin(debug_img), debug_img.shape)) # print(np.sum(debug_img) / 3) # debug_max = 0.5 # debug_min = -0.5 # debug_img = np.clip((debug_img - debug_min) / (debug_max - debug_min), 0, 1) # debug_img = debug_img[:, :, 0] # import matplotlib.cm as cm # debug_img = cm.viridis(debug_img) # skimage.io.imsave('debug.png', np.power(debug_img, 1/2.2)) # exit() ret_list = [] ret_list.append(None) # seed ret_list.append(None) # num_shapes ret_list.append(None) # num_materials ret_list.append(None) # num_lights ret_list.append(d_cam_position) ret_list.append(d_cam_look) ret_list.append(d_cam_up) ret_list.append(d_ndc_to_cam) ret_list.append(d_cam_to_ndc) ret_list.append(None) # clip near ret_list.append(None) # resolution ret_list.append(None) # fisheye num_shapes = len(ctx.shapes) for i in range(num_shapes): ret_list.append(d_vertices_list[i]) ret_list.append(None) # indices ret_list.append(d_uvs_list[i]) ret_list.append(d_normals_list[i]) ret_list.append(None) # material id ret_list.append(None) # light id num_materials = len(ctx.materials) for i in range(num_materials): ret_list.append(d_diffuse_list[i]) ret_list.append(None) # diffuse_uv_scale ret_list.append(d_specular_list[i]) ret_list.append(None) # specular_uv_scale ret_list.append(d_roughness_list[i]) ret_list.append(None) # roughness_uv_scale ret_list.append(None) # two sided num_area_lights = len(ctx.area_lights) for i in range(num_area_lights): ret_list.append(None) # shape id ret_list.append(d_intensity_list[i].cpu()) ret_list.append(None) # two sided if ctx.envmap is not None: ret_list.append(d_envmap_values) ret_list.append(None) # uv_scale ret_list.append(None) # env_to_world ret_list.append(d_world_to_env) ret_list.append(None) # sample_cdf_ys ret_list.append(None) # sample_cdf_xs ret_list.append(None) # pdf_norm else: ret_list.append(None) ret_list.append(None) ret_list.append(None) ret_list.append(None) ret_list.append(None) ret_list.append(None) ret_list.append(None) ret_list.append(None) # num samples ret_list.append(None) # num bounces ret_list.append(None) # channels ret_list.append(None) # sampler type return tuple(ret_list)
def forward(ctx, seed, *args): """ Forward rendering pass: given a scene and output an image. """ # Unpack arguments current_index = 0 num_shapes = args[current_index] current_index += 1 num_materials = args[current_index] current_index += 1 num_lights = args[current_index] current_index += 1 cam_position = args[current_index] current_index += 1 cam_look_at = args[current_index] current_index += 1 cam_up = args[current_index] current_index += 1 ndc_to_cam = args[current_index] current_index += 1 cam_to_ndc = args[current_index] current_index += 1 clip_near = args[current_index] current_index += 1 resolution = args[current_index] current_index += 1 fisheye = args[current_index] current_index += 1 camera = redner.Camera(resolution[1], resolution[0], redner.float_ptr(cam_position.data_ptr()), redner.float_ptr(cam_look_at.data_ptr()), redner.float_ptr(cam_up.data_ptr()), redner.float_ptr(ndc_to_cam.data_ptr()), redner.float_ptr(cam_to_ndc.data_ptr()), clip_near, fisheye) shapes = [] for i in range(num_shapes): vertices = args[current_index] current_index += 1 indices = args[current_index] current_index += 1 uvs = args[current_index] current_index += 1 normals = args[current_index] current_index += 1 material_id = args[current_index] current_index += 1 light_id = args[current_index] current_index += 1 assert(vertices.is_contiguous()) assert(indices.is_contiguous()) if uvs is not None: assert(uvs.is_contiguous()) if normals is not None: assert(normals.is_contiguous()) shapes.append(redner.Shape(\ redner.float_ptr(vertices.data_ptr()), redner.int_ptr(indices.data_ptr()), redner.float_ptr(uvs.data_ptr() if uvs is not None else 0), redner.float_ptr(normals.data_ptr() if normals is not None else 0), int(vertices.shape[0]), int(indices.shape[0]), material_id, light_id)) materials = [] for i in range(num_materials): diffuse_reflectance = args[current_index] current_index += 1 diffuse_uv_scale = args[current_index] current_index += 1 specular_reflectance = args[current_index] current_index += 1 specular_uv_scale = args[current_index] current_index += 1 roughness = args[current_index] current_index += 1 roughness_uv_scale = args[current_index] current_index += 1 two_sided = args[current_index] current_index += 1 assert(diffuse_reflectance.is_contiguous()) if diffuse_reflectance.dim() == 1: diffuse_reflectance = redner.Texture3(\ redner.float_ptr(diffuse_reflectance.data_ptr()), 0, 0, 0, redner.float_ptr(diffuse_uv_scale.data_ptr())) else: diffuse_reflectance = redner.Texture3(\ redner.float_ptr(diffuse_reflectance.data_ptr()), int(diffuse_reflectance.shape[2]), # width int(diffuse_reflectance.shape[1]), # height int(diffuse_reflectance.shape[0]), # num levels redner.float_ptr(diffuse_uv_scale.data_ptr())) assert(specular_reflectance.is_contiguous()) if specular_reflectance.dim() == 1: specular_reflectance = redner.Texture3(\ redner.float_ptr(specular_reflectance.data_ptr()), 0, 0, 0, redner.float_ptr(specular_uv_scale.data_ptr())) else: specular_reflectance = redner.Texture3(\ redner.float_ptr(specular_reflectance.data_ptr()), int(specular_reflectance.shape[2]), # width int(specular_reflectance.shape[1]), # height int(specular_reflectance.shape[0]), # num levels redner.float_ptr(specular_uv_scale.data_ptr())) assert(roughness.is_contiguous()) if roughness.dim() == 1: roughness = redner.Texture1(\ redner.float_ptr(roughness.data_ptr()), 0, 0, 0, redner.float_ptr(roughness_uv_scale.data_ptr())) else: assert(roughness.dim() == 4) roughness = redner.Texture1(\ redner.float_ptr(roughness.data_ptr()), int(roughness.shape[2]), # width int(roughness.shape[1]), # height int(roughness.shape[0]), # num levels redner.float_ptr(roughness_uv_scale.data_ptr())) materials.append(redner.Material(\ diffuse_reflectance, specular_reflectance, roughness, two_sided)) area_lights = [] for i in range(num_lights): shape_id = args[current_index] current_index += 1 intensity = args[current_index] current_index += 1 two_sided = args[current_index] current_index += 1 area_lights.append(redner.AreaLight(\ shape_id, redner.float_ptr(intensity.data_ptr()), two_sided)) envmap = None if args[current_index] is not None: values = args[current_index] current_index += 1 envmap_uv_scale = args[current_index] current_index += 1 env_to_world = args[current_index] current_index += 1 world_to_env = args[current_index] current_index += 1 sample_cdf_ys = args[current_index] current_index += 1 sample_cdf_xs = args[current_index] current_index += 1 pdf_norm = args[current_index] current_index += 1 values = redner.Texture3(\ redner.float_ptr(values.data_ptr()), int(values.shape[2]), # width int(values.shape[1]), # height int(values.shape[0]), # num levels redner.float_ptr(envmap_uv_scale.data_ptr())) envmap = redner.EnvironmentMap(\ values, redner.float_ptr(env_to_world.data_ptr()), redner.float_ptr(world_to_env.data_ptr()), redner.float_ptr(sample_cdf_ys.data_ptr()), redner.float_ptr(sample_cdf_xs.data_ptr()), pdf_norm) else: current_index += 7 start = time.time() scene = redner.Scene(camera, shapes, materials, area_lights, envmap, pyredner.get_use_gpu(), pyredner.get_device().index if pyredner.get_device().index is not None else -1) time_elapsed = time.time() - start if print_timing: print('Scene construction, time: %.5f s' % time_elapsed) num_samples = args[current_index] current_index += 1 max_bounces = args[current_index] current_index += 1 channels = args[current_index] current_index += 1 sampler_type = args[current_index] current_index += 1 # check that num_samples is a tuple if isinstance(num_samples, int): num_samples = (num_samples, num_samples) options = redner.RenderOptions(seed, num_samples[0], max_bounces, channels, sampler_type) num_channels = redner.compute_num_channels(channels) rendered_image = torch.zeros(resolution[0], resolution[1], num_channels, device = pyredner.get_device()) start = time.time() redner.render(scene, options, redner.float_ptr(rendered_image.data_ptr()), redner.float_ptr(0), None, redner.float_ptr(0)) time_elapsed = time.time() - start if print_timing: print('Forward pass, time: %.5f s' % time_elapsed) # # For debugging # debug_img = torch.zeros(256, 256, 3) # redner.render(scene, # options, # redner.float_ptr(rendered_image.data_ptr()), # redner.float_ptr(0), # None, # redner.float_ptr(debug_img.data_ptr())) # pyredner.imwrite(debug_img, 'debug.exr') # exit() ctx.shapes = shapes ctx.materials = materials ctx.area_lights = area_lights ctx.envmap = envmap ctx.scene = scene ctx.options = options ctx.num_samples = num_samples return rendered_image
def forward(ctx, seed, *args): """ Forward rendering pass: given a scene and output an image. """ # Unpack arguments current_index = 0 num_shapes = args[current_index] current_index += 1 num_materials = args[current_index] current_index += 1 num_lights = args[current_index] current_index += 1 cam_to_world = args[current_index] current_index += 1 world_to_cam = args[current_index] current_index += 1 fov_factor = args[current_index] current_index += 1 clip_near = args[current_index] current_index += 1 resolution = args[current_index] current_index += 1 fisheye = args[current_index] current_index += 1 assert (cam_to_world.is_contiguous()) assert (world_to_cam.is_contiguous()) camera = redner.Camera(resolution[1], resolution[0], redner.float_ptr(cam_to_world.data_ptr()), redner.float_ptr(world_to_cam.data_ptr()), fov_factor.item(), clip_near, fisheye) shapes = [] for i in range(num_shapes): vertices = args[current_index] current_index += 1 indices = args[current_index] current_index += 1 uvs = args[current_index] current_index += 1 normals = args[current_index] current_index += 1 material_id = args[current_index] current_index += 1 light_id = args[current_index] current_index += 1 assert (vertices.is_contiguous()) assert (indices.is_contiguous()) if uvs is not None: assert (uvs.is_contiguous()) if normals is not None: assert (normals.is_contiguous()) shapes.append(redner.Shape(\ redner.float_ptr(vertices.data_ptr()), redner.int_ptr(indices.data_ptr()), redner.float_ptr(uvs.data_ptr() if uvs is not None else 0), redner.float_ptr(normals.data_ptr() if normals is not None else 0), int(vertices.shape[0]), int(indices.shape[0]), material_id, light_id)) materials = [] for i in range(num_materials): diffuse_reflectance = args[current_index] current_index += 1 diffuse_uv_scale = args[current_index] current_index += 1 specular_reflectance = args[current_index] current_index += 1 specular_uv_scale = args[current_index] current_index += 1 roughness = args[current_index] current_index += 1 roughness_uv_scale = args[current_index] current_index += 1 two_sided = args[current_index] current_index += 1 assert (diffuse_reflectance.is_contiguous()) if diffuse_reflectance.dim() == 1: diffuse_reflectance = redner.Texture3(\ redner.float_ptr(diffuse_reflectance.data_ptr()), 0, 0, 0, redner.float_ptr(diffuse_uv_scale.data_ptr())) else: diffuse_reflectance = redner.Texture3(\ redner.float_ptr(diffuse_reflectance.data_ptr()), int(diffuse_reflectance.shape[2]), # width int(diffuse_reflectance.shape[1]), # height int(diffuse_reflectance.shape[0]), # num levels redner.float_ptr(diffuse_uv_scale.data_ptr())) assert (specular_reflectance.is_contiguous()) if specular_reflectance.dim() == 1: specular_reflectance = redner.Texture3(\ redner.float_ptr(specular_reflectance.data_ptr()), 0, 0, 0, redner.float_ptr(specular_uv_scale.data_ptr())) else: specular_reflectance = redner.Texture3(\ redner.float_ptr(specular_reflectance.data_ptr()), int(specular_reflectance.shape[2]), # width int(specular_reflectance.shape[1]), # height int(specular_reflectance.shape[0]), # num levels redner.float_ptr(specular_uv_scale.data_ptr())) assert (roughness.is_contiguous()) if roughness.dim() == 1: roughness = redner.Texture1(\ redner.float_ptr(roughness.data_ptr()), 0, 0, 0, redner.float_ptr(roughness_uv_scale.data_ptr())) else: roughness = redner.Texture1(\ redner.float_ptr(roughness.data_ptr()), int(roughness.shape[2]), # width int(roughness.shape[1]), # height int(roughness.shape[0]), # num levels redner.float_ptr(roughness_uv_scale.data_ptr())) materials.append(redner.Material(\ diffuse_reflectance, specular_reflectance, roughness, two_sided)) lights = [] for i in range(num_lights): shape_id = args[current_index] current_index += 1 intensity = args[current_index] current_index += 1 lights.append( redner.Light(shape_id, redner.float_ptr(intensity.data_ptr()))) scene = redner.Scene(camera, shapes, materials, lights, pyredner.get_use_gpu()) num_samples = args[current_index] current_index += 1 max_bounces = args[current_index] current_index += 1 options = redner.RenderOptions(seed, num_samples, max_bounces) rendered_image = torch.zeros(resolution[0], resolution[1], 3, device=pyredner.get_device()) redner.render(scene, options, redner.float_ptr(rendered_image.data_ptr()), redner.float_ptr(0), None, redner.float_ptr(0)) # # For debugging # debug_img = torch.zeros(256, 256, 3) # redner.render(scene, # options, # redner.float_ptr(rendered_image.data_ptr()), # redner.float_ptr(0), # None, # redner.float_ptr(debug_img.data_ptr())) # pyredner.imwrite(debug_img, 'debug.exr') # exit() ctx.shapes = shapes ctx.materials = materials ctx.lights = lights ctx.scene = scene ctx.options = options return rendered_image
def backward(ctx, grad_img): if not grad_img.is_contiguous(): grad_img = grad_img.contiguous() scene = ctx.scene options = ctx.options d_fov_factor = torch.zeros(1) d_cam_to_world = torch.zeros(4, 4) d_world_to_cam = torch.zeros(4, 4) d_camera = redner.DCamera(redner.float_ptr(d_cam_to_world.data_ptr()), redner.float_ptr(d_world_to_cam.data_ptr()), redner.float_ptr(d_fov_factor.data_ptr())) d_vertices_list = [] d_uvs_list = [] d_normals_list = [] d_shapes = [] for shape in ctx.shapes: num_vertices = shape.num_vertices d_vertices = torch.zeros(num_vertices, 3, device=pyredner.get_device()) d_uvs = torch.zeros( num_vertices, 2, device=pyredner.get_device()) if shape.has_uvs() else None d_normals = torch.zeros( num_vertices, 3, device=pyredner.get_device()) if shape.has_normals() else None d_vertices_list.append(d_vertices) d_uvs_list.append(d_uvs) d_normals_list.append(d_normals) d_shapes.append(redner.DShape(\ redner.float_ptr(d_vertices.data_ptr()), redner.float_ptr(d_uvs.data_ptr() if d_uvs is not None else 0), redner.float_ptr(d_normals.data_ptr() if d_normals is not None else 0))) d_diffuse_list = [] d_specular_list = [] d_roughness_list = [] d_materials = [] for material in ctx.materials: diffuse_size = material.get_diffuse_size() specular_size = material.get_specular_size() roughness_size = material.get_roughness_size() if diffuse_size[0] == 0: d_diffuse = torch.zeros(3, device=pyredner.get_device()) else: d_diffuse = torch.zeros(diffuse_size[2], diffuse_size[1], diffuse_size[0], 3, device=pyredner.get_device()) if specular_size[0] == 0: d_specular = torch.zeros(3, device=pyredner.get_device()) else: d_specular = torch.zeros(specular_size[2], specular_size[1], specular_size[0], 3, device=pyredner.get_device()) if roughness_size[0] == 0: d_roughness = torch.zeros(1, device=pyredner.get_device()) else: d_roughness = torch.zeros(roughness_size[2], roughness_size[1], roughness_size[0], device=pyredner.get_device()) d_diffuse_list.append(d_diffuse) d_specular_list.append(d_specular) d_roughness_list.append(d_roughness) d_diffuse_uv_scale = torch.zeros(2) d_specular_uv_scale = torch.zeros(2) d_roughness_uv_scale = torch.zeros(2) d_diffuse_tex = redner.Texture3(\ redner.float_ptr(d_diffuse.data_ptr()), diffuse_size[0], diffuse_size[1], diffuse_size[2], redner.float_ptr(d_diffuse_uv_scale.data_ptr())) d_specular_tex = redner.Texture3(\ redner.float_ptr(d_specular.data_ptr()), specular_size[0], specular_size[1], specular_size[2], redner.float_ptr(d_specular_uv_scale.data_ptr())) d_roughness_tex = redner.Texture1(\ redner.float_ptr(d_roughness.data_ptr()), roughness_size[0], roughness_size[1], roughness_size[2], redner.float_ptr(d_roughness_uv_scale.data_ptr())) d_materials.append(redner.DMaterial(\ d_diffuse_tex, d_specular_tex, d_roughness_tex)) d_intensity_list = [] d_lights = [] for light in ctx.lights: d_intensity = torch.zeros(3, device=pyredner.get_device()) d_intensity_list.append(d_intensity) d_lights.append( redner.DLight(redner.float_ptr(d_intensity.data_ptr()))) d_scene = redner.DScene(d_camera, d_shapes, d_materials, d_lights, pyredner.get_use_gpu()) if not get_use_correlated_random_number(): # Decouple the forward/backward random numbers by adding a big prime number options.seed += 1000003 redner.render(scene, options, redner.float_ptr(0), redner.float_ptr(grad_img.data_ptr()), d_scene, redner.float_ptr(0)) # # For debugging # grad_img = torch.ones(256, 256, 3) # debug_img = torch.zeros(256, 256, 3) # redner.render(scene, options, # redner.float_ptr(0), # redner.float_ptr(grad_img.data_ptr()), # d_scene, # redner.float_ptr(debug_img.data_ptr())) # pyredner.imwrite(debug_img, 'debug.exr') # exit() ret_list = [] ret_list.append(None) # seed ret_list.append(None) # num_shapes ret_list.append(None) # num_materials ret_list.append(None) # num_lights ret_list.append(d_cam_to_world) ret_list.append(d_world_to_cam) ret_list.append(d_fov_factor) ret_list.append(None) # clip near ret_list.append(None) # resolution ret_list.append(None) # fisheye num_shapes = len(ctx.shapes) for i in range(num_shapes): ret_list.append(d_vertices_list[i]) ret_list.append(None) # indices ret_list.append(d_uvs_list[i]) ret_list.append(d_normals_list[i]) ret_list.append(None) # material id ret_list.append(None) # light id num_materials = len(ctx.materials) for i in range(num_materials): ret_list.append(d_diffuse_list[i]) ret_list.append(None) # diffuse_uv_scale ret_list.append(d_specular_list[i]) ret_list.append(None) # specular_uv_scale ret_list.append(d_roughness_list[i]) ret_list.append(None) # roughness_uv_scale ret_list.append(None) # two sided num_lights = len(ctx.lights) for i in range(num_lights): ret_list.append(None) # shape id ret_list.append(d_intensity_list[i].cpu()) ret_list.append(None) # num samples ret_list.append(None) # num bounces return tuple(ret_list)
import pyredner import numpy as np import torch import scipy # Optimize for material parameters and camera pose # Use GPU if available pyredner.set_use_gpu(torch.cuda.is_available()) # Load the scene from a Mitsuba scene file scene = pyredner.load_mitsuba('scenes/teapot.xml') # The last material is the teapot material, set it to the target scene.materials[-1].diffuse_reflectance = \ pyredner.Texture(torch.tensor([0.3, 0.2, 0.2], device = pyredner.get_device())) scene.materials[-1].specular_reflectance = \ pyredner.Texture(torch.tensor([0.6, 0.6, 0.6], device = pyredner.get_device())) scene.materials[-1].roughness = \ pyredner.Texture(torch.tensor([0.05], device = pyredner.get_device())) args = pyredner.RenderFunction.serialize_scene(\ scene = scene, num_samples = 1024, max_bounces = 2) # Alias of the render function render = pyredner.RenderFunction.apply # Render our target. The first argument is the seed for RNG in the renderer. img = render(0, *args) pyredner.imwrite(img.cpu(), 'results/test_teapot_reflectance/target.exr') pyredner.imwrite(img.cpu(), 'results/test_teapot_reflectance/target.png')
# Set up the scene using Pytorch tensor position = torch.tensor([0.0, 0.0, -5.0]) look_at = torch.tensor([0.0, 0.0, 0.0]) up = torch.tensor([0.0, 1.0, 0.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position = position, look_at = look_at, up = up, fov = fov, clip_near = clip_near, resolution = resolution) if pyredner.get_use_gpu(): diffuse = diffuse.cuda(device = pyredner.get_device()) specular = specular.cuda(device = pyredner.get_device()) roughness = roughness.cuda(device = pyredner.get_device()) mat_perlin = pyredner.Material(\ diffuse_reflectance = diffuse, specular_reflectance = specular, roughness = roughness) mat_black = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device())) materials = [mat_perlin, mat_black] vertices = torch.tensor([[-1.5,-1.5,0.0], [-1.5,1.5,0.0], [1.5,-1.5,0.0], [1.5,1.5,0.0]], device = pyredner.get_device()) indices = torch.tensor([[0, 1, 2], [1, 3, 2]], dtype = torch.int32, device = pyredner.get_device()) uvs = torch.tensor([[0.05, 0.05], [0.05, 0.95], [0.95, 0.05], [0.95, 0.95]], device = pyredner.get_device())
# Set up the pyredner scene for rendering: # Setup camera cam = pyredner.Camera( position=torch.tensor([0.0, 0.0, -5.0]), look_at=torch.tensor([0.0, 0.0, 0.0]), up=torch.tensor([0.0, 1.0, 0.0]), fov=torch.tensor([45.0]), # in degree clip_near=1e-2, # needs to > 0 resolution=(256, 256), fisheye=False) # Setup materials mat_grey = pyredner.Material(\ diffuse_reflectance = \ torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device())) # The material list of the scene materials = [mat_grey] # Setup geometries shape_triangle = pyredner.Shape(\ vertices = torch.tensor([[-1.7, 1.0, 0.0], [1.0, 1.0, 0.0], [-0.5, -1.0, 0.0]], device = pyredner.get_device()), indices = torch.tensor([[0, 1, 2]], dtype = torch.int32, device = pyredner.get_device()), uvs = None, normals = None, material_id = 0) # Setup light source shape shape_light = pyredner.Shape(\ vertices = torch.tensor([[-1.0, -1.0, -7.0],
cam = pyredner.Camera(position = torch.tensor([0.0, 0.0, -5.0]), look_at = torch.tensor([0.0, 0.0, 0.0]), up = torch.tensor([0.0, 1.0, 0.0]), fov = torch.tensor([45.0]), # in degree clip_near = 1e-2, # needs to > 0 resolution = (256, 256), fisheye = False) # Next, we setup the materials for the scene. # All materials in the scene are stored in a Python list, # the index of a material in the list is its material id. # Our simple scene only has a single grey material with reflectance 0.5. # If you are using GPU, make sure to copy the reflectance to GPU memory. mat_grey = pyredner.Material(\ diffuse_reflectance = \ torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device())) # The material list of the scene materials = [mat_grey] # Next, we setup the geometry for the scene. # 3D objects in redner are called "Shape". # All shapes in the scene are stored in a Python list, # the index of a shape in the list is its shape id. # Right now, a shape is always a triangle mesh, which has a list of # triangle vertices and a list of triangle indices. # The vertices are a Nx3 torch float tensor, # and the indices are a Mx3 torch integer tensor. # Optionally, for each vertex you can specify its UV coordinate for texture mapping, # and a normal for Phong interpolation. # Each shape also needs to be assigned a material using material id, # which is the index of the material in the material array.
def forward(ctx, seed, *args): """ Forward rendering pass: given a scene and output an image. """ # Unpack arguments current_index = 0 num_shapes = args[current_index] current_index += 1 num_materials = args[current_index] current_index += 1 num_lights = args[current_index] current_index += 1 cam_position = args[current_index] current_index += 1 cam_look_at = args[current_index] current_index += 1 cam_up = args[current_index] current_index += 1 ndc_to_cam = args[current_index] current_index += 1 cam_to_ndc = args[current_index] current_index += 1 clip_near = args[current_index] current_index += 1 resolution = args[current_index] current_index += 1 camera_type = args[current_index] current_index += 1 camera = redner.Camera(resolution[1], resolution[0], redner.float_ptr(cam_position.data_ptr()), redner.float_ptr(cam_look_at.data_ptr()), redner.float_ptr(cam_up.data_ptr()), redner.float_ptr(ndc_to_cam.data_ptr()), redner.float_ptr(cam_to_ndc.data_ptr()), clip_near, camera_type) shapes = [] for i in range(num_shapes): vertices = args[current_index] current_index += 1 indices = args[current_index] current_index += 1 uvs = args[current_index] current_index += 1 normals = args[current_index] current_index += 1 material_id = args[current_index] current_index += 1 light_id = args[current_index] current_index += 1 assert(vertices.is_contiguous()) assert(indices.is_contiguous()) if uvs is not None: assert(uvs.is_contiguous()) if normals is not None: assert(normals.is_contiguous()) shapes.append(redner.Shape(\ redner.float_ptr(vertices.data_ptr()), redner.int_ptr(indices.data_ptr()), redner.float_ptr(uvs.data_ptr() if uvs is not None else 0), redner.float_ptr(normals.data_ptr() if normals is not None else 0), int(vertices.shape[0]), int(indices.shape[0]), material_id, light_id)) materials = [] for i in range(num_materials): diffuse_reflectance = args[current_index] current_index += 1 diffuse_uv_scale = args[current_index] current_index += 1 specular_reflectance = args[current_index] current_index += 1 specular_uv_scale = args[current_index] current_index += 1 roughness = args[current_index] current_index += 1 roughness_uv_scale = args[current_index] current_index += 1 normal_map = args[current_index] current_index += 1 normal_map_uv_scale = args[current_index] current_index += 1 two_sided = args[current_index] current_index += 1 assert(diffuse_reflectance.is_contiguous()) if diffuse_reflectance.dim() == 1: diffuse_reflectance = redner.Texture3(\ redner.float_ptr(diffuse_reflectance.data_ptr()), 0, 0, 0, redner.float_ptr(diffuse_uv_scale.data_ptr())) else: diffuse_reflectance = redner.Texture3(\ redner.float_ptr(diffuse_reflectance.data_ptr()), int(diffuse_reflectance.shape[2]), # width int(diffuse_reflectance.shape[1]), # height int(diffuse_reflectance.shape[0]), # num levels redner.float_ptr(diffuse_uv_scale.data_ptr())) assert(specular_reflectance.is_contiguous()) if specular_reflectance.dim() == 1: specular_reflectance = redner.Texture3(\ redner.float_ptr(specular_reflectance.data_ptr()), 0, 0, 0, redner.float_ptr(specular_uv_scale.data_ptr())) else: specular_reflectance = redner.Texture3(\ redner.float_ptr(specular_reflectance.data_ptr()), int(specular_reflectance.shape[2]), # width int(specular_reflectance.shape[1]), # height int(specular_reflectance.shape[0]), # num levels redner.float_ptr(specular_uv_scale.data_ptr())) assert(roughness.is_contiguous()) if roughness.dim() == 1: roughness = redner.Texture1(\ redner.float_ptr(roughness.data_ptr()), 0, 0, 0, redner.float_ptr(roughness_uv_scale.data_ptr())) else: assert(roughness.dim() == 4) roughness = redner.Texture1(\ redner.float_ptr(roughness.data_ptr()), int(roughness.shape[2]), # width int(roughness.shape[1]), # height int(roughness.shape[0]), # num levels redner.float_ptr(roughness_uv_scale.data_ptr())) if normal_map is not None: assert(normal_map.dim() == 4) normal_map = redner.Texture3(\ redner.float_ptr(normal_map.data_ptr()), int(normal_map.shape[2]), # width int(normal_map.shape[1]), # height int(normal_map.shape[0]), # num levels redner.float_ptr(normal_map_uv_scale.data_ptr())) else: normal_map = redner.Texture3(\ redner.float_ptr(0), 0, 0, 0, redner.float_ptr(0)) materials.append(redner.Material(\ diffuse_reflectance, specular_reflectance, roughness, normal_map, two_sided)) area_lights = [] for i in range(num_lights): shape_id = args[current_index] current_index += 1 intensity = args[current_index] current_index += 1 two_sided = args[current_index] current_index += 1 area_lights.append(redner.AreaLight(\ shape_id, redner.float_ptr(intensity.data_ptr()), two_sided)) envmap = None if args[current_index] is not None: values = args[current_index] current_index += 1 envmap_uv_scale = args[current_index] current_index += 1 env_to_world = args[current_index] current_index += 1 world_to_env = args[current_index] current_index += 1 sample_cdf_ys = args[current_index] current_index += 1 sample_cdf_xs = args[current_index] current_index += 1 pdf_norm = args[current_index] current_index += 1 values = redner.Texture3(\ redner.float_ptr(values.data_ptr()), int(values.shape[2]), # width int(values.shape[1]), # height int(values.shape[0]), # num levels redner.float_ptr(envmap_uv_scale.data_ptr())) envmap = redner.EnvironmentMap(\ values, redner.float_ptr(env_to_world.data_ptr()), redner.float_ptr(world_to_env.data_ptr()), redner.float_ptr(sample_cdf_ys.data_ptr()), redner.float_ptr(sample_cdf_xs.data_ptr()), pdf_norm) else: current_index += 7 # Options num_samples = args[current_index] current_index += 1 max_bounces = args[current_index] current_index += 1 channels = args[current_index] current_index += 1 sampler_type = args[current_index] current_index += 1 use_primary_edge_sampling = args[current_index] current_index += 1 use_secondary_edge_sampling = args[current_index] current_index += 1 start = time.time() scene = redner.Scene(camera, shapes, materials, area_lights, envmap, pyredner.get_use_gpu(), pyredner.get_device().index if pyredner.get_device().index is not None else -1, use_primary_edge_sampling, use_secondary_edge_sampling) time_elapsed = time.time() - start if print_timing: print('Scene construction, time: %.5f s' % time_elapsed) # check that num_samples is a tuple if isinstance(num_samples, int): num_samples = (num_samples, num_samples) options = redner.RenderOptions(seed, num_samples[0], max_bounces, channels, sampler_type) num_channels = redner.compute_num_channels(channels) rendered_image = torch.zeros(resolution[0], resolution[1], num_channels, device = pyredner.get_device()) start = time.time() redner.render(scene, options, redner.float_ptr(rendered_image.data_ptr()), redner.float_ptr(0), None, redner.float_ptr(0)) time_elapsed = time.time() - start if print_timing: print('Forward pass, time: %.5f s' % time_elapsed) # # For debugging # debug_img = torch.zeros(256, 256, 3) # redner.render(scene, # options, # redner.float_ptr(rendered_image.data_ptr()), # redner.float_ptr(0), # None, # redner.float_ptr(debug_img.data_ptr())) # pyredner.imwrite(debug_img, 'debug.exr') # exit() ctx.shapes = shapes ctx.materials = materials ctx.area_lights = area_lights ctx.envmap = envmap ctx.scene = scene ctx.options = options ctx.num_samples = num_samples return rendered_image
print('scene loaded') max_bounces = 6 args = pyredner.RenderFunction.serialize_scene(\ scene = scene, num_samples = 512, max_bounces = max_bounces) render = pyredner.RenderFunction.apply # Render our target. The first argument is the seed for RNG in the renderer. img = render(0, *args) pyredner.imwrite(img.cpu(), 'results/test_living_room/target.exr') pyredner.imwrite(img.cpu(), 'results/test_living_room/target.png') target = pyredner.imread('results/test_living_room/target.exr') if pyredner.get_use_gpu(): target = target.cuda(device = pyredner.get_device()) scene.camera.look_at = torch.tensor([-0.556408, 0.951295, -3.98066], requires_grad=True) scene.camera.position = torch.tensor([0.00419251, 0.973707, -4.80844], requires_grad=True) scene.camera.up = torch.tensor([-0.00920347, 0.999741, 0.020835], requires_grad=True) args = pyredner.RenderFunction.serialize_scene(\ scene = scene, num_samples = 512, max_bounces = max_bounces) img = render(1, *args) pyredner.imwrite(img.cpu(), 'results/test_living_room/init.exr') pyredner.imwrite(img.cpu(), 'results/test_living_room/init.png') diff = torch.abs(target - img) pyredner.imwrite(diff.cpu(), 'results/test_living_room/init_diff.png')
look_at = torch.tensor([0.0, 0.0, 0.0]) up = torch.tensor([0.0, 1.0, 0.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position = position, look_at = look_at, up = up, fov = fov, clip_near = clip_near, resolution = resolution) mat_grey = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device())) mat_black = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device())) materials = [mat_grey, mat_black] floor_vertices = torch.tensor([[-2.0,0.0,-2.0],[-2.0,0.0,2.0],[2.0,0.0,-2.0],[2.0,0.0,2.0]], device = pyredner.get_device()) floor_indices = torch.tensor([[0,1,2], [1,3,2]], device = pyredner.get_device(), dtype = torch.int32) shape_floor = pyredner.Shape(floor_vertices, floor_indices, None, None, 0) blocker_vertices = torch.tensor(\ [[-0.5,3.0,-0.5],[-0.5,3.0,0.5],[0.5,3.0,-0.5],[0.5,3.0,0.5]], device = pyredner.get_device()) blocker_indices = torch.tensor([[0,1,2], [1,3,2]], device = pyredner.get_device(), dtype = torch.int32)
import pyredner import numpy as np import torch # Optimize for a textured plane in a specular reflection # Use GPU if available pyredner.set_use_gpu(torch.cuda.is_available()) # Load the scene from a Mitsuba scene file scene = pyredner.load_mitsuba('scenes/teapot_specular.xml') # The last material is the teapot material, set it to a specular material scene.materials[-1].diffuse_reflectance = \ pyredner.Texture(torch.tensor([0.15, 0.2, 0.15], device = pyredner.get_device())) scene.materials[-1].specular_reflectance = \ pyredner.Texture(torch.tensor([0.8, 0.8, 0.8], device = pyredner.get_device())) scene.materials[-1].roughness = \ pyredner.Texture(torch.tensor([0.0001], device = pyredner.get_device())) args=pyredner.RenderFunction.serialize_scene(\ scene = scene, num_samples = 512, max_bounces = 2) render = pyredner.RenderFunction.apply # Render our target. The first argument is the seed for RNG in the renderer. img = render(0, *args) pyredner.imwrite(img.cpu(), 'results/test_teapot_specular/target.exr') pyredner.imwrite(img.cpu(), 'results/test_teapot_specular/target.png') target = pyredner.imread('results/test_teapot_specular/target.exr') if pyredner.get_use_gpu():
position = torch.tensor([0.0, 0.0, -5.0]) look_at = torch.tensor([0.0, 0.0, 0.0]) up = torch.tensor([0.0, 1.0, 0.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position = position, look_at = look_at, up = up, fov = fov, clip_near = clip_near, resolution = resolution) mat_grey = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device())) materials = [mat_grey] vertices = torch.tensor([[-1.3,1.0,0.0], [1.0,1.0,0.0], [-0.5,-2.0,-7.0]], device = pyredner.get_device()) indices = torch.tensor([[0, 1, 2]], dtype = torch.int32, device = pyredner.get_device()) shape_triangle = pyredner.Shape(vertices, indices, None, None, 0) light_vertices = torch.tensor([[-1.0,-1.0,-7.0],[1.0,-1.0,-7.0],[-1.0,1.0,-7.0],[1.0,1.0,-7.0]], device = pyredner.get_device()) light_indices = torch.tensor([[0,1,2],[1,3,2]], dtype = torch.int32, device = pyredner.get_device()) shape_light = pyredner.Shape(light_vertices, light_indices, None, None, 0) shapes = [shape_triangle, shape_light] light_intensity = torch.tensor([20.0,20.0,20.0]) light = pyredner.AreaLight(1, light_intensity) area_lights = [light] scene = pyredner.Scene(cam, shapes, materials, area_lights) args = pyredner.RenderFunction.serialize_scene(\ scene = scene,
look_at = torch.tensor([0.0, 0.0, 0.0]) up = torch.tensor([0.0, 1.0, 0.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position = position, look_at = look_at, up = up, fov = fov, clip_near = clip_near, resolution = resolution) mat_grey = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device())) materials = [mat_grey] vertices = torch.tensor([[-1.7,1.0,0.0], [1.0,1.0,0.0], [-0.5,-1.0,0.0]], device = pyredner.get_device()) indices = torch.tensor([[0, 1, 2]], dtype = torch.int32, device = pyredner.get_device()) shape_triangle = pyredner.Shape(vertices, indices, None, None, 0) light_vertices = torch.tensor([[-1.0,-1.0,-9.0],[1.0,-1.0,-9.0],[-1.0,1.0,-9.0],[1.0,1.0,-9.0]], device = pyredner.get_device()) light_indices = torch.tensor([[0,1,2],[1,3,2]], dtype = torch.int32, device = pyredner.get_device()) shape_light = pyredner.Shape(light_vertices, light_indices, None, None, 0) shapes = [shape_triangle, shape_light] light_intensity = torch.tensor([30.0,30.0,30.0]) light = pyredner.AreaLight(1, light_intensity) area_lights = [light]
look_at = torch.tensor([0.0, 0.0, 0.0]) up = torch.tensor([0.0, 1.0, 0.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position = position, look_at = look_at, up = up, fov = fov, clip_near = clip_near, resolution = resolution) checkerboard_texture = pyredner.imread('checkerboard.exr') if pyredner.get_use_gpu(): checkerboard_texture = checkerboard_texture.cuda(device = pyredner.get_device()) mat_checkerboard = pyredner.Material(\ diffuse_reflectance = checkerboard_texture) mat_black = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device())) materials = [mat_checkerboard, mat_black] vertices = torch.tensor([[-1.0,-1.0,0.0], [-1.0,1.0,0.0], [1.0,-1.0,0.0], [1.0,1.0,0.0]], device = pyredner.get_device()) indices = torch.tensor([[0, 1, 2], [1, 3, 2]], dtype = torch.int32, device = pyredner.get_device()) uvs = torch.tensor([[0.05, 0.05], [0.05, 0.95], [0.95, 0.05], [0.95, 0.95]], device = pyredner.get_device()) shape_plane = pyredner.Shape(vertices, indices, uvs, None, 0) light_vertices = torch.tensor([[-1.0,-1.0,-7.0],[1.0,-1.0,-7.0],[-1.0,1.0,-7.0],[1.0,1.0,-7.0]],
import math # Use GPU if available pyredner.set_use_gpu(torch.cuda.is_available()) cam = pyredner.Camera(position = torch.tensor([0.0, 0.0, -5.0]), look_at = torch.tensor([0.0, 0.0, 0.0]), up = torch.tensor([0.0, 1.0, 0.0]), fov = torch.tensor([45.0]), # in degree clip_near = 1e-2, # needs to > 0 resolution = (256, 256), fisheye = False) mat_grey = pyredner.Material(\ diffuse_reflectance = \ torch.tensor([0.4, 0.4, 0.4], device = pyredner.get_device()), specular_reflectance = \ torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device()), roughness = \ torch.tensor([0.05], device = pyredner.get_device())) materials = [mat_grey] vertices, indices, uvs, normals = pyredner.generate_sphere(128, 64) shape_sphere = pyredner.Shape(\ vertices = vertices, indices = indices, uvs = uvs, normals = normals, material_id = 0) shapes = [shape_sphere]
# Use GPU if available pyredner.set_use_gpu(torch.cuda.is_available()) # Setup camera cam = pyredner.Camera(position = torch.tensor([0.0, 0.0, -5.0]), look_at = torch.tensor([0.0, 0.0, 0.0]), up = torch.tensor([0.0, 1.0, 0.0]), fov = torch.tensor([45.0]), # in degree clip_near = 1e-2, # needs to > 0 resolution = (256, 256), fisheye = False) # Setup material mat_grey = pyredner.Material(\ diffuse_reflectance = \ torch.tensor([0.4, 0.4, 0.4], device = pyredner.get_device()), specular_reflectance = \ torch.tensor([0.5, 0.5, 0.5], device = pyredner.get_device()), roughness = \ torch.tensor([0.02], device = pyredner.get_device())) materials = [mat_grey] # Setup scene geometry: we use the utility function "generate_sphere" to generate a sphere # triangle mesh vertices, indices, uvs, normals = pyredner.generate_sphere(128, 64) shape_sphere = pyredner.Shape(\ vertices = vertices, indices = indices, uvs = uvs, normals = normals, material_id = 0)
# Set up the scene using Pytorch tensor position = torch.tensor([0.0, 0.0, -5.0]) look_at = torch.tensor([0.0, 0.0, 0.0]) up = torch.tensor([0.0, 1.0, 0.0]) fov = torch.tensor([45.0]) clip_near = 1e-2 resolution = (256, 256) cam = pyredner.Camera(position=position, look_at=look_at, up=up, fov=fov, clip_near=clip_near, resolution=resolution) if pyredner.get_use_gpu(): diffuse = diffuse.cuda(device=pyredner.get_device()) specular = specular.cuda(device=pyredner.get_device()) roughness = roughness.cuda(device=pyredner.get_device()) mat_perlin = pyredner.Material(\ diffuse_reflectance = diffuse, specular_reflectance = specular, roughness = roughness) mat_black = pyredner.Material(\ diffuse_reflectance = torch.tensor([0.0, 0.0, 0.0], device = pyredner.get_device())) materials = [mat_perlin, mat_black] vertices = torch.tensor( [[-1.5, -1.5, 0.0], [-1.5, 1.5, 0.0], [1.5, -1.5, 0.0], [1.5, 1.5, 0.0]], device=pyredner.get_device()) indices = torch.tensor([[0, 1, 2], [1, 3, 2]], dtype=torch.int32, device=pyredner.get_device())