示例#1
0
/* call this with NULL to restore assigned ID pointers in preview scene */
static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
	Scene *sce;
	Base *base;
	Main *pr_main = sp->pr_main;
	
	sce = preview_get_scene(pr_main);
	if (sce) {
		
		/* this flag tells render to not execute depsgraph or ipos etc */
		sce->r.scemode |= R_PREVIEWBUTS;
		/* set world always back, is used now */
		sce->world = pr_main->world.first;
		/* now: exposure copy */
		if (scene->world) {
			sce->world->exp = scene->world->exp;
			sce->world->range = scene->world->range;
		}
		
		sce->r.color_mgt_flag = scene->r.color_mgt_flag;
		BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);

		BKE_color_managed_view_settings_free(&sce->view_settings);
		BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
		
		/* prevent overhead for small renders and icons (32) */
		if (id && sp->sizex < 40) {
			sce->r.tilex = sce->r.tiley = 64;
		}
		else {
			sce->r.tilex = sce->r.xsch / 4;
			sce->r.tiley = sce->r.ysch / 4;
		}
		
		if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
			sce->r.alphamode = R_ALPHAPREMUL;
		else
			sce->r.alphamode = R_ADDSKY;

		sce->r.cfra = scene->r.cfra;

		if (id_type == ID_TE && sp->pr_method == PR_ICON_RENDER) {
			/* force blender internal for texture icons render,
			 * seems commonly used render engines does not support
			 * such kind of rendering
			 */
			BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
		}
		else {
			BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
		}
		
		if (id_type == ID_MA) {
			Material *mat = NULL, *origmat = (Material *)id;
			
			if (origmat) {
				/* work on a copy */
				mat = localize_material(origmat);
				sp->matcopy = mat;
				BLI_addtail(&pr_main->mat, mat);
				
				if (!BKE_scene_use_new_shading_nodes(scene)) {
					init_render_material(mat, 0, NULL);     /* call that retrieves mode_l */
					end_render_material(mat);
					
					/* un-useful option */
					if (sp->pr_method == PR_ICON_RENDER)
						mat->shade_flag &= ~MA_OBCOLOR;

					/* turn on raytracing if needed */
					if (mat->mode_l & MA_RAYMIRROR)
						sce->r.mode |= R_RAYTRACE;
					if (mat->material_type == MA_TYPE_VOLUME)
						sce->r.mode |= R_RAYTRACE;
					if ((mat->mode_l & MA_RAYTRANSP) && (mat->mode_l & MA_TRANSP))
						sce->r.mode |= R_RAYTRACE;
					if (preview_mat_has_sss(mat, NULL))
						sce->r.mode |= R_SSS;
					
					/* turn off fake shadows if needed */
					/* this only works in a specific case where the preview.blend contains
					 * an object starting with 'c' which has a material linked to it (not the obdata)
					 * and that material has a fake shadow texture in the active texture slot */
					for (base = sce->base.first; base; base = base->next) {
						if (base->object->id.name[2] == 'c') {
							Material *shadmat = give_current_material(base->object, base->object->actcol);
							if (shadmat) {
								if (mat->mode & MA_SHADBUF) shadmat->septex = 0;
								else shadmat->septex |= 1;
							}
						}
					}
					
					/* turn off bounce lights for volume, 
					 * doesn't make much visual difference and slows it down too */
					if (mat->material_type == MA_TYPE_VOLUME) {
						for (base = sce->base.first; base; base = base->next) {
							if (base->object->type == OB_LAMP) {
								/* if doesn't match 'Lamp.002' --> main key light */
								if (strcmp(base->object->id.name + 2, "Lamp.002") != 0) {
									base->object->restrictflag |= OB_RESTRICT_RENDER;
								}
							}
						}
					}
				}
				else {
					/* use current scene world to light sphere */
					if (mat->pr_type == MA_SPHERE_A)
						sce->world = scene->world;
				}
				
				if (sp->pr_method == PR_ICON_RENDER) {
					if (mat->material_type == MA_TYPE_HALO) {
						sce->lay = 1 << MA_FLAT;
					}
					else {
						sce->lay = 1 << MA_SPHERE_A;

						/* same as above, use current scene world to light sphere */
						if (BKE_scene_use_new_shading_nodes(scene))
							sce->world = scene->world;
					}
				}
				else {
					sce->lay = 1 << mat->pr_type;
					if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
						/* two previews, they get copied by wmJob */
						BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, TRUE);
						BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, TRUE);
					}
				}
			}
			else {
				sce->r.mode &= ~(R_OSA | R_RAYTRACE | R_SSS);
				
			}
			
			for (base = sce->base.first; base; base = base->next) {
				if (base->object->id.name[2] == 'p') {
					/* copy over object color, in case material uses it */
					copy_v4_v4(base->object->col, sp->col);
					
					if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
						/* don't use assign_material, it changed mat->id.us, which shows in the UI */
						Material ***matar = give_matarar(base->object);
						int actcol = max_ii(base->object->actcol - 1, 0);

						if (matar && actcol < base->object->totcol)
							(*matar)[actcol] = mat;
					}
					else if (base->object->type == OB_LAMP) {
						base->object->restrictflag &= ~OB_RESTRICT_RENDER;
					}
				}
			}
		}
		else if (id_type == ID_TE) {
			Tex *tex = NULL, *origtex = (Tex *)id;
			
			if (origtex) {
				tex = localize_texture(origtex);
				sp->texcopy = tex;
				BLI_addtail(&pr_main->tex, tex);
			}
			sce->lay = 1 << MA_TEXTURE;
			
			for (base = sce->base.first; base; base = base->next) {
				if (base->object->id.name[2] == 't') {
					Material *mat = give_current_material(base->object, base->object->actcol);
					if (mat && mat->mtex[0]) {
						mat->mtex[0]->tex = tex;
						
						if (tex && sp->slot)
							mat->mtex[0]->which_output = sp->slot->which_output;

						mat->mtex[0]->mapto &= ~MAP_ALPHA;
						mat->alpha = 1.0f;

						/* show alpha in this case */
						if (tex == NULL || (tex->flag & TEX_PRV_ALPHA)) {
							if (!(tex && tex->type == TEX_IMAGE && (tex->imaflag & (TEX_USEALPHA | TEX_CALCALPHA)) == 0)) {
								mat->mtex[0]->mapto |= MAP_ALPHA;
								mat->alpha = 0.0f;
							}
						}
					}
				}
			}

			if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
				/* two previews, they get copied by wmJob */
				BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, TRUE);
				BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, TRUE);
			}
		}
		else if (id_type == ID_LA) {
			Lamp *la = NULL, *origla = (Lamp *)id;

			/* work on a copy */
			if (origla) {
				la = localize_lamp(origla);
				sp->lampcopy = la;
				BLI_addtail(&pr_main->lamp, la);
			}

			sce->lay = 1 << MA_LAMP;

			if (!BKE_scene_use_new_shading_nodes(scene)) {
				if (la && la->type == LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
					sce->lay = 1 << MA_ATMOS;
					sce->world = scene->world;
					sce->camera = (Object *)BLI_findstring(&pr_main->object, "CameraAtmo", offsetof(ID, name) + 2);
				}
				else {
					sce->world = NULL;
					sce->camera = (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name) + 2);
				}
			}
				
			for (base = sce->base.first; base; base = base->next) {
				if (base->object->id.name[2] == 'p') {
					if (base->object->type == OB_LAMP)
						base->object->data = la;
				}
			}

			if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
				/* two previews, they get copied by wmJob */
				BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, TRUE);
				BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, TRUE);
			}
		}
		else if (id_type == ID_WO) {
			World *wrld = NULL, *origwrld = (World *)id;

			if (origwrld) {
				wrld = localize_world(origwrld);
				sp->worldcopy = wrld;
				BLI_addtail(&pr_main->world, wrld);
			}

			sce->lay = 1 << MA_SKY;
			sce->world = wrld;

			if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
				/* two previews, they get copied by wmJob */
				BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, TRUE);
				BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, TRUE);
			}
		}
		
		return sce;
	}
	
	return NULL;
}
示例#2
0
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	/* new render clears all callbacks */
	Main *mainp;
	Scene *scene = CTX_data_scene(C);
	SceneRenderLayer *srl = NULL;
	Render *re;
	wmJob *wm_job;
	RenderJob *rj;
	Image *ima;
	int jobflag;
	const bool is_animation = RNA_boolean_get(op->ptr, "animation");
	const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
	const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
	View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL;
	struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
	const char *name;
	ScrArea *sa;
	
	/* only one render job at a time */
	if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
		return OPERATOR_CANCELLED;

	if (RE_force_single_renderlayer(scene))
		WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL);

	if (!RE_is_rendering_allowed(scene, camera_override, op->reports)) {
		return OPERATOR_CANCELLED;
	}

	if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
		return OPERATOR_CANCELLED;
	}
	
	/* stop all running jobs, except screen one. currently previews frustrate Render */
	WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));

	/* get main */
	if (G.debug_value == 101) {
		/* thread-safety experiment, copy main from the undo buffer */
		mainp = BKE_undo_get_main(&scene);
	}
	else
		mainp = CTX_data_main(C);

	/* cancel animation playback */
	if (ED_screen_animation_playing(CTX_wm_manager(C)))
		ED_screen_animation_play(C, 0, 0);
	
	/* handle UI stuff */
	WM_cursor_wait(1);

	/* flush sculpt and editmode changes */
	ED_editors_flush_edits(C, true);

	/* cleanup sequencer caches before starting user triggered render.
	 * otherwise, invalidated cache entries can make their way into
	 * the output rendering. We can't put that into RE_BlenderFrame,
	 * since sequence rendering can call that recursively... (peter) */
	BKE_sequencer_cache_cleanup();

	// store spare
	// get view3d layer, local layer, make this nice api call to render
	// store spare

	/* ensure at least 1 area shows result */
	sa = render_view_open(C, event->x, event->y);

	jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
	
	/* custom scene and single layer re-render */
	screen_render_scene_layer_set(op, mainp, &scene, &srl);

	if (RNA_struct_property_is_set(op->ptr, "layer"))
		jobflag |= WM_JOB_SUSPEND;

	/* job custom data */
	rj = MEM_callocN(sizeof(RenderJob), "render job");
	rj->main = mainp;
	rj->scene = scene;
	rj->current_scene = rj->scene;
	rj->srl = srl;
	rj->camera_override = camera_override;
	rj->lay_override = 0;
	rj->anim = is_animation;
	rj->write_still = is_write_still && !is_animation;
	rj->iuser.scene = scene;
	rj->iuser.ok = 1;
	rj->reports = op->reports;
	rj->orig_layer = 0;
	rj->last_layer = 0;
	rj->sa = sa;

	BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings);
	BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings);

	if (sa) {
		SpaceImage *sima = sa->spacedata.first;
		rj->orig_layer = sima->iuser.layer;
	}

	if (v3d) {
		if (scene->lay != v3d->lay) {
			rj->lay_override = v3d->lay;
			rj->v3d_override = true;
		}
		else if (camera_override && camera_override != scene->camera)
			rj->v3d_override = true;

		if (v3d->localvd)
			rj->lay_override |= v3d->localvd->lay;
	}

	/* Lock the user interface depending on render settings. */
	if (scene->r.use_lock_interface) {
		int renderlay = rj->lay_override ? rj->lay_override : scene->lay;

		WM_set_locked_interface(CTX_wm_manager(C), true);

		/* Set flag interface need to be unlocked.
		 *
		 * This is so because we don't have copy of render settings
		 * accessible from render job and copy is needed in case
		 * of non-locked rendering, so we wouldn't try to unlock
		 * anything if option was initially unset but then was
		 * enabled during rendering.
		 */
		rj->interface_locked = true;

		/* Clean memory used by viewport? */
		clean_viewport_memory(rj->main, scene, renderlay);
	}

	/* setup job */
	if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render";
	else name = "Render";

	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER);
	WM_jobs_customdata_set(wm_job, rj, render_freejob);
	WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
	WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob);

	/* get a render result image, and make sure it is empty */
	ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
	BKE_image_backup_render(rj->scene, ima);
	rj->image = ima;

	/* setup new render */
	re = RE_NewRender(scene->id.name);
	RE_test_break_cb(re, rj, render_breakjob);
	RE_draw_lock_cb(re, rj, render_drawlock);
	RE_display_update_cb(re, rj, image_rect_update);
	RE_current_scene_update_cb(re, rj, current_scene_update);
	RE_stats_draw_cb(re, rj, image_renderinfo_cb);
	RE_progress_cb(re, rj, render_progress_update);

	rj->re = re;
	G.is_break = false;

	/* store actual owner of job, so modal operator could check for it,
	 * the reason of this is that active scene could change when rendering
	 * several layers from compositor [#31800]
	 */
	op->customdata = scene;

	WM_jobs_start(CTX_wm_manager(C), wm_job);

	WM_cursor_wait(0);
	WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);

	/* we set G.is_rendering here already instead of only in the job, this ensure
	 * main loop or other scene updates are disabled in time, since they may
	 * have started before the job thread */
	G.is_rendering = true;

	/* add modal handler for ESC */
	WM_event_add_modal_handler(C, op);

	return OPERATOR_RUNNING_MODAL;
}
示例#3
0
Scene *BKE_scene_copy(Scene *sce, int type)
{
	Scene *scen;
	ToolSettings *ts;
	Base *base, *obase;
	
	if (type == SCE_COPY_EMPTY) {
		ListBase lb;
		/* XXX. main should become an arg */
		scen = BKE_scene_add(G.main, sce->id.name + 2);
		
		lb = scen->r.layers;
		scen->r = sce->r;
		scen->r.layers = lb;
		scen->unit = sce->unit;
		scen->physics_settings = sce->physics_settings;
		scen->gm = sce->gm;
		scen->audio = sce->audio;

		MEM_freeN(scen->toolsettings);
	}
	else {
		scen = BKE_libblock_copy(&sce->id);
		BLI_duplicatelist(&(scen->base), &(sce->base));
		
		clear_id_newpoins();
		
		id_us_plus((ID *)scen->world);
		id_us_plus((ID *)scen->set);
		id_us_plus((ID *)scen->gm.dome.warptext);

		scen->ed = NULL;
		scen->theDag = NULL;
		scen->obedit = NULL;
		scen->stats = NULL;
		scen->fps_info = NULL;

		BLI_duplicatelist(&(scen->markers), &(sce->markers));
		BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces));
		BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers));
		BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets));

		if (sce->nodetree) {
			/* ID's are managed on both copy and switch */
			scen->nodetree = ntreeCopyTree(sce->nodetree);
			ntreeSwitchID(scen->nodetree, &sce->id, &scen->id);
		}

		obase = sce->base.first;
		base = scen->base.first;
		while (base) {
			id_us_plus(&base->object->id);
			if (obase == sce->basact) scen->basact = base;
	
			obase = obase->next;
			base = base->next;
		}

		/* copy color management settings */
		BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings);
		BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings);
		BKE_color_managed_view_settings_copy(&scen->r.im_format.view_settings, &sce->r.im_format.view_settings);

		BLI_strncpy(scen->sequencer_colorspace_settings.name, sce->sequencer_colorspace_settings.name,
		            sizeof(scen->sequencer_colorspace_settings.name));

		/* remove animation used by sequencer */
		if (type != SCE_COPY_FULL)
			remove_sequencer_fcurves(scen);
	}

	/* tool settings */
	scen->toolsettings = MEM_dupallocN(sce->toolsettings);

	ts = scen->toolsettings;
	if (ts) {
		if (ts->vpaint) {
			ts->vpaint = MEM_dupallocN(ts->vpaint);
			ts->vpaint->paintcursor = NULL;
			ts->vpaint->vpaint_prev = NULL;
			ts->vpaint->wpaint_prev = NULL;
			BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint);
		}
		if (ts->wpaint) {
			ts->wpaint = MEM_dupallocN(ts->wpaint);
			ts->wpaint->paintcursor = NULL;
			ts->wpaint->vpaint_prev = NULL;
			ts->wpaint->wpaint_prev = NULL;
			BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint);
		}
		if (ts->sculpt) {
			ts->sculpt = MEM_dupallocN(ts->sculpt);
			BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint);
		}

		BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint);
		ts->imapaint.paintcursor = NULL;
		ts->particle.paintcursor = NULL;
	}
	
	/* make a private copy of the avicodecdata */
	if (sce->r.avicodecdata) {
		scen->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata);
		scen->r.avicodecdata->lpFormat = MEM_dupallocN(scen->r.avicodecdata->lpFormat);
		scen->r.avicodecdata->lpParms = MEM_dupallocN(scen->r.avicodecdata->lpParms);
	}
	
	/* make a private copy of the qtcodecdata */
	if (sce->r.qtcodecdata) {
		scen->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata);
		scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms);
	}
	
	if (sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */
		scen->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties);
	}

	/* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations
	 * are done outside of blenkernel with ED_objects_single_users! */

	/*  camera */
	if (type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) {
		ID_NEW(scen->camera);
	}
	
	/* before scene copy */
	sound_create_scene(scen);

	/* world */
	if (type == SCE_COPY_FULL) {
		BKE_copy_animdata_id_action((ID *)scen);
		if (scen->world) {
			id_us_plus((ID *)scen->world);
			scen->world = BKE_world_copy(scen->world);
			BKE_copy_animdata_id_action((ID *)scen->world);
		}

		if (sce->ed) {
			scen->ed = MEM_callocN(sizeof(Editing), "addseq");
			scen->ed->seqbasep = &scen->ed->seqbase;
			BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL);
		}
	}

	return scen;
}
示例#4
0
/* call this with NULL to restore assigned ID pointers in preview scene */
static Scene *preview_prepare_scene(
    Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
  Scene *sce;
  Main *pr_main = sp->pr_main;

  memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name));

  sce = preview_get_scene(pr_main);
  if (sce) {
    ViewLayer *view_layer = sce->view_layers.first;

    /* this flag tells render to not execute depsgraph or ipos etc */
    sce->r.scemode |= R_BUTS_PREVIEW;
    /* set world always back, is used now */
    sce->world = pr_main->worlds.first;
    /* now: exposure copy */
    if (scene->world) {
      sce->world->exp = scene->world->exp;
      sce->world->range = scene->world->range;
    }

    sce->r.color_mgt_flag = scene->r.color_mgt_flag;
    BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);

    BKE_color_managed_view_settings_free(&sce->view_settings);
    BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);

    /* prevent overhead for small renders and icons (32) */
    if (id && sp->sizex < 40) {
      sce->r.tilex = sce->r.tiley = 64;
    }
    else {
      sce->r.tilex = sce->r.xsch / 4;
      sce->r.tiley = sce->r.ysch / 4;
    }

    if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) {
      sce->r.alphamode = R_ALPHAPREMUL;
    }
    else {
      sce->r.alphamode = R_ADDSKY;
    }

    sce->r.cfra = scene->r.cfra;

    if (id_type == ID_TE) {
      /* Texture is not actually rendered with engine, just set dummy value. */
      BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
    }
    else {
      BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
    }

    if (id_type == ID_MA) {
      Material *mat = NULL, *origmat = (Material *)id;

      if (origmat) {
        /* work on a copy */
        BLI_assert(sp->id_copy != NULL);
        mat = sp->matcopy = (Material *)sp->id_copy;
        sp->id_copy = NULL;
        BLI_addtail(&pr_main->materials, mat);

        /* Use current scene world for lighting. */
        if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) {
          /* Use current scene world to light sphere. */
          sce->world = preview_get_localized_world(sp, scene->world);
        }
        else if (sce->world) {
          /* Use a default world color. Using the current
           * scene world can be slow if it has big textures. */
          sce->world->use_nodes = false;
          sce->world->horr = 0.05f;
          sce->world->horg = 0.05f;
          sce->world->horb = 0.05f;
        }

        if (sp->pr_method == PR_ICON_RENDER && sp->pr_main == G_pr_main_grease_pencil) {
          /* For grease pencil, always use sphere for icon renders. */
          set_preview_visibility(sce, view_layer, MA_SPHERE_A, sp->pr_method);
        }
        else {
          /* Use specified preview shape for both preview panel and icon previews. */
          set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
        }

        if (sp->pr_method != PR_ICON_RENDER) {
          if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
            /* two previews, they get copied by wmJob */
            BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
            /* WATCH: Accessing origmat is not safe! */
            BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
          }
        }
      }
      else {
        sce->display.render_aa = SCE_DISPLAY_AA_OFF;
      }

      for (Base *base = view_layer->object_bases.first; base; base = base->next) {
        if (base->object->id.name[2] == 'p') {
          /* copy over object color, in case material uses it */
          copy_v4_v4(base->object->color, sp->color);

          if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
            /* don't use assign_material, it changed mat->id.us, which shows in the UI */
            Material ***matar = give_matarar(base->object);
            int actcol = max_ii(base->object->actcol - 1, 0);

            if (matar && actcol < base->object->totcol) {
              (*matar)[actcol] = mat;
            }
          }
          else if (base->object->type == OB_LAMP) {
            base->flag |= BASE_VISIBLE;
          }
        }
      }
    }
    else if (id_type == ID_TE) {
      Tex *tex = NULL, *origtex = (Tex *)id;

      if (origtex) {
        BLI_assert(sp->id_copy != NULL);
        tex = sp->texcopy = (Tex *)sp->id_copy;
        sp->id_copy = NULL;
        BLI_addtail(&pr_main->textures, tex);
      }

      if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
        /* two previews, they get copied by wmJob */
        BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true);
        /* WATCH: Accessing origtex is not safe! */
        BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
      }
    }
    else if (id_type == ID_LA) {
      Light *la = NULL, *origla = (Light *)id;

      /* work on a copy */
      if (origla) {
        BLI_assert(sp->id_copy != NULL);
        la = sp->lampcopy = (Light *)sp->id_copy;
        sp->id_copy = NULL;
        BLI_addtail(&pr_main->lights, la);
      }

      set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);

      if (sce->world) {
        /* Only use lighting from the light. */
        sce->world->use_nodes = false;
        sce->world->horr = 0.0f;
        sce->world->horg = 0.0f;
        sce->world->horb = 0.0f;
      }

      for (Base *base = view_layer->object_bases.first; base; base = base->next) {
        if (base->object->id.name[2] == 'p') {
          if (base->object->type == OB_LAMP) {
            base->object->data = la;
          }
        }
      }

      if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
        /* two previews, they get copied by wmJob */
        BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true);
        /* WATCH: Accessing origla is not safe! */
        BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
      }
    }
    else if (id_type == ID_WO) {
      World *wrld = NULL, *origwrld = (World *)id;

      if (origwrld) {
        BLI_assert(sp->id_copy != NULL);
        wrld = sp->worldcopy = (World *)sp->id_copy;
        sp->id_copy = NULL;
        BLI_addtail(&pr_main->worlds, wrld);
      }

      set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
      sce->world = wrld;

      if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
        /* two previews, they get copied by wmJob */
        BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true);
        /* WATCH: Accessing origwrld is not safe! */
        BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
      }
    }

    return sce;
  }

  return NULL;
}