Skip to content

How to get OpenGL-like transparent surface (X-ray look with edge/depth feeling) from MeshRenderer? #1993

@wjh19990923

Description

@wjh19990923
class STLRenderer(Renderer):
    """
    This class is for rendering stl_anatomies.
    For using this class, you don't need to worried about all the class's methods. We handle them.
    You just need to create your scene, create an object of renderer, then bind the scene to the renderer.
    And call the render function
    """

    def __init__(self, device=None):
        super(STLRenderer, self).__init__(device=device)
        self.sigma = 1e-7
        self.gamma = 1e-7

    def set_rasterizer(self, camera: Camera):
        blur_radius = np.log(1.0 / 1e-7 - 1.0) * self.sigma

        # to speed up the STL renderer, we need lower faces_per_pixel, None for bin_size
        # if there is warning or need to increase accuracy, faces_per_pixel=100, bin_size=0
        raster_settings = RasterizationSettings(image_size=self.img_pixels_num, blur_radius=blur_radius,
                                                faces_per_pixel=100, bin_size=None)
        rasterizer = MeshRasterizer(cameras=camera, raster_settings=raster_settings)
        return rasterizer

    def set_shader(self, camera: Camera):
        # blend_params = BlendParams(self.sigma, self.gamma, (0, 0, 0))
        blend_params_Silhouette = BlendParams(sigma=self.sigma, gamma=self.gamma)

        # lights = PointLights(
        # device=self.device,
        # location=((0.0, 1.0, 0.0),),
        # ambient_color=((1.0, 0.0, 0.0),),
        # diffuse_color=((0.0, 0.0, 0.0),),
        # specular_color=((0.0, 0.0, 0.0),),
        # )
        # materials = Materials(
        # ambient_color=((1, 1, 1),),
        # diffuse_color=((1, 1, 1),),
        # specular_color=((1, 1, 1),),
        # shininess=0,
        # device=self.device,
        # )
        # shader = SoftPhongShader(
        # lights=lights,
        # cameras=camera,
        # materials=materials,
        # blend_params=blend_params,
        # )
        # I am not sure if phone renderer actually has gradient, but soft silhoutee does.
        shader = SoftSilhouetteShader(blend_params=blend_params_Silhouette)
        return shader

    def render(
            self, cam_index: int = 0, width_pixels_num: int = 512, height_pixels_num: int = 512,
            scale_output=True
    ):
        """
        It generates a grayscale rendered image of the scene from view point of the camera given by user.
        param: width_pixels_num:
        height_pixels_num:
        param: shadow: If it is False, it will generate the image in RGB values.
        scale_output: scale to 0-1

        return: it returns a torch.tensor on self.device in the shape of:
                (batch_size, height_pixels_num, width_pixels_num, 3) when shadow is False
                (batch_size, height_pixels_num, width_pixels_num) when shadow is True
        """
        assert self.scene.anatomies_type == "STL", "Scene must only have stl anatomies"
        camera = self.scene.cameras[cam_index]
        self.set_resolution(width_pixels_num=width_pixels_num, height_pixels_num=height_pixels_num)

        rendered_img = torch.zeros(self.scene.get_batch_size(), *self.img_pixels_num, device=self.device)
        for anatomy in self.scene.anatomies:
            self.change_camera_extrinsic_mat_based_anatomy(anatomy=anatomy, camera=camera)
            rasterizer = self.set_rasterizer(camera=camera)
            shader = self.set_shader(camera=camera)
            renderer = MeshRenderer(rasterizer=rasterizer, shader=shader)
            rendered_img = torch.max(rendered_img, renderer(anatomy)[..., 3])  # maximum selecting pixel
            # rendered_img += renderer(anatomy)[..., 3] # overlapping
            self.return_back_camera_extrinsic_mat_original_value(camera=camera)

        # rendered_img = rendered_img.sum(dim=3)
        img_min = torch.min(rendered_img)
        img_max = torch.max(rendered_img)
        if scale_output:
            rendered_img = (1 / (img_max - img_min)) * (rendered_img - img_min)
        return rendered_img

I’d like to reproduce an OpenGL-style transparent surface rendering in PyTorch3D: the mesh remains surface-shaded (Phong-like), but is semi-transparent so that I can perceive some depth/edges of the surface behind the front layer (an “X-ray” look).

Image

do you know what setting should I give to MeshRenderer?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions