Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/render/render_preview.c
| Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
| #include "BLO_readfile.h" | #include "BLO_readfile.h" | ||||
| #include "DNA_brush_types.h" | #include "DNA_brush_types.h" | ||||
| #include "DNA_camera_types.h" | #include "DNA_camera_types.h" | ||||
| #include "DNA_collection_types.h" | #include "DNA_collection_types.h" | ||||
| #include "DNA_light_types.h" | #include "DNA_light_types.h" | ||||
| #include "DNA_material_types.h" | #include "DNA_material_types.h" | ||||
| #include "DNA_mesh_types.h" | |||||
| #include "DNA_node_types.h" | #include "DNA_node_types.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_screen_types.h" | #include "DNA_screen_types.h" | ||||
| #include "DNA_space_types.h" | #include "DNA_space_types.h" | ||||
| #include "DNA_world_types.h" | #include "DNA_world_types.h" | ||||
| #include "BKE_animsys.h" | #include "BKE_animsys.h" | ||||
| ▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | switch (pr_type) { | ||||
| case MA_ATMOS: | case MA_ATMOS: | ||||
| return "Atmosphere"; | return "Atmosphere"; | ||||
| default: | default: | ||||
| BLI_assert_msg(0, "Unknown preview type"); | BLI_assert_msg(0, "Unknown preview type"); | ||||
| return ""; | return ""; | ||||
| } | } | ||||
| } | } | ||||
| static bool render_engine_supports_ray_visibility(const Scene *sce) | |||||
| { | |||||
| return !STREQ(sce->r.engine, RE_engine_id_BLENDER_EEVEE); | |||||
| } | |||||
| static void switch_preview_collection_visibilty(ViewLayer *view_layer, const ePreviewType pr_type) | static void switch_preview_collection_visibilty(ViewLayer *view_layer, const ePreviewType pr_type) | ||||
| { | { | ||||
| /* Set appropriate layer as visible. */ | /* Set appropriate layer as visible. */ | ||||
| LayerCollection *lc = view_layer->layer_collections.first; | LayerCollection *lc = view_layer->layer_collections.first; | ||||
| const char *collection_name = preview_collection_name(pr_type); | const char *collection_name = preview_collection_name(pr_type); | ||||
| for (lc = lc->layer_collections.first; lc; lc = lc->next) { | for (lc = lc->layer_collections.first; lc; lc = lc->next) { | ||||
| if (STREQ(lc->collection->id.name + 2, collection_name)) { | if (STREQ(lc->collection->id.name + 2, collection_name)) { | ||||
| lc->collection->flag &= ~COLLECTION_HIDE_RENDER; | lc->collection->flag &= ~COLLECTION_HIDE_RENDER; | ||||
| } | } | ||||
| else { | else { | ||||
| lc->collection->flag |= COLLECTION_HIDE_RENDER; | lc->collection->flag |= COLLECTION_HIDE_RENDER; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void switch_preview_floor_visibility(ViewLayer *view_layer, | static const char *preview_floor_material_name(const Scene *scene, | ||||
| const ePreviewRenderMethod pr_method) | |||||
| { | |||||
| if (pr_method == PR_ICON_RENDER && render_engine_supports_ray_visibility(scene)) { | |||||
| return "FloorHidden"; | |||||
| } | |||||
| return "Floor"; | |||||
| } | |||||
| static void switch_preview_floor_material(Main *pr_main, | |||||
| Mesh *me, | |||||
| const Scene *scene, | |||||
| const ePreviewRenderMethod pr_method) | |||||
| { | |||||
| if (me->totcol == 0) { | |||||
| return; | |||||
| } | |||||
| const char *material_name = preview_floor_material_name(scene, pr_method); | |||||
| Material *mat = BLI_findstring(&pr_main->materials, material_name, offsetof(ID, name) + 2); | |||||
| if (mat) { | |||||
| me->mat[0] = mat; | |||||
| } | |||||
| } | |||||
| static void switch_preview_floor_visibility(Main *pr_main, | |||||
| const Scene *scene, | |||||
| ViewLayer *view_layer, | |||||
jbakker: `preview_floor_material_name` would be consistent with `preview_world_name` | |||||
| const ePreviewRenderMethod pr_method) | const ePreviewRenderMethod pr_method) | ||||
| { | { | ||||
| /* Hide floor for icon renders. */ | /* Hide floor for icon renders. */ | ||||
| LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | ||||
| if (STREQ(base->object->id.name + 2, "Floor")) { | if (STREQ(base->object->id.name + 2, "Floor")) { | ||||
| base->object->visibility_flag &= ~OB_HIDE_RENDER; | |||||
| if (pr_method == PR_ICON_RENDER) { | if (pr_method == PR_ICON_RENDER) { | ||||
| if (!render_engine_supports_ray_visibility(scene)) { | |||||
| base->object->visibility_flag |= OB_HIDE_RENDER; | base->object->visibility_flag |= OB_HIDE_RENDER; | ||||
| } | } | ||||
| else { | } | ||||
| base->object->visibility_flag &= ~OB_HIDE_RENDER; | if (base->object->type == OB_MESH) { | ||||
| switch_preview_floor_material(pr_main, base->object->data, scene, pr_method); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void set_preview_visibility(Scene *scene, | static void set_preview_visibility(Main *pr_main, | ||||
| Scene *scene, | |||||
| ViewLayer *view_layer, | ViewLayer *view_layer, | ||||
| const ePreviewType pr_type, | const ePreviewType pr_type, | ||||
| const ePreviewRenderMethod pr_method) | const ePreviewRenderMethod pr_method) | ||||
| { | { | ||||
| switch_preview_collection_visibilty(view_layer, pr_type); | switch_preview_collection_visibilty(view_layer, pr_type); | ||||
| switch_preview_floor_visibility(view_layer, pr_method); | switch_preview_floor_visibility(pr_main, scene, view_layer, pr_method); | ||||
| BKE_layer_collection_sync(scene, view_layer); | BKE_layer_collection_sync(scene, view_layer); | ||||
| } | } | ||||
| static World *preview_get_localized_world(ShaderPreview *sp, World *world) | static World *preview_get_localized_world(ShaderPreview *sp, World *world) | ||||
| { | { | ||||
| if (world == NULL) { | if (world == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| Show All 37 Lines | switch (GS(id->name)) { | ||||
| default: | default: | ||||
| if (!allow_failure) { | if (!allow_failure) { | ||||
| BLI_assert_msg(0, "ID type preview not supported."); | BLI_assert_msg(0, "ID type preview not supported."); | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| static World *preview_get_world(Main *pr_main) | static const char *preview_world_name(const Scene *sce, | ||||
| const ID_Type id_type, | |||||
| const ePreviewRenderMethod pr_method) | |||||
| { | |||||
| /* When rendering material icons the floor will not be shown in the output. Cycles will use a | |||||
| * material trick to show the floor in the reflections, but hide the floor for camera rays. For | |||||
| * Eevee we use a transparent world that has a projected grid. | |||||
Done Inline ActionsThis patch is meant to improve things, but the comment says the opposite (it says that not rendering the floor leads to less readability). This wording would solve that: "... not be rendered, as this would lead to less readability ..." sybren: This patch is meant to improve things, but the comment says the opposite (it says that not… | |||||
| * | |||||
| * In the future when Eevee supports vulkan raytracing we can re-evaluate and perhaps remove this | |||||
| * approximation. | |||||
| */ | |||||
| if (id_type == ID_MA && pr_method == PR_ICON_RENDER && | |||||
| !render_engine_supports_ray_visibility(sce)) { | |||||
| return "WorldFloor"; | |||||
| } | |||||
| return "World"; | |||||
| } | |||||
| static World *preview_get_world(Main *pr_main, | |||||
| const Scene *sce, | |||||
| const ID_Type id_type, | |||||
| const ePreviewRenderMethod pr_method) | |||||
| { | { | ||||
| World *result = NULL; | World *result = NULL; | ||||
| const char *world_name = "World"; | const char *world_name = preview_world_name(sce, id_type, pr_method); | ||||
| result = BLI_findstring(&pr_main->worlds, world_name, offsetof(ID, name) + 2); | result = BLI_findstring(&pr_main->worlds, world_name, offsetof(ID, name) + 2); | ||||
| /* No world found return first world. */ | /* No world found return first world. */ | ||||
| if (result == NULL) { | if (result == NULL) { | ||||
| result = pr_main->worlds.first; | result = pr_main->worlds.first; | ||||
| } | } | ||||
| BLI_assert_msg(result, "Preview file has no world."); | BLI_assert_msg(result, "Preview file has no world."); | ||||
| return result; | return result; | ||||
| } | } | ||||
| static void preview_sync_exposure(World *dst, const World *src) | static void preview_sync_exposure(World *dst, const World *src) | ||||
| { | { | ||||
| BLI_assert(dst); | BLI_assert(dst); | ||||
| BLI_assert(src); | BLI_assert(src); | ||||
| dst->exp = src->exp; | dst->exp = src->exp; | ||||
| dst->range = src->range; | dst->range = src->range; | ||||
| } | } | ||||
| static World *preview_prepare_world(Main *pr_main, const World *world) | static World *preview_prepare_world(Main *pr_main, | ||||
| const Scene *sce, | |||||
| const World *world, | |||||
| const ID_Type id_type, | |||||
| const ePreviewRenderMethod pr_method) | |||||
| { | { | ||||
| World *result = preview_get_world(pr_main); | World *result = preview_get_world(pr_main, sce, id_type, pr_method); | ||||
| if (world) { | if (world) { | ||||
| preview_sync_exposure(result, world); | preview_sync_exposure(result, world); | ||||
| } | } | ||||
| return result; | return result; | ||||
| } | } | ||||
| /* call this with a pointer to initialize preview scene */ | /* call this with a pointer to initialize preview scene */ | ||||
| /* call this with NULL to restore assigned ID pointers in preview scene */ | /* call this with NULL to restore assigned ID pointers in preview scene */ | ||||
| Show All 37 Lines | if (sce) { | ||||
| } | } | ||||
| else { | else { | ||||
| sce->r.alphamode = R_ADDSKY; | sce->r.alphamode = R_ADDSKY; | ||||
| } | } | ||||
| sce->r.cfra = scene->r.cfra; | sce->r.cfra = scene->r.cfra; | ||||
| /* Setup the world. */ | /* Setup the world. */ | ||||
| sce->world = preview_prepare_world(pr_main, scene->world); | sce->world = preview_prepare_world(pr_main, sce, scene->world, id_type, sp->pr_method); | ||||
| if (id_type == ID_TE) { | if (id_type == ID_TE) { | ||||
| /* Texture is not actually rendered with engine, just set dummy value. */ | /* 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)); | BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine)); | ||||
| } | } | ||||
| if (id_type == ID_MA) { | if (id_type == ID_MA) { | ||||
| Material *mat = NULL, *origmat = (Material *)id; | Material *mat = NULL, *origmat = (Material *)id; | ||||
| if (origmat) { | if (origmat) { | ||||
| /* work on a copy */ | /* work on a copy */ | ||||
| BLI_assert(sp->id_copy != NULL); | BLI_assert(sp->id_copy != NULL); | ||||
| mat = sp->matcopy = (Material *)sp->id_copy; | mat = sp->matcopy = (Material *)sp->id_copy; | ||||
| sp->id_copy = NULL; | sp->id_copy = NULL; | ||||
| BLI_addtail(&pr_main->materials, mat); | BLI_addtail(&pr_main->materials, mat); | ||||
| /* Use current scene world for lighting. */ | /* Use current scene world for lighting. */ | ||||
| if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) { | if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) { | ||||
| /* Use current scene world to light sphere. */ | /* Use current scene world to light sphere. */ | ||||
| sce->world = preview_get_localized_world(sp, scene->world); | sce->world = preview_get_localized_world(sp, scene->world); | ||||
| } | } | ||||
| else if (sce->world) { | else if (sce->world && sp->pr_method != PR_ICON_RENDER) { | ||||
| /* Use a default world color. Using the current | /* Use a default world color. Using the current | ||||
| * scene world can be slow if it has big textures. */ | * scene world can be slow if it has big textures. */ | ||||
| sce->world->use_nodes = false; | sce->world->use_nodes = false; | ||||
| sce->world->horr = 0.05f; | sce->world->horr = 0.05f; | ||||
| sce->world->horg = 0.05f; | sce->world->horg = 0.05f; | ||||
| sce->world->horb = 0.05f; | sce->world->horb = 0.05f; | ||||
| } | } | ||||
| /* For grease pencil, always use sphere for icon renders. */ | /* For grease pencil, always use sphere for icon renders. */ | ||||
| const ePreviewType preview_type = (sp->pr_method == PR_ICON_RENDER && | const ePreviewType preview_type = (sp->pr_method == PR_ICON_RENDER && | ||||
| sp->pr_main == G_pr_main_grease_pencil) ? | sp->pr_main == G_pr_main_grease_pencil) ? | ||||
| MA_SPHERE_A : | MA_SPHERE_A : | ||||
| mat->pr_type; | mat->pr_type; | ||||
| set_preview_visibility(sce, view_layer, preview_type, sp->pr_method); | set_preview_visibility(pr_main, sce, view_layer, preview_type, sp->pr_method); | ||||
| if (sp->pr_method != PR_ICON_RENDER) { | if (sp->pr_method != PR_ICON_RENDER) { | ||||
| if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) { | if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) { | ||||
| /* two previews, they get copied by wmJob */ | /* two previews, they get copied by wmJob */ | ||||
| BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true); | BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true); | ||||
| /* WATCH: Accessing origmat is not safe! */ | /* WATCH: Accessing origmat is not safe! */ | ||||
| BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true); | BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | else if (id_type == ID_LA) { | ||||
| /* work on a copy */ | /* work on a copy */ | ||||
| if (origla) { | if (origla) { | ||||
| BLI_assert(sp->id_copy != NULL); | BLI_assert(sp->id_copy != NULL); | ||||
| la = sp->lampcopy = (Light *)sp->id_copy; | la = sp->lampcopy = (Light *)sp->id_copy; | ||||
| sp->id_copy = NULL; | sp->id_copy = NULL; | ||||
| BLI_addtail(&pr_main->lights, la); | BLI_addtail(&pr_main->lights, la); | ||||
| } | } | ||||
| set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method); | set_preview_visibility(pr_main, sce, view_layer, MA_LAMP, sp->pr_method); | ||||
| if (sce->world) { | if (sce->world) { | ||||
| /* Only use lighting from the light. */ | /* Only use lighting from the light. */ | ||||
| sce->world->use_nodes = false; | sce->world->use_nodes = false; | ||||
| sce->world->horr = 0.0f; | sce->world->horr = 0.0f; | ||||
| sce->world->horg = 0.0f; | sce->world->horg = 0.0f; | ||||
| sce->world->horb = 0.0f; | sce->world->horb = 0.0f; | ||||
| } | } | ||||
| Show All 18 Lines | else if (id_type == ID_WO) { | ||||
| if (origwrld) { | if (origwrld) { | ||||
| BLI_assert(sp->id_copy != NULL); | BLI_assert(sp->id_copy != NULL); | ||||
| wrld = sp->worldcopy = (World *)sp->id_copy; | wrld = sp->worldcopy = (World *)sp->id_copy; | ||||
| sp->id_copy = NULL; | sp->id_copy = NULL; | ||||
| BLI_addtail(&pr_main->worlds, wrld); | BLI_addtail(&pr_main->worlds, wrld); | ||||
| } | } | ||||
| set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method); | set_preview_visibility(pr_main, sce, view_layer, MA_SKY, sp->pr_method); | ||||
| sce->world = wrld; | sce->world = wrld; | ||||
| if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) { | if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) { | ||||
| /* two previews, they get copied by wmJob */ | /* two previews, they get copied by wmJob */ | ||||
| BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true); | BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true); | ||||
| /* WATCH: Accessing origwrld is not safe! */ | /* WATCH: Accessing origwrld is not safe! */ | ||||
| BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true); | BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,303 Lines • Show Last 20 Lines | |||||
preview_floor_material_name would be consistent with preview_world_name