This was caused by a wrong flag equality check when in xray mode because the xray mode was masking the effect option flags that are not supported in this mode. This means the never passed and the TAA was reset before every redraw, leading to infinite rendering.
312 lines
10 KiB
C
312 lines
10 KiB
C
/*
|
|
* 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.
|
|
*
|
|
* Copyright 2018, Blender Foundation.
|
|
*/
|
|
|
|
/** \file
|
|
* \ingroup draw_engine
|
|
*/
|
|
#include "DRW_render.h"
|
|
|
|
#include "workbench_private.h"
|
|
|
|
#include "BLI_memblock.h"
|
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
#include "ED_screen.h"
|
|
#include "ED_view3d.h"
|
|
|
|
#include "UI_resources.h"
|
|
|
|
#include "GPU_uniform_buffer.h"
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name World Data
|
|
* \{ */
|
|
|
|
GPUUniformBuf *workbench_material_ubo_alloc(WORKBENCH_PrivateData *wpd)
|
|
{
|
|
struct GPUUniformBuf **ubo = BLI_memblock_alloc(wpd->material_ubo);
|
|
if (*ubo == NULL) {
|
|
*ubo = GPU_uniformbuf_create(sizeof(WORKBENCH_UBO_Material) * MAX_MATERIAL);
|
|
}
|
|
return *ubo;
|
|
}
|
|
|
|
static void workbench_ubo_free(void *elem)
|
|
{
|
|
GPUUniformBuf **ubo = elem;
|
|
DRW_UBO_FREE_SAFE(*ubo);
|
|
}
|
|
|
|
static void workbench_view_layer_data_free(void *storage)
|
|
{
|
|
WORKBENCH_ViewLayerData *vldata = (WORKBENCH_ViewLayerData *)storage;
|
|
|
|
DRW_UBO_FREE_SAFE(vldata->dof_sample_ubo);
|
|
DRW_UBO_FREE_SAFE(vldata->world_ubo);
|
|
DRW_UBO_FREE_SAFE(vldata->cavity_sample_ubo);
|
|
DRW_TEXTURE_FREE_SAFE(vldata->cavity_jitter_tx);
|
|
|
|
BLI_memblock_destroy(vldata->material_ubo_data, NULL);
|
|
BLI_memblock_destroy(vldata->material_ubo, workbench_ubo_free);
|
|
}
|
|
|
|
static WORKBENCH_ViewLayerData *workbench_view_layer_data_ensure_ex(struct ViewLayer *view_layer)
|
|
{
|
|
WORKBENCH_ViewLayerData **vldata = (WORKBENCH_ViewLayerData **)
|
|
DRW_view_layer_engine_data_ensure_ex(view_layer,
|
|
(DrawEngineType *)&workbench_view_layer_data_ensure_ex,
|
|
&workbench_view_layer_data_free);
|
|
|
|
if (*vldata == NULL) {
|
|
*vldata = MEM_callocN(sizeof(**vldata), "WORKBENCH_ViewLayerData");
|
|
size_t matbuf_size = sizeof(WORKBENCH_UBO_Material) * MAX_MATERIAL;
|
|
(*vldata)->material_ubo_data = BLI_memblock_create_ex(matbuf_size, matbuf_size * 2);
|
|
(*vldata)->material_ubo = BLI_memblock_create_ex(sizeof(void *), sizeof(void *) * 8);
|
|
(*vldata)->world_ubo = GPU_uniformbuf_create_ex(sizeof(WORKBENCH_UBO_World), NULL, "wb_World");
|
|
}
|
|
|
|
return *vldata;
|
|
}
|
|
|
|
/* \} */
|
|
|
|
static void workbench_studiolight_data_update(WORKBENCH_PrivateData *wpd, WORKBENCH_UBO_World *wd)
|
|
{
|
|
StudioLight *studiolight = wpd->studio_light;
|
|
float view_matrix[4][4], rot_matrix[4][4];
|
|
DRW_view_viewmat_get(NULL, view_matrix, false);
|
|
|
|
if (USE_WORLD_ORIENTATION(wpd)) {
|
|
axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z);
|
|
mul_m4_m4m4(rot_matrix, view_matrix, rot_matrix);
|
|
swap_v3_v3(rot_matrix[2], rot_matrix[1]);
|
|
negate_v3(rot_matrix[2]);
|
|
}
|
|
else {
|
|
unit_m4(rot_matrix);
|
|
}
|
|
|
|
if (U.edit_studio_light) {
|
|
studiolight = BKE_studiolight_studio_edit_get();
|
|
}
|
|
|
|
/* Studio Lights. */
|
|
for (int i = 0; i < 4; i++) {
|
|
WORKBENCH_UBO_Light *light = &wd->lights[i];
|
|
|
|
SolidLight *sl = (studiolight) ? &studiolight->light[i] : NULL;
|
|
if (sl && sl->flag) {
|
|
copy_v3_v3(light->light_direction, sl->vec);
|
|
mul_mat3_m4_v3(rot_matrix, light->light_direction);
|
|
/* We should predivide the power by PI but that makes the lights really dim. */
|
|
copy_v3_v3(light->specular_color, sl->spec);
|
|
copy_v3_v3(light->diffuse_color, sl->col);
|
|
light->wrapped = sl->smooth;
|
|
}
|
|
else {
|
|
copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f);
|
|
copy_v3_fl(light->specular_color, 0.0f);
|
|
copy_v3_fl(light->diffuse_color, 0.0f);
|
|
light->wrapped = 0.0f;
|
|
}
|
|
}
|
|
|
|
if (studiolight) {
|
|
copy_v3_v3(wd->ambient_color, studiolight->light_ambient);
|
|
}
|
|
else {
|
|
copy_v3_fl(wd->ambient_color, 1.0f);
|
|
}
|
|
|
|
wd->use_specular = workbench_is_specular_highlight_enabled(wpd);
|
|
}
|
|
|
|
void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
|
|
{
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
RegionView3D *rv3d = draw_ctx->rv3d;
|
|
View3D *v3d = draw_ctx->v3d;
|
|
Scene *scene = draw_ctx->scene;
|
|
WORKBENCH_ViewLayerData *vldata = workbench_view_layer_data_ensure_ex(draw_ctx->view_layer);
|
|
|
|
wpd->is_playback = DRW_state_is_playback();
|
|
wpd->is_navigating = DRW_state_is_navigating();
|
|
|
|
wpd->ctx_mode = CTX_data_mode_enum_ex(
|
|
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
|
|
|
|
wpd->preferences = &U;
|
|
wpd->scene = scene;
|
|
wpd->sh_cfg = draw_ctx->sh_cfg;
|
|
|
|
/* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
|
|
* But this is a workaround for a missing update tagging. */
|
|
DRWState clip_state = RV3D_CLIPPING_ENABLED(v3d, rv3d) ? DRW_STATE_CLIP_PLANES : 0;
|
|
if (clip_state != wpd->clip_state) {
|
|
wpd->view_updated = true;
|
|
}
|
|
wpd->clip_state = clip_state;
|
|
|
|
wpd->vldata = vldata;
|
|
wpd->world_ubo = vldata->world_ubo;
|
|
|
|
wpd->taa_sample_len = workbench_antialiasing_sample_count_get(wpd);
|
|
|
|
wpd->volumes_do = false;
|
|
BLI_listbase_clear(&wpd->smoke_domains);
|
|
|
|
/* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
|
|
* But this is a workaround for a missing update tagging. */
|
|
if ((rv3d != NULL) && (rv3d->rflag & RV3D_GPULIGHT_UPDATE)) {
|
|
wpd->view_updated = true;
|
|
rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
|
|
}
|
|
|
|
if (!v3d || (v3d->shading.type == OB_RENDER && BKE_scene_uses_blender_workbench(scene))) {
|
|
short shading_flag = scene->display.shading.flag;
|
|
if (XRAY_FLAG_ENABLED((&scene->display))) {
|
|
/* Disable shading options that aren't supported in transparency mode. */
|
|
shading_flag &= ~(V3D_SHADING_SHADOW | V3D_SHADING_CAVITY | V3D_SHADING_DEPTH_OF_FIELD);
|
|
}
|
|
|
|
/* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
|
|
* But this is a workaround for a missing update tagging from operators. */
|
|
if ((XRAY_ENABLED(wpd) != XRAY_ENABLED(&scene->display)) ||
|
|
(shading_flag != wpd->shading.flag)) {
|
|
wpd->view_updated = true;
|
|
}
|
|
|
|
wpd->shading = scene->display.shading;
|
|
wpd->shading.flag = shading_flag;
|
|
if (XRAY_FLAG_ENABLED((&scene->display))) {
|
|
wpd->shading.xray_alpha = XRAY_ALPHA((&scene->display));
|
|
}
|
|
else {
|
|
wpd->shading.xray_alpha = 1.0f;
|
|
}
|
|
|
|
if (scene->r.alphamode == R_ALPHAPREMUL) {
|
|
copy_v4_fl(wpd->background_color, 0.0f);
|
|
}
|
|
else if (scene->world) {
|
|
World *wo = scene->world;
|
|
copy_v4_fl4(wpd->background_color, wo->horr, wo->horg, wo->horb, 1.0f);
|
|
}
|
|
else {
|
|
copy_v4_fl4(wpd->background_color, 0.0f, 0.0f, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
else {
|
|
short shading_flag = v3d->shading.flag;
|
|
if (XRAY_ENABLED(v3d)) {
|
|
/* Disable shading options that aren't supported in transparency mode. */
|
|
shading_flag &= ~(V3D_SHADING_SHADOW | V3D_SHADING_CAVITY | V3D_SHADING_DEPTH_OF_FIELD);
|
|
}
|
|
|
|
/* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
|
|
* But this is a workaround for a missing update tagging from operators. */
|
|
if (XRAY_ENABLED(v3d) != XRAY_ENABLED(wpd) || shading_flag != wpd->shading.flag) {
|
|
wpd->view_updated = true;
|
|
}
|
|
|
|
wpd->shading = v3d->shading;
|
|
wpd->shading.flag = shading_flag;
|
|
if (wpd->shading.type < OB_SOLID) {
|
|
wpd->shading.light = V3D_LIGHTING_FLAT;
|
|
wpd->shading.color_type = V3D_SHADING_OBJECT_COLOR;
|
|
wpd->shading.xray_alpha = 0.0f;
|
|
}
|
|
else if (XRAY_ENABLED(v3d)) {
|
|
wpd->shading.xray_alpha = XRAY_ALPHA(v3d);
|
|
}
|
|
else {
|
|
wpd->shading.xray_alpha = 1.0f;
|
|
}
|
|
|
|
/* No background. The overlays will draw the correct one. */
|
|
copy_v4_fl(wpd->background_color, 0.0f);
|
|
}
|
|
|
|
wpd->cull_state = CULL_BACKFACE_ENABLED(wpd) ? DRW_STATE_CULL_BACK : 0;
|
|
|
|
if (wpd->shading.light == V3D_LIGHTING_MATCAP) {
|
|
wpd->studio_light = BKE_studiolight_find(wpd->shading.matcap, STUDIOLIGHT_TYPE_MATCAP);
|
|
}
|
|
else {
|
|
wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
|
|
}
|
|
|
|
/* If matcaps are missing, use this as fallback. */
|
|
if (UNLIKELY(wpd->studio_light == NULL)) {
|
|
wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
|
|
}
|
|
|
|
{
|
|
/* Material UBOs. */
|
|
wpd->material_ubo_data = vldata->material_ubo_data;
|
|
wpd->material_ubo = vldata->material_ubo;
|
|
wpd->material_chunk_count = 1;
|
|
wpd->material_chunk_curr = 0;
|
|
wpd->material_index = 1;
|
|
/* Create default material ubo. */
|
|
wpd->material_ubo_data_curr = BLI_memblock_alloc(wpd->material_ubo_data);
|
|
wpd->material_ubo_curr = workbench_material_ubo_alloc(wpd);
|
|
/* Init default material used by vertex color & texture. */
|
|
workbench_material_ubo_data(
|
|
wpd, NULL, NULL, &wpd->material_ubo_data_curr[0], V3D_SHADING_MATERIAL_COLOR);
|
|
}
|
|
}
|
|
|
|
void workbench_update_world_ubo(WORKBENCH_PrivateData *wpd)
|
|
{
|
|
WORKBENCH_UBO_World wd;
|
|
|
|
copy_v2_v2(wd.viewport_size, DRW_viewport_size_get());
|
|
copy_v2_v2(wd.viewport_size_inv, DRW_viewport_invert_size_get());
|
|
copy_v3_v3(wd.object_outline_color, wpd->shading.object_outline_color);
|
|
wd.object_outline_color[3] = 1.0f;
|
|
wd.ui_scale = G_draw.block.sizePixel;
|
|
wd.matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
|
|
|
|
workbench_studiolight_data_update(wpd, &wd);
|
|
workbench_shadow_data_update(wpd, &wd);
|
|
workbench_cavity_data_update(wpd, &wd);
|
|
|
|
GPU_uniformbuf_update(wpd->world_ubo, &wd);
|
|
}
|
|
|
|
void workbench_update_material_ubos(WORKBENCH_PrivateData *UNUSED(wpd))
|
|
{
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
WORKBENCH_ViewLayerData *vldata = workbench_view_layer_data_ensure_ex(draw_ctx->view_layer);
|
|
|
|
BLI_memblock_iter iter, iter_data;
|
|
BLI_memblock_iternew(vldata->material_ubo, &iter);
|
|
BLI_memblock_iternew(vldata->material_ubo_data, &iter_data);
|
|
WORKBENCH_UBO_Material *matchunk;
|
|
while ((matchunk = BLI_memblock_iterstep(&iter_data))) {
|
|
GPUUniformBuf **ubo = BLI_memblock_iterstep(&iter);
|
|
BLI_assert(*ubo != NULL);
|
|
GPU_uniformbuf_update(*ubo, matchunk);
|
|
}
|
|
|
|
BLI_memblock_clear(vldata->material_ubo, workbench_ubo_free);
|
|
BLI_memblock_clear(vldata->material_ubo_data, NULL);
|
|
}
|