static void screen_opengl_render_apply(OGLRender *oglrender) { Scene *scene = oglrender->scene; ARegion *ar = oglrender->ar; View3D *v3d = oglrender->v3d; RegionView3D *rv3d = oglrender->rv3d; RenderResult *rr; Object *camera = NULL; ImBuf *ibuf; void *lock; float winmat[4][4]; int sizex = oglrender->sizex; int sizey = oglrender->sizey; const short view_context = (v3d != NULL); bool draw_bgpic = true; bool draw_sky = (scene->r.alphamode == R_ADDSKY); unsigned char *rect = NULL; rr = RE_AcquireResultRead(oglrender->re); if (oglrender->is_sequencer) { SeqRenderData context; int chanshown = oglrender->sseq ? oglrender->sseq->chanshown : 0; context = BKE_sequencer_new_render_data(oglrender->bmain, scene, oglrender->sizex, oglrender->sizey, 100.0f); ibuf = BKE_sequencer_give_ibuf(context, CFRA, chanshown); if (ibuf) { ImBuf *linear_ibuf; BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); linear_ibuf = IMB_dupImBuf(ibuf); IMB_freeImBuf(ibuf); if (linear_ibuf->rect_float == NULL) { /* internally sequencer working in display space and stores both bytes and float buffers in that space. * It is possible that byte->float onversion didn't happen in sequencer (e.g. when adding image sequence/movie * into sequencer) there'll be only byte buffer. Create float buffer from existing byte buffer, making it linear */ IMB_float_from_rect(linear_ibuf); } else { /* ensure float buffer is in linear space, not in display space */ BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); IMB_freeImBuf(linear_ibuf); } } else if (view_context) { ED_view3d_draw_offscreen_init(scene, v3d); GPU_offscreen_bind(oglrender->ofs); /* bind */ /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { /*int is_ortho = scene->r.mode & R_ORTHO;*/ camera = v3d->camera; RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); } else { rctf viewplane; float clipsta, clipend; int is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL); if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend); else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); if ((scene->r.mode & R_OSA) == 0) { ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); } else { /* simple accumulation, less hassle then FSAA FBO's */ static float jit_ofs[32][2]; float winmat_jitter[4][4]; int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1"); int i, j; BLI_jitter_init(jit_ofs[0], scene->r.osa); /* first sample buffer, also initializes 'rv3d->persmat' */ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); for (i = 0; i < sizex * sizey * 4; i++) accum_buffer[i] = rect[i]; /* skip the first sample */ for (j = 1; j < scene->r.osa; j++) { copy_m4_m4(winmat_jitter, winmat); window_translate_m4(winmat_jitter, rv3d->persmat, (jit_ofs[j][0] * 2.0f) / sizex, (jit_ofs[j][1] * 2.0f) / sizey); ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); for (i = 0; i < sizex * sizey * 4; i++) accum_buffer[i] += rect[i]; } for (i = 0; i < sizex * sizey * 4; i++) rect[i] = accum_buffer[i] / scene->r.osa; MEM_freeN(accum_buffer); } GPU_offscreen_unbind(oglrender->ofs); /* unbind */ } else { /* shouldnt suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rect, OB_SOLID, FALSE, TRUE, (draw_sky) ? R_ADDSKY: R_ALPHAPREMUL, err_out); camera = scene->camera; if (ibuf_view) { /* steal rect reference from ibuf */ rect = (unsigned char *)ibuf_view->rect; ibuf_view->mall &= ~IB_rect; IMB_freeImBuf(ibuf_view); } else { fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out); } } /* note on color management: * * OpenGL renders into sRGB colors, but render buffers are expected to be * linear So we convert to linear here, so the conversion back to bytes can make it * sRGB (or other display space) again, and so that e.g. openexr saving also saves the * correct linear float buffer. */ if (rect) { int profile_to; if (BKE_scene_check_color_management_enabled(scene)) profile_to = IB_PROFILE_LINEAR_RGB; else profile_to = IB_PROFILE_SRGB; /* sequencer has got trickier conversion happened above * also assume opengl's space matches byte buffer color space */ IMB_buffer_float_from_byte(rr->rectf, rect, profile_to, IB_PROFILE_SRGB, true, oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); } /* rr->rectf is now filled with image data */ if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) BKE_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4); RE_ReleaseResult(oglrender->re); /* update byte from float buffer */ ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { /* update display buffer */ if (ibuf->rect == NULL) imb_addrectImBuf(ibuf); IMB_partial_display_buffer_update(ibuf, rr->rectf, rect, rr->rectx, 0, 0, &scene->view_settings, &scene->display_settings, 0, 0, rr->rectx, rr->recty, true); /* write file for animation */ if (oglrender->write_still) { char name[FILE_MAX]; int ok; if (scene->r.im_format.planes == R_IMF_CHAN_DEPTH_8) { IMB_color_to_bw(ibuf); } BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, FALSE); ok = BKE_imbuf_write_as(ibuf, name, &scene->r.im_format, TRUE); /* no need to stamp here */ if (ok) printf("OpenGL Render written to '%s'\n", name); else printf("OpenGL Render failed to write '%s'\n", name); } } BKE_image_release_ibuf(oglrender->ima, ibuf, lock); if (rect) MEM_freeN(rect); }
static void draw_plane_marker_image(Scene *scene, MovieTrackingPlaneTrack *plane_track, MovieTrackingPlaneMarker *plane_marker) { Image *image = plane_track->image; ImBuf *ibuf; void *lock; if (image == NULL) { return; } ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); if (ibuf) { unsigned char *display_buffer; void *cache_handle; if (image->flag & IMA_VIEW_AS_RENDER) { display_buffer = IMB_display_buffer_acquire(ibuf, &scene->view_settings, &scene->display_settings, &cache_handle); } else { display_buffer = IMB_display_buffer_acquire(ibuf, NULL, &scene->display_settings, &cache_handle); } if (display_buffer) { GLuint texid; float frame_corners[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}}; float perspective_matrix[3][3]; float gl_matrix[4][4]; bool transparent = false; BKE_tracking_homography_between_two_quads(frame_corners, plane_marker->corners, perspective_matrix); homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix); if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) { transparent = true; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity); GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR); glGenTextures(1, (GLuint *)&texid); glBindTexture(GL_TEXTURE_2D, texid); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); glPushMatrix(); glMultMatrixf(gl_matrix); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f); glEnd(); glPopMatrix(); glBindTexture(GL_TEXTURE_2D, 0); GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); if (transparent) { glDisable(GL_BLEND); } } IMB_display_buffer_release(cache_handle); } BKE_image_release_ibuf(image, ibuf, lock); }
// refresh texture static PyObject *Texture_refresh(Texture *self, PyObject *args) { // get parameter - refresh source PyObject *param; double ts = -1.0; if (!PyArg_ParseTuple(args, "O|d:refresh", ¶m, &ts) || !PyBool_Check(param)) { // report error PyErr_SetString(PyExc_TypeError, "The value must be a bool"); return NULL; } // some trick here: we are in the business of loading a texture, // no use to do it if we are still in the same rendering frame. // We find this out by looking at the engine current clock time KX_KetsjiEngine* engine = KX_GetActiveEngine(); if (engine->GetClockTime() != self->m_lastClock) { self->m_lastClock = engine->GetClockTime(); // set source refresh bool refreshSource = (param == Py_True); // try to proces texture from source try { // if source is available if (self->m_source != NULL) { // check texture code if (!self->m_orgSaved) { self->m_orgSaved = true; // save original image code if (self->m_useMatTexture) self->m_orgTex = self->m_matTexture->swapTexture(self->m_actTex); else { // Swapping will work only if the GPU has already loaded the image. // If not, it will delete and overwrite our texture on next render. // To avoid that, we acquire the image buffer now. // WARNING: GPU has a ImageUser to pass, we don't. Using NULL // works on image file, not necessarily on other type of image. self->m_imgBuf = BKE_image_acquire_ibuf(self->m_imgTexture, NULL, NULL); self->m_orgTex = self->m_imgTexture->bindcode[TEXTARGET_TEXTURE_2D]; self->m_imgTexture->bindcode[TEXTARGET_TEXTURE_2D] = self->m_actTex; } } // get texture unsigned int * texture = self->m_source->m_image->getImage(self->m_actTex, ts); // if texture is available if (texture != NULL) { // get texture size short * orgSize = self->m_source->m_image->getSize(); // calc scaled sizes short size[2]; if (GLEW_ARB_texture_non_power_of_two) { size[0] = orgSize[0]; size[1] = orgSize[1]; } else { size[0] = ImageBase::calcSize(orgSize[0]); size[1] = ImageBase::calcSize(orgSize[1]); } // scale texture if needed if (size[0] != orgSize[0] || size[1] != orgSize[1]) { IMB_freeImBuf(self->m_scaledImBuf); self->m_scaledImBuf = IMB_allocFromBuffer(texture, NULL, orgSize[0], orgSize[1]); IMB_scaleImBuf(self->m_scaledImBuf, size[0], size[1]); // use scaled image instead original texture = self->m_scaledImBuf->rect; } // load texture for rendering loadTexture(self->m_actTex, texture, size, self->m_mipmap); } // refresh texture source, if required if (refreshSource) { self->m_source->m_image->refresh(); } } } CATCH_EXCP; }
/* already have tested for tface and ima and zspan */ static void shade_tface(BakeShade *bs) { VlakRen *vlr = bs->vlr; ObjectInstanceRen *obi = bs->obi; ObjectRen *obr = obi->obr; MTFace *tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); Image *ima = tface->tpage; float vec[4][2]; int a, i1, i2, i3; /* check valid zspan */ if (ima != bs->ima) { BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); bs->ima = ima; bs->ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); /* note, these calls only free/fill contents of zspan struct, not zspan itself */ zbuf_free_span(bs->zspan); zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); } bs->rectx = bs->ibuf->x; bs->recty = bs->ibuf->y; bs->rect = bs->ibuf->rect; bs->rect_colorspace = bs->ibuf->rect_colorspace; bs->rect_float = bs->ibuf->rect_float; bs->vcol = NULL; bs->quad = 0; bs->rect_mask = NULL; bs->displacement_buffer = NULL; if (bs->use_mask || bs->use_displacement_buffer) { BakeImBufuserData *userdata = bs->ibuf->userdata; if (userdata == NULL) { BLI_lock_thread(LOCK_CUSTOM1); userdata = bs->ibuf->userdata; if (userdata == NULL) /* since the thread was locked, its possible another thread alloced the value */ userdata = MEM_callocN(sizeof(BakeImBufuserData), "BakeImBufuserData"); if (bs->use_mask) { if (userdata->mask_buffer == NULL) { userdata->mask_buffer = MEM_callocN(sizeof(char) * bs->rectx * bs->recty, "BakeMask"); } } if (bs->use_displacement_buffer) { if (userdata->displacement_buffer == NULL) { userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp"); } } bs->ibuf->userdata = userdata; BLI_unlock_thread(LOCK_CUSTOM1); } bs->rect_mask = userdata->mask_buffer; bs->displacement_buffer = userdata->displacement_buffer; } /* get pixel level vertex coordinates */ for (a = 0; a < 4; a++) { /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests * where a pixel gets in between 2 faces or the middle of a quad, * camera aligned quads also have this problem but they are less common. * Add a small offset to the UVs, fixes bug #18685 - Campbell */ vec[a][0] = tface->uv[a][0] * (float)bs->rectx - (0.5f + 0.001f); vec[a][1] = tface->uv[a][1] * (float)bs->recty - (0.5f + 0.002f); } /* UV indices have to be corrected for possible quad->tria splits */ i1 = 0; i2 = 1; i3 = 2; vlr_set_uv_indices(vlr, &i1, &i2, &i3); bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]); zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade); if (vlr->v4) { bs->quad = 1; bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]); zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade); } }
/* returns 0 if nothing was handled */ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress) { BakeShade *handles; ListBase threads; Image *ima; int a, vdone = false, result = BAKE_RESULT_OK; bool use_mask = false; bool use_displacement_buffer = false; bool do_manage = BKE_scene_check_color_management_enabled(re->scene); re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene); /* initialize render global */ R = *re; R.bakebuf = NULL; /* initialize static vars */ get_next_bake_face(NULL); /* do we need a mask? */ if (re->r.bake_filter) use_mask = true; /* do we need buffer to store displacements */ if (ELEM(type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { if (((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) || (type == RE_BAKE_DERIVATIVE)) { use_displacement_buffer = true; use_mask = true; } } /* baker uses this flag to detect if image was initialized */ if ((R.r.bake_flag & R_BAKE_VCOL) == 0) { for (ima = G.main->image.first; ima; ima = ima->id.next) { ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); ima->id.flag |= LIB_DOIT; ima->flag &= ~IMA_USED_FOR_RENDER; if (ibuf) { ibuf->userdata = NULL; /* use for masking if needed */ } BKE_image_release_ibuf(ima, ibuf, NULL); } } if (R.r.bake_flag & R_BAKE_VCOL) { /* untag all meshes */ BKE_main_id_tag_listbase(&G.main->mesh, false); } BLI_init_threads(&threads, do_bake_thread, re->r.threads); handles = MEM_callocN(sizeof(BakeShade) * re->r.threads, "BakeShade"); /* get the threads running */ for (a = 0; a < re->r.threads; a++) { /* set defaults in handles */ handles[a].ssamp.shi[0].lay = re->lay; if (type == RE_BAKE_SHADOW) { handles[a].ssamp.shi[0].passflag = SCE_PASS_SHADOW; } else { handles[a].ssamp.shi[0].passflag = SCE_PASS_COMBINED; } handles[a].ssamp.shi[0].combinedflag = ~(SCE_PASS_SPEC); handles[a].ssamp.shi[0].thread = a; handles[a].ssamp.shi[0].do_manage = do_manage; handles[a].ssamp.tot = 1; handles[a].type = type; handles[a].actob = actob; if (R.r.bake_flag & R_BAKE_VCOL) handles[a].zspan = NULL; else handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake"); handles[a].use_mask = use_mask; handles[a].use_displacement_buffer = use_displacement_buffer; handles[a].do_update = do_update; /* use to tell the view to update */ handles[a].displacement_min = FLT_MAX; handles[a].displacement_max = -FLT_MAX; BLI_insert_thread(&threads, &handles[a]); } /* wait for everything to be done */ a = 0; while (a != re->r.threads) { PIL_sleep_ms(50); /* calculate progress */ for (vdone = false, a = 0; a < re->r.threads; a++) vdone += handles[a].vdone; if (progress) *progress = (float)(vdone / (float)re->totvlak); for (a = 0; a < re->r.threads; a++) { if (handles[a].ready == false) { break; } } } /* filter and refresh images */ if ((R.r.bake_flag & R_BAKE_VCOL) == 0) { float displacement_min = FLT_MAX, displacement_max = -FLT_MAX; if (use_displacement_buffer) { for (a = 0; a < re->r.threads; a++) { displacement_min = min_ff(displacement_min, handles[a].displacement_min); displacement_max = max_ff(displacement_max, handles[a].displacement_max); } } for (ima = G.main->image.first; ima; ima = ima->id.next) { if ((ima->id.flag & LIB_DOIT) == 0) { ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); BakeImBufuserData *userdata; if (ima->flag & IMA_USED_FOR_RENDER) result = BAKE_RESULT_FEEDBACK_LOOP; if (!ibuf) continue; userdata = (BakeImBufuserData *)ibuf->userdata; if (userdata) { if (use_displacement_buffer) { if (type == RE_BAKE_DERIVATIVE) { float user_scale = (R.r.bake_flag & R_BAKE_USERSCALE) ? R.r.bake_user_scale : -1.0f; RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer, displacement_min, displacement_max, user_scale); } else { RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, displacement_min, displacement_max); } } RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter); } ibuf->userflags |= IB_BITMAPDIRTY; BKE_image_release_ibuf(ima, ibuf, NULL); } } /* calculate return value */ for (a = 0; a < re->r.threads; a++) { zbuf_free_span(handles[a].zspan); MEM_freeN(handles[a].zspan); } } MEM_freeN(handles); BLI_end_threads(&threads); if (vdone == 0) { result = BAKE_RESULT_NO_OBJECTS; } return result; }
/* if all is good tag image and return true */ static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports) { Image *image; void *lock; int i; if ((ob->lay & scene->lay) == 0) { BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not on a scene layer", ob->id.name + 2); return false; } if (ob->type != OB_MESH) { BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2); return false; } else { Mesh *me = (Mesh *)ob->data; if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) { BKE_reportf(reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2); return false; } } for (i = 0; i < ob->totcol; i++) { bNodeTree *ntree = NULL; bNode *node = NULL; ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree); if (image) { ImBuf *ibuf; if (node) { if (BKE_node_is_connected_to_output(ntree, node)) { /* we don't return false since this may be a false positive * this can't be RPT_ERROR though, otherwise it prevents * multiple highpoly objects to be baked at once */ BKE_reportf(reports, RPT_INFO, "Circular dependency for image \"%s\" from object \"%s\"", image->id.name + 2, ob->id.name + 2); } } ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); if (ibuf) { BKE_image_release_ibuf(image, ibuf, lock); } else { BKE_reportf(reports, RPT_ERROR, "Uninitialized image \"%s\" from object \"%s\"", image->id.name + 2, ob->id.name + 2); BKE_image_release_ibuf(image, ibuf, lock); return false; } } else { Material *mat = give_current_material(ob, i); if (mat != NULL) { BKE_reportf(reports, RPT_INFO, "No active image found in material \"%s\" (%d) for object \"%s\"", mat->id.name + 2, i, ob->id.name + 2); } else { BKE_reportf(reports, RPT_INFO, "No active image found in material slot (%d) for object \"%s\"", i, ob->id.name + 2); } continue; } image->id.tag |= LIB_TAG_DOIT; } return true; }
static void render_endjob(void *rjv) { RenderJob *rj = rjv; /* this render may be used again by the sequencer without the active 'Render' where the callbacks * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */ RE_InitRenderCB(rj->re); if (rj->main != G.main) free_main(rj->main); /* else the frame will not update for the original value */ if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { /* possible this fails of loading new file while rendering */ if (G.main->wm.first) { ED_update_for_newframe(G.main, rj->scene, 1); } } /* XXX above function sets all tags in nodes */ ntreeCompositClearTags(rj->scene->nodetree); /* potentially set by caller */ rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE; if (rj->srl) { nodeUpdateID(rj->scene->nodetree, &rj->scene->id); WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); } /* XXX render stability hack */ G.is_rendering = FALSE; WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL); /* Partial render result will always update display buffer * for first render layer only. This is nice because you'll * see render progress during rendering, but it ends up in * wrong display buffer shown after rendering. * * The code below will mark display buffer as invalid after * rendering in case multiple layers were rendered, which * ensures display buffer matches render layer after * rendering. * * Perhaps proper way would be to toggle active render * layer in image editor and job, so we always display * layer being currently rendered. But this is not so much * trivial at this moment, especially because of external * engine API, so lets use simple and robust way for now * - sergey - */ if (rj->scene->r.layers.first != rj->scene->r.layers.last || rj->image_outdated) { void *lock; Image *ima = rj->image; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); if (ibuf) ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; BKE_image_release_ibuf(ima, ibuf, lock); } }
static void icon_preview_startjob(void *customdata, short *stop, short *do_update) { ShaderPreview *sp = customdata; if (sp->pr_method == PR_ICON_DEFERRED) { PreviewImage *prv = sp->owner; ImBuf *thumb; char *deferred_data = PRV_DEFERRED_DATA(prv); int source = deferred_data[0]; char *path = &deferred_data[1]; // printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path); thumb = IMB_thumb_manage(path, THB_LARGE, source); if (thumb) { /* PreviewImage assumes premultiplied alhpa... */ IMB_premultiply_alpha(thumb); icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect); IMB_freeImBuf(thumb); } } else { ID *id = sp->id; short idtype = GS(id->name); if (idtype == ID_IM) { Image *ima = (Image *)id; ImBuf *ibuf = NULL; ImageUser iuser = {NULL}; /* ima->ok is zero when Image cannot load */ if (ima == NULL || ima->ok == 0) return; /* setup dummy image user */ iuser.ok = iuser.framenr = 1; iuser.scene = sp->scene; /* elubie: this needs to be changed: here image is always loaded if not * already there. Very expensive for large images. Need to find a way to * only get existing ibuf */ ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (ibuf == NULL || ibuf->rect == NULL) { BKE_image_release_ibuf(ima, ibuf, NULL); return; } icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = true; BKE_image_release_ibuf(ima, ibuf, NULL); } else if (idtype == ID_BR) { Brush *br = (Brush *)id; br->icon_imbuf = get_brush_icon(br); memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int)); if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) return; icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = true; } else { /* re-use shader job */ shader_preview_startjob(customdata, stop, do_update); /* world is rendered with alpha=0, so it wasn't displayed * this could be render option for sky to, for later */ if (idtype == ID_WO) { set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); } else if (idtype == ID_MA) { Material *ma = (Material *)id; if (ma->material_type == MA_TYPE_HALO) set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); } } } }
bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) { ImBuf *ibuf; if (!img || img->ok==0) { mOk = false; return mOk; } ibuf= BKE_image_acquire_ibuf(img, NULL, NULL); if (ibuf==NULL) { img->ok = 0; mOk = false; return mOk; } mipmap = mipmap && GPU_get_mipmap(); mTexture = img->bindcode[TEXTARGET_TEXTURE_2D]; mType = GL_TEXTURE_2D; mUnit = unit; ActivateUnit(mUnit); if (mTexture != 0) { glBindTexture(GL_TEXTURE_2D, mTexture ); Validate(); BKE_image_release_ibuf(img, ibuf, NULL); return mOk; } // look for an existing gl image BL_TextureMap::iterator mapLook = g_textureManager.find(img->id.name); if (mapLook != g_textureManager.end()) { if (mapLook->second.gl_texture != 0) { mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_2D, mTexture); mOk = IsValid(); BKE_image_release_ibuf(img, ibuf, NULL); return mOk; } } mNeedsDeleted = 1; glGenTextures(1, (GLuint*)&mTexture); #ifdef WITH_DDS if (ibuf->ftype == IMB_FTYPE_DDS) InitGLCompressedTex(ibuf, mipmap); else InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); #else InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); #endif // track created units BL_TextureObject obj; obj.gl_texture = mTexture; obj.ref_buffer = img; g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)img->id.name, obj)); glDisable(GL_TEXTURE_2D); ActivateUnit(0); Validate(); BKE_image_release_ibuf(img, ibuf, NULL); return mOk; }
void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { /// Image output OutputSocket *outputImage = this->getOutputSocket(0); bNode *editorNode = this->getbNode(); Image *image = (Image *)editorNode->id; ImageUser *imageuser = (ImageUser *)editorNode->storage; int framenumber = context->getFramenumber(); int numberOfOutputs = this->getNumberOfOutputSockets(); bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0; BKE_image_user_frame_calc(imageuser, context->getFramenumber(), 0); /* force a load, we assume iuser index will be set OK anyway */ if (image && image->type == IMA_TYPE_MULTILAYER) { bool is_multilayer_ok = false; ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL); if (image->rr) { RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer); if (rl) { OutputSocket *socket; int index; is_multilayer_ok = true; for (index = 0; index < numberOfOutputs; index++) { NodeOperation *operation = NULL; socket = this->getOutputSocket(index); if (socket->isConnected() || index == 0) { bNodeSocket *bnodeSocket = socket->getbNodeSocket(); /* Passes in the file can differ from passes stored in sockets (#36755). * Look up the correct file pass using the socket identifier instead. */ #if 0 NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;*/ int passindex = storage->pass_index;*/ RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex); #endif int passindex; RenderPass *rpass; for (rpass = (RenderPass *)rl->passes.first, passindex = 0; rpass; rpass = rpass->next, ++passindex) if (STREQ(rpass->name, bnodeSocket->identifier)) break; if (rpass) { imageuser->pass = passindex; switch (rpass->channels) { case 1: operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE); break; /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */ /* XXX any way to detect actual vector images? */ case 3: operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR); break; case 4: operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR); break; default: /* dummy operation is added below */ break; } if (index == 0 && operation) { addPreviewOperation(graph, context, operation->getOutputSocket()); } } } /* incase we can't load the layer */ if (operation == NULL) { convertToOperations_invalid_index(graph, index); } } }
void ImagesExporter::export_UV_Image(Image *image, bool use_copies) { std::string name(id_name(image)); std::string translated_name(translate_id(name)); bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end(); if (not_yet_exported) { ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (!imbuf) { fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name); return; } bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0; ImageFormatData imageFormat; BKE_imbuf_to_image_format(&imageFormat, imbuf); short image_source = image->source; bool is_generated = image_source == IMA_SRC_GENERATED; bool is_packed = image->packedfile != NULL; char export_path[FILE_MAX]; char source_path[FILE_MAX]; char export_dir[FILE_MAX]; char export_file[FILE_MAX]; // Destination folder for exported assets BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir)); if (is_generated || is_dirty || use_copies || is_packed) { // make absolute destination path BLI_strncpy(export_file, name.c_str(), sizeof(export_file)); BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat); BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file); // make dest directory if it doesn't exist BLI_make_existing_file(export_path); } if (is_generated || is_dirty || is_packed) { // This image in its current state only exists in Blender memory. // So we have to export it. The export will keep the image state intact, // so the exported file will not be associated with the image. if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) { fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path); return; } BLI_strncpy(export_path, export_file, sizeof(export_path)); } else { // make absolute source path BLI_strncpy(source_path, image->name, sizeof(source_path)); BLI_path_abs(source_path, G.main->name); BLI_cleanup_path(NULL, source_path); if (use_copies) { // This image is already located on the file system. // But we want to create copies here. // To move images into the same export directory. // Note: If an image is already located in the export folder, // then skip the copy (as it would result in a file copy error). if (BLI_path_cmp(source_path, export_path) != 0) { if (BLI_copy(source_path, export_path) != 0) { fprintf(stderr, "Collada export: Cannot copy image:\n source:%s\ndest :%s\n", source_path, export_path); return; } } BLI_strncpy(export_path, export_file, sizeof(export_path)); } else { // Do not make any copies, but use the source path directly as reference // to the original image BLI_strncpy(export_path, source_path, sizeof(export_path)); } } COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */ img.add(mSW); fprintf(stdout, "Collada export: Added image: %s\n", export_file); mImages.push_back(translated_name); BKE_image_release_ibuf(image, imbuf, NULL); } }
void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact) { PropertyRNA *prop; PointerRNA imaptr; RNAUpdateCb *cb; Image *ima; ImageUser *iuser; ImBuf *ibuf; Scene *scene= CTX_data_scene(C); uiLayout *row, *split, *col; uiBlock *block; uiBut *but; char str[128]; void *lock; if(!ptr->data) return; prop= RNA_struct_find_property(ptr, propname); if(!prop) { printf("%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname); return; } if(RNA_property_type(prop) != PROP_POINTER) { printf("%s: expected pointer property for %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname); return; } block= uiLayoutGetBlock(layout); imaptr= RNA_property_pointer_get(ptr, prop); ima= imaptr.data; iuser= userptr->data; cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); cb->ptr= *ptr; cb->prop= prop; cb->iuser= iuser; uiLayoutSetContextPointer(layout, "edit_image", &imaptr); if(!compact) uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL); if(ima) { uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL); if(ima->source == IMA_SRC_VIEWER) { ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); BKE_image_release_ibuf(ima, lock); uiItemL(layout, ima->id.name+2, ICON_NONE); uiItemL(layout, str, ICON_NONE); if(ima->type==IMA_TYPE_COMPOSITE) { // XXX not working yet #if 0 iuser= ntree_get_active_iuser(scene->nodetree); if(iuser) { uiBlockBeginAlign(block); uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, ""); uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110,120,100,20, 0, 0, 0, 0, 0, ""); but= uiDefBut(block, BUT, B_NOP, "Free Cache", 210,120,100,20, 0, 0, 0, 0, 0, ""); uiButSetFunc(but, image_freecache_cb, ima, NULL); if(iuser->frames) sprintf(str, "(%d) Frames:", iuser->framenr); else strcpy(str, "Frames:"); uiBlockBeginAlign(block); uiDefButI(block, NUM, imagechanged, str, 10, 90,150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use"); uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie"); } #endif } else if(ima->type==IMA_TYPE_R_RESULT) { /* browse layer/passes */ Render *re= RE_GetRender(scene->id.name); RenderResult *rr= RE_AcquireResultRead(re); uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot); RE_ReleaseResult(re); } } else { uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE); if(ima->source != IMA_SRC_GENERATED) { row= uiLayoutRow(layout, 1); if (ima->packedfile) uiItemO(row, "", ICON_PACKAGE, "image.unpack"); else uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); row= uiLayoutRow(row, 0); uiLayoutSetEnabled(row, ima->packedfile==NULL); uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); } // XXX what was this for? #if 0 /* check for re-render, only buttons */ if(imagechanged==B_IMAGECHANGED) { if(iuser->flag & IMA_ANIM_REFRESHED) { iuser->flag &= ~IMA_ANIM_REFRESHED; WM_event_add_notifier(C, NC_IMAGE, ima); } } #endif /* multilayer? */ if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) { uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL); } else if(ima->source != IMA_SRC_GENERATED) { if(compact == 0) { ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); BKE_image_release_ibuf(ima, lock); uiItemL(layout, str, ICON_NONE); } } if(ima->source != IMA_SRC_GENERATED) { if(compact == 0) { /* background image view doesnt need these */ uiItemS(layout); split= uiLayoutSplit(layout, 0, 0); col= uiLayoutColumn(split, 0); uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE); row= uiLayoutRow(col, 0); uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields")); uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE); uiItemR(split, &imaptr, "use_premultiply", 0, NULL, ICON_NONE); } } if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { uiItemS(layout); split= uiLayoutSplit(layout, 0, 0); col= uiLayoutColumn(split, 0); sprintf(str, "(%d) Frames", iuser->framenr); uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE); if(ima->anim) { block= uiLayoutGetBlock(col); but= uiDefBut(block, BUT, 0, "Match Movie Length", 0, 0, UI_UNIT_X*2, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Set the number of frames to match the movie or sequence"); uiButSetFunc(but, set_frames_cb, ima, iuser); } uiItemR(col, userptr, "frame_start", 0, "Start", ICON_NONE); uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE); col= uiLayoutColumn(split, 0); row= uiLayoutRow(col, 0); uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields")); uiItemR(row, userptr, "fields_per_frame", 0, "Fields", ICON_NONE); uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE); uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE); } else if(ima->source==IMA_SRC_GENERATED) { split= uiLayoutSplit(layout, 0, 0); col= uiLayoutColumn(split, 1); uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE); uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); } } uiBlockSetNFunc(block, NULL, NULL, NULL); } MEM_freeN(cb); }
static void icon_preview_startjob(void *customdata, short *stop, short *do_update) { ShaderPreview *sp = customdata; ID *id = sp->id; short idtype = GS(id->name); if (idtype == ID_IM) { Image *ima = (Image *)id; ImBuf *ibuf = NULL; ImageUser iuser = {NULL}; /* ima->ok is zero when Image cannot load */ if (ima == NULL || ima->ok == 0) return; /* setup dummy image user */ iuser.ok = iuser.framenr = 1; iuser.scene = sp->scene; /* elubie: this needs to be changed: here image is always loaded if not * already there. Very expensive for large images. Need to find a way to * only get existing ibuf */ ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (ibuf == NULL || ibuf->rect == NULL) { BKE_image_release_ibuf(ima, ibuf, NULL); return; } icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = true; BKE_image_release_ibuf(ima, ibuf, NULL); } else if (idtype == ID_BR) { Brush *br = (Brush *)id; br->icon_imbuf = get_brush_icon(br); memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int)); if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) return; icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = true; } else { /* re-use shader job */ shader_preview_startjob(customdata, stop, do_update); /* world is rendered with alpha=0, so it wasn't displayed * this could be render option for sky to, for later */ if (idtype == ID_WO) { set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); } else if (idtype == ID_MA) { Material *ma = (Material *)id; if (ma->material_type == MA_TYPE_HALO) set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); } } }
void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { /// Image output OutputSocket *outputImage = this->getOutputSocket(0); bNode *editorNode = this->getbNode(); Image *image = (Image *)editorNode->id; ImageUser *imageuser = (ImageUser *)editorNode->storage; int framenumber = context->getFramenumber(); int numberOfOutputs = this->getNumberOfOutputSockets(); bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0; BKE_image_user_frame_calc(imageuser, context->getFramenumber(), 0); /* force a load, we assume iuser index will be set OK anyway */ if (image && image->type == IMA_TYPE_MULTILAYER) { bool is_multilayer_ok = false; ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL); if (image->rr) { RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer); if (rl) { OutputSocket *socket; int index; is_multilayer_ok = true; for (index = 0; index < numberOfOutputs; index++) { NodeOperation *operation = NULL; socket = this->getOutputSocket(index); if (socket->isConnected() || index == 0) { bNodeSocket *bnodeSocket = socket->getbNodeSocket(); NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage; int passindex = storage->pass_index; RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex); if (rpass) { imageuser->pass = passindex; switch (rpass->channels) { case 1: operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE); break; /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */ /* XXX any way to detect actual vector images? */ case 3: operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR); break; case 4: operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR); break; default: /* dummy operation is added below */ break; } if (index == 0 && operation) { addPreviewOperation(graph, context, operation->getOutputSocket()); } } } /* incase we can't load the layer */ if (operation == NULL) { convertToOperations_invalid_index(graph, index); } } } } BKE_image_release_ibuf(image, ibuf, NULL); /* without this, multilayer that fail to load will crash blender [#32490] */ if (is_multilayer_ok == false) { convertToOperations_invalid(graph, context); } } else { if (numberOfOutputs > 0) { ImageOperation *operation = new ImageOperation(); if (outputImage->isConnected()) { if (outputStraightAlpha) { NodeOperation *alphaConvertOperation = new ConvertPremulToStraightOperation(); addLink(graph, operation->getOutputSocket(0), alphaConvertOperation->getInputSocket(0)); outputImage->relinkConnections(alphaConvertOperation->getOutputSocket()); graph->addOperation(alphaConvertOperation); } else { outputImage->relinkConnections(operation->getOutputSocket()); } } operation->setImage(image); operation->setImageUser(imageuser); operation->setFramenumber(framenumber); graph->addOperation(operation); addPreviewOperation(graph, context, operation->getOutputSocket()); } if (numberOfOutputs > 1) { OutputSocket *alphaImage = this->getOutputSocket(1); if (alphaImage->isConnected()) { ImageAlphaOperation *alphaOperation = new ImageAlphaOperation(); alphaOperation->setImage(image); alphaOperation->setImageUser(imageuser); alphaOperation->setFramenumber(framenumber); alphaImage->relinkConnections(alphaOperation->getOutputSocket()); graph->addOperation(alphaOperation); } } if (numberOfOutputs > 2) { OutputSocket *depthImage = this->getOutputSocket(2); if (depthImage->isConnected()) { ImageDepthOperation *depthOperation = new ImageDepthOperation(); depthOperation->setImage(image); depthOperation->setImageUser(imageuser); depthOperation->setFramenumber(framenumber); depthImage->relinkConnections(depthOperation->getOutputSocket()); graph->addOperation(depthOperation); } } if (numberOfOutputs > 3) { /* happens when unlinking image datablock from multilayer node */ for (int i = 3; i < numberOfOutputs; i++) { OutputSocket *output = this->getOutputSocket(i); NodeOperation *operation = NULL; switch (output->getDataType()) { case COM_DT_VALUE: { SetValueOperation *valueoperation = new SetValueOperation(); valueoperation->setValue(0.0f); operation = valueoperation; break; } case COM_DT_VECTOR: { SetVectorOperation *vectoroperation = new SetVectorOperation(); vectoroperation->setX(0.0f); vectoroperation->setY(0.0f); vectoroperation->setW(0.0f); operation = vectoroperation; break; } case COM_DT_COLOR: { SetColorOperation *coloroperation = new SetColorOperation(); coloroperation->setChannel1(0.0f); coloroperation->setChannel2(0.0f); coloroperation->setChannel3(0.0f); coloroperation->setChannel4(0.0f); operation = coloroperation; break; } } if (operation) { output->relinkConnections(operation->getOutputSocket()); graph->addOperation(operation); } } } } }
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); OGLRender *oglrender = op->customdata; Scene *scene = oglrender->scene; ImBuf *ibuf, *ibuf_save = NULL; void *lock; char name[FILE_MAX]; int ok = 0; const short view_context = (oglrender->v3d != NULL); Object *camera = NULL; int is_movie; /* go to next frame */ if (CFRA < oglrender->nfra) CFRA++; while (CFRA < oglrender->nfra) { unsigned int lay = screen_opengl_layers(oglrender); if (lay & 0xFF000000) lay &= 0xFF000000; BKE_scene_update_for_newframe(bmain, scene, lay); CFRA++; } is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); if (!is_movie) { BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE); if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) { BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name); ok = true; goto finally; } } WM_cursor_time(oglrender->win, scene->r.cfra); BKE_scene_update_for_newframe(bmain, scene, screen_opengl_layers(oglrender)); if (view_context) { if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) { /* since BKE_scene_update_for_newframe() is used rather * then ED_update_for_newframe() the camera needs to be set */ if (BKE_scene_camera_switch_update(scene)) { oglrender->v3d->camera = scene->camera; } camera = oglrender->v3d->camera; } } else { BKE_scene_camera_switch_update(scene); camera = scene->camera; } /* render into offscreen buffer */ screen_opengl_render_apply(oglrender); /* save to disk */ ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { int needs_free = FALSE; ibuf_save = ibuf; if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) { ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings, &scene->display_settings, &scene->r.im_format); needs_free = TRUE; } /* color -> grayscale */ /* editing directly would alter the render view */ if (scene->r.im_format.planes == R_IMF_PLANES_BW) { ImBuf *ibuf_bw = IMB_dupImBuf(ibuf_save); IMB_color_to_bw(ibuf_bw); if (needs_free) IMB_freeImBuf(ibuf_save); ibuf_save = ibuf_bw; } else { /* this is lightweight & doesnt re-alloc the buffers, only do this * to save the correct bit depth since the image is always RGBA */ ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf_save->x, ibuf_save->y, scene->r.im_format.planes, 0); ibuf_cpy->rect = ibuf_save->rect; ibuf_cpy->rect_float = ibuf_save->rect_float; ibuf_cpy->zbuf_float = ibuf_save->zbuf_float; if (needs_free) { ibuf_cpy->mall = ibuf_save->mall; ibuf_save->mall = 0; IMB_freeImBuf(ibuf_save); } ibuf_save = ibuf_cpy; } if (is_movie) { ok = oglrender->mh->append_movie(&scene->r, PSFRA, CFRA, (int *)ibuf_save->rect, oglrender->sizex, oglrender->sizey, oglrender->reports); if (ok) { printf("Append frame %d", scene->r.cfra); BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra); } } else { ok = BKE_imbuf_write_stamp(scene, camera, ibuf_save, name, &scene->r.im_format); if (ok == 0) { printf("Write error: cannot save %s\n", name); BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name); } else { printf("Saved: %s", name); BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name); } } if (needs_free) IMB_freeImBuf(ibuf_save); } BKE_image_release_ibuf(oglrender->ima, ibuf, lock); /* movie stats prints have no line break */ printf("\n"); finally: /* Step the frame and bail early if needed */ /* go to next frame */ oglrender->nfra += scene->r.frame_step; /* stop at the end or on error */ if (CFRA >= PEFRA || !ok) { screen_opengl_render_end(C, op->customdata); return 0; } return 1; }
bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) { if (!GLEW_ARB_texture_cube_map) { spit("cubemaps not supported"); mOk = false; return mOk; } else if (!cubemap || cubemap->ima->ok==0) { mOk = false; return mOk; } ImBuf *ibuf= BKE_image_acquire_ibuf(cubemap->ima, NULL, NULL); if (ibuf==0) { cubemap->ima->ok = 0; mOk = false; return mOk; } mNeedsDeleted = 1; mType = GL_TEXTURE_CUBE_MAP_ARB; mTexture = 0; mUnit = unit; ActivateUnit(mUnit); BL_TextureMap::iterator mapLook = g_textureManager.find(cubemap->ima->id.name); if (mapLook != g_textureManager.end()) { if (mapLook->second.gl_texture != 0 && mapLook->second.ref_buffer == cubemap->ima) { mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); mOk = IsValid(); BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; } } glGenTextures(1, (GLuint*)&mTexture); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); // track created units BL_TextureObject obj; obj.gl_texture = mTexture; obj.ref_buffer = cubemap->ima; g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)cubemap->ima->id.name, obj)); bool needs_split = false; if (!cubemap->cube[0]) { needs_split = true; spit ("Re-Generating texture buffer"); } if (needs_split) my_envmap_split_ima(cubemap, ibuf); if (!is_power_of_2_i(cubemap->cube[0]->x) || !is_power_of_2_i(cubemap->cube[0]->y)) { spit("invalid envmap size please render with CubeRes @ power of two"); my_free_envmapdata(cubemap); mOk = false; BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; } #define SetCubeMapFace(face, num) \ glTexImage2D(face, 0,GL_RGBA, \ cubemap->cube[num]->x, \ cubemap->cube[num]->y, \ 0, GL_RGBA, GL_UNSIGNED_BYTE, \ cubemap->cube[num]->rect) SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 5); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 1); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 2); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 4); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); if (GLEW_VERSION_1_2) glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); if (needs_split) my_free_envmapdata(cubemap); glDisable(GL_TEXTURE_CUBE_MAP_ARB); ActivateUnit(0); mOk = IsValid(); BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; }
static int get_next_bake_face(BakeShade *bs) { ObjectRen *obr; VlakRen *vlr; MTFace *tface; static int v = 0, vdone = false; static ObjectInstanceRen *obi = NULL; if (bs == NULL) { vlr = NULL; v = vdone = false; obi = R.instancetable.first; return 0; } BLI_lock_thread(LOCK_CUSTOM1); for (; obi; obi = obi->next, v = 0) { obr = obi->obr; /* only allow non instances here */ if (obr->flag & R_INSTANCEABLE) continue; for (; v < obr->totvlak; v++) { vlr = RE_findOrAddVlak(obr, v); if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) { if (R.r.bake_flag & R_BAKE_VCOL) { /* Gather face data for vertex color bake */ Mesh *me; int *origindex, vcollayer; CustomDataLayer *cdl; if (obr->ob->type != OB_MESH) continue; me = obr->ob->data; origindex = RE_vlakren_get_origindex(obr, vlr, 0); if (origindex == NULL) continue; if (*origindex >= me->totpoly) { /* Small hack for Array modifier, which gives false * original indices - z0r */ continue; } #if 0 /* Only shade selected faces. */ if ((me->mface[*origindex].flag & ME_FACE_SEL) == 0) continue; #endif vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL); if (vcollayer == -1) continue; cdl = &me->ldata.layers[vcollayer]; bs->mpoly = me->mpoly + *origindex; bs->vcol = ((MLoopCol *)cdl->data) + bs->mpoly->loopstart; bs->mloop = me->mloop + bs->mpoly->loopstart; /* Tag mesh for reevaluation. */ me->id.flag |= LIB_DOIT; } else { Image *ima = NULL; ImBuf *ibuf = NULL; const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f}; const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f}; const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f}; const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f}; const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f}; const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f}; tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); if (!tface || !tface->tpage) continue; ima = tface->tpage; ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf == NULL) continue; if (ibuf->rect == NULL && ibuf->rect_float == NULL) { BKE_image_release_ibuf(ima, ibuf, NULL); continue; } if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4)) { BKE_image_release_ibuf(ima, ibuf, NULL); continue; } if (ima->flag & IMA_USED_FOR_RENDER) { ima->id.flag &= ~LIB_DOIT; BKE_image_release_ibuf(ima, ibuf, NULL); continue; } /* find the image for the first time? */ if (ima->id.flag & LIB_DOIT) { ima->id.flag &= ~LIB_DOIT; /* we either fill in float or char, this ensures things go fine */ if (ibuf->rect_float) imb_freerectImBuf(ibuf); /* clear image */ if (R.r.bake_flag & R_BAKE_CLEAR) { if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid); else if (ELEM(R.r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid); else IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); } /* might be read by UI to set active image for display */ R.bakebuf = ima; } /* Tag image for redraw. */ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; BKE_image_release_ibuf(ima, ibuf, NULL); } bs->obi = obi; bs->vlr = vlr; bs->vdone++; /* only for error message if nothing was rendered */ v++; BLI_unlock_thread(LOCK_CUSTOM1); return 1; } } } BLI_unlock_thread(LOCK_CUSTOM1); return 0; }
static bool write_internal_bake_pixels( Image *image, BakePixel pixel_array[], float *buffer, const int width, const int height, const int margin, const bool is_clear, const bool is_noncolor) { ImBuf *ibuf; void *lock; bool is_float; char *mask_buffer = NULL; const size_t num_pixels = (size_t)width * (size_t)height; ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); if (!ibuf) return false; if (margin > 0 || !is_clear) { mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer); } is_float = (ibuf->flags & IB_rectfloat); /* colormanagement conversions */ if (!is_noncolor) { const char *from_colorspace; const char *to_colorspace; from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); if (is_float) to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); else to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf); if (from_colorspace != to_colorspace) IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false); } /* populates the ImBuf */ if (is_clear) { if (is_float) { IMB_buffer_float_from_float( ibuf->rect_float, buffer, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } else { IMB_buffer_byte_from_float( (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } } else { if (is_float) { IMB_buffer_float_from_float_mask( ibuf->rect_float, buffer, ibuf->channels, ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer); } else { IMB_buffer_byte_from_float_mask( (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, false, ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer); } } /* margins */ if (margin > 0) RE_bake_margin(ibuf, mask_buffer, margin); ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY; if (ibuf->rect_float) ibuf->userflags |= IB_RECT_INVALID; /* force mipmap recalc */ if (ibuf->mipmap[0]) { ibuf->userflags |= IB_MIPMAP_INVALID; imb_freemipmapImBuf(ibuf); } BKE_image_release_ibuf(image, ibuf, NULL); if (mask_buffer) MEM_freeN(mask_buffer); return true; }