diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-07-11 12:43:56 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-07-17 17:46:09 +0300 |
commit | 644fadf2f0131f8ecd73da6c994ec8a8d4b0a7d1 (patch) | |
tree | 91860a43b1d538802608a2aa7316828606e7cd99 /source/blender/draw/engines/workbench | |
parent | 7b3a18f0aa3ed9612aca602878a8ebdf2f1250f9 (diff) |
Render: add "OpenGL" render engine.
This is intended for quick renders for previsualization, animation previews
or sequencer previews. It provides the same settings as found in the 3D view
Shading popover in solid display mode, but in the scene render properties.
The "Workbench" engine was removed, and this name no longer appears in the
user interface, it's purely an internal name. We might come up with a better
name for this OpenGL engine still, but it's good to be consistent with the
OpenGL Render operator name since this has a similar purpose.
Diffstat (limited to 'source/blender/draw/engines/workbench')
9 files changed, 258 insertions, 40 deletions
diff --git a/source/blender/draw/engines/workbench/solid_mode.c b/source/blender/draw/engines/workbench/solid_mode.c index b28263d48cf..5c64cebd981 100644 --- a/source/blender/draw/engines/workbench/solid_mode.c +++ b/source/blender/draw/engines/workbench/solid_mode.c @@ -30,6 +30,8 @@ #include "GPU_shader.h" +#include "RE_pipeline.h" + #include "workbench_private.h" /* Functions */ @@ -69,6 +71,7 @@ static void workbench_solid_draw_scene(void *vedata) { WORKBENCH_Data *data = vedata; workbench_deferred_draw_scene(data); + workbench_deferred_draw_finish(data); } static void workbench_solid_engine_free(void) @@ -82,6 +85,11 @@ static void workbench_solid_view_update(void *vedata) workbench_taa_view_updated(data); } +static void workbench_render_to_image(void *vedata, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect) +{ + workbench_render(vedata, engine, render_layer, rect); +} + static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data); DrawEngineType draw_engine_workbench_solid = { @@ -97,5 +105,5 @@ DrawEngineType draw_engine_workbench_solid = { &workbench_solid_draw_scene, &workbench_solid_view_update, NULL, - NULL, + &workbench_render_to_image, }; diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index ede1bd7fcb5..07df067f324 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -19,37 +19,37 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) wpd->user_preferences = &U; View3D *v3d = draw_ctx->v3d; - if (v3d) { + if (!v3d) { + wpd->shading = scene->display.shading; + } + else if (v3d->shading.type == OB_RENDER && + BKE_scene_uses_blender_opengl(scene)) + { + wpd->shading = scene->display.shading; + } + else { wpd->shading = v3d->shading; - if (wpd->shading.light == V3D_LIGHTING_MATCAP) { - wpd->studio_light = BKE_studiolight_find( - wpd->shading.matcap, STUDIOLIGHT_ORIENTATION_VIEWNORMAL); - } - else { - wpd->studio_light = BKE_studiolight_find( - wpd->shading.studio_light, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD); - } + } + + if (wpd->shading.light == V3D_LIGHTING_MATCAP) { + wpd->studio_light = BKE_studiolight_find( + wpd->shading.matcap, STUDIOLIGHT_ORIENTATION_VIEWNORMAL); } else { - memset(&wpd->shading, 0, sizeof(wpd->shading)); - wpd->shading.light = V3D_LIGHTING_STUDIO; - wpd->shading.shadow_intensity = 0.5; - copy_v3_fl(wpd->shading.single_color, 0.8f); - wpd->studio_light = BKE_studiolight_find_first(STUDIOLIGHT_INTERNAL); + wpd->studio_light = BKE_studiolight_find( + wpd->shading.studio_light, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD); } wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity; WORKBENCH_UBO_World *wd = &wpd->world_data; wd->matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0; - wd->background_alpha = 1.0f; + wd->background_alpha = (v3d || scene->r.alphamode == R_ADDSKY) ? 1.0f : 0.0f; - if ((v3d->flag3 & V3D_SHOW_WORLD) && - (scene->world != NULL)) - { + if (!v3d || ((v3d->flag3 & V3D_SHOW_WORLD) && (scene->world != NULL))) { copy_v3_v3(wd->background_color_low, &scene->world->horr); copy_v3_v3(wd->background_color_high, &scene->world->horr); } - else { + else if (v3d) { UI_GetThemeColor3fv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_LOW_GRAD : TH_HIGH_GRAD, wd->background_color_low); UI_GetThemeColor3fv(TH_HIGH_GRAD, wd->background_color_high); @@ -58,6 +58,10 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) srgb_to_linearrgb_v3_v3(wd->background_color_high, wd->background_color_high); srgb_to_linearrgb_v3_v3(wd->background_color_low, wd->background_color_low); } + else { + zero_v3(wd->background_color_low); + zero_v3(wd->background_color_high); + } studiolight_update_world(wpd->studio_light, wd); diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index d17c48b0360..0ad755049b1 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -842,6 +842,7 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) WORKBENCH_PrivateData *wpd = stl->g_data; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + /* TODO. */ if (TAA_ENABLED(wpd)) { workbench_taa_draw_scene_start(vedata); } @@ -885,7 +886,15 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) DRW_draw_pass(psl->volume_pass); } + /* TODO */ workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx); +} + +void workbench_deferred_draw_finish(WORKBENCH_Data *vedata) +{ + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; + workbench_private_data_free(wpd); workbench_volume_smoke_textures_free(wpd); } diff --git a/source/blender/draw/engines/workbench/workbench_effect_aa.c b/source/blender/draw/engines/workbench/workbench_effect_aa.c index f1d5d5d6078..66f1de7f9fc 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_aa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_aa.c @@ -45,6 +45,18 @@ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx) } } +static void workspace_aa_draw_transform(GPUTexture *tx) +{ + if (DRW_state_is_image_render()) { + /* Linear result for render. */ + DRW_transform_none(tx); + } + else { + /* Display space result for viewport. */ + DRW_transform_to_display(tx); + } +} + void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx) { WORKBENCH_StorageList *stl = vedata->stl; @@ -56,7 +68,7 @@ void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx) DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); if (FXAA_ENABLED(wpd)) { GPU_framebuffer_bind(fbl->effect_fb); - DRW_transform_to_display(tx); + workspace_aa_draw_transform(tx); GPU_framebuffer_bind(dfbl->color_only_fb); DRW_draw_pass(psl->effect_aa_pass); } @@ -69,11 +81,11 @@ void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx) */ if (effect_info->jitter_index == 1) { GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_transform_to_display(tx); + workspace_aa_draw_transform(tx); } else { GPU_framebuffer_bind(fbl->effect_fb); - DRW_transform_to_display(tx); + workspace_aa_draw_transform(tx); GPU_framebuffer_bind(dfbl->color_only_fb); DRW_draw_pass(psl->effect_aa_pass); } @@ -81,6 +93,6 @@ void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx) } else { GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_transform_to_display(tx); + workspace_aa_draw_transform(tx); } } diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c index fbeccc19660..403338d55c4 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_taa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c @@ -93,15 +93,19 @@ int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata) WORKBENCH_PrivateData *wpd = stl->g_data; int result = 1; if (TAA_ENABLED(wpd)) { - if (IN_RANGE_INCL( + if (DRW_state_is_image_render()) { + const Scene *scene = DRW_context_state_get()->scene; + result = (scene->r.mode & R_OSA) ? scene->r.osa : 1; + } + else if (IN_RANGE_INCL( wpd->user_preferences->gpu_viewport_quality, GPU_VIEWPORT_QUALITY_TAA8, GPU_VIEWPORT_QUALITY_TAA16)) { result = 8; } else if (IN_RANGE_INCL( - wpd->user_preferences->gpu_viewport_quality, - GPU_VIEWPORT_QUALITY_TAA16, GPU_VIEWPORT_QUALITY_TAA32)) + wpd->user_preferences->gpu_viewport_quality, + GPU_VIEWPORT_QUALITY_TAA16, GPU_VIEWPORT_QUALITY_TAA32)) { result = 16; } @@ -276,10 +280,12 @@ void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata) GPU_framebuffer_blit(dfbl->color_only_fb, 0, fbl->effect_taa_fb, 0, GPU_COLOR_BIT); - DRW_viewport_matrix_override_unset_all(); + if (!DRW_state_is_image_render()) { + DRW_viewport_matrix_override_unset_all(); + } copy_m4_m4(effect_info->last_mat, effect_info->curr_mat); - if (effect_info->jitter_index != 0) { + if (effect_info->jitter_index != 0 && !DRW_state_is_image_render()) { DRW_viewport_request_redraw(); } } diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 26ae1c289c8..642c5820895 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -29,16 +29,16 @@ #include "DRW_render.h" #include "workbench_engine.h" -/* Shaders */ - -#define WORKBENCH_ENGINE "BLENDER_WORKBENCH" +#include "workbench_private.h" +#define OPENGL_ENGINE "BLENDER_OPENGL" /* Note: currently unused, we may want to register so we can see this when debugging the view. */ -RenderEngineType DRW_engine_viewport_workbench_type = { +RenderEngineType DRW_engine_viewport_opengl_type = { NULL, NULL, - WORKBENCH_ENGINE, N_("Workbench"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, + OPENGL_ENGINE, N_("OpenGL"), RE_INTERNAL, + NULL, &DRW_render_to_image, NULL, NULL, NULL, NULL, + &workbench_render_update_passes, &draw_engine_workbench_solid, {NULL, NULL, NULL} }; diff --git a/source/blender/draw/engines/workbench/workbench_engine.h b/source/blender/draw/engines/workbench/workbench_engine.h index a7f168db093..24f68cacd21 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.h +++ b/source/blender/draw/engines/workbench/workbench_engine.h @@ -28,6 +28,6 @@ extern DrawEngineType draw_engine_workbench_solid; extern DrawEngineType draw_engine_workbench_transparent; -extern RenderEngineType DRW_engine_viewport_workbench_type; +extern RenderEngineType DRW_engine_viewport_opengl_type; #endif /* __WORKBENCH_ENGINE_H__ */ diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 13e9686aa85..99d1b7060fd 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -36,6 +36,7 @@ #include "DRW_render.h" +#include "workbench_engine.h" #define WORKBENCH_ENGINE "BLENDER_WORKBENCH" #define M_GOLDEN_RATION_CONJUGATE 0.618033988749895 @@ -51,7 +52,7 @@ #define CAVITY_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_CAVITY) #define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW) -#define IS_NAVIGATING(wpd) (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING) +#define IS_NAVIGATING(wpd) ((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING)) #define FXAA_ENABLED(wpd) ((!DRW_state_is_opengl_render()) && (IN_RANGE(wpd->user_preferences->gpu_viewport_quality, GPU_VIEWPORT_QUALITY_FXAA, GPU_VIEWPORT_QUALITY_TAA8) || ((wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8) && IS_NAVIGATING(wpd)))) #define TAA_ENABLED(wpd) (wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && !IS_NAVIGATING(wpd)) #define SPECULAR_HIGHLIGHT_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd))) @@ -61,6 +62,11 @@ #define NORMAL_ENCODING_ENABLED() (true) +struct RenderEngine; +struct RenderLayer; +struct rcti; + + typedef struct WORKBENCH_FramebufferList { /* Deferred render buffers */ struct GPUFrameBuffer *prepass_fb; @@ -231,6 +237,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata); void workbench_deferred_engine_free(void); void workbench_deferred_draw_background(WORKBENCH_Data *vedata); void workbench_deferred_draw_scene(WORKBENCH_Data *vedata); +void workbench_deferred_draw_finish(WORKBENCH_Data *vedata); void workbench_deferred_cache_init(WORKBENCH_Data *vedata); void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob); void workbench_deferred_cache_finish(WORKBENCH_Data *vedata); @@ -293,8 +300,8 @@ void workbench_volume_cache_init(WORKBENCH_Data *vedata); void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Object *ob, struct ModifierData *md); void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd); - -extern DrawEngineType draw_engine_workbench_solid; -extern DrawEngineType draw_engine_workbench_transparent; +/* workbench_render.c */ +void workbench_render(WORKBENCH_Data *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const struct rcti *rect); +void workbench_render_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer); #endif diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c new file mode 100644 index 00000000000..1b25d4c875c --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_render.c @@ -0,0 +1,172 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file workbench_render.c + * \ingroup draw_engine + * + * Render functions for final render output. + */ + +#include "BLI_rect.h" + +#include "BKE_report.h" + +#include "DRW_render.h" + +#include "GPU_shader.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "RE_pipeline.h" + +#include "workbench_private.h" + +static void workbench_render_cache( + void *vedata, struct Object *ob, + struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph)) +{ + workbench_deferred_solid_cache_populate(vedata, ob); +} + +static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *depsgraph) +{ + /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); + float frame = BKE_scene_frame_get(scene); + + /* Set the persective, view and window matrix. */ + float winmat[4][4], wininv[4][4]; + float viewmat[4][4], viewinv[4][4]; + float persmat[4][4], persinv[4][4]; + + RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat); + RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv); + + invert_m4_m4(viewmat, viewinv); + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(persinv, persmat); + invert_m4_m4(wininv, winmat); + + DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV); + DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV); +} + +static bool workbench_render_framebuffers_init(void) +{ + /* For image render, allocate own buffers because we don't have a viewport. */ + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + dtxl->color = GPU_texture_create_2D(size[0], size[1], GPU_RGBA8, NULL, NULL); + dtxl->depth = GPU_texture_create_2D(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL); + + if (!(dtxl->depth && dtxl->color)) { + return false; + } + + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + GPU_framebuffer_ensure_config(&dfbl->default_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(dtxl->color) + }); + + GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_NONE + }); + + GPU_framebuffer_ensure_config(&dfbl->color_only_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(dtxl->color) + }); + + bool ok = true; + ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL); + + return ok; +} + +static void workbench_render_framebuffers_finish(void) +{ +} + +void workbench_render(WORKBENCH_Data *data, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + + Depsgraph *depsgraph = draw_ctx->depsgraph; + workbench_render_matrices_init(engine, depsgraph); + + if (!workbench_render_framebuffers_init()) { + RE_engine_report(engine, RPT_ERROR, "Failed to allocate OpenGL buffers"); + return; + } + + /* Init engine. */ + workbench_deferred_engine_init(data); + + /* Init objects. */ + workbench_deferred_cache_init(data); + DRW_render_object_iter(data, engine, depsgraph, workbench_render_cache); + workbench_deferred_cache_finish(data); + DRW_render_instance_buffer_finish(); + + /* Draw. */ + int num_samples = workbench_taa_calculate_num_iterations(data); + for (int sample = 0; sample < num_samples; sample++) { + if (RE_engine_test_break(engine)) { + break; + } + + workbench_deferred_draw_background(data); + workbench_deferred_draw_scene(data); + } + + workbench_deferred_draw_finish(data); + + /* Write render output. */ + const char *viewname = RE_GetActiveRenderView(engine->re); + RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname); + + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + GPU_framebuffer_bind(dfbl->color_only_fb); + GPU_framebuffer_read_color(dfbl->color_only_fb, + rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + 4, 0, rp->rect); + + workbench_render_framebuffers_finish(); +} + +void workbench_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer) +{ + RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); +} |