code: def specular(
      points, normals, direction, color, camera_position, shininess
  ) -> torch.Tensor:
      """
      Calculate the specular component of light reflection.
  
      Args:
          points: (N, ..., 3) xyz coordinates of the points.
          normals: (N, ..., 3) xyz normal vectors for each point.
          color: (N, 3) RGB color of the specular component of the light.
          direction: (N, 3) vector direction of the light.
          camera_position: (N, 3) The xyz position of the camera.
          shininess: (N)  The specular exponent of the material.
  
      Returns:
          colors: (N, ..., 3), same shape as the input points.
  
      The points, normals, camera_position, and direction should be in the same
      coordinate frame i.e. if the points have been transformed from
      world -> view space then the normals, camera_position, and light direction
      should also be in view space.
  
      To use with a batch of packed points reindex in the following way.
      .. code-block:: python::
  
          Args:
              points: (P, 3)
              normals: (P, 3)
              color: (N, 3)[batch_idx] -> (P, 3)
              direction: (N, 3)[batch_idx] -> (P, 3)
              camera_position: (N, 3)[batch_idx] -> (P, 3)
              shininess: (N)[batch_idx] -> (P)
          Returns:
              colors: (P, 3)
  
          where batch_idx is of shape (P). For meshes batch_idx can be:
          meshes.verts_packed_to_mesh_idx() or meshes.faces_packed_to_mesh_idx().
      """
      # TODO: handle multiple directional lights
      # TODO: attenuate based on inverse squared distance to the light source
  
      if points.shape != normals.shape:
          msg = "Expected points and normals to have the same shape: got %r, %r"
          raise ValueError(msg % (points.shape, normals.shape))
  
      # Ensure all inputs have same batch dimension as points
      matched_tensors = convert_to_tensors_and_broadcast(
          points,
          color,
          direction,
          camera_position,
          shininess,
          device=points.device,
      )
      _, color, direction, camera_position, shininess = matched_tensors
  
      # Reshape direction and color so they have all the arbitrary intermediate
      # dimensions as points. Assume first dim = batch dim and last dim = 3.
      points_dims = points.shape[1:-1]
      expand_dims = (-1,) + (1,) * len(points_dims)
      if direction.shape != normals.shape:
          direction = direction.view(expand_dims + (3,))
      if color.shape != normals.shape:
          color = color.view(expand_dims + (3,))
      if camera_position.shape != normals.shape:
          camera_position = camera_position.view(expand_dims + (3,))
      if shininess.shape != normals.shape:
          shininess = shininess.view(expand_dims)
  
      # Renormalize the normals in case they have been interpolated.
      # We tried a version that uses F.cosine_similarity instead of renormalizing,
      # but it was slower.
      normals = F.normalize(normals, p=2, dim=-1, eps=1e-6)
      direction = F.normalize(direction, p=2, dim=-1, eps=1e-6)
      cos_angle = torch.sum(normals * direction, dim=-1)
      # No specular highlights if angle is less than 0.
      mask = (cos_angle > 0).to(torch.float32)
  
      # Calculate the specular reflection.
      view_direction = camera_position - points
      view_direction = F.normalize(
          view_direction, p=2, dim=-1, eps=1e-6
      )
      reflect_direction = -direction + 2 * (
          cos_angle[..., None] * normals
      )
  
      # Cosine of the angle between the reflected light ray and the viewer
      alpha = (
          F.relu(torch.sum(view_direction * reflect_direction, dim=-1))
          * mask
      )
      return color * torch.pow(alpha, shininess)[..., None]
  
imports: import torch
  import torch.nn.functional
  from ..common.datatypes import Device
  from .utils import convert_to_tensors_and_broadcast, TensorProperties
label_desc: Use image node_id 2 for calling a global function with example usage: specular(points, normals, direction, color, camera_position, shininess) and returns: unknown