class_docstr: Class to represent NeRF model.
  
  Args:
      num_ray_points: Number of points to sample along rays.
      irregular_ray_sampling: Whether to sample ray points irregularly.
      num_pos_freqs: Number of frequencies for positional encoding.
      num_dir_freqs: Number of frequencies for directional encoding.
      num_units: Number of sub-units.
      num_unit_layers: Number of fully connected layers in each sub-unit.
      num_hidden: Layer hidden dimensions.
      log_space_encoding: Whether to apply log spacing for encoding.
docstr: Forward method.
  
  Args:
      origins: Ray origins with shape :math:`(B, 3)`.
      directions: Ray directions with shape :math:`(B, 3)`.
  
  Returns:
      Rendered image pixels :math:`(B, 3)`.
docstr_tok: ["Forward","method",".","Args",":","origins",":","Ray","origins","with","shape",":","math",":","`","(","B",",","3",")","`",".","directions",":","Ray","directions","with","shape",":","math",":","`","(","B",",","3",")","`",".","Returns",":","Rendered","image","pixels",":","math",":","`","(","B",",","3",")","`","."]
code: def forward(self, origins: Tensor, directions: Tensor) -> Tensor:
      """Forward method.
  
      Args:
          origins: Ray origins with shape :math:`(B, 3)`.
          directions: Ray directions with shape :math:`(B, 3)`.
  
      Returns:
          Rendered image pixels :math:`(B, 3)`.
      """
      # Sample xyz for ray parameters
      batch_size = origins.shape[0]
      lengths = sample_lengths(
          batch_size,
          self._num_ray_points,
          device=origins.device,
          dtype=origins.dtype,
          irregular=self._irregular_ray_sampling,
      )  # FIXME: handle the case of hierarchical sampling
      points_3d = sample_ray_points(origins, directions, lengths)
  
      # Encode positions & directions
      points_3d_encoded = self._pos_encoder(points_3d)
      directions_encoded = self._dir_encoder(
          F.normalize(directions, dim=-1)
      )
  
      # Map positional encodings to latent features (MLP with skip connections)
      y = self._mlp(points_3d_encoded)
      y = self._fc1(y)
  
      # Calculate ray point density values
      densities_ray_points = self._sigma(y)
      densities_ray_points = (
          densities_ray_points
          + torch.randn_like(densities_ray_points) * 0.1
      )
      densities_ray_points = torch.relu(
          densities_ray_points
      )  # FIXME: Revise this
  
      # Calculate ray point rgb values
      y = torch.cat(
          (
              y,
              directions_encoded[..., None, :].expand(
                  -1, self._num_ray_points, -1
              ),
          ),
          dim=-1,
      )
      y = self._fc2(y)
      rgbs_ray_points = self._rgb(y)
  
      # Rendering rgbs and densities along rays
      rgbs = self._renderer(
          rgbs_ray_points, densities_ray_points, points_3d
      )
  
      # Return pixel point rendered rgb
      return rgbs
  
imports: from __future__ import annotations
  import torch
  from torch import nn
  from torch.nn import functional
  from kornia.core import Module, Tensor
  from kornia.geometry.camera import PinholeCamera
  from kornia.geometry.ray import Ray
  from kornia.nerf.positional_encoder import PositionalEncoder
  from kornia.nerf.samplers import sample_lengths, sample_ray_points
  from kornia.nerf.volume_renderer import IrregularRenderer, RegularRenderer
  from kornia.utils._compat import torch_inference_mode
  from kornia.utils.grid import create_meshgrid
label_desc: Use image node_id 2 for calling the NerfModel obj's underlying member method code with example usage: obj.forward(origins, directions) and returns: rgbs