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