|
Blender
V2.59
|
00001 /* 00002 * $Id: render_opengl.c 38109 2011-07-05 07:46:25Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2008 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include <math.h> 00033 #include <string.h> 00034 #include <stddef.h> 00035 00036 #include <GL/glew.h> 00037 00038 #include "MEM_guardedalloc.h" 00039 00040 #include "BLI_math.h" 00041 #include "BLI_blenlib.h" 00042 #include "BLI_editVert.h" 00043 #include "BLI_dlrbTree.h" 00044 #include "BLI_utildefines.h" 00045 00046 #include "DNA_scene_types.h" 00047 #include "DNA_object_types.h" 00048 00049 #include "BKE_context.h" 00050 #include "BKE_image.h" 00051 #include "BKE_main.h" 00052 #include "BKE_report.h" 00053 #include "BKE_scene.h" 00054 #include "BKE_writeavi.h" 00055 00056 #include "WM_api.h" 00057 #include "WM_types.h" 00058 00059 #include "ED_screen.h" 00060 #include "ED_view3d.h" 00061 #include "ED_image.h" 00062 00063 #include "RE_pipeline.h" 00064 #include "IMB_imbuf_types.h" 00065 #include "IMB_imbuf.h" 00066 00067 #include "RNA_access.h" 00068 #include "RNA_define.h" 00069 00070 00071 #include "GPU_extensions.h" 00072 00073 #include "wm_window.h" 00074 00075 #include "render_intern.h" 00076 00077 typedef struct OGLRender { 00078 Render *re; 00079 Scene *scene; 00080 00081 View3D *v3d; 00082 RegionView3D *rv3d; 00083 ARegion *ar; 00084 00085 Image *ima; 00086 ImageUser iuser; 00087 00088 GPUOffScreen *ofs; 00089 int sizex, sizey; 00090 int write_still; 00091 00092 ReportList *reports; 00093 bMovieHandle *mh; 00094 int cfrao, nfra; 00095 00096 wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/ 00097 } OGLRender; 00098 00099 /* added because v3d is not always valid */ 00100 static unsigned int screen_opengl_layers(OGLRender *oglrender) 00101 { 00102 if(oglrender->v3d) { 00103 return oglrender->scene->lay | oglrender->v3d->lay; 00104 } 00105 else { 00106 return oglrender->scene->lay; 00107 } 00108 } 00109 00110 static void screen_opengl_render_apply(OGLRender *oglrender) 00111 { 00112 Scene *scene= oglrender->scene; 00113 ARegion *ar= oglrender->ar; 00114 View3D *v3d= oglrender->v3d; 00115 RegionView3D *rv3d= oglrender->rv3d; 00116 RenderResult *rr; 00117 Object *camera= NULL; 00118 ImBuf *ibuf; 00119 void *lock; 00120 float winmat[4][4]; 00121 int sizex= oglrender->sizex; 00122 int sizey= oglrender->sizey; 00123 const short view_context= (v3d != NULL); 00124 00125 rr= RE_AcquireResultRead(oglrender->re); 00126 00127 /* note on color management: 00128 * looked into how best to deal with color management here and found heres how it should work. 00129 * 00130 * OpenGL materials etc are color corrected, so a float buffer from the graphics card is 00131 * color corrected, without running any conversion functions. 00132 * 00133 * With color correction disabled blender expects the rr->rectf to be non-color managed so 00134 * just do a direct copy from the byte array to the rectf with no conversion too. 00135 * notice IMB_float_from_rect has the profile set so no conversion is done. 00136 */ 00137 00138 if(view_context) { 00139 GPU_offscreen_bind(oglrender->ofs); /* bind */ 00140 00141 /* render 3d view */ 00142 if(rv3d->persp==RV3D_CAMOB && v3d->camera) { 00143 /*int is_ortho= scene->r.mode & R_ORTHO;*/ 00144 camera= v3d->camera; 00145 RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); 00146 00147 } 00148 else { 00149 rctf viewplane; 00150 float clipsta, clipend; 00151 00152 int is_ortho= ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL); 00153 if(is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend); 00154 else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); 00155 } 00156 00157 if((scene->r.mode & R_OSA) == 0) { 00158 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat); 00159 glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, rr->rectf); 00160 } 00161 else { 00162 /* simple accumulation, less hassle then FSAA FBO's */ 00163 # define SAMPLES 5 /* fixed, easy to have more but for now this is ok */ 00164 const float jit_ofs[SAMPLES][2] = {{0, 0}, {0.5f, 0.5f}, {-0.5f,-0.5f}, {-0.5f, 0.5f}, {0.5f, -0.5f}}; 00165 float winmat_jitter[4][4]; 00166 float *accum_buffer= MEM_mallocN(sizex * sizey * sizeof(float) * 4, "accum1"); 00167 float *accum_tmp= MEM_mallocN(sizex * sizey * sizeof(float) * 4, "accum2"); 00168 int j; 00169 00170 /* first sample buffer, also initializes 'rv3d->persmat' */ 00171 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat); 00172 glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, accum_buffer); 00173 00174 /* skip the first sample */ 00175 for(j=1; j < SAMPLES; j++) { 00176 copy_m4_m4(winmat_jitter, winmat); 00177 window_translate_m4(winmat_jitter, rv3d->persmat, jit_ofs[j][0] / sizex, jit_ofs[j][1] / sizey); 00178 00179 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter); 00180 glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, accum_tmp); 00181 add_vn_vn(accum_buffer, accum_tmp, sizex*sizey*sizeof(float)); 00182 } 00183 00184 mul_vn_vn_fl(rr->rectf, accum_buffer, sizex*sizey*sizeof(float), 1.0/SAMPLES); 00185 00186 MEM_freeN(accum_buffer); 00187 MEM_freeN(accum_tmp); 00188 } 00189 00190 GPU_offscreen_unbind(oglrender->ofs); /* unbind */ 00191 } 00192 else { 00193 /* shouldnt suddenly give errors mid-render but possible */ 00194 char err_out[256]= "unknown"; 00195 ImBuf *ibuf_view= ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rectfloat, OB_SOLID, err_out); 00196 camera= scene->camera; 00197 00198 if(ibuf_view) { 00199 memcpy(rr->rectf, ibuf_view->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); 00200 IMB_freeImBuf(ibuf_view); 00201 } 00202 else { 00203 fprintf(stderr, "screen_opengl_render_apply: failed to get buffer, %s\n", err_out); 00204 } 00205 } 00206 00207 /* rr->rectf is now filled with image data */ 00208 00209 if((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) 00210 BKE_stamp_buf(scene, camera, NULL, rr->rectf, rr->rectx, rr->recty, 4); 00211 00212 RE_ReleaseResult(oglrender->re); 00213 00214 /* update byte from float buffer */ 00215 ibuf= BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); 00216 00217 if(ibuf) { 00218 image_buffer_rect_update(NULL, rr, ibuf, NULL); 00219 00220 if(oglrender->write_still) { 00221 char name[FILE_MAX]; 00222 int ok; 00223 00224 if(scene->r.planes == 8) { 00225 IMB_color_to_bw(ibuf); 00226 } 00227 00228 BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, FALSE); 00229 ok= BKE_write_ibuf(ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality); /* no need to stamp here */ 00230 if(ok) printf("OpenGL Render written to '%s'\n", name); 00231 else printf("OpenGL Render failed to write '%s'\n", name); 00232 } 00233 } 00234 00235 BKE_image_release_ibuf(oglrender->ima, lock); 00236 } 00237 00238 static int screen_opengl_render_init(bContext *C, wmOperator *op) 00239 { 00240 /* new render clears all callbacks */ 00241 Scene *scene= CTX_data_scene(C); 00242 RenderResult *rr; 00243 GPUOffScreen *ofs; 00244 OGLRender *oglrender; 00245 int sizex, sizey; 00246 short is_view_context= RNA_boolean_get(op->ptr, "view_context"); 00247 const short is_animation= RNA_boolean_get(op->ptr, "animation"); 00248 const short is_write_still= RNA_boolean_get(op->ptr, "write_still"); 00249 char err_out[256]= "unknown"; 00250 00251 /* ensure we have a 3d view */ 00252 00253 if(!ED_view3d_context_activate(C)) { 00254 RNA_boolean_set(op->ptr, "view_context", 0); 00255 is_view_context= 0; 00256 } 00257 00258 /* only one render job at a time */ 00259 if(WM_jobs_test(CTX_wm_manager(C), scene)) 00260 return 0; 00261 00262 if(!is_view_context && scene->camera==NULL) { 00263 BKE_report(op->reports, RPT_ERROR, "Scene has no camera."); 00264 return 0; 00265 } 00266 00267 if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) { 00268 BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected."); 00269 return 0; 00270 } 00271 00272 /* stop all running jobs, currently previews frustrate Render */ 00273 WM_jobs_stop_all(CTX_wm_manager(C)); 00274 00275 /* handle UI stuff */ 00276 WM_cursor_wait(1); 00277 00278 /* create offscreen buffer */ 00279 sizex= (scene->r.size*scene->r.xsch)/100; 00280 sizey= (scene->r.size*scene->r.ysch)/100; 00281 00282 /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ 00283 ofs= GPU_offscreen_create(&sizex, &sizey, err_out); 00284 00285 if(!ofs) { 00286 BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer, %s", err_out); 00287 return 0; 00288 } 00289 00290 /* allocate opengl render */ 00291 oglrender= MEM_callocN(sizeof(OGLRender), "OGLRender"); 00292 op->customdata= oglrender; 00293 00294 oglrender->ofs= ofs; 00295 oglrender->sizex= sizex; 00296 oglrender->sizey= sizey; 00297 oglrender->scene= scene; 00298 00299 oglrender->write_still= is_write_still && !is_animation; 00300 00301 if(is_view_context) { 00302 oglrender->v3d= CTX_wm_view3d(C); 00303 oglrender->ar= CTX_wm_region(C); 00304 oglrender->rv3d= CTX_wm_region_view3d(C); 00305 00306 /* MUST be cleared on exit */ 00307 oglrender->scene->customdata_mask_modal= ED_view3d_datamask(oglrender->scene, oglrender->v3d); 00308 } 00309 00310 /* create image and image user */ 00311 oglrender->ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); 00312 BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE); 00313 00314 oglrender->iuser.scene= scene; 00315 oglrender->iuser.ok= 1; 00316 00317 /* create render and render result */ 00318 oglrender->re= RE_NewRender(scene->id.name); 00319 RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL); 00320 00321 rr= RE_AcquireResultWrite(oglrender->re); 00322 if(rr->rectf==NULL) 00323 rr->rectf= MEM_callocN(sizeof(float)*4*sizex*sizey, "screen_opengl_render_init rect"); 00324 RE_ReleaseResult(oglrender->re); 00325 00326 return 1; 00327 } 00328 00329 static void screen_opengl_render_end(bContext *C, OGLRender *oglrender) 00330 { 00331 Main *bmain= CTX_data_main(C); 00332 Scene *scene= oglrender->scene; 00333 00334 if(oglrender->mh) { 00335 if(BKE_imtype_is_movie(scene->r.imtype)) 00336 oglrender->mh->end_movie(); 00337 } 00338 00339 if(oglrender->timer) { /* exec will not have a timer */ 00340 scene->r.cfra= oglrender->cfrao; 00341 scene_update_for_newframe(bmain, scene, screen_opengl_layers(oglrender)); 00342 00343 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), oglrender->timer); 00344 } 00345 00346 WM_cursor_wait(0); 00347 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, oglrender->scene); 00348 00349 GPU_offscreen_free(oglrender->ofs); 00350 00351 oglrender->scene->customdata_mask_modal= 0; 00352 00353 MEM_freeN(oglrender); 00354 } 00355 00356 static int screen_opengl_render_cancel(bContext *C, wmOperator *op) 00357 { 00358 screen_opengl_render_end(C, op->customdata); 00359 00360 return OPERATOR_CANCELLED; 00361 } 00362 00363 /* share between invoke and exec */ 00364 static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op) 00365 { 00366 /* initialize animation */ 00367 OGLRender *oglrender; 00368 Scene *scene; 00369 00370 oglrender= op->customdata; 00371 scene= oglrender->scene; 00372 00373 oglrender->reports= op->reports; 00374 oglrender->mh= BKE_get_movie_handle(scene->r.imtype); 00375 if(BKE_imtype_is_movie(scene->r.imtype)) { 00376 if(!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports)) { 00377 screen_opengl_render_end(C, oglrender); 00378 return 0; 00379 } 00380 } 00381 00382 oglrender->cfrao= scene->r.cfra; 00383 oglrender->nfra= PSFRA; 00384 scene->r.cfra= PSFRA; 00385 00386 return 1; 00387 } 00388 static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) 00389 { 00390 Main *bmain= CTX_data_main(C); 00391 OGLRender *oglrender= op->customdata; 00392 Scene *scene= oglrender->scene; 00393 ImBuf *ibuf; 00394 void *lock; 00395 char name[FILE_MAXDIR+FILE_MAXFILE]; 00396 int ok= 0; 00397 const short view_context= (oglrender->v3d != NULL); 00398 Object *camera= NULL; 00399 00400 /* update animated image textures for gpu, etc, 00401 * call before scene_update_for_newframe so modifiers with textuers dont lag 1 frame */ 00402 ED_image_update_frame(bmain, scene->r.cfra); 00403 00404 /* go to next frame */ 00405 while(CFRA<oglrender->nfra) { 00406 unsigned int lay= screen_opengl_layers(oglrender); 00407 00408 if(lay & 0xFF000000) 00409 lay &= 0xFF000000; 00410 00411 scene_update_for_newframe(bmain, scene, lay); 00412 CFRA++; 00413 } 00414 00415 scene_update_for_newframe(bmain, scene, screen_opengl_layers(oglrender)); 00416 00417 if(view_context) { 00418 if(oglrender->rv3d->persp==RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) { 00419 /* since scene_update_for_newframe() is used rather 00420 * then ED_update_for_newframe() the camera needs to be set */ 00421 if(scene_camera_switch_update(scene)) { 00422 oglrender->v3d->camera= scene->camera; 00423 } 00424 00425 camera= oglrender->v3d->camera; 00426 } 00427 } 00428 else { 00429 scene_camera_switch_update(scene); 00430 00431 camera= scene->camera; 00432 } 00433 00434 /* render into offscreen buffer */ 00435 screen_opengl_render_apply(oglrender); 00436 00437 /* save to disk */ 00438 ibuf= BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); 00439 00440 if(ibuf) { 00441 /* color -> greyscale */ 00442 /* editing directly would alter the render view */ 00443 if(scene->r.planes == 8) { 00444 ImBuf *ibuf_bw= IMB_dupImBuf(ibuf); 00445 IMB_color_to_bw(ibuf_bw); 00446 // IMB_freeImBuf(ibuf); /* owned by the image */ 00447 ibuf= ibuf_bw; 00448 } 00449 else { 00450 /* this is lightweight & doesnt re-alloc the buffers, only do this 00451 * to save the correct bit depth since the image is always RGBA */ 00452 ImBuf *ibuf_cpy= IMB_allocImBuf(ibuf->x, ibuf->y, scene->r.planes, 0); 00453 ibuf_cpy->rect= ibuf->rect; 00454 ibuf_cpy->rect_float= ibuf->rect_float; 00455 ibuf_cpy->zbuf_float= ibuf->zbuf_float; 00456 ibuf= ibuf_cpy; 00457 } 00458 00459 if(BKE_imtype_is_movie(scene->r.imtype)) { 00460 ok= oglrender->mh->append_movie(&scene->r, CFRA, (int*)ibuf->rect, oglrender->sizex, oglrender->sizey, oglrender->reports); 00461 if(ok) { 00462 printf("Append frame %d", scene->r.cfra); 00463 BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra); 00464 } 00465 } 00466 else { 00467 BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, TRUE); 00468 ok= BKE_write_ibuf_stamp(scene, camera, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality); 00469 00470 if(ok==0) { 00471 printf("Write error: cannot save %s\n", name); 00472 BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name); 00473 } 00474 else { 00475 printf("Saved: %s", name); 00476 BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name); 00477 } 00478 } 00479 00480 /* imbuf knows which rects are not part of ibuf */ 00481 IMB_freeImBuf(ibuf); 00482 } 00483 00484 BKE_image_release_ibuf(oglrender->ima, lock); 00485 00486 /* movie stats prints have no line break */ 00487 printf("\n"); 00488 00489 /* go to next frame */ 00490 oglrender->nfra += scene->r.frame_step; 00491 scene->r.cfra++; 00492 00493 /* stop at the end or on error */ 00494 if(scene->r.cfra > PEFRA || !ok) { 00495 screen_opengl_render_end(C, op->customdata); 00496 return 0; 00497 } 00498 00499 return 1; 00500 } 00501 00502 00503 static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *event) 00504 { 00505 OGLRender *oglrender= op->customdata; 00506 int anim= RNA_boolean_get(op->ptr, "animation"); 00507 int ret; 00508 00509 switch(event->type) { 00510 case ESCKEY: 00511 /* cancel */ 00512 screen_opengl_render_end(C, op->customdata); 00513 return OPERATOR_FINISHED; 00514 case TIMER: 00515 /* render frame? */ 00516 if(oglrender->timer == event->customdata) 00517 break; 00518 default: 00519 /* nothing to do */ 00520 return OPERATOR_RUNNING_MODAL; 00521 } 00522 00523 /* run first because screen_opengl_render_anim_step can free oglrender */ 00524 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, oglrender->scene); 00525 00526 if(anim == 0) { 00527 screen_opengl_render_apply(op->customdata); 00528 screen_opengl_render_end(C, op->customdata); 00529 return OPERATOR_FINISHED; 00530 } 00531 else 00532 ret= screen_opengl_render_anim_step(C, op); 00533 00534 /* stop at the end or on error */ 00535 if(ret == 0) { 00536 return OPERATOR_FINISHED; 00537 } 00538 00539 return OPERATOR_RUNNING_MODAL; 00540 } 00541 00542 static int screen_opengl_render_invoke(bContext *C, wmOperator *op, wmEvent *event) 00543 { 00544 OGLRender *oglrender; 00545 int anim= RNA_boolean_get(op->ptr, "animation"); 00546 00547 if(!screen_opengl_render_init(C, op)) 00548 return OPERATOR_CANCELLED; 00549 00550 if(anim) { 00551 if(!screen_opengl_render_anim_initialize(C, op)) 00552 return OPERATOR_CANCELLED; 00553 } 00554 00555 oglrender= op->customdata; 00556 render_view_open(C, event->x, event->y); 00557 00558 WM_event_add_modal_handler(C, op); 00559 oglrender->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); 00560 00561 return OPERATOR_RUNNING_MODAL; 00562 } 00563 00564 /* executes blocking render */ 00565 static int screen_opengl_render_exec(bContext *C, wmOperator *op) 00566 { 00567 const short is_animation= RNA_boolean_get(op->ptr, "animation"); 00568 00569 if(!screen_opengl_render_init(C, op)) 00570 return OPERATOR_CANCELLED; 00571 00572 if(!is_animation) { /* same as invoke */ 00573 /* render image */ 00574 screen_opengl_render_apply(op->customdata); 00575 screen_opengl_render_end(C, op->customdata); 00576 00577 return OPERATOR_FINISHED; 00578 } 00579 else { 00580 int ret= 1; 00581 00582 if(!screen_opengl_render_anim_initialize(C, op)) 00583 return OPERATOR_CANCELLED; 00584 00585 while(ret) { 00586 ret= screen_opengl_render_anim_step(C, op); 00587 } 00588 } 00589 00590 // no redraw needed, we leave state as we entered it 00591 // ED_update_for_newframe(C, 1); 00592 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, CTX_data_scene(C)); 00593 00594 return OPERATOR_FINISHED; 00595 } 00596 00597 void RENDER_OT_opengl(wmOperatorType *ot) 00598 { 00599 /* identifiers */ 00600 ot->name= "OpenGL Render"; 00601 ot->description= "OpenGL render active viewport"; 00602 ot->idname= "RENDER_OT_opengl"; 00603 00604 /* api callbacks */ 00605 ot->invoke= screen_opengl_render_invoke; 00606 ot->exec= screen_opengl_render_exec; /* blocking */ 00607 ot->modal= screen_opengl_render_modal; 00608 ot->cancel= screen_opengl_render_cancel; 00609 00610 ot->poll= ED_operator_screenactive; 00611 00612 RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene"); 00613 RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)"); 00614 RNA_def_boolean(ot->srna, "view_context", 1, "View Context", "Use the current 3D view for rendering, else use scene settings."); 00615 } 00616 00617 /* function for getting an opengl buffer from a View3D, used by sequencer */ 00618 // extern void *sequencer_view3d_cb;