docstr: Test output of phong and gouraud shading matches a reference image using
  the default values for the light sources.
  
  Args:
      elevated_camera: Defines whether the camera observing the scene should
                     have an elevation of 45 degrees.
docstr_tok: ["Test","output","of","phong","and","gouraud","shading","matches","a","reference","image","using","the","default","values","for","the","light","sources",".","Args",":","elevated_camera",":","Defines","whether","the","camera","observing","the","scene","should","have","an","elevation","of","45","degrees","."]
code: def test_simple_sphere(
      self, elevated_camera=False, check_depth=False
  ):
      """
      Test output of phong and gouraud shading matches a reference image using
      the default values for the light sources.
  
      Args:
          elevated_camera: Defines whether the camera observing the scene should
                         have an elevation of 45 degrees.
      """
      device = torch.device("cuda:0")
  
      # Init mesh
      sphere_mesh = ico_sphere(5, device)
      verts_padded = sphere_mesh.verts_padded()
      faces_padded = sphere_mesh.faces_padded()
      feats = torch.ones_like(verts_padded, device=device)
      textures = TexturesVertex(verts_features=feats)
      sphere_mesh = Meshes(
          verts=verts_padded, faces=faces_padded, textures=textures
      )
  
      # Init rasterizer settings
      if elevated_camera:
          # Elevated and rotated camera
          R, T = look_at_view_transform(dist=2.7, elev=45.0, azim=45.0)
          postfix = "_elevated_"
          # If y axis is up, the spot of light should
          # be on the bottom left of the sphere.
      else:
          # No elevation or azimuth rotation
          R, T = look_at_view_transform(2.7, 0.0, 0.0)
          postfix = "_"
      for cam_type in (
          FoVPerspectiveCameras,
          FoVOrthographicCameras,
          PerspectiveCameras,
          OrthographicCameras,
          FishEyeCameras,
      ):
          if cam_type == FishEyeCameras:
              cam_kwargs = {
                  "radial_params": torch.tensor(
                      [
                          [-1, -2, -3, 0, 0, 1],
                      ],
                      dtype=torch.float32,
                  ),
                  "tangential_params": torch.tensor(
                      [[0.7002747019, -0.4005228974]],
                      dtype=torch.float32,
                  ),
                  "thin_prism_params": torch.tensor(
                      [
                          [
                              -1.000134884,
                              -1.000084822,
                              -1.0009420014,
                              -1.0001276838,
                          ],
                      ],
                      dtype=torch.float32,
                  ),
              }
              cameras = cam_type(
                  device=device,
                  R=R,
                  T=T,
                  use_tangential=True,
                  use_radial=True,
                  use_thin_prism=True,
                  world_coordinates=True,
                  **cam_kwargs,
              )
          else:
              cameras = cam_type(device=device, R=R, T=T)
  
          # Init shader settings
          materials = Materials(device=device)
          lights = PointLights(device=device)
          lights.location = torch.tensor(
              [0.0, 0.0, +2.0], device=device
          )[None]
  
          raster_settings = RasterizationSettings(
              image_size=512, blur_radius=0.0, faces_per_pixel=1
          )
          blend_params = BlendParams(0.5, 1e-4, (0, 0, 0))
  
          # Test several shaders
          rasterizer_tests = [
              RasterizerTest(
                  MeshRasterizer, HardPhongShader, "phong", "hard_phong"
              ),
              RasterizerTest(
                  MeshRasterizer,
                  HardGouraudShader,
                  "gouraud",
                  "hard_gouraud",
              ),
              RasterizerTest(
                  MeshRasterizer, HardFlatShader, "flat", "hard_flat"
              ),
              RasterizerTest(
                  MeshRasterizerOpenGL,
                  SplatterPhongShader,
                  "splatter",
                  "splatter_phong",
              ),
          ]
          for test in rasterizer_tests:
              shader = test.shader(
                  lights=lights,
                  cameras=cameras,
                  materials=materials,
                  blend_params=blend_params,
              )
              if test.rasterizer == MeshRasterizer:
                  rasterizer = test.rasterizer(
                      cameras=cameras, raster_settings=raster_settings
                  )
              elif test.rasterizer == MeshRasterizerOpenGL:
                  if type(cameras) in [
                      PerspectiveCameras,
                      OrthographicCameras,
                      FishEyeCameras,
                  ]:
                      # MeshRasterizerOpenGL is only compatible with FoV cameras.
                      continue
                  rasterizer = test.rasterizer(
                      cameras=cameras,
                      raster_settings=raster_settings,
                  )
  
              if check_depth:
                  renderer = MeshRendererWithFragments(
                      rasterizer=rasterizer, shader=shader
                  )
                  images, fragments = renderer(sphere_mesh)
                  self.assertClose(
                      fragments.zbuf, rasterizer(sphere_mesh).zbuf
                  )
                  # Check the alpha channel is the mask. For soft rasterizers, the
                  # boundary will not match exactly so we use quantiles to compare.
                  self.assertLess(
                      (
                          images[..., -1]
                          - (fragments.pix_to_face[..., 0] >= 0).float()
                      ).quantile(0.99),
                      0.005,
                  )
              else:
                  renderer = MeshRenderer(
                      rasterizer=rasterizer, shader=shader
                  )
                  images = renderer(sphere_mesh)
  
              rgb = images[0, ..., :3].squeeze().cpu()
              filename = "simple_sphere_light_%s%s%s.png" % (
                  test.reference_name,
                  postfix,
                  cam_type.__name__,
              )
  
              image_ref = load_rgb_image("test_%s" % filename, DATA_DIR)
              if DEBUG:
                  debug_filename = "simple_sphere_light_%s%s%s.png" % (
                      test.debug_name,
                      postfix,
                      cam_type.__name__,
                  )
                  filename = "DEBUG_%s" % debug_filename
                  Image.fromarray(
                      (rgb.numpy() * 255).astype(np.uint8)
                  ).save(DATA_DIR / filename)
              self.assertClose(rgb, image_ref, atol=0.05)
  
          ########################################################
          # Move the light to the +z axis in world space so it is
          # behind the sphere. Note that +Z is in, +Y up,
          # +X left for both world and camera space.
          ########################################################
          lights.location[..., 2] = -2.0
          phong_shader = HardPhongShader(
              lights=lights,
              cameras=cameras,
              materials=materials,
              blend_params=blend_params,
          )
          if check_depth:
              phong_renderer = MeshRendererWithFragments(
                  rasterizer=rasterizer, shader=phong_shader
              )
              images, fragments = phong_renderer(
                  sphere_mesh, lights=lights
              )
              self.assertClose(
                  fragments.zbuf,
                  rasterizer(sphere_mesh, lights=lights).zbuf,
              )
              # Check the alpha channel is the mask
              self.assertLess(
                  (
                      images[..., -1]
                      - (fragments.pix_to_face[..., 0] >= 0).float()
                  ).quantile(0.99),
                  0.005,
              )
          else:
              phong_renderer = MeshRenderer(
                  rasterizer=rasterizer, shader=phong_shader
              )
              images = phong_renderer(sphere_mesh, lights=lights)
          rgb = images[0, ..., :3].squeeze().cpu()
          if DEBUG:
              filename = "DEBUG_simple_sphere_dark%s%s.png" % (
                  postfix,
                  cam_type.__name__,
              )
              Image.fromarray(
                  (rgb.numpy() * 255).astype(np.uint8)
              ).save(DATA_DIR / filename)
  
          image_ref_phong_dark = load_rgb_image(
              "test_simple_sphere_dark%s%s.png"
              % (postfix, cam_type.__name__),
              DATA_DIR,
          )
          # Soft shaders (SplatterPhong) will have a different boundary than hard
          # ones, but should be identical otherwise.
          self.assertLess(
              (rgb - image_ref_phong_dark).quantile(0.99), 0.005
          )
  
imports: import os
  import unittest
  from collections import namedtuple
  from itertools import product
  import numpy
  import torch
  from PIL import Image
  from pytorch3d.io import load_obj, load_objs_as_meshes
  from pytorch3d.renderer import AmbientLights, FoVOrthographicCameras, FoVPerspectiveCameras, look_at_view_transform, Materials, MeshRasterizer, MeshRenderer, MeshRendererWithFragments, OrthographicCameras, PerspectiveCameras, PointLights, RasterizationSettings, TexturesAtlas, TexturesUV, TexturesVertex
  from pytorch3d.renderer.fisheyecameras import FishEyeCameras
  from pytorch3d.renderer.mesh.shader import BlendParams, HardFlatShader, HardGouraudShader, HardPhongShader, SoftPhongShader, SoftSilhouetteShader, SplatterPhongShader, TexturedSoftPhongShader
  from pytorch3d.renderer.opengl import MeshRasterizerOpenGL
  from pytorch3d.structures.meshes import join_meshes_as_batch, join_meshes_as_scene, Meshes
  from pytorch3d.utils.ico_sphere import ico_sphere
  from pytorch3d.utils.torus import torus
  from .common_testing import get_pytorch3d_dir, get_tests_dir, load_rgb_image, TestCaseMixin
label_desc: Use image node_id 1 for calling the TestRenderMeshes obj's underlying member method code with example usage: obj.test_simple_sphere(elevated_camera, check_depth) without return types