def generate_quad_light(position: tf.Tensor, look_at: tf.Tensor, size: tf.Tensor, intensity: tf.Tensor): """ Generate a pyredner.Object that is a quad light source. Args ==== position: tf.Tensor 1-d tensor of size 3 look_at: tf.Tensor 1-d tensor of size 3 size: tf.Tensor 1-d tensor of size 2 intensity: tf.Tensor 1-d tensor of size 3 Returns ======= pyredner.Object quad light source """ d = look_at - position d = d / tf.norm(d) # ONB -- generate two axes that are orthogonal to d a = 1 / (1 + d[2]) b = -d[0] * d[1] * a x = tf.where(d[2] < (-1 + 1e-6), tf.constant([0.0, -1.0, 0.0]), tf.stack([1 - d[0] * d[0] * a, b, -d[0]])) y = tf.where(d[2] < (-1 + 1e-6), tf.constant([-1.0, 0.0, 0.0]), tf.stack([b, 1 - d[1] * d[1] * a, -d[1]])) v0 = position - x * size[0] * 0.5 - y * size[1] * 0.5 v1 = position + x * size[0] * 0.5 - y * size[1] * 0.5 v2 = position - x * size[0] * 0.5 + y * size[1] * 0.5 v3 = position + x * size[0] * 0.5 + y * size[1] * 0.5 with tf.device(pyredner.get_device_name()): vertices = tf.stack((v0, v1, v2, v3), axis=0) indices = tf.constant([[0, 1, 2], [1, 3, 2]], dtype=tf.int32) m = pyredner.Material(diffuse_reflectance=tf.constant([0.0, 0.0, 0.0])) return pyredner.Object(vertices=vertices, indices=indices, material=m, light_intensity=intensity)
with tf.device('/device:cpu:' + str(pyredner.get_cpu_device_id())): position = tf.Variable([0.0, 0.0, -5.0], dtype=tf.float32) look_at = tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32) up = tf.Variable([0.0, 1.0, 0.0], dtype=tf.float32) fov = tf.Variable([45.0], dtype=tf.float32) 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_perlin = pyredner.Material(diffuse_reflectance=diffuse, specular_reflectance=specular, roughness=roughness) with tf.device(pyredner.get_device_name()): mat_black = pyredner.Material( diffuse_reflectance=tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32)) materials = [mat_perlin, mat_black] vertices = tf.Variable([[-1.5, -1.5, 0.0], [-1.5, 1.5, 0.0], [1.5, -1.5, 0.0], [1.5, 1.5, 0.0]], dtype=tf.float32) indices = tf.constant([[0, 1, 2], [1, 3, 2]], dtype=tf.int32) uvs = tf.Variable([[0.05, 0.05], [0.05, 0.95], [0.95, 0.05], [0.95, 0.95]], dtype=tf.float32) shape_plane = pyredner.Shape(vertices, indices, 0, uvs) light_vertices = tf.Variable([[-1.0, -1.0, -7.0], [1.0, -1.0, -7.0], [-1.0, 1.0, -7.0], [1.0, 1.0, -7.0]], dtype=tf.float32)
def load_obj(filename: str, obj_group: bool = True, flip_tex_coords: bool = True, use_common_indices: bool = False, return_objects: bool = False): """ Load from a Wavefront obj file as PyTorch tensors. Args ==== 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. 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] """ 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 = tf.constant(indices, dtype=tf.int32) if len(uv_indices) == 0: uv_indices = None else: uv_indices = tf.constant(uv_indices, dtype=tf.int32) if len(normal_indices) == 0: normal_indices = None else: normal_indices = tf.constant(normal_indices, dtype=tf.int32) vertices = tf.constant(vertices) if len(uvs) == 0: uvs = None else: uvs = tf.constant(uvs) if len(normals) == 0: normals = None else: normals = tf.constant(normals) 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 = tf.constant(m.Kd, dtype=tf.float32) else: diffuse_reflectance = pyredner.imread(m.map_Kd) if m.map_Ks is None: specular_reflectance = tf.constant(m.Ks, dtype=tf.float32) else: specular_reflectance = pyredner.imread(m.map_Ks) if m.map_Ns is None: roughness = tf.constant([2.0 / (m.Ns + 2.0)], dtype=tf.float32) else: roughness = 2.0 / (pyredner.imread(m.map_Ns) + 2.0) if m.Ke != (0.0, 0.0, 0.0): light_map[mtl_name] = tf.constant(m.Ke, dtype=tf.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 = \ tf.constant((0.5, 0.5, 0.5))) 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
dtype=tf.float32, use_resource=True) look_at = tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32, use_resource=True) up = tf.Variable([0.0, 1.0, 0.0], dtype=tf.float32, use_resource=True) fov = tf.Variable([45.0], dtype=tf.float32, use_resource=True) 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) with tf.device(pyredner.get_device_name()): mat_grey = pyredner.Material(diffuse_reflectance=tf.Variable( [0.5, 0.5, 0.5], dtype=tf.float32, use_resource=True)) mat_black = pyredner.Material(diffuse_reflectance=tf.Variable( [0.0, 0.0, 0.0], dtype=tf.float32, use_resource=True)) materials = [mat_grey, mat_black] # tf.constant allocates arrays on host memory for int32 arrays (some tensorflow internal mess), # but pyredner.Shape constructor automatically converts the memory to device if necessary. floor_vertices = tf.Variable([[-2.0, 0.0, -2.0], [-2.0, 0.0, 2.0], [2.0, 0.0, -2.0], [2.0, 0.0, 2.0]], dtype=tf.float32, use_resource=True) floor_indices = tf.constant([[0, 1, 2], [1, 3, 2]], dtype=tf.int32) shape_floor = pyredner.Shape(floor_vertices, floor_indices, None, None, 0) blocker_vertices = tf.Variable([[-0.5, 3.0, -0.5], [-0.5, 3.0, 0.5], [0.5, 3.0, -0.5], [0.5, 3.0, 0.5]], dtype=tf.float32,
pyredner.set_use_gpu( tf.test.is_gpu_available(cuda_only=True, min_cuda_compute_capability=None)) with tf.device('/device:cpu:' + str(pyredner.get_cpu_device_id())): cam = pyredner.Camera( position=tf.Variable([0.0, 0.0, -5.0], dtype=tf.float32), look_at=tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32), up=tf.Variable([0.0, 1.0, 0.0], dtype=tf.float32), fov=tf.Variable([45.0], dtype=tf.float32), # in degree clip_near=1e-2, # needs to > 0 resolution=(256, 256), fisheye=False) with tf.device(pyredner.get_device_name()): mat_grey = pyredner.Material( diffuse_reflectance=tf.Variable([0.4, 0.4, 0.4], dtype=tf.float32), specular_reflectance=tf.Variable([0.5, 0.5, 0.5], dtype=tf.float32), roughness=tf.Variable([0.05], dtype=tf.float32)) materials = [mat_grey] with tf.device(pyredner.get_device_name()): 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] with tf.device(pyredner.get_device_name()): envmap = pyredner.imread('sunsky.exr')
def parse_material(node, two_sided=False): node_id = None if 'id' in node.attrib: node_id = node.attrib['id'] if node.attrib['type'] == 'diffuse': diffuse_reflectance = tf.constant([0.5, 0.5, 0.5]) diffuse_uv_scale = [1.0, 1.0] specular_reflectance = tf.constant([0.0, 0.0, 0.0]) specular_uv_scale = [1.0, 1.0] roughness = tf.constant([1.0]) for child in node: if child.attrib['name'] == 'reflectance': if child.tag == 'texture': for grandchild in child: if grandchild.attrib['name'] == 'filename': diffuse_reflectance = pyredner.imread( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'uscale': diffuse_uv_scale[0] = float( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'vscale': diffuse_uv_scale[1] = float( grandchild.attrib['value']) elif child.tag == 'rgb' or child.tag == 'spectrum': diffuse_reflectance = parse_vector(child.attrib['value']) elif child.attrib['name'] == 'specular': if child.tag == 'texture': for grandchild in child: if grandchild.attrib['name'] == 'filename': specular_reflectance = pyredner.imread( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'uscale': specular_uv_scale[0] = float( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'vscale': specular_uv_scale[1] = float( grandchild.attrib['value']) elif child.tag == 'rgb' or child.tag == 'spectrum': specular_reflectance = parse_vector(child.attrib['value']) elif child.attrib['name'] == 'roughness': roughness = tf.constant([float(child.attrib['value'])]) diffuse_uv_scale = tf.constant(diffuse_uv_scale) specular_uv_scale = tf.constant(specular_uv_scale) return (node_id, pyredner.Material(diffuse_reflectance=pyredner.Texture( diffuse_reflectance, diffuse_uv_scale), specular_reflectance=pyredner.Texture( specular_reflectance, specular_uv_scale), roughness=pyredner.Texture(roughness), two_sided=two_sided)) elif node.attrib['type'] == 'roughplastic': diffuse_reflectance = tf.constant([0.5, 0.5, 0.5]) diffuse_uv_scale = [1.0, 1.0] specular_reflectance = tf.constant([0.0, 0.0, 0.0]) specular_uv_scale = [1.0, 1.0] roughness = tf.constant([1.0]) for child in node: if child.attrib['name'] == 'diffuseReflectance': if child.tag == 'texture': for grandchild in child: if grandchild.attrib['name'] == 'filename': diffuse_reflectance = pyredner.imread( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'uscale': diffuse_uv_scale[0] = float( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'vscale': diffuse_uv_scale[1] = float( grandchild.attrib['value']) elif child.tag == 'rgb' or child.tag == 'spectrum': diffuse_reflectance = parse_vector(child.attrib['value']) elif child.attrib['name'] == 'specularReflectance': if child.tag == 'texture': for grandchild in child: if grandchild.attrib['name'] == 'filename': specular_reflectance = pyredner.imread( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'uscale': specular_uv_scale[0] = float( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'vscale': specular_uv_scale[1] = float( grandchild.attrib['value']) elif child.tag == 'rgb' or child.tag == 'spectrum': specular_reflectance = parse_vector(child.attrib['value']) elif child.attrib['name'] == 'alpha': alpha = float(child.attrib['value']) roughness = tf.constant([alpha * alpha]) diffuse_uv_scale = tf.constant(diffuse_uv_scale) specular_uv_scale = tf.constant(specular_uv_scale) return (node_id, pyredner.Material(diffuse_reflectance=pyredner.Texture( diffuse_reflectance, diffuse_uv_scale), specular_reflectance=pyredner.Texture( specular_reflectance, specular_uv_scale), roughness=pyredner.Texture(roughness), two_sided=two_sided)) elif node.attrib['type'] == 'twosided': ret = parse_material(node[0], True) return (node_id, ret[1]) else: print('Unsupported material type:', node.attrib['type']) assert (False)
position = tf.Variable([0.0, 0.0, -1.0], dtype=tf.float32) look_at = tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32) up = tf.Variable([0.0, 1.0, 0.0], dtype=tf.float32) fov = tf.Variable([45.0], dtype=tf.float32) 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, fisheye=True) with tf.device(pyredner.get_device_name()): mat_grey = pyredner.Material(diffuse_reflectance = \ tf.Variable([0.5, 0.5, 0.5], dtype=tf.float32)) materials = [mat_grey] vertices = tf.Variable( [[-1.7, 1.0, 0.0], [1.0, 1.0, 0.0], [-0.5, -1.0, 0.0]], dtype=tf.float32) indices = tf.constant([[0, 1, 2]], dtype=tf.int32) shape_triangle = pyredner.Shape(vertices, indices, 0) light_vertices = tf.Variable([[-1.0, -1.0, -9.0], [1.0, -1.0, -9.0], [-1.0, 1.0, -9.0], [1.0, 1.0, -9.0]], dtype=tf.float32) light_indices = tf.constant([[0, 1, 2], [1, 3, 2]], dtype=tf.int32) shape_light = pyredner.Shape(light_vertices, light_indices, 0) shapes = [shape_triangle, shape_light] with tf.device('/device:cpu:' + str(pyredner.get_cpu_device_id())): light_intensity = tf.Variable([30.0, 30.0, 30.0], dtype=tf.float32)
position = tf.Variable([0.0, 2.0, -4.0], dtype=tf.float32) look_at = tf.Variable([0.0, -2.0, 0.0], dtype=tf.float32) up = tf.Variable([0.0, 1.0, 0.0], dtype=tf.float32) fov = tf.Variable([45.0], dtype=tf.float32) 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) with tf.device(pyredner.get_device_name()): mat_shiny = pyredner.Material( diffuse_reflectance=tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32), specular_reflectance=tf.Variable([1.0, 1.0, 1.0], dtype=tf.float32), roughness=tf.Variable([0.0005], dtype=tf.float32)) mat_grey = pyredner.Material( diffuse_reflectance=tf.Variable([0.5, 0.5, 0.5], dtype=tf.float32)) mat_black = pyredner.Material( diffuse_reflectance=tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32)) materials = [mat_shiny, mat_grey, mat_black] ############################################# # Shapes # tf.constant allocates arrays on host memory for int32 arrays (some tensorflow internal mess), # but pyredner.Shape constructor automatically converts the memory to device if necessary. # floor floor_vertices = tf.Variable([[-4.0, 0.0, -4.0], [-4.0, 0.0, 4.0],
def load_obj(filename, obj_group=True, flip_tex_coords=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 = tf.constant(indices, dtype=tf.int32) vertices = tf.constant(vertices) if len(uvs) == 0: uvs = None else: uvs = tf.constant(uvs) if len(normals) == 0: normals = None else: normals = tf.constant(normals) 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 = tf.constant(m.Kd, dtype=tf.float32) else: diffuse_reflectance = pyredner.imread(m.map_Kd) if m.map_Ks is None: specular_reflectance = tf.constant(m.Ks, dtype=tf.float32) else: specular_reflectance = pyredner.imread(m.map_Ks) if m.map_Ns is None: roughness = tf.constant([2.0 / (m.Ns + 2.0)], dtype=tf.float32) else: roughness = 2.0 / (pyredner.imread(m.map_Ks) + 2.0) if m.Ke != (0.0, 0.0, 0.0): light_map[mtl_name] = tf.constant(m.Ke, dtype=tf.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: 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) f.close() return material_map, mesh_list, light_map
# Tensorflow by default allocates all GPU memory, leaving very little for rendering. # We set the environment variable TF_FORCE_GPU_ALLOW_GROWTH to true to enforce on demand # memory allocation to reduce page faults. import os os.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true' import tensorflow as tf tf.compat.v1.enable_eager_execution() import pyredner_tensorflow as pyredner vertices, indices, uvs, normals = pyredner.generate_sphere(16, 32) m = pyredner.Material(diffuse_reflectance=tf.constant((0.5, 0.5, 0.5))) obj = pyredner.Object(vertices=vertices, indices=indices, uvs=uvs, normals=normals, material=m) filename = 'results/test_save_obj/sphere.obj' directory = os.path.dirname(filename) if directory != '' and not os.path.exists(directory): os.makedirs(directory) pyredner.save_obj(obj, 'results/test_save_obj/sphere.obj')
def load_obj(filename, obj_group=True, flip_tex_coords=True, use_common_indices=False): """ Load from a Wavefront obj file as PyTorch tensors. XXX: this is slow, maybe move to C++? Args: obj_group -- split the meshes based on materials flip_tex_coords -- flip the v coordinate of uv by applying v' = 1 - v use_common_indices -- 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. """ 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 = tf.constant(indices, dtype=tf.int32) if len(uv_indices) == 0: uv_indices = None else: uv_indices = tf.constant(uv_indices, dtype=tf.int32) if len(normal_indices) == 0: normal_indices = None else: normal_indices = tf.constant(normal_indices, dtype=tf.int32) vertices = tf.constant(vertices) if len(uvs) == 0: uvs = None else: uvs = tf.constant(uvs) if len(normals) == 0: normals = None else: normals = tf.constant(normals) return TriangleMesh(indices, uv_indices, normal_indices, vertices, 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, 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 = tf.constant(m.Kd, dtype=tf.float32) else: diffuse_reflectance = pyredner.imread(m.map_Kd) if m.map_Ks is None: specular_reflectance = tf.constant(m.Ks, dtype=tf.float32) else: specular_reflectance = pyredner.imread(m.map_Ks) if m.map_Ns is None: roughness = tf.constant([2.0 / (m.Ns + 2.0)], dtype=tf.float32) else: roughness = 2.0 / (pyredner.imread(m.map_Ks) + 2.0) if m.Ke != (0.0, 0.0, 0.0): light_map[mtl_name] = tf.constant(m.Ke, dtype=tf.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: 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) 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) f.close() return material_map, mesh_list, light_map
def parse_material(node, two_sided=False): node_id = None if 'id' in node.attrib: node_id = node.attrib['id'] if node.attrib['type'] == 'diffuse': diffuse_reflectance = tf.constant([0.5, 0.5, 0.5]) diffuse_uv_scale = [1.0, 1.0] specular_reflectance = tf.constant([0.0, 0.0, 0.0]) specular_uv_scale = [1.0, 1.0] roughness = tf.constant([1.0]) for child in node: if child.attrib['name'] == 'reflectance': if child.tag == 'texture': for grandchild in child: if grandchild.attrib['name'] == 'filename': diffuse_reflectance = pyredner.imread( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'uscale': diffuse_uv_scale[0] = float( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'vscale': diffuse_uv_scale[1] = float( grandchild.attrib['value']) elif child.tag == 'rgb' or child.tag == 'spectrum' or child.tag == 'srgb': diffuse_reflectance = parse_vector(child.attrib['value']) if child.tag == 'srgb': diffuse_reflectance = pyredner.srgb_to_linear( diffuse_reflectance) elif child.attrib['name'] == 'specular': if child.tag == 'texture': for grandchild in child: if grandchild.attrib['name'] == 'filename': specular_reflectance = pyredner.imread( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'uscale': specular_uv_scale[0] = float( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'vscale': specular_uv_scale[1] = float( grandchild.attrib['value']) elif child.tag == 'rgb' or child.tag == 'spectrum' or child.tag == 'srgb': specular_reflectance = parse_vector(child.attrib['value']) if child.tag == 'srgb': specular_reflectance = pyredner.srgb_to_linear( specular_reflectance) elif child.attrib['name'] == 'roughness': roughness = tf.constant([float(child.attrib['value'])]) diffuse_uv_scale = tf.constant(diffuse_uv_scale) specular_uv_scale = tf.constant(specular_uv_scale) return (node_id, pyredner.Material(diffuse_reflectance=pyredner.Texture( diffuse_reflectance, diffuse_uv_scale), specular_reflectance=pyredner.Texture( specular_reflectance, specular_uv_scale), roughness=pyredner.Texture(roughness), two_sided=two_sided)) elif node.attrib['type'] == 'roughplastic': diffuse_reflectance = tf.constant([0.5, 0.5, 0.5]) diffuse_uv_scale = [1.0, 1.0] # Mitsuba defaults specular reflectance to 1.0, but we use Schilick approximation and # use the specular reflectance for representing both index of refraction and color tint # for metal materials simultaneously. # Schilick's appsoximation set R0 to ((n1 - n2) / (n1 + n2))^2. Mitsuba defaults # IOR to n1=1 and n2=1.5, so R0 ~= 0.04 specular_reflectance = tf.constant([0.04, 0.04, 0.04]) specular_uv_scale = [1.0, 1.0] roughness = tf.constant([0.01]) for child in node: if child.attrib['name'] == 'diffuseReflectance' or child.attrib[ 'name'] == 'diffuse_reflectance': if child.tag == 'texture': for grandchild in child: if grandchild.attrib['name'] == 'filename': diffuse_reflectance = pyredner.imread( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'uscale': diffuse_uv_scale[0] = float( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'vscale': diffuse_uv_scale[1] = float( grandchild.attrib['value']) elif child.tag == 'rgb' or child.tag == 'spectrum' or child.tag == 'srgb': diffuse_reflectance = parse_vector(child.attrib['value']) if child.tag == 'srgb': diffuse_reflectance = pyredner.srgb_to_linear( diffuse_reflectance) elif child.attrib['name'] == 'specularReflectance' or child.attrib[ 'name'] == 'specular_reflectance': if child.tag == 'texture': for grandchild in child: if grandchild.attrib['name'] == 'filename': specular_reflectance = pyredner.imread( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'uscale': specular_uv_scale[0] = float( grandchild.attrib['value']) elif grandchild.attrib['name'] == 'vscale': specular_uv_scale[1] = float( grandchild.attrib['value']) elif child.tag == 'rgb' or child.tag == 'spectrum' or child.tag == 'srgb': specular_reflectance = parse_vector(child.attrib['value']) if child.tag == 'srgb': specular_reflectance = pyredner.srgb_to_linear( specular_reflectance) elif child.attrib['name'] == 'alpha': if child.tag == 'texture': roughness, roughness_uv_scale = parse_texture(child) roughness = roughness * roughness else: alpha = float(child.attrib['value']) roughness = tf.constant([alpha * alpha]) diffuse_uv_scale = tf.constant(diffuse_uv_scale) specular_uv_scale = tf.constant(specular_uv_scale) return (node_id, pyredner.Material(diffuse_reflectance=pyredner.Texture( diffuse_reflectance, diffuse_uv_scale), specular_reflectance=pyredner.Texture( specular_reflectance, specular_uv_scale), roughness=pyredner.Texture(roughness), two_sided=two_sided)) elif node.attrib['type'] == 'twosided': ret = parse_material(node[0], True) return (node_id, ret[1]) else: print('Unsupported material type:', node.attrib['type']) assert (False)
clip_near = 1e-2 # randomly generate distortion parameters tf.random.set_seed(1234) target_distort_params = (tf.random.uniform([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') mat_checkerboard = pyredner.Material(\ diffuse_reflectance = checkerboard_texture) mat_black = pyredner.Material(\ diffuse_reflectance = tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32)) plane = pyredner.Object(vertices=tf.Variable([[-1.0, -1.0, 0.0], [-1.0, 1.0, 0.0], [1.0, -1.0, 0.0], [1.0, 1.0, 0.0]]), indices=tf.constant([[0, 1, 2], [1, 3, 2]], dtype=tf.int32), uvs=tf.Variable([[0.05, 0.05], [0.05, 0.95], [0.95, 0.05], [0.95, 0.95]]), material=mat_checkerboard) scene = pyredner.Scene(camera=cam, objects=[plane]) img = pyredner.render_albedo(scene=scene) pyredner.imwrite(img, 'results/test_camera_distortion/target.exr')
# Use GPU if available pyredner.set_use_gpu( tf.test.is_gpu_available(cuda_only=True, min_cuda_compute_capability=None)) with tf.device('/device:cpu:' + str(pyredner.get_cpu_device_id())): cam = pyredner.Camera( position=tf.Variable([0.0, 0.0, -5.0], dtype=tf.float32), look_at=tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32), up=tf.Variable([0.0, 1.0, 0.0], dtype=tf.float32), fov=tf.Variable([45.0], dtype=tf.float32), # in degree clip_near=1e-2, # needs to > 0 resolution=(256, 256), fisheye=False) with tf.device(pyredner.get_device_name()): mat_vertex_color = pyredner.Material(use_vertex_color=True) materials = [mat_vertex_color] with tf.device(pyredner.get_device_name()): # For the target we randomize the vertex color. vertices, indices, uvs, normals = pyredner.generate_sphere(128, 64) vertex_color = tf.random.uniform(vertices.shape, 0.0, 1.0) shape_sphere = pyredner.Shape(vertices=vertices, indices=indices, uvs=uvs, normals=normals, colors=vertex_color, material_id=0) shapes = [shape_sphere] with tf.device(pyredner.get_device_name()):
with tf.device('/device:cpu:' + str(pyredner.get_cpu_device_id())): position = tf.Variable([0.0, 0.0, -5.0], dtype=tf.float32) look_at = tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32) up = tf.Variable([0.0, 1.0, 0.0], dtype=tf.float32) fov = tf.Variable([45.0], dtype=tf.float32) 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) with tf.device(pyredner.get_device_name()): mat_green = pyredner.Material( diffuse_reflectance = tf.Variable([0.35, 0.75, 0.35], dtype=tf.float32)) mat_red = pyredner.Material( diffuse_reflectance = tf.Variable([0.75, 0.35, 0.35], dtype=tf.float32)) mat_black = pyredner.Material( diffuse_reflectance = tf.Variable([0.0, 0.0, 0.0], dtype=tf.float32)) materials = [mat_green,mat_red,mat_black] tri0_vertices = tf.Variable( [[-1.7,1.0,0.0], [1.0,1.0,0.0], [-0.5,-1.0,0.0]], dtype=tf.float32) tri1_vertices = tf.Variable( [[-1.0,1.5,1.0], [0.2,1.5,1.0], [0.2,-1.5,1.0]], dtype=tf.float32) tri0_indices = tf.constant([[0, 1, 2]], dtype=tf.int32) tri1_indices = tf.constant([[0, 1, 2]], dtype=tf.int32) shape_tri0 = pyredner.Shape(tri0_vertices, tri0_indices, 0) shape_tri1 = pyredner.Shape(tri1_vertices, tri1_indices, 1) light_vertices = tf.Variable([[-1.0,-1.0,-7.0],[1.0,-1.0,-7.0],[-1.0,1.0,-7.0],[1.0,1.0,-7.0]], dtype=tf.float32)