Nothing
#' Render Scene
#'
#' Takes the scene description and renders an image, either to the device or to a filename. The
#' user can also interactively fly around the 3D scene if they have X11 support on their system
#' or are on Windows.
#'
#' @param scene Tibble of object locations and properties.
#' @param width Default `400`. Width of the render, in pixels.
#' @param height Default `400`. Height of the render, in pixels.
#' @param fov Default `20`. Field of view, in degrees. If this is `0`, the camera will use an orthographic projection. The size of the plane
#' used to create the orthographic projection is given in argument `ortho_dimensions`. From `0` to `180`, this uses a perspective
#' projections. If this value is `360`, a 360 degree environment image will be rendered.
#' @param samples Default `100`. The maximum number of samples for each pixel. If this is a length-2
#' vector and the `sample_method` is `stratified`, this will control the number of strata in each dimension.
#' The total number of samples in this case will be the product of the two numbers.
#' @param preview Default `interactive()`. Whether to display a real-time progressive preview of the render. Press ESC to cancel the render.
#' If `deferred_render = TRUE`, the preview stays interactive until the final render is explicitly started.
#' @param interactive Default `interactive()`. Whether the scene preview should be interactive. Camera movement orbits around the
#' lookat point (unless the mode is switched to free flying), with the following control mapping:
#' W = Forward, S = Backward, A = Left, D = Right, Q = Up, Z = Down,
#' Shift-W/Shift-S = Pitch Camera Forward/Back, Shift-A/Shift-D = Roll Camera Left/Right,
#' E = 2x Step Distance (max 128), C = 0.5x Step Distance, Up Key = Zoom In (decrease FOV), Down Key = Zoom Out (increase FOV),
#' Left Key = Decrease Aperture, Right Key = Increase Aperture, 1 = Decrease Focal Distance, 2 = Increase Focal Distance,
#' 3/4 = Rotate Environment Light,
#' Right bracket/left bracket = Increase/Decrease Preview Exposure, Shift + right bracket/left bracket = Increase/Decrease shutter speed,
#' Shift-Enter = Save Preview Snapshot, R = Reset Camera,
#' Return = Toggle between deferred and final render if `deferred_render = TRUE`, TAB: Toggle Orbit Mode,
#' Left Mouse Click: Set Look At and Focal Distance, Right Mouse Click: Set Look At.
#' If the interactive preview window is wide enough, a status bar at the bottom shows the current camera, exposure, environment rotation,
#' and keyframe state.
#' K: Save Keyframe (at the conclusion of the render, this will create the `ray_keyframes`
#' data.frame in the global environment, which can be passed to `generate_camera_motion()` to tween between those saved positions.
#' L: Reset Camera to Last Keyframe (if set), Shift-L: Toggle keyframe path open/closed,
#' < and >: Jump to previous/next keyframe, /: Delete current keyframe,
#' M: Preview/cancel keyframe motion,
#' F: Toggle Fast Travel Mode,
#' B: Toggle Camera Motion Blur,
#' H: Toggle Atmospheric Haze, Y: Toggle Altitude Queries (with `sky_light()`).
#' Haze requires altitude queries: enabling haze also enables altitude queries,
#' and disabling altitude queries also disables haze. Each change restarts sampling.
#'
#' Initial step size is 1/20th of the distance from `lookat` to `lookfrom`.
#'
#' With \code{integrator_type = "nee"}, clicks select the first point where accumulated volume opacity
#' reaches 15\%, or the first ordinary surface if reached sooner. Picking integrates extinction
#' deterministically with a fixed shutter sample and a centered lens sample. Thin or empty regions
#' allow selection of surfaces behind them; invisible container faces are skipped. Clicking the
#' background without reaching this opacity turns perspective and panoramic cameras toward that
#' direction, preserving focal distance and orbit radius. Orthographic background clicks leave the
#' view unchanged. Selected surface and volume points remain the orbit center when rotating.
#' Right clicking preserves the focal distance.
#' Some options aren't available for all cameras. When using a realistic camera,
#' the aperture and field of view cannot be changed from their initial settings.
#' @param deferred_render Default `FALSE`. If `TRUE` and interactive preview is enabled, rayrender will keep
#' updating the progressive preview until Return is pressed. Pressing Return toggles the full render in the
#' same window; pressing Return again returns to deferred mode.
#' @param denoise Default `TRUE`. Whether to de-noise the final image and preview images. Note, this requires
#' the free Intel Open Image Denoise (OIDN) library be installed on your system. Pre-compiled binaries can be installed from
#' ppenimagedenoise.org, as well as . Linking during rayrender installation is done by defining the environment variable
#' OIDN_PATH (set it in the .Renviron file by calling `usethis::edit_r_environ()`) to the top-level directory for OIDN (the directory containing the "lib", "bin", and "include"
#' directories) and re-installing this package from source.
#' @param camera_description_file Default `NA`. Filename of a camera description file for rendering with
#' a realistic camera. Several camera files are built-in: `"50mm"`,`"wide"`,`"fisheye"`, and `"telephoto"`.
#' @param camera_scale Default `1`. Amount to scale the camera up or down in size. Use this rather than scaling a
#' scene.
#' @param iso Default `100`. Camera exposure.
#' @param auto_exposure Default `FALSE`. If `TRUE`, automatically adjust the exposure with
#' `rayimage::render_exposure(auto = TRUE)`. If `preview = TRUE`, the preview window exposure
#' is calibrated from the 90\% luminance quantile of the first rendered frame.
#' @param film_size Default `22`, in `mm` (scene units in `m`. Size of the film if using a realistic camera, otherwise
#' ignored.
#' @param min_variance Default `0`. Minimum acceptable variance for a block of pixels for the
#' adaptive sampler. Smaller numbers give higher quality images, at the expense of longer rendering times.
#' If this is set to zero, the adaptive sampler will be turned off and the renderer
#' will use the maximum number of samples everywhere.
#' @param min_adaptive_size Default `8`. Width of the minimum block size in the adaptive sampler.
#' @param sample_method Default `sobol`. The type of sampling method used to generate
#' random numbers. The other options are `random` (worst quality but fastest),
#' `stratified` (only implemented for completion), `sobol_blue` (best option for sample counts below 256),
#' and `sobol` (slowest but best quality, better than `sobol_blue` for sample counts greater than 256). If
#' `samples > 256` and `sobol_blue` is selected, the method will automatically switch to `sample_method = "sobol"`.
#' @param max_depth Default `NA`, automatically sets to 50. Maximum number of bounces a ray can make in a scene. Alternatively,
#' if a debugging option is chosen, this sets the bounce to query the debugging parameter (only for some options).
#' @param roulette_active_depth Default `100`. Number of ray bounces until a ray can stop bouncing via
#' Russian roulette.
#' @param ambient_light Default `FALSE`, unless there are no emitting objects in the scene.
#' If `TRUE`, the background will be a gradient varying from `backgroundhigh` directly up (+y) to
#' `backgroundlow` directly down (-y).
#' @param lookfrom Default `c(0,1,10)`. Location of the camera.
#' @param lookat Default `c(0,0,0)`. Location where the camera is pointed.
#' @param camera_up Default `c(0,1,0)`. Vector indicating the "up" position of the camera.
#' @param aperture Default `0.1`. Aperture of the camera. Smaller numbers will increase depth of field, causing
#' less blurring in areas not in focus.
#' @param clamp_value Default `Inf`. If a bright light or a reflective material is in the scene, occasionally
#' there will be bright spots that will not go away even with a large number of samples. These
#' can be removed (at the cost of slightly darkening the image) by setting this to a small number greater than 1.
#' @param filename Default `NULL`. If present, the renderer will write to the filename instead
#' of the current device. Can write to JPEG/JPG, PNG, and high dynamic range EXR images. In the
#' interactive preview, press Shift+Enter to save the current preview. A source filename with an
#' extension produces numbered snapshots with the number inserted before the extension; otherwise
#' snapshots are saved as `rayrender_snapshot1.png`, `rayrender_snapshot2.png`, and so on in the
#' current directory.
#' @param backgroundhigh Default `#80b4ff`. The "high" color in the background gradient. Can be either
#' a hexadecimal code, or a numeric rgb vector listing three intensities between `0` and `1`.
#' @param backgroundlow Default `#ffffff`. The "low" color in the background gradient. Can be either
#' a hexadecimal code, or a numeric rgb vector listing three intensities between `0` and `1`.
#' @param shutteropen Default `0`. Time at which the shutter is open. Only affects moving objects.
#' @param shutterclose Default `1`. Time at which the shutter is open. Only affects moving objects.
#' @param camera_motion_blur Default `FALSE`. Whether to blur camera movement over the shutter interval. Press `B` in interactive preview to toggle.
#' @param shutter_speed Default `NULL`. Optional render-time override for the
#' selected camera's frame-relative shutter speed. A value of `1` samples the
#' full frame-to-frame motion interval, `2` samples one-half, and `4` samples
#' one-quarter. Higher values produce less motion blur. `Inf` disables temporal
#' motion blur. This does not affect exposure or brightness.
#' @param focal_distance Default `NULL`, automatically set to the `lookfrom-lookat` distance unless
#' otherwise specified.
#' @param ortho_dimensions Default `c(1,1)`. Width and height of the orthographic camera. Will only be used if `fov = 0`.
#' @param tonemap Default `raw`, no tonemapping. Choose the tone mapping function,
#' `reinhard` scales values by their individual color channels `color/(1+color)` and then performs the
#' gamma adjustment. `uncharted` uses the mapping developed for Uncharted 2 by John Hable. `hbd` uses an
#' optimized formula by Jim Hejl and Richard Burgess-Dawson.
#' @param bloom Default `TRUE`. Set to `FALSE` to get the raw, pathtraced image. Otherwise,
#' this performs a convolution of the HDR image of the scene with a sharp, long-tailed
#' exponential kernel, which does not visibly affect dimly pixels, but does result in emitters light
#' slightly bleeding into adjacent pixels. This provides an antialiasing effect for lights, even when
#' tonemapping the image. Pass in a matrix to specify the convolution kernel manually, or a positive number
#' to control the intensity of the bloom (higher number = more bloom).
#' @param environment_light Default `NULL`. An image to be used for the background for rays that escape
#' the scene. Supports EXR, HDR, PNG, and JPEG images. For reusable scene lights and
#' multiple environments, use \code{\link{infinite_light}()} and \code{\link{add_infinite_light}()}. This
#' argument adds a light to any infinite lights already attached to the scene.
#' @param rotate_env Default `0`. The number of degrees to rotate all infinite lights around the scene,
#' in addition to their individual rotations.
#' @param intensity_env Default `1`. The amount to increase the intensity of the environment lighting. Useful
#' if using a LDR (JPEG or PNG) image as an environment map. Applies only to the
#' `environment_light` argument; scene lights have their own intensity.
#' @param transparent_background Default `FALSE`. If `TRUE`, any initial camera rays that escape the scene
#' will be marked as transparent in the final image. If for a pixel some rays escape and others hit a surface,
#' those pixels will be partially transparent.
#' @param integrator_type Default `"rtiow"` (the algorithm specified in the book "Raytracing in One Weekend", a basic
#' form of path guiding). Other options include `"nee"` (Next Event Estimation, with direct light sampling)
#' and `"basic"` (basic pathtracing, for high sample reference renders and debugging only).
#' With `nee`, surfaces and participating media use RGB null-scattering transport;
#' \code{nee} is selected automatically for scenes containing \code{\link{sky_light}()} or attached
#' media (including clouds and media inside instances), overriding \code{rtiow} or \code{basic}.
#' See \code{\link{set_medium}()}.
#' @param debug_channel Default `none`. If `depth`, function will return a depth map of rays into the scene
#' instead of an image. If `normals`, function will return an image of scene normals, mapped from 0 to 1.
#' If `uv`, function will return an image of the uv coords. If `variance`, function will return an image
#' showing the number of samples needed to take for each block to converge. If `dpdu` or `dpdv`, function will return
#' an image showing the differential `u` and `u` coordinates. If `color`, function will return the raw albedo
#' values (with white for `metal` and `dielectric` materials).
#' @param plot_scene Default `TRUE`. Whether to plot the rendered scene.
#' @param parallel Default `TRUE`. If `FALSE`, it will use all available cores to render the image
#' (or the number specified in `options("cores")` or `options("Ncpus")` if that option is not `NULL`).
#' @param bvh_type Default `"sah"`, "surface area heuristic". Method of building the bounding volume
#' hierarchy structure used when rendering. Other option is "equal", which splits tree into groups
#' of equal size.
#' @param progress Default `interactive()` if interactive session, `FALSE` otherwise.
#' @param verbose Default `FALSE`. Prints information and timing information about scene
#' construction and raytracing progress.
#' @param print_debug_info Default `FALSE`. This will print out additional information on the compilation environment with
#' each render.
#' @param new_page Default `TRUE`. Whether to call `grid::grid.newpage()` when plotting the image (if
#' no filename specified). Set to `FALSE` for faster plotting (does not affect render time).
#' @param screen_text Default `NULL`. Optional screen-space text overlay created with `screen_text()`,
#' or a list of `screen_text()` outputs to draw in order.
#' @param screen_line Default `NULL`. Optional screen-space line overlay created with `screen_line()`,
#' or a list of `screen_line()` outputs to draw in order.
#' Labels are anchored to 3D world-space points, projected through the current camera, and drawn after
#' rendering so text size and justification are independent of scene scale and view distance.
#' @param camera Default `NULL`. Scene-attached camera name, `"all"`, or a `ray_camera` object created with `camera()`.
#' @param start_frame Default `1`. First camera frame to render when using an animated camera.
#' @param end_frame Default `NA`. Last camera frame to render when using an animated camera. If `NA`, renders through the final frame.
#' @param mode Default `"auto"`. Rendering mode. `"auto"` renders a still image for static cameras and an animation for animated cameras.
#' @export
#' @importFrom grDevices col2rgb
#' @return A pathtraced image to the current device, or an image saved to a file. Invisibly returns the
#' array (containing either debug data or the RGB).
#'
#'@examplesIf interactive() || identical(Sys.getenv("IN_PKGDOWN"), "true")
#' # Generate a large checkered sphere as the ground
#' scene = generate_ground(depth = -0.5,
#' material = diffuse(color = "white", checkercolor = "darkgreen"))
#' render_scene(scene, parallel = TRUE, samples = 16, sample_method = "sobol")
#' # Add a sphere to the center
#' scene = scene |>
#' add_object(sphere(x = 0, y = 0, z = 0, radius = 0.5, material = diffuse(color = c(1, 0, 1))))
#' render_scene(scene, fov = 20, parallel = TRUE, samples = 16)
#' # Add a marbled cube
#' scene = scene |>
#' add_object(cube(x = 1.1, y = 0, z = 0, material = diffuse(noise = 3)))
#' render_scene(scene, fov = 20, parallel = TRUE, samples = 16)
#' # Add a metallic gold sphere, using stratified sampling for a higher quality render
#' # We also add a light, which turns off the default ambient lighting
#' scene = scene |>
#' add_object(sphere(x = -1.1, y = 0, z = 0, radius = 0.5,
#' material = metal(color = "gold", fuzz = 0.1))) |>
#' add_object(sphere(y=10,z=-13,radius=2,material=light(intensity=40)))
#' render_scene(scene, fov = 20, parallel = TRUE, samples = 16)
#' # Lower the number of samples to render more quickly (here, we also use only one core).
#' render_scene(scene, samples = 4, parallel = FALSE)
#' # Add a floating R plot using the iris dataset as a png onto a floating 2D rectangle
#' tempfileplot = tempfile()
#' png(filename = tempfileplot, height = 400, width = 800)
#' plot(iris$Petal.Length, iris$Sepal.Width, col = iris$Species, pch = 18, cex = 4)
#' dev.off()
#' image_array = aperm(png::readPNG(tempfileplot), c(2, 1, 3))
#' scene = scene |>
#' add_object(xy_rect(x = 0, y = 1.1, z = 0, xwidth = 2, angle = c(0, 0, 0),
#' flipped = TRUE,
#' material = diffuse(image_texture = image_array)))
#' render_scene(scene, fov = 20, parallel = TRUE, samples = 16)
#' # Move the camera
#' render_scene(scene, lookfrom = c(7, 1.5, 10), lookat = c(0, 0.5, 0), fov = 15, parallel = TRUE)
#' # Change the background gradient to a firey sky
#' render_scene(scene, lookfrom = c(7, 1.5, 10), lookat = c(0, 0.5, 0), fov = 15,
#' backgroundhigh = "orange", backgroundlow = "red", parallel = TRUE,
#' ambient = TRUE,
#' samples = 16)
#' # Increase the aperture to blur objects that are further from the focal plane.
#' render_scene(scene, lookfrom = c(7, 1.5, 10), lookat = c(0, 0.5, 0), fov = 15,
#' aperture = 1, parallel = TRUE, samples = 16)
#' # We can also capture a 360 environment image by setting `fov = 360` (can be used for VR).
#' # The left edge of the image is directly where the camera is pointing--we point the image
#' # backwards so the full cornell box is in the "center" of the environment map.
#' generate_cornell() |>
#' add_object(ellipsoid(x = 555 / 2, y = 100, z = 555 / 2, a = 50, b = 100, c = 50,
#' material = metal(color = "lightblue"))) |>
#' add_object(cube(x = 100, y = 130 / 2, z = 200, xwidth = 130, ywidth = 130, zwidth = 130,
#' material = diffuse(checkercolor = "purple",
#' checkerperiod = 30), angle = c(0, 10, 0))) |>
#' add_object(pig(x = 100, y = 190, z = 200, scale = 40, angle = c(0, 30, 0))) |>
#' add_object(sphere(x = 420, y = 555 / 8, z = 100, radius = 555 / 8,
#' material = dielectric(color = "orange"))) |>
#' add_object(xz_rect(x = 555 / 2, z = 555 / 2, y = 1, xwidth = 555, zwidth = 555,
#' material = glossy(checkercolor = "white",
#' checkerperiod = 10, color = "dodgerblue"))) |>
#' render_scene(lookfrom = c(278, 278, -10), lookat = c(278, 278, -300), clamp_value = 100,
#' fov = 360, samples = 16, width = 800, height = 800)
#' # Spin the camera around the scene, decreasing the number of samples to render faster. To make
#' # an animation, specify the a filename in `render_scene` for each frame and use the `av` package
#' # or ffmpeg to combine them all into a movie.
#' t = 1:9
#' xpos = 10 * sin(t * 18 * pi / 180 + pi / 2)
#' zpos = 10 * cos(t * 18 * pi / 180 + pi / 2)
#' image_output = list()
#' for (i in 1:9) {
#' image_output[[i]] = render_scene(scene, samples = 16, plot_scene = FALSE,
#' lookfrom = c(xpos[i], 1.5, zpos[i]), lookat = c(0, 0.5, 0), parallel = TRUE)
#' }
#' rayimage::plot_image_grid(image_output, dim = c(3,3) )
render_scene = function(
scene,
width = 400,
height = 400,
fov = 20,
samples = 100,
camera_description_file = NA,
preview = interactive(),
interactive = TRUE,
deferred_render = FALSE,
denoise = TRUE,
camera_scale = 1,
iso = 100,
auto_exposure = FALSE,
film_size = 22,
min_variance = 0,
min_adaptive_size = 8,
sample_method = "sobol_blue",
max_depth = NA,
roulette_active_depth = 100,
ambient_light = NULL,
lookfrom = c(0, 1, -10),
lookat = c(0, 0, 0),
camera_up = c(0, 1, 0),
aperture = 0.1,
clamp_value = Inf,
filename = NA,
backgroundhigh = "#80b4ff",
backgroundlow = "#ffffff",
shutteropen = 0.0,
shutterclose = 1.0,
camera_motion_blur = FALSE,
shutter_speed = NULL,
focal_distance = NULL,
ortho_dimensions = c(1, 1),
tonemap = "raw",
bloom = TRUE,
parallel = TRUE,
bvh_type = "sah",
environment_light = NULL,
rotate_env = 0,
intensity_env = 1,
transparent_background = FALSE,
debug_channel = "none",
plot_scene = TRUE,
progress = interactive(),
verbose = FALSE,
print_debug_info = FALSE,
new_page = TRUE,
integrator_type = "rtiow",
screen_text = NULL,
screen_line = NULL,
camera = NULL,
start_frame = 1,
end_frame = NA,
mode = c("auto", "image", "animation", "preview")
) {
mode = match.arg(mode)
if (!is.logical(camera_motion_blur) || length(camera_motion_blur) != 1) {
stop("camera_motion_blur must be a single TRUE/FALSE value.")
}
shutter_speed_supplied = !is.null(shutter_speed)
if (shutter_speed_supplied) {
validate_shutter_speed(shutter_speed)
}
camera_shutter_speed = if (shutter_speed_supplied) shutter_speed else 2
camera_arg = if (missing(camera)) NULL else camera
filename_supplied = !missing(filename)
legacy_camera_supplied = c(
lookfrom = !missing(lookfrom),
lookat = !missing(lookat),
camera_up = !missing(camera_up),
fov = !missing(fov),
aperture = !missing(aperture),
focal_distance = !missing(focal_distance),
ortho_dimensions = !missing(ortho_dimensions),
camera_description_file = !missing(camera_description_file),
camera_scale = !missing(camera_scale),
iso = !missing(iso),
film_size = !missing(film_size),
shutteropen = !missing(shutteropen),
shutterclose = !missing(shutterclose),
camera_motion_blur = !missing(camera_motion_blur),
filename = filename_supplied
)
legacy_camera_geometry_supplied = any(legacy_camera_supplied[c(
"lookfrom",
"lookat",
"camera_up",
"fov",
"aperture",
"focal_distance",
"ortho_dimensions"
)])
metadata_supplied = legacy_camera_supplied[c(
"camera_description_file",
"camera_scale",
"iso",
"film_size",
"shutteropen",
"shutterclose",
"camera_motion_blur",
"shutter_speed",
"filename"
)]
metadata_overrides = list(
camera_description_file = camera_description_file,
camera_scale = camera_scale,
iso = iso,
film_size = film_size,
shutteropen = shutteropen,
shutterclose = shutterclose,
camera_motion_blur = camera_motion_blur,
shutter_speed = camera_shutter_speed,
filename = filename
)
metadata_supplied[["shutter_speed"]] = shutter_speed_supplied
scene_camera_available = length(ray_scene_cameras(scene)) > 0 ||
!is.null(camera_arg)
legacy_filename = if (
!legacy_camera_geometry_supplied &&
scene_camera_available
) {
NA_character_
} else {
filename
}
legacy_camera = render_scene_legacy_camera(
scene = scene,
supplied = legacy_camera_supplied,
lookfrom = lookfrom,
lookat = lookat,
camera_up = camera_up,
fov = fov,
aperture = aperture,
focal_distance = focal_distance,
ortho_dimensions = ortho_dimensions,
filename = legacy_filename,
camera_description_file = camera_description_file,
camera_scale = camera_scale,
iso = iso,
film_size = film_size,
shutteropen = shutteropen,
shutterclose = shutterclose,
camera_motion_blur = camera_motion_blur,
shutter_speed = camera_shutter_speed,
message_cornell = is.null(camera_arg) &&
length(ray_scene_cameras(scene)) == 0
)
cameras = resolve_scene_camera(
scene = scene,
camera = camera_arg,
legacy_camera = legacy_camera,
legacy_camera_supplied = legacy_camera_geometry_supplied,
allow_all = TRUE,
default_camera = legacy_camera
)
if (!legacy_camera_geometry_supplied) {
cameras = lapply(
cameras,
apply_camera_overrides,
overrides = metadata_overrides,
supplied = metadata_supplied
)
}
if (length(cameras) > 1) {
validate_camera_output_filenames(
cameras,
mode = mode,
start_frame = start_frame,
end_frame = end_frame
)
batch_blockers = character()
if (!camera_batch_metadata_compatible(cameras)) {
batch_blockers = c(batch_blockers, "camera metadata differs")
}
if (!is.null(screen_text) || !is.null(screen_line)) {
batch_blockers = c(batch_blockers, "screen overlays are enabled")
}
if (isTRUE(auto_exposure)) {
batch_blockers = c(batch_blockers, "auto_exposure is enabled")
}
if (isTRUE(deferred_render)) {
batch_blockers = c(batch_blockers, "deferred_render is enabled")
}
if (isTRUE(print_debug_info)) {
batch_blockers = c(batch_blockers, "print_debug_info is enabled")
}
if (
isTRUE(preview) &&
isTRUE(interactive) &&
!identical(mode, "preview")
) {
batch_blockers = c(batch_blockers, "interactive preview is enabled")
}
if (length(batch_blockers) == 0) {
return(render_camera_batch(
scene = scene,
cameras = cameras,
mode = mode,
start_frame = start_frame,
end_frame = end_frame,
width = width,
height = height,
preview = if (identical(mode, "preview")) TRUE else preview,
denoise = denoise,
samples = samples,
min_variance = min_variance,
min_adaptive_size = min_adaptive_size,
sample_method = sample_method,
keep_colors = FALSE,
sample_dist = Inf,
max_depth = if (is.na(max_depth)) 50 else max_depth,
roulette_active_depth = roulette_active_depth,
ambient_light = ambient_light,
clamp_value = clamp_value,
backgroundhigh = backgroundhigh,
backgroundlow = backgroundlow,
focal_distance = focal_distance,
ortho_dimensions = ortho_dimensions,
tonemap = tonemap,
bloom = bloom,
parallel = parallel,
bvh_type = bvh_type,
environment_light = environment_light,
rotate_env = rotate_env,
intensity_env = intensity_env,
debug_channel = debug_channel,
plot_scene = if (identical(mode, "preview")) FALSE else plot_scene,
progress = progress,
verbose = verbose,
transparent_background = transparent_background,
integrator_type = integrator_type,
force_no_write = identical(mode, "preview")
))
}
warning(
"Rendering cameras one at a time because ",
paste(batch_blockers, collapse = ", "),
"."
)
output = lapply(cameras, function(cam) {
render_scene(
scene = scene,
width = width,
height = height,
samples = samples,
preview = preview,
interactive = interactive,
deferred_render = deferred_render,
denoise = denoise,
auto_exposure = auto_exposure,
min_variance = min_variance,
min_adaptive_size = min_adaptive_size,
sample_method = sample_method,
max_depth = max_depth,
roulette_active_depth = roulette_active_depth,
ambient_light = ambient_light,
clamp_value = clamp_value,
backgroundhigh = backgroundhigh,
backgroundlow = backgroundlow,
tonemap = tonemap,
bloom = bloom,
parallel = parallel,
bvh_type = bvh_type,
environment_light = environment_light,
rotate_env = rotate_env,
intensity_env = intensity_env,
transparent_background = transparent_background,
debug_channel = debug_channel,
plot_scene = plot_scene,
progress = progress,
verbose = verbose,
print_debug_info = print_debug_info,
new_page = new_page,
integrator_type = integrator_type,
screen_text = screen_text,
screen_line = screen_line,
camera = cam,
start_frame = start_frame,
end_frame = end_frame,
mode = mode
)
})
names(output) = vapply(cameras, function(cam) cam$name, character(1))
return(invisible(output))
}
selected_camera = cameras[[1]]
render_mode = camera_render_mode(selected_camera, mode)
if (
render_mode == "animation" ||
(render_mode == "preview" && nrow(selected_camera$motion) > 1)
) {
return(render_animation_camera(
scene = scene,
camera = selected_camera,
start_frame = start_frame,
end_frame = end_frame,
width = width,
height = height,
preview = if (render_mode == "preview") TRUE else preview,
denoise = denoise,
samples = samples,
min_variance = min_variance,
min_adaptive_size = min_adaptive_size,
sample_method = sample_method,
keep_colors = FALSE,
sample_dist = Inf,
max_depth = if (is.na(max_depth)) 50 else max_depth,
roulette_active_depth = roulette_active_depth,
ambient_light = ambient_light,
clamp_value = clamp_value,
backgroundhigh = backgroundhigh,
backgroundlow = backgroundlow,
focal_distance = focal_distance,
ortho_dimensions = ortho_dimensions,
tonemap = tonemap,
bloom = bloom,
parallel = parallel,
bvh_type = bvh_type,
environment_light = environment_light,
rotate_env = rotate_env,
intensity_env = intensity_env,
debug_channel = debug_channel,
plot_scene = if (render_mode == "preview") FALSE else plot_scene,
progress = progress,
verbose = verbose,
transparent_background = transparent_background,
integrator_type = integrator_type,
force_no_write = render_mode == "preview"
))
}
snapshot_filename = if (
length(selected_camera$filename) == 1 &&
!is.na(selected_camera$filename) &&
nzchar(tools::file_ext(selected_camera$filename))
) {
selected_camera$filename
} else {
NA_character_
}
frame = if (render_mode %in% c("image", "preview")) {
camera_frame_range(nrow(selected_camera$motion), start_frame, start_frame)[
1
]
} else {
1
}
camera_args = camera_frame_args(selected_camera, frame)
lookfrom = camera_args$lookfrom
lookat = camera_args$lookat
camera_up = camera_args$camera_up
fov = camera_args$fov
aperture = camera_args$aperture
focal_distance = camera_args$focal_distance
ortho_dimensions = camera_args$ortho_dimensions
camera_description_file = camera_args$camera_description_file
camera_scale = camera_args$camera_scale
iso = camera_args$iso
film_size = camera_args$film_size
shutteropen = camera_args$shutteropen
shutterclose = camera_args$shutterclose
camera_motion_blur = camera_args$camera_motion_blur
shutter_speed = camera_args$shutter_speed
filename = camera_image_filename(selected_camera, frame)
if (render_mode == "preview") {
filename = NA
preview = TRUE
plot_scene = FALSE
}
init_time()
if (print_debug_info) {
message(sprintf(
"------Debug Info------
RAY_HAS_X11: %s
HAS_SSE: %s
HAS_SSE2: %s
HAS_SSE3: %s
HAS_SSE41: %s
HAS_NEON: %s
HAS_OIDN: %s
----------------------",
ifelse(has_gui_capability(), "TRUE", "FALSE"),
ifelse(cppdef_HAS_SSE(), "TRUE", "FALSE"),
ifelse(cppdef_HAS_SSE2(), "TRUE", "FALSE"),
ifelse(cppdef_HAS_SSE3(), "TRUE", "FALSE"),
ifelse(cppdef_HAS_SSE41(), "TRUE", "FALSE"),
ifelse(cppdef_HAS_NEON(), "TRUE", "FALSE"),
ifelse(cppdef_HAS_OIDN(), "TRUE", "FALSE")
))
}
if (samples > 256 && sample_method == "sobol_blue") {
warning(
'"sobol_blue" sample method only valid for `samples` than or equal to 256--switching to `sample_method = "sobol"`'
)
sample_method = "sobol"
}
if (width < 3 || height < 3) {
stop("Must specify a minimum width/height of 3 or more pixels")
}
if (
preview &&
interactive &&
has_gui_capability() &&
!is.numeric(debug_channel) &&
debug_channel == "none"
) {
controls_lines = c(
"------------------------ Interactive Mode Controls ------------------------",
"Move: W/A/S/D horizontal | Q/Z vertical | E/C step size | F fast travel",
"Look: Shift-W/S pitch | Shift-A/D roll | Tab toggle orbit",
"Lens/Env: Up/Down FOV | Left/Right aperture | 1/2 focal | 3/4 env rotate",
"Keyframes: K save | L last | Shift-L loop | </> prev/next | / delete | M preview/cancel",
"Mouse: Left click lookat + focal distance | Right click lookat",
"Status: Wide window shows camera/exposure/env/keyframes/loop",
"Exposure: ]/[ preview exposure | Shift-]/[ shutter speed",
"Blur: B camera motion blur",
"Atmosphere: H haze | Y altitude queries (haze requires altitude queries)",
"Snapshot: Shift-Enter save current preview",
"General: P print camera | R reset camera | ESC close"
)
if (deferred_render) {
controls_lines = c(
controls_lines,
"Render: Return start final render"
)
}
controls_message = paste(controls_lines, collapse = "\n")
message(controls_message)
}
print_time(verbose, "Pre-processing scene")
debug_string = debug_channel
scene_list = prepare_scene_list(
scene = scene,
width = width,
height = height,
fov = fov,
samples = samples,
camera_description_file = camera_description_file,
camera_scale = camera_scale,
iso = iso,
film_size = film_size,
min_variance = min_variance,
min_adaptive_size = min_adaptive_size,
sample_method = sample_method,
max_depth = max_depth,
roulette_active_depth = roulette_active_depth,
ambient_light = ambient_light,
lookfrom = lookfrom,
lookat = lookat,
camera_up = camera_up,
aperture = aperture,
clamp_value = clamp_value,
filename = filename,
backgroundhigh = backgroundhigh,
backgroundlow = backgroundlow,
shutteropen = shutteropen,
shutterclose = shutterclose,
camera_motion_blur = camera_motion_blur,
shutter_speed = shutter_speed,
focal_distance = focal_distance,
ortho_dimensions = ortho_dimensions,
tonemap = tonemap,
bloom = bloom,
parallel = parallel,
bvh_type = bvh_type,
environment_light = environment_light,
rotate_env = -rotate_env,
intensity_env = intensity_env,
debug_channel = debug_channel,
plot_scene = plot_scene,
progress = progress,
verbose = verbose,
sample_dist = Inf,
deferred_render = deferred_render,
integrator_type = integrator_type,
denoise = denoise,
print_debug_info = print_debug_info
)
print_time(verbose, "Pre-processed scene")
camera_info = scene_list$camera_info
scene_info = scene_list$scene_info
render_info = scene_list$render_info
render_info$transparent_background = transparent_background
processed_scene = scene_info$scene
screen_text_native_overlay = screen_text_needs_native_overlay(screen_text)
screen_line_native_overlay = screen_line_needs_native_overlay(screen_line)
render_info$screen_text_preview = if (
isTRUE(preview) || screen_text_native_overlay
) {
prepare_screen_text_preview(screen_text)
} else {
list(active = FALSE)
}
render_info$screen_text_occlusion = prepare_screen_text_occlusion(screen_text)
render_info$screen_text_native_overlay = screen_text_native_overlay
render_info$screen_line_preview = if (
isTRUE(preview) || screen_line_native_overlay
) {
prepare_screen_line_preview(screen_line)
} else {
list(active = FALSE)
}
render_info$screen_line_occlusion = prepare_screen_line_occlusion(screen_line)
render_info$screen_line_native_overlay = screen_line_native_overlay
camera_info$preview = preview
camera_info$interactive = interactive
camera_info$auto_exposure = auto_exposure
camera_info$camera_motion_blur = isTRUE(camera_motion_blur)
camera_info$shutter_speed = shutter_speed
camera_info$snapshot_filename = snapshot_filename
camera_info$keyframe_motion_args = normalize_keyframe_motion_args(
selected_camera$keyframe_motion_args
)
debug_channel = scene_info$debug_channel # converted to numeric
#Pathtrace Scene
rgb_mat = render_scene_rcpp(
scene = processed_scene,
camera_info = camera_info,
scene_info = scene_info,
render_info = render_info
)
screen_camera_info = attr(rgb_mat, "screen_camera_info")
if (!is.null(screen_camera_info)) {
camera_info$screen_camera_origin = screen_camera_info$origin
camera_info$screen_camera_u = screen_camera_info$u
camera_info$screen_camera_v = screen_camera_info$v
camera_info$screen_camera_w = screen_camera_info$w
camera_info$screen_camera_fov = screen_camera_info$fov
camera_info$screen_camera_ortho_dimensions =
screen_camera_info$ortho_dimensions
}
if (!is.null(attr(rgb_mat, "keyframes"))) {
message(
"Saving camera keyframes: Call `get_saved_keyframes()` function to return them."
)
keyframes = do.call(
rbind,
lapply(attr(rgb_mat, "keyframes"), as.data.frame)
)
assign("keyframes", keyframes, envir = ray_environment)
}
preview_exposure = attr(rgb_mat, "preview_exposure")
if (is.null(preview_exposure)) {
preview_exposure = 1
}
return_array = post_process_scene(
rgb_mat,
camera_info$iso,
use_iso = FALSE,
tonemap,
debug_string,
filename,
plot_scene,
bloom,
new_page,
transparent_background = transparent_background,
auto_exposure = auto_exposure,
verbose = verbose,
screen_text = screen_text,
screen_line = screen_line,
camera_info = camera_info,
screen_text_visible = attr(rgb_mat, "screen_text_visible"),
screen_text_overlay = attr(rgb_mat, "screen_text_overlay"),
screen_line_visible = attr(rgb_mat, "screen_line_visible"),
screen_line_overlay = attr(rgb_mat, "screen_line_overlay"),
exposure_adjustment = preview_exposure
)
print_time(verbose, "Post-processed image")
return(invisible(return_array))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.