Blender  V2.93
cycles_standalone.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdio.h>
18 
19 #include "device/device.h"
20 #include "render/buffers.h"
21 #include "render/camera.h"
22 #include "render/integrator.h"
23 #include "render/scene.h"
24 #include "render/session.h"
25 
26 #include "util/util_args.h"
27 #include "util/util_foreach.h"
28 #include "util/util_function.h"
29 #include "util/util_image.h"
30 #include "util/util_logging.h"
31 #include "util/util_path.h"
32 #include "util/util_progress.h"
33 #include "util/util_string.h"
34 #include "util/util_time.h"
35 #include "util/util_transform.h"
36 #include "util/util_unique_ptr.h"
37 #include "util/util_version.h"
38 
39 #ifdef WITH_CYCLES_STANDALONE_GUI
40 # include "util/util_view.h"
41 #endif
42 
43 #include "app/cycles_xml.h"
44 
46 
47 struct Options {
50  string filepath;
51  int width, height;
54  bool quiet;
56  string output_path;
58 
59 static void session_print(const string &str)
60 {
61  /* print with carriage return to overwrite previous */
62  printf("\r%s", str.c_str());
63 
64  /* add spaces to overwrite longer previous print */
65  static int maxlen = 0;
66  int len = str.size();
67  maxlen = max(len, maxlen);
68 
69  for (int i = len; i < maxlen; i++)
70  printf(" ");
71 
72  /* flush because we don't write an end of line */
73  fflush(stdout);
74 }
75 
76 static void session_print_status()
77 {
78  string status, substatus;
79 
80  /* get status */
81  float progress = options.session->progress.get_progress();
82  options.session->progress.get_status(status, substatus);
83 
84  if (substatus != "")
85  status += ": " + substatus;
86 
87  /* print status */
88  status = string_printf("Progress %05.2f %s", (double)progress * 100, status.c_str());
89  session_print(status);
90 }
91 
92 static bool write_render(const uchar *pixels, int w, int h, int channels)
93 {
94  string msg = string_printf("Writing image %s", options.output_path.c_str());
95  session_print(msg);
96 
97  unique_ptr<ImageOutput> out = unique_ptr<ImageOutput>(ImageOutput::create(options.output_path));
98  if (!out) {
99  return false;
100  }
101 
102  ImageSpec spec(w, h, channels, TypeDesc::UINT8);
103  if (!out->open(options.output_path, spec)) {
104  return false;
105  }
106 
107  /* conversion for different top/bottom convention */
108  out->write_image(
109  TypeDesc::UINT8, pixels + (h - 1) * w * channels, AutoStride, -w * channels, AutoStride);
110 
111  out->close();
112 
113  return true;
114 }
115 
117 {
118  static BufferParams buffer_params;
119  buffer_params.width = options.width;
120  buffer_params.height = options.height;
121  buffer_params.full_width = options.width;
122  buffer_params.full_height = options.height;
123 
124  return buffer_params;
125 }
126 
127 static void scene_init()
128 {
130 
131  /* Read XML */
133 
134  /* Camera width/height override? */
135  if (!(options.width == 0 || options.height == 0)) {
136  options.scene->camera->set_full_width(options.width);
137  options.scene->camera->set_full_height(options.height);
138  }
139  else {
140  options.width = options.scene->camera->get_full_width();
141  options.height = options.scene->camera->get_full_height();
142  }
143 
144  /* Calculate Viewplane */
145  options.scene->camera->compute_auto_viewplane();
146 }
147 
148 static void session_init()
149 {
152 
155 #ifdef WITH_CYCLES_STANDALONE_GUI
156  else
158 #endif
159 
160  /* load scene */
161  scene_init();
163 
165  options.session->start();
166 }
167 
168 static void session_exit()
169 {
170  if (options.session) {
171  delete options.session;
172  options.session = NULL;
173  }
174 
176  session_print("Finished Rendering.");
177  printf("\n");
178  }
179 }
180 
181 #ifdef WITH_CYCLES_STANDALONE_GUI
182 static void display_info(Progress &progress)
183 {
184  static double latency = 0.0;
185  static double last = 0;
186  double elapsed = time_dt();
187  string str, interactive;
188 
189  latency = (elapsed - last);
190  last = elapsed;
191 
192  double total_time, sample_time;
193  string status, substatus;
194 
195  progress.get_time(total_time, sample_time);
196  progress.get_status(status, substatus);
197  float progress_val = progress.get_progress();
198 
199  if (substatus != "")
200  status += ": " + substatus;
201 
202  interactive = options.interactive ? "On" : "Off";
203 
204  str = string_printf(
205  "%s"
206  " Time: %.2f"
207  " Latency: %.4f"
208  " Progress: %05.2f"
209  " Average: %.4f"
210  " Interactive: %s",
211  status.c_str(),
212  total_time,
213  latency,
214  (double)progress_val * 100,
215  sample_time,
216  interactive.c_str());
217 
218  view_display_info(str.c_str());
219 
220  if (options.show_help)
222 }
223 
224 static void display()
225 {
226  static DeviceDrawParams draw_params = DeviceDrawParams();
227 
228  options.session->draw(session_buffer_params(), draw_params);
229 
230  display_info(options.session->progress);
231 }
232 
233 static void motion(int x, int y, int button)
234 {
235  if (options.interactive) {
236  Transform matrix = options.session->scene->camera->get_matrix();
237 
238  /* Translate */
239  if (button == 0) {
240  float3 translate = make_float3(x * 0.01f, -(y * 0.01f), 0.0f);
241  matrix = matrix * transform_translate(translate);
242  }
243 
244  /* Rotate */
245  else if (button == 2) {
246  float4 r1 = make_float4((float)x * 0.1f, 0.0f, 1.0f, 0.0f);
247  matrix = matrix * transform_rotate(DEG2RADF(r1.x), make_float3(r1.y, r1.z, r1.w));
248 
249  float4 r2 = make_float4(y * 0.1f, 1.0f, 0.0f, 0.0f);
250  matrix = matrix * transform_rotate(DEG2RADF(r2.x), make_float3(r2.y, r2.z, r2.w));
251  }
252 
253  /* Update and Reset */
254  options.session->scene->camera->set_matrix(matrix);
255  options.session->scene->camera->need_flags_update = true;
256  options.session->scene->camera->need_device_update = true;
257 
259  }
260 }
261 
262 static void resize(int width, int height)
263 {
264  options.width = width;
266 
267  if (options.session) {
268  /* Update camera */
269  options.session->scene->camera->set_full_width(options.width);
270  options.session->scene->camera->set_full_height(options.height);
271  options.session->scene->camera->compute_auto_viewplane();
272  options.session->scene->camera->need_flags_update = true;
273  options.session->scene->camera->need_device_update = true;
274 
276  }
277 }
278 
279 static void keyboard(unsigned char key)
280 {
281  /* Toggle help */
282  if (key == 'h')
284 
285  /* Reset */
286  else if (key == 'r')
288 
289  /* Cancel */
290  else if (key == 27) // escape
291  options.session->progress.set_cancel("Canceled");
292 
293  /* Pause */
294  else if (key == 'p') {
297  }
298 
299  /* Interactive Mode */
300  else if (key == 'i')
302 
303  /* Navigation */
304  else if (options.interactive && (key == 'w' || key == 'a' || key == 's' || key == 'd')) {
305  Transform matrix = options.session->scene->camera->get_matrix();
306  float3 translate;
307 
308  if (key == 'w')
309  translate = make_float3(0.0f, 0.0f, 0.1f);
310  else if (key == 's')
311  translate = make_float3(0.0f, 0.0f, -0.1f);
312  else if (key == 'a')
313  translate = make_float3(-0.1f, 0.0f, 0.0f);
314  else if (key == 'd')
315  translate = make_float3(0.1f, 0.0f, 0.0f);
316 
317  matrix = matrix * transform_translate(translate);
318 
319  /* Update and Reset */
320  options.session->scene->camera->set_matrix(matrix);
321  options.session->scene->camera->need_flags_update = true;
322  options.session->scene->camera->need_device_update = true;
323 
325  }
326 
327  /* Set Max Bounces */
328  else if (options.interactive && (key == '0' || key == '1' || key == '2' || key == '3')) {
329  int bounce;
330  switch (key) {
331  case '0':
332  bounce = 0;
333  break;
334  case '1':
335  bounce = 1;
336  break;
337  case '2':
338  bounce = 2;
339  break;
340  case '3':
341  bounce = 3;
342  break;
343  default:
344  bounce = 0;
345  break;
346  }
347 
348  options.session->scene->integrator->set_max_bounce(bounce);
349 
351  }
352 }
353 #endif
354 
355 static int files_parse(int argc, const char *argv[])
356 {
357  if (argc > 0)
358  options.filepath = argv[0];
359 
360  return 0;
361 }
362 
363 static void options_parse(int argc, const char **argv)
364 {
365  options.width = 0;
366  options.height = 0;
367  options.filepath = "";
368  options.session = NULL;
369  options.quiet = false;
370 
371  /* device names */
372  string device_names = "";
373  string devicename = "CPU";
374  bool list = false;
375 
376  /* List devices for which support is compiled in. */
377  vector<DeviceType> types = Device::available_types();
378  foreach (DeviceType type, types) {
379  if (device_names != "")
380  device_names += ", ";
381 
382  device_names += Device::string_from_type(type);
383  }
384 
385  /* shading system */
386  string ssname = "svm";
387 
388  /* parse options */
389  ArgParse ap;
390  bool help = false, debug = false, version = false;
391  int verbosity = 1;
392 
393  ap.options("Usage: cycles [options] file.xml",
394  "%*",
395  files_parse,
396  "",
397  "--device %s",
398  &devicename,
399  ("Devices to use: " + device_names).c_str(),
400 #ifdef WITH_OSL
401  "--shadingsys %s",
402  &ssname,
403  "Shading system to use: svm, osl",
404 #endif
405  "--background",
407  "Render in background, without user interface",
408  "--quiet",
409  &options.quiet,
410  "In background mode, don't print progress messages",
411  "--samples %d",
413  "Number of samples to render",
414  "--output %s",
416  "File path to write output image",
417  "--threads %d",
419  "CPU Rendering Threads",
420  "--width %d",
421  &options.width,
422  "Window width in pixel",
423  "--height %d",
424  &options.height,
425  "Window height in pixel",
426  "--tile-width %d",
428  "Tile width in pixels",
429  "--tile-height %d",
431  "Tile height in pixels",
432  "--list-devices",
433  &list,
434  "List information about all available devices",
435 #ifdef WITH_CYCLES_LOGGING
436  "--debug",
437  &debug,
438  "Enable debug logging",
439  "--verbose %d",
440  &verbosity,
441  "Set verbosity of the logger",
442 #endif
443  "--help",
444  &help,
445  "Print help message",
446  "--version",
447  &version,
448  "Print version number",
449  NULL);
450 
451  if (ap.parse(argc, argv) < 0) {
452  fprintf(stderr, "%s\n", ap.geterror().c_str());
453  ap.usage();
454  exit(EXIT_FAILURE);
455  }
456 
457  if (debug) {
459  util_logging_verbosity_set(verbosity);
460  }
461 
462  if (list) {
464  printf("Devices:\n");
465 
466  foreach (DeviceInfo &info, devices) {
467  printf(" %-10s%s%s\n",
468  Device::string_from_type(info.type).c_str(),
469  info.description.c_str(),
470  (info.display_device) ? " (display)" : "");
471  }
472 
473  exit(EXIT_SUCCESS);
474  }
475  else if (version) {
476  printf("%s\n", CYCLES_VERSION_STRING);
477  exit(EXIT_SUCCESS);
478  }
479  else if (help || options.filepath == "") {
480  ap.usage();
481  exit(EXIT_SUCCESS);
482  }
483 
484  if (ssname == "osl")
486  else if (ssname == "svm")
488 
489 #ifndef WITH_CYCLES_STANDALONE_GUI
491 #endif
492 
493  /* Use progressive rendering */
495 
496  /* find matching device */
497  DeviceType device_type = Device::type_from_string(devicename.c_str());
499 
500  bool device_available = false;
501  if (!devices.empty()) {
503  device_available = true;
504  }
505 
506  /* handle invalid configurations */
507  if (options.session_params.device.type == DEVICE_NONE || !device_available) {
508  fprintf(stderr, "Unknown device: %s\n", devicename.c_str());
509  exit(EXIT_FAILURE);
510  }
511 #ifdef WITH_OSL
512  else if (!(ssname == "osl" || ssname == "svm")) {
513  fprintf(stderr, "Unknown shading system: %s\n", ssname.c_str());
514  exit(EXIT_FAILURE);
515  }
518  fprintf(stderr, "OSL shading system only works with CPU device\n");
519  exit(EXIT_FAILURE);
520  }
521 #endif
522  else if (options.session_params.samples < 0) {
523  fprintf(stderr, "Invalid number of samples: %d\n", options.session_params.samples);
524  exit(EXIT_FAILURE);
525  }
526  else if (options.filepath == "") {
527  fprintf(stderr, "No file path specified\n");
528  exit(EXIT_FAILURE);
529  }
530 
531  /* For smoother Viewport */
533 }
534 
536 
537 using namespace ccl;
538 
539 int main(int argc, const char **argv)
540 {
541  util_logging_init(argv[0]);
542  path_init();
543  options_parse(argc, argv);
544 
545 #ifdef WITH_CYCLES_STANDALONE_GUI
547 #endif
548  session_init();
549  options.session->wait();
550  session_exit();
551 #ifdef WITH_CYCLES_STANDALONE_GUI
552  }
553  else {
554  string title = "Cycles: " + path_filename(options.filepath);
555 
556  /* init/exit are callback so they run while GL is initialized */
557  view_main_loop(title.c_str(),
558  options.width,
559  options.height,
560  session_init,
561  session_exit,
562  resize,
563  display,
564  keyboard,
565  motion);
566  }
567 #endif
568 
569  return 0;
570 }
#define DEG2RADF(_deg)
unsigned char uchar
Definition: BLI_sys_types.h:86
struct Scene Scene
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
int width
Definition: buffers.h:43
int full_width
Definition: buffers.h:49
int height
Definition: buffers.h:44
int full_height
Definition: buffers.h:50
bool display_device
Definition: device.h:78
DeviceType type
Definition: device.h:74
string description
Definition: device.h:75
static vector< DeviceInfo > available_devices(uint device_type_mask=DEVICE_MASK_ALL)
Definition: device.cpp:488
static DeviceType type_from_string(const char *name)
Definition: device.cpp:433
static vector< DeviceType > available_types()
Definition: device.cpp:469
static string string_from_type(DeviceType type)
Definition: device.cpp:451
float get_progress()
void set_cancel(const string &cancel_message_)
Definition: util_progress.h:98
void get_status(string &status_, string &substatus_)
void get_time(double &total_time_, double &render_time_)
void set_update_callback(function< void()> function)
ShadingSystem shadingsystem
Definition: scene.h:166
bool progressive
Definition: session.h:50
int samples
Definition: session.h:52
int threads
Definition: session.h:58
DeviceInfo device
Definition: session.h:46
function< bool(const uchar *pixels, int width, int height, int channels)> write_render_cb
Definition: session.h:74
int start_resolution
Definition: session.h:55
int2 tile_size
Definition: session.h:53
bool background
Definition: session.h:47
void wait()
Definition: session.cpp:1003
Device * device
Definition: session.h:132
bool draw(BufferParams &params, DeviceDrawParams &draw_params)
Definition: session.cpp:897
void set_pause(bool pause)
Definition: session.cpp:946
void start()
Definition: session.cpp:128
Progress progress
Definition: session.h:136
void reset(BufferParams &params, int samples)
Definition: session.cpp:928
Scene * scene
Definition: session.h:133
static void session_init()
int main(int argc, const char **argv)
static void scene_init()
static void session_print_status()
static void session_exit()
static void options_parse(int argc, const char **argv)
static BufferParams & session_buffer_params()
CCL_NAMESPACE_BEGIN struct Options options
static bool write_render(const uchar *pixels, int w, int h, int channels)
static void session_print(const string &str)
static int files_parse(int argc, const char *argv[])
void xml_read_file(Scene *scene, const char *filepath)
Definition: cycles_xml.cpp:693
#define function_bind
#define DEVICE_MASK(type)
Definition: device.h:70
DeviceType
Definition: device.h:43
@ DEVICE_NONE
Definition: device.h:44
@ DEVICE_CPU
Definition: device.h:45
#define str(s)
#define CCL_NAMESPACE_END
#define make_float4(x, y, z, w)
#define make_float3(x, y, z)
static char ** types
Definition: makesdna.c:164
Vector< CPUDevice > devices
list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
@ SHADINGSYSTEM_OSL
Definition: shader.h:48
@ SHADINGSYSTEM_SVM
Definition: shader.h:48
SceneParams scene_params
string output_path
SessionParams session_params
Session * session
Integrator * integrator
Definition: scene.h:231
struct Object * camera
float max
void util_logging_init(const char *argv0)
void util_logging_verbosity_set(int verbosity)
void util_logging_start()
string path_filename(const string &path)
Definition: util_path.cpp:389
void path_init(const string &path, const string &user_path)
Definition: util_path.cpp:338
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: util_string.cpp:32
CCL_NAMESPACE_BEGIN double time_dt()
Definition: util_time.cpp:48
ccl_device_inline Transform transform_rotate(float angle, float3 axis)
ccl_device_inline Transform transform_translate(float3 t)
#define CYCLES_VERSION_STRING
Definition: util_version.h:30
void view_main_loop(const char *title, int width, int height, ViewInitFunc initf, ViewExitFunc exitf, ViewResizeFunc resize, ViewDisplayFunc display, ViewKeyboardFunc keyboard, ViewMotionFunc motion)
Definition: util_view.cpp:231
void view_display_info(const char *info)
Definition: util_view.cpp:65
void view_redraw()
Definition: util_view.cpp:277
void view_display_help()
Definition: util_view.cpp:82
uint len