static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) { LinkData *link; bool use_displacement_buffer = ELEM(bkr->mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE); for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL, IMA_IBUF_IMA); BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata; if (ibuf->x <= 0 || ibuf->y <= 0) continue; if (use_displacement_buffer) { if (bkr->mode == RE_BAKE_DERIVATIVE) { RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer, result->height_min, result->height_max, bkr->user_scale); } else { RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, result->height_min, result->height_max); } } RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter); ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; if (ibuf->rect_float) ibuf->userflags |= IB_RECT_INVALID; if (ibuf->mipmap[0]) { ibuf->userflags |= IB_MIPMAP_INVALID; imb_freemipmapImBuf(ibuf); } if (ibuf->userdata) { if (userdata->displacement_buffer) MEM_freeN(userdata->displacement_buffer); MEM_freeN(userdata->mask_buffer); MEM_freeN(userdata); ibuf->userdata = NULL; } BKE_image_release_ibuf(ima, ibuf, NULL); } }
/* 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; 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_IBUF_IMA); 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 */ tag_main_lb(&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.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, IMA_IBUF_IMA); 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; }