Workbench: Added a quality slider for the viewport

Currently only attached to the Anti Aliasing of the solid mode of the
viewport. But eventually we could add other options here. Quality
setting can be found in the System tab of the userpref.

The slider goes from No Antialiasing (0.0 - 0.1) to FXAA (0.1 - 0.25) to
TAA8 (0.25 - 0.6) to TAA16 (0.6 - 0.8) to TAA32 (0.8 - 1.0)
This commit is contained in:
Jeroen Bakker 2018-06-27 12:55:49 +02:00
parent cf2dcd57c0
commit 20b8e1d8f1
Notes: blender-bot 2023-02-14 08:29:54 +01:00
Referenced by issue #55644, Multires ignores render subdivision when simplified
Referenced by issue #55645, Particle system option 'Use Count' doesnt list objects in the used collection any more
10 changed files with 166 additions and 74 deletions

View File

@ -550,8 +550,7 @@ class USERPREF_PT_system(Panel):
col.prop(system, "use_region_overlap")
col.separator()
col.label(text="Max Viewport Anti-aliasing Method")
col.prop(system, "max_anti_alias_method", text="")
col.prop(system, "gpu_viewport_quality")
col.separator()

View File

@ -17,14 +17,14 @@ layout(std140) uniform samples_block {
vec4 ssao_samples[500];
};
#define ssao_samples_num ssao_params.x
#define jitter_tilling ssao_params.yz
#define dfdy_sign ssao_params.w
#define ssao_samples_num ssao_params.x
#define jitter_tilling ssao_params.yz
#define ssao_iteration ssao_params.w
#define ssao_distance ssao_settings.x
#define ssao_factor_cavity ssao_settings.y
#define ssao_factor_edge ssao_settings.z
#define ssao_attenuation ssao_settings.a
#define ssao_distance ssao_settings.x
#define ssao_factor_cavity ssao_settings.y
#define ssao_factor_edge ssao_settings.z
#define ssao_attenuation ssao_settings.a
vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth)
{

View File

@ -24,19 +24,24 @@ void ssao_factors(
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
int num_samples = int(ssao_samples_num);
/* Note. Putting noise usage here to put some ALU after texture fetch. */
vec2 rotX = noise.rg;
vec2 rotY = vec2(-rotX.y, rotX.x);
for (int x = 0; x < num_samples && x < 500; x++) {
for (int x = 0; x < num_samples; x++) {
int sample_index = x;
if (sample_index > 500) {
continue;
}
/* ssao_samples[x].xy is sample direction (normalized).
* ssao_samples[x].z is sample distance from disk center. */
/* Rotate with random direction to get jittered result. */
vec2 dir_jittered = vec2(dot(ssao_samples[x].xy, rotX), dot(ssao_samples[x].xy, rotY));
dir_jittered.xy *= ssao_samples[x].z + noise.b;
vec2 dir_jittered = vec2(dot(ssao_samples[sample_index].xy, rotX), dot(ssao_samples[sample_index].xy, rotY));
dir_jittered.xy *= ssao_samples[sample_index].z + noise.b;
vec2 uvcoords = screenco.xy + dir_jittered * offset;

View File

@ -71,7 +71,6 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
const int ssao_samples = scene->display.matcap_ssao_samples;
float invproj[4][4];
float dfdyfacs[2];
const bool is_persp = DRW_viewport_is_persp_get();
/* view vectors for the corners of the view frustum.
* Can be used to recreate the world space position easily */
@ -83,12 +82,10 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
int i;
const float *size = DRW_viewport_size_get();
DRW_state_dfdy_factors_get(dfdyfacs);
wpd->ssao_params[0] = ssao_samples;
wpd->ssao_params[1] = size[0] / 64.0;
wpd->ssao_params[2] = size[1] / 64.0;
wpd->ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
wpd->ssao_params[3] = 0;
/* distance, factor, factor, attenuation */
copy_v4_fl4(wpd->ssao_settings, scene->display.matcap_ssao_distance, wpd->shading.cavity_valley_factor, wpd->shading.cavity_ridge_factor, scene->display.matcap_ssao_attenuation);

View File

@ -268,7 +268,6 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
{
WORKBENCH_FramebufferList *fbl = vedata->fbl;
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_TextureList *txl = vedata->txl;
WORKBENCH_PassList *psl = vedata->psl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
@ -382,7 +381,8 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
/* AO Samples Tex */
const int ssao_samples = scene->display.matcap_ssao_samples;
const int ssao_samples_single_iteration = scene->display.matcap_ssao_samples;
const int ssao_samples = MIN2(ssao_samples_single_iteration, 500);
if (e_data.sampling_ubo && (e_data.cached_sample_num != ssao_samples)) {
DRW_UBO_FREE_SAFE(e_data.sampling_ubo);
DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx);
@ -404,6 +404,19 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
psl->prepass_hair_pass = DRW_pass_create("Prepass", state);
}
{
if (TAA_ENABLED(wpd)) {
psl->effect_aa_pass = workbench_taa_create_pass(vedata, &e_data.composite_buffer_tx);
}
else if (FXAA_ENABLED(wpd)) {
psl->effect_aa_pass = workbench_fxaa_create_pass(&e_data.effect_buffer_tx);
stl->effects->jitter_index = 0;
}
else {
psl->effect_aa_pass = NULL;
}
}
{
int state = DRW_STATE_WRITE_COLOR;
psl->cavity_pass = DRW_pass_create("Cavity", state);
@ -421,19 +434,6 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
DRW_shgroup_uniform_block(grp, "samples_block", e_data.sampling_ubo);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
{
if (TAA_ENABLED(wpd)) {
psl->effect_aa_pass = workbench_taa_create_pass(txl, stl->effects, fbl, &e_data.composite_buffer_tx);
}
else if (FXAA_ENABLED(wpd)) {
psl->effect_aa_pass = workbench_fxaa_create_pass(&e_data.effect_buffer_tx);
stl->effects->jitter_index = 0;
}
else {
psl->effect_aa_pass = NULL;
}
}
}
void workbench_deferred_engine_free(void)
@ -845,7 +845,7 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
if (taa_enabled)
{
workbench_taa_draw_scene_start(effect_info);
workbench_taa_draw_scene_start(vedata);
}
/* clear in background */

View File

@ -1,28 +1,90 @@
#include "workbench_private.h"
#include "BLI_jitter_2d.h"
static struct {
struct GPUShader *effect_taa_sh;
float jitter_8[8][2];
float jitter_16[16][2];
float jitter_32[32][2];
} e_data = {NULL};
extern char datatoc_workbench_effect_taa_frag_glsl[];
/*
* Sub-sample positions for TAA8
* first sample needs to be at 0.0f, 0.0f
* as that sample depicts the z-buffer
*/
static const float SAMPLE_LOCS_8[8][2] = {
{ 0.125f-0.125f, 0.375f-0.375f},
{-0.625f-0.125f, -0.625f-0.375f},
{ 0.875f-0.125f, 0.875f-0.375f},
{-0.875f-0.125f, 0.125f-0.375f},
{ 0.625f-0.125f, -0.125f-0.375f},
{-0.375f-0.125f, 0.625f-0.375f},
{ 0.375f-0.125f, -0.875f-0.375f},
{-0.125f-0.125f, -0.375f-0.375f},
};
static void workbench_taa_jitter_init_order(float (*table)[2], int num)
{
BLI_jitter_init(table, num);
/* find closest element to center */
int closest_index = 0;
float closest_squared_distance = 1.0f;
for (int index = 0 ; index < num; index++) {
const float squared_dist = SQUARE(table[index][0]) + SQUARE(table[index][1]);
if (squared_dist < closest_squared_distance) {
closest_squared_distance = squared_dist;
closest_index = index;
}
}
/* move jitter table so that closest sample is in center */
for (int index = 0 ; index < num; index++) {
sub_v2_v2(table[index], table[closest_index]);
}
/* swap center sample to the start of the table */
if (closest_index != 0) {
swap_v2_v2(table[0], table[closest_index]);
}
/* sort list based on furtest distance with previous */
for (int i = 0 ; i < num - 2; i ++)
{
float f_squared_dist = 0.0;
int f_index = i;
for(int j = i + 1; j < num; j ++)
{
const float squared_dist = SQUARE(table[i][0] - table[j][0]) + SQUARE(table[i][1] - table[j][1]);
if (squared_dist > f_squared_dist)
{
f_squared_dist = squared_dist;
f_index = j;
}
}
swap_v2_v2(table[i+1], table[f_index]);
}
}
static void workbench_taa_jitter_init(void)
{
workbench_taa_jitter_init_order(e_data.jitter_8, 8);
workbench_taa_jitter_init_order(e_data.jitter_16, 16);
workbench_taa_jitter_init_order(e_data.jitter_32, 32);
}
int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata)
{
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_PrivateData *wpd = stl->g_data;
int result = 1;
if (TAA_ENABLED(wpd))
{
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))
{
result = 16;
}
else {
result = 32;
}
}
return result;
}
void workbench_taa_engine_init(WORKBENCH_Data *vedata)
{
@ -33,6 +95,7 @@ void workbench_taa_engine_init(WORKBENCH_Data *vedata)
if (e_data.effect_taa_sh == NULL)
{
e_data.effect_taa_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_taa_frag_glsl, NULL);
workbench_taa_jitter_init();
}
/* reset complete drawing when navigating. */
@ -68,8 +131,13 @@ void workbench_taa_engine_free(void)
}
DRWPass *workbench_taa_create_pass(WORKBENCH_TextureList *txl, WORKBENCH_EffectInfo *effect_info, WORKBENCH_FramebufferList *fbl, GPUTexture **color_buffer_tx)
DRWPass *workbench_taa_create_pass(WORKBENCH_Data *vedata, GPUTexture **color_buffer_tx)
{
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_TextureList *txl = vedata->txl;
WORKBENCH_EffectInfo *effect_info = stl->effects;
WORKBENCH_FramebufferList *fbl = vedata->fbl;
WORKBENCH_PrivateData *wpd = stl->g_data;
/*
* jitter_index is not updated yet. This will be done in during draw phase.
* so for now it is inversed.
@ -120,20 +188,45 @@ DRWPass *workbench_taa_create_pass(WORKBENCH_TextureList *txl, WORKBENCH_EffectI
effect_info->final_color_tx = txl->history_buffer2_tx;
effect_info->final_color_fb = fbl->effect_taa_uneven_fb;
}
/*
* Set the offset for the cavity shader so every iteration different
* samples will be selected
*/
wpd->ssao_params[3] = previous_jitter_index;
return pass;
}
void workbench_taa_draw_scene_start(WORKBENCH_EffectInfo *effect_info)
void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata)
{
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_EffectInfo *effect_info = stl->effects;
const float *viewport_size = DRW_viewport_size_get();
const int samples = 8;
int num_samples = 8;
float (*samples)[2] = e_data.jitter_8;
float mix_factor;
num_samples = workbench_taa_calculate_num_iterations(vedata);
switch(num_samples)
{
case 8:
samples = e_data.jitter_8;
break;
case 16:
samples = e_data.jitter_16;
break;
case 32:
default:
samples = e_data.jitter_32;
break;
}
mix_factor = 1.0f / (effect_info->jitter_index + 1);
const int bitmask = samples - 1;
const int bitmask = num_samples - 1;
const int jitter_index = effect_info->jitter_index;
const float *transform_offset = SAMPLE_LOCS_8[jitter_index];
const float *transform_offset = samples[jitter_index];
effect_info->jitter_index = (jitter_index + 1) & bitmask;
/* construct new matrices from transform delta */

View File

@ -52,10 +52,8 @@
#define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW)
#define IS_NAVIGATING(wpd) (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING)
#define FXAA_ENABLED(wpd) ((!DRW_state_is_opengl_render()) && ((wpd->user_preferences->gpu_viewport_antialias == USER_AA_FXAA) || (ELEM(wpd->user_preferences->gpu_viewport_antialias, USER_AA_TAA8) && IS_NAVIGATING(wpd))))
#define TAA8_ENABLED(wpd) (ELEM(wpd->user_preferences->gpu_viewport_antialias, USER_AA_TAA8) && (!DRW_state_is_opengl_render()) && (!IS_NAVIGATING(wpd)))
#define TAA_ENABLED(wpd) (TAA8_ENABLED(wpd))
#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)))
#define OBJECT_ID_PASS_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED(wpd))
@ -269,11 +267,12 @@ void workbench_fxaa_draw_pass(WORKBENCH_PrivateData *wpd, GPUFrameBuffer *fb, GP
/* workbench_effect_taa.c */
void workbench_taa_engine_init(WORKBENCH_Data *vedata);
void workbench_taa_engine_free(void);
DRWPass *workbench_taa_create_pass(WORKBENCH_TextureList *txl, WORKBENCH_EffectInfo *effect_info, WORKBENCH_FramebufferList *fbl, GPUTexture **color_buffer_tx);
DRWPass *workbench_taa_create_pass(WORKBENCH_Data *vedata, GPUTexture **color_buffer_tx);
void workbench_taa_draw_pass(WORKBENCH_EffectInfo *effect_info, /*WORKBENCH_PrivateData *wpd, , GPUFrameBuffer *fb, GPUTexture *tx, */DRWPass *effect_aa_pass);
void workbench_taa_draw_scene_start(WORKBENCH_EffectInfo *effect_info);
void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata);
void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata);
void workbench_taa_view_updated(WORKBENCH_Data *vedata);
int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata);
/* workbench_materials.c */
int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima);

View File

@ -3031,7 +3031,6 @@ void init_userdef_do_versions(Main *bmain)
rgba_char_args_set(ts->panelcolors.sub_back, 0, 0, 0, 25);
}
}
U.gpu_viewport_antialias = USER_AA_FXAA;
}
/**
@ -3039,6 +3038,7 @@ void init_userdef_do_versions(Main *bmain)
*/
{
/* (keep this block even if it becomes empty). */
U.gpu_viewport_quality = 0.6f;
}
if (((bTheme *)U.themes.first)->tui.manipulator_hi[3] == 0) {

View File

@ -48,6 +48,11 @@ struct ColorBand;
#define MAX_STYLE_NAME 64
#define GPU_VIEWPORT_QUALITY_FXAA 0.10f
#define GPU_VIEWPORT_QUALITY_TAA8 0.25f
#define GPU_VIEWPORT_QUALITY_TAA16 0.6f
#define GPU_VIEWPORT_QUALITY_TAA32 0.8f
/* default offered by Blender.
* uiFont.uifont_id */
typedef enum eUIFont_ID {
@ -548,7 +553,7 @@ typedef struct UserDef {
short undosteps;
short pad1;
int undomemory;
int pad3;
float gpu_viewport_quality;
short gp_manhattendist, gp_euclideandist, gp_eraser;
short gp_settings; /* eGP_UserdefSettings */
short tb_leftmouse, tb_rightmouse;
@ -573,7 +578,7 @@ typedef struct UserDef {
char keyhandles_new; /* handle types for newly added keyframes */
char gpu_select_method;
char gpu_select_pick_deph;
char gpu_viewport_antialias;
char pad0;
char view_frame_type; /* eZoomFrame_Mode */
int view_frame_keyframes; /* number of keyframes to zoom around current frame */

View File

@ -4173,13 +4173,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
static const EnumPropertyItem gpu_antialias_method_items[] = {
{USER_AA_NONE, "OFF", 0, "Off", "Disable Anti Alias in viewport"},
{USER_AA_FXAA, "FXAA", 0, "FXAA", "Use FXAA, a fast screenspace Anti Alias method"},
{USER_AA_TAA8, "TAA8", 0, "TAA 8x", "Use TAA with 8 samples when screen is static, when not static fallback to FXAA"},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL);
RNA_def_struct_sdna(srna, "UserDef");
RNA_def_struct_nested(brna, srna, "UserPreferences");
@ -4438,13 +4431,14 @@ static void rna_def_userdef_system(BlenderRNA *brna)
"Draw tool/property regions over the main region, when using Triple Buffer");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
prop = RNA_def_property(srna, "max_anti_alias_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "gpu_viewport_antialias");
RNA_def_property_enum_items(prop, gpu_antialias_method_items);
RNA_def_property_ui_text(prop, "Viewport Anti-aliasing",
"Method to draw the Anti-Aliasing in the viewport");
prop = RNA_def_property(srna, "gpu_viewport_quality", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "gpu_viewport_quality");
RNA_def_property_float_default(prop, 0.6f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Viewport Quality", "Quality setting for Solid mode rendering in the 3d viewport");
RNA_def_property_update(prop, 0, "rna_userdef_update");
#ifdef WITH_OPENSUBDIV
prop = RNA_def_property(srna, "opensubdiv_compute_type", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);