EEVEE: Use Fullscreen maxZBuffer instead of halfres

This removes the need for per mipmap scalling factor and trilinear interpolation
issues. We pad the texture so that all mipmaps have pixels in the next mip.

This simplifies the downsampling shader too.

This also change the SSR radiance buffer as well in the same fashion.
This commit is contained in:
Clément Foucault 2021-03-04 11:59:49 +01:00
parent 6afe2d373a
commit ba75ea8012
Notes: blender-bot 2023-02-14 05:44:22 +01:00
Referenced by issue #89777, Contact Shadows causes wrong shading in Reflection Plane
Referenced by issue #88219, Regression: Massive drops in Animation playback (fps) in the viewport
Referenced by issue #86858, 2.93 screen space reflection/refraction (?) regressions - white artifacts and missing translucency glow
16 changed files with 187 additions and 248 deletions

View File

@ -44,7 +44,7 @@ static struct {
#define SETUP_BUFFER(tex, fb, fb_color) \
{ \
eGPUTextureFormat format = (DRW_state_is_scene_render()) ? GPU_RGBA32F : GPU_RGBA16F; \
DRW_texture_ensure_fullscreen_2d(&tex, format, DRW_TEX_FILTER | DRW_TEX_MIPMAP); \
DRW_texture_ensure_fullscreen_2d(&tex, format, DRW_TEX_FILTER); \
GPU_framebuffer_ensure_config(&fb, \
{ \
GPU_ATTACHMENT_TEXTURE(dtxl->depth), \
@ -117,20 +117,27 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
/**
* MinMax Pyramid
*/
const bool half_res_hiz = true;
int size[2], div;
common_data->hiz_mip_offset = (half_res_hiz) ? 1 : 0;
div = (half_res_hiz) ? 2 : 1;
size[0] = max_ii(size_fs[0] / div, 1);
size[1] = max_ii(size_fs[1] / div, 1);
int div = 1 << MAX_SCREEN_BUFFERS_LOD_LEVEL;
effects->hiz_size[0] = divide_ceil_u(size_fs[0], div) * div;
effects->hiz_size[1] = divide_ceil_u(size_fs[1], div) * div;
if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
/* Intel gpu seems to have problem rendering to only depth format */
DRW_texture_ensure_2d(&txl->maxzbuffer, size[0], size[1], GPU_R32F, DRW_TEX_MIPMAP);
/* Intel gpu seems to have problem rendering to only depth hiz_format */
DRW_texture_ensure_2d(&txl->maxzbuffer, UNPACK2(effects->hiz_size), GPU_R32F, DRW_TEX_MIPMAP);
GPU_framebuffer_ensure_config(&fbl->maxzbuffer_fb,
{
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(txl->maxzbuffer),
});
}
else {
DRW_texture_ensure_2d(
&txl->maxzbuffer, size[0], size[1], GPU_DEPTH_COMPONENT24, DRW_TEX_MIPMAP);
&txl->maxzbuffer, UNPACK2(effects->hiz_size), GPU_DEPTH_COMPONENT24, DRW_TEX_MIPMAP);
GPU_framebuffer_ensure_config(&fbl->maxzbuffer_fb,
{
GPU_ATTACHMENT_TEXTURE(txl->maxzbuffer),
GPU_ATTACHMENT_NONE,
});
}
if (fbl->downsample_fb == NULL) {
@ -138,13 +145,35 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
}
/**
* Compute Mipmap texel alignment.
* Compute hiZ texel alignment.
*/
for (int i = 0; i < 10; i++) {
int mip_size[3];
GPU_texture_get_mipmap_size(txl->color, i, mip_size);
common_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, i));
common_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, i));
common_data->hiz_uv_scale[0] = viewport_size[0] / effects->hiz_size[0];
common_data->hiz_uv_scale[1] = viewport_size[1] / effects->hiz_size[1];
common_data->hiz_uv_scale[2] = 1.0f / effects->hiz_size[0];
common_data->hiz_uv_scale[3] = 1.0f / effects->hiz_size[1];
/* Compute pixel size. Size is multiplied by 2 because it is applied in NDC [-1..1] range. */
sldata->common_data.ssr_pixelsize[0] = 2.0f / size_fs[0];
sldata->common_data.ssr_pixelsize[1] = 2.0f / size_fs[1];
/**
* Color buffer with correct downsampling alignment.
* Used for SSReflections & SSRefractions.
*/
if ((effects->enabled_effects & EFFECT_RADIANCE_BUFFER) != 0) {
DRW_texture_ensure_2d(&txl->filtered_radiance,
UNPACK2(effects->hiz_size),
GPU_R11F_G11F_B10F,
DRW_TEX_FILTER | DRW_TEX_MIPMAP);
GPU_framebuffer_ensure_config(&fbl->radiance_filtered_fb,
{
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(txl->filtered_radiance),
});
}
else {
txl->filtered_radiance = NULL;
}
/**
@ -210,7 +239,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
DRWState downsample_write = DRW_STATE_WRITE_DEPTH;
DRWState downsample_write = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS;
DRWShadingGroup *grp;
/* Intel gpu seems to have problem rendering to only depth format.
@ -221,12 +250,17 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
{
if (effects->enabled_effects & EFFECT_RADIANCE_BUFFER) {
DRW_PASS_CREATE(psl->color_copy_ps, DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(EEVEE_shaders_effect_color_copy_sh_get(), psl->color_copy_ps);
DRW_shgroup_uniform_texture_ref_ex(grp, "source", &e_data.color_src, GPU_SAMPLER_DEFAULT);
DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
DRW_PASS_CREATE(psl->color_downsample_ps, DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(EEVEE_shaders_effect_downsample_sh_get(), psl->color_downsample_ps);
DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src);
DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
DRW_shgroup_call(grp, quad, NULL);
DRW_shgroup_uniform_texture_ex(grp, "source", txl->filtered_radiance, GPU_SAMPLER_FILTER);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
{
@ -241,34 +275,21 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
/* Perform min/max down-sample. */
DRW_PASS_CREATE(psl->maxz_downlevel_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
DRW_PASS_CREATE(psl->maxz_downlevel_ps, downsample_write);
grp = DRW_shgroup_create(EEVEE_shaders_effect_maxz_downlevel_sh_get(), psl->maxz_downlevel_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref_ex(grp, "depthBuffer", &txl->maxzbuffer, GPU_SAMPLER_DEFAULT);
DRW_shgroup_call(grp, quad, NULL);
/* Copy depth buffer to halfres top level of HiZ */
DRW_PASS_CREATE(psl->maxz_downdepth_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(EEVEE_shaders_effect_maxz_downdepth_sh_get(), psl->maxz_downdepth_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_call(grp, quad, NULL);
DRW_PASS_CREATE(psl->maxz_downdepth_layer_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(EEVEE_shaders_effect_maxz_downdepth_layer_sh_get(),
psl->maxz_downdepth_layer_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
DRW_shgroup_call(grp, quad, NULL);
DRW_PASS_CREATE(psl->maxz_copydepth_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
/* Copy depth buffer to top level of HiZ */
DRW_PASS_CREATE(psl->maxz_copydepth_ps, downsample_write);
grp = DRW_shgroup_create(EEVEE_shaders_effect_maxz_copydepth_sh_get(), psl->maxz_copydepth_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_texture_ref_ex(grp, "depthBuffer", &e_data.depth_src, GPU_SAMPLER_DEFAULT);
DRW_shgroup_call(grp, quad, NULL);
DRW_PASS_CREATE(psl->maxz_copydepth_layer_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
DRW_PASS_CREATE(psl->maxz_copydepth_layer_ps, downsample_write);
grp = DRW_shgroup_create(EEVEE_shaders_effect_maxz_copydepth_layer_sh_get(),
psl->maxz_copydepth_layer_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_texture_ref_ex(grp, "depthBuffer", &e_data.depth_src, GPU_SAMPLER_DEFAULT);
DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
DRW_shgroup_call(grp, quad, NULL);
}
@ -331,12 +352,6 @@ static void max_downsample_cb(void *vedata, int UNUSED(level))
DRW_draw_pass(psl->maxz_downlevel_ps);
}
static void simple_downsample_cb(void *vedata, int UNUSED(level))
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
DRW_draw_pass(psl->color_downsample_ps);
}
static void simple_downsample_cube_cb(void *vedata, int level)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
@ -348,58 +363,22 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int l
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
e_data.depth_src = depth_src;
e_data.depth_src_layer = layer;
#if 0 /* Not required for now */
DRW_stats_group_start("Min buffer");
/* Copy depth buffer to min texture top level */
GPU_framebuffer_texture_attach(fbl->downsample_fb, stl->g_data->minzbuffer, 0, 0);
GPU_framebuffer_bind(fbl->downsample_fb);
if (layer >= 0) {
DRW_draw_pass(psl->minz_downdepth_layer_ps);
}
else {
DRW_draw_pass(psl->minz_downdepth_ps);
}
GPU_framebuffer_texture_detach(stl->g_data->minzbuffer);
/* Create lower levels */
GPU_framebuffer_recursive_downsample(
fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata);
DRW_stats_group_end();
#endif
int minmax_size[3], depth_size[3];
GPU_texture_get_mipmap_size(depth_src, 0, depth_size);
GPU_texture_get_mipmap_size(txl->maxzbuffer, 0, minmax_size);
bool is_full_res_minmaxz = equals_v2v2_int(minmax_size, depth_size);
DRW_stats_group_start("Max buffer");
/* Copy depth buffer to max texture top level */
GPU_framebuffer_texture_attach(fbl->downsample_fb, txl->maxzbuffer, 0, 0);
GPU_framebuffer_bind(fbl->downsample_fb);
GPU_framebuffer_bind(fbl->maxzbuffer_fb);
if (layer >= 0) {
if (is_full_res_minmaxz) {
DRW_draw_pass(psl->maxz_copydepth_layer_ps);
}
else {
DRW_draw_pass(psl->maxz_downdepth_layer_ps);
}
DRW_draw_pass(psl->maxz_copydepth_layer_ps);
}
else {
if (is_full_res_minmaxz) {
DRW_draw_pass(psl->maxz_copydepth_ps);
}
else {
DRW_draw_pass(psl->maxz_downdepth_ps);
}
DRW_draw_pass(psl->maxz_copydepth_ps);
}
/* Create lower levels */
GPU_framebuffer_recursive_downsample(fbl->downsample_fb, 8, &max_downsample_cb, vedata);
GPU_framebuffer_texture_detach(fbl->downsample_fb, txl->maxzbuffer);
GPU_framebuffer_recursive_downsample(
fbl->maxzbuffer_fb, MAX_SCREEN_BUFFERS_LOD_LEVEL, &max_downsample_cb, vedata);
DRW_stats_group_end();
/* Restore */
@ -412,19 +391,28 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int l
}
}
static void downsample_radiance_cb(void *vedata, int UNUSED(level))
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
DRW_draw_pass(psl->color_downsample_ps);
}
/**
* Simple down-sampling algorithm. Reconstruct mip chain up to mip level.
*/
void EEVEE_downsample_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level)
void EEVEE_effects_downsample_radiance_buffer(EEVEE_Data *vedata, GPUTexture *texture_src)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_FramebufferList *fbl = vedata->fbl;
e_data.color_src = texture_src;
/* Create lower levels */
DRW_stats_group_start("Downsample buffer");
GPU_framebuffer_texture_attach(fbl->downsample_fb, texture_src, 0, 0);
GPU_framebuffer_recursive_downsample(fbl->downsample_fb, level, &simple_downsample_cb, vedata);
GPU_framebuffer_texture_detach(fbl->downsample_fb, texture_src);
e_data.color_src = texture_src;
DRW_stats_group_start("Downsample Radiance");
GPU_framebuffer_bind(fbl->radiance_filtered_fb);
DRW_draw_pass(psl->color_copy_ps);
GPU_framebuffer_recursive_downsample(
fbl->radiance_filtered_fb, MAX_SCREEN_BUFFERS_LOD_LEVEL, &downsample_radiance_cb, vedata);
DRW_stats_group_end();
}

View File

@ -112,19 +112,20 @@ static struct GPUTexture *create_hammersley_sample_texture(int samples)
static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
{
EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *fx = stl->effects;
/* XXX TODO OPTIMIZATION: This is a complete waist of texture memory.
* Instead of allocating each planar probe for each viewport,
* only alloc them once using the biggest viewport resolution. */
const float *viewport_size = DRW_viewport_size_get();
/* TODO get screen percentage from layer setting */
// const DRWContextState *draw_ctx = DRW_context_state_get();
// ViewLayer *view_layer = draw_ctx->view_layer;
float screen_percentage = 1.0f;
int screen_divider = 1;
int width = max_ii(1, (int)(viewport_size[0] * screen_percentage));
int height = max_ii(1, (int)(viewport_size[1] * screen_percentage));
int width = max_ii(1, fx->hiz_size[0] / screen_divider);
int height = max_ii(1, fx->hiz_size[1] / screen_divider);
/* Fix case were the pool was allocated width the dummy size (1,1,1). */
if (txl->planar_pool && (num_planar_ref > 0) &&
@ -139,12 +140,12 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
if (num_planar_ref > 0) {
txl->planar_pool = DRW_texture_create_2d_array(width,
height,
max_ii(1, num_planar_ref),
num_planar_ref,
GPU_R11F_G11F_B10F,
DRW_TEX_FILTER | DRW_TEX_MIPMAP,
NULL);
txl->planar_depth = DRW_texture_create_2d_array(
width, height, max_ii(1, num_planar_ref), GPU_DEPTH_COMPONENT24, 0, NULL);
width, height, num_planar_ref, GPU_DEPTH_COMPONENT24, 0, NULL);
}
else if (num_planar_ref == 0) {
/* Makes Opengl Happy : Create a placeholder texture that will never be sampled but still
@ -674,10 +675,12 @@ static void lightbake_planar_ensure_view(EEVEE_PlanarReflection *eplanar,
const DRWView *main_view,
DRWView **r_planar_view)
{
float winmat[4][4], viewmat[4][4];
float winmat[4][4], viewmat[4][4], persmat[4][4];
DRW_view_viewmat_get(main_view, viewmat, false);
/* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */
DRW_view_winmat_get(main_view, winmat, false);
DRW_view_persmat_get(main_view, persmat, false);
/* Invert X to avoid flipping the triangle facing direction. */
winmat[0][0] = -winmat[0][0];
winmat[1][0] = -winmat[1][0];
@ -729,7 +732,6 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
/* For shading, save max level of the octahedron map */
sldata->common_data.prb_lod_cube_max = (float)light_cache->mips_len;
sldata->common_data.prb_lod_planar_max = (float)MAX_PLANAR_LOD_LEVEL;
sldata->common_data.prb_irradiance_vis_size = light_cache->vis_res;
sldata->common_data.prb_irradiance_smooth = square_f(scene_eval->eevee.gi_irradiance_smoothing);
sldata->common_data.prb_num_render_cube = max_ii(1, light_cache->cube_len);
@ -1220,7 +1222,7 @@ static void EEVEE_lightbake_filter_planar(EEVEE_Data *vedata)
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->planar_pool)});
GPU_framebuffer_recursive_downsample(
fbl->planar_downsample_fb, MAX_PLANAR_LOD_LEVEL, &downsample_planar, vedata);
fbl->planar_downsample_fb, MAX_SCREEN_BUFFERS_LOD_LEVEL, &downsample_planar, vedata);
DRW_stats_group_end();
}

View File

@ -128,7 +128,7 @@ void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
DRW_shgroup_uniform_float_copy(
shgrp, "refractionDepth", (refract_depth) ? *refract_depth : 0.0);
if (use_ssrefraction) {
DRW_shgroup_uniform_texture_ref(shgrp, "colorBuffer", &vedata->txl->refract_color);
DRW_shgroup_uniform_texture_ref(shgrp, "colorBuffer", &vedata->txl->filtered_radiance);
}
}
if (use_alpha_blend) {

View File

@ -161,7 +161,7 @@ BLI_INLINE bool eevee_hdri_preview_overlay_enabled(const View3D *v3d)
((v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER) == 0))))
#define MIN_CUBE_LOD_LEVEL 3
#define MAX_PLANAR_LOD_LEVEL 9
#define MAX_SCREEN_BUFFERS_LOD_LEVEL 6
/* All the renderpasses that use the GPUMaterial for accumulation */
#define EEVEE_RENDERPASSES_MATERIAL \
@ -308,6 +308,7 @@ typedef struct EEVEE_PassList {
struct DRWPass *sss_blur_ps;
struct DRWPass *sss_resolve_ps;
struct DRWPass *sss_translucency_ps;
struct DRWPass *color_copy_ps;
struct DRWPass *color_downsample_ps;
struct DRWPass *color_downsample_cube_ps;
struct DRWPass *velocity_object;
@ -320,13 +321,7 @@ typedef struct EEVEE_PassList {
struct DRWPass *alpha_checker;
/* HiZ */
struct DRWPass *minz_downlevel_ps;
struct DRWPass *maxz_downlevel_ps;
struct DRWPass *minz_downdepth_ps;
struct DRWPass *maxz_downdepth_ps;
struct DRWPass *minz_downdepth_layer_ps;
struct DRWPass *maxz_downdepth_layer_ps;
struct DRWPass *minz_copydepth_ps;
struct DRWPass *maxz_copydepth_ps;
struct DRWPass *maxz_copydepth_layer_ps;
@ -362,6 +357,7 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *gtao_fb;
struct GPUFrameBuffer *gtao_debug_fb;
struct GPUFrameBuffer *downsample_fb;
struct GPUFrameBuffer *maxzbuffer_fb;
struct GPUFrameBuffer *bloom_blit_fb;
struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP];
struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1];
@ -394,7 +390,6 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *volumetric_integ_fb;
struct GPUFrameBuffer *volumetric_accum_fb;
struct GPUFrameBuffer *screen_tracing_fb;
struct GPUFrameBuffer *refract_fb;
struct GPUFrameBuffer *mist_accum_fb;
struct GPUFrameBuffer *material_accum_fb;
struct GPUFrameBuffer *renderpass_fb;
@ -412,6 +407,7 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *main_color_fb;
struct GPUFrameBuffer *effect_fb;
struct GPUFrameBuffer *effect_color_fb;
struct GPUFrameBuffer *radiance_filtered_fb;
struct GPUFrameBuffer *double_buffer_fb;
struct GPUFrameBuffer *double_buffer_color_fb;
struct GPUFrameBuffer *double_buffer_depth_fb;
@ -436,7 +432,6 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *ssr_accum;
struct GPUTexture *shadow_accum;
struct GPUTexture *cryptomatte;
struct GPUTexture *refract_color;
struct GPUTexture *taa_history;
/* Could not be pool texture because of mipmapping. */
struct GPUTexture *dof_reduced_color;
@ -460,6 +455,7 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *planar_depth;
struct GPUTexture *maxzbuffer;
struct GPUTexture *filtered_radiance;
struct GPUTexture *renderpass;
@ -618,7 +614,7 @@ typedef struct EEVEE_LightProbesInfo {
float roughness;
float firefly_fac;
float lodfactor;
float lod_rt_max, lod_cube_max, lod_planar_max;
float lod_rt_max, lod_cube_max;
float visibility_range;
float visibility_blur;
float intensity_fac;
@ -708,8 +704,9 @@ typedef enum EEVEE_EffectsFlag {
EFFECT_REFRACT = (1 << 6),
EFFECT_GTAO = (1 << 7),
EFFECT_TAA = (1 << 8),
EFFECT_POST_BUFFER = (1 << 9), /* Not really an effect but a feature */
EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */
EFFECT_POST_BUFFER = (1 << 9), /* Not really an effect but a feature */
EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */
EFFECT_RADIANCE_BUFFER = (1 << 10), /* Not really an effect but a feature */
EFFECT_SSS = (1 << 11),
EFFECT_VELOCITY_BUFFER = (1 << 12), /* Not really an effect but a feature */
EFFECT_TAA_REPROJECT = (1 << 13), /* should be mutually exclusive with EFFECT_TAA */
@ -817,11 +814,10 @@ typedef struct EEVEE_EffectsInfo {
struct GPUTexture *dof_scatter_src_tx;
struct GPUTexture *dof_reduce_input_coc_tx; /* Just references to actual textures. */
struct GPUTexture *dof_reduce_input_color_tx;
/* Alpha Checker */
float color_checker_dark[4];
float color_checker_light[4];
/* Other */
float prev_persmat[4][4];
/* Size used by all fullscreen buffers using mipmaps. */
int hiz_size[2];
/* Lookdev */
int sphere_size;
eDRWLevelOfDetail sphere_lod;
@ -859,7 +855,7 @@ typedef struct EEVEE_EffectsInfo {
* - sizeof(bool) == sizeof(int) in GLSL so use int in C */
typedef struct EEVEE_CommonUniformBuffer {
float prev_persmat[4][4]; /* mat4 */
float mip_ratio[10][4]; /* vec2[10] */
float hiz_uv_scale[4]; /* vec4 */
/* Ambient Occlusion */
/* -- 16 byte aligned -- */
float ao_dist, pad1, ao_factor, pad2; /* vec4 */
@ -899,15 +895,15 @@ typedef struct EEVEE_CommonUniformBuffer {
int prb_irradiance_vis_size; /* int */
float prb_irradiance_smooth; /* float */
float prb_lod_cube_max; /* float */
float prb_lod_planar_max; /* float */
/* Misc */
int hiz_mip_offset; /* int */
int ray_type; /* int */
float ray_depth; /* float */
float alpha_hash_offset; /* float */
float alpha_hash_scale; /* float */
float pad7; /* float */
float pad8; /* float */
float pad9; /* float */
float pad10; /* float */
} EEVEE_CommonUniformBuffer;
BLI_STATIC_ASSERT_ALIGN(EEVEE_CommonUniformBuffer, 16)
@ -1201,6 +1197,7 @@ struct GPUShader *EEVEE_shaders_depth_of_field_gather_get(EEVEE_DofGatherPass pa
struct GPUShader *EEVEE_shaders_depth_of_field_filter_get(void);
struct GPUShader *EEVEE_shaders_depth_of_field_scatter_get(bool is_foreground, bool bokeh_tx);
struct GPUShader *EEVEE_shaders_depth_of_field_resolve_get(bool use_bokeh_tx, bool use_hq_gather);
struct GPUShader *EEVEE_shaders_effect_color_copy_sh_get(void);
struct GPUShader *EEVEE_shaders_effect_downsample_sh_get(void);
struct GPUShader *EEVEE_shaders_effect_downsample_cube_sh_get(void);
struct GPUShader *EEVEE_shaders_effect_minz_downlevel_sh_get(void);
@ -1472,8 +1469,8 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
const bool minimal);
void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_effects_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_effects_downsample_radiance_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src);
void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);

View File

@ -42,29 +42,15 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
const float *viewport_size = DRW_viewport_size_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
/* Compute pixel size, (shared with contact shadows) */
copy_v2_v2(common_data->ssr_pixelsize, viewport_size);
invert_v2(common_data->ssr_pixelsize);
if (scene_eval->eevee.flag & SCE_EEVEE_SSR_ENABLED) {
const bool use_refraction = (scene_eval->eevee.flag & SCE_EEVEE_SSR_REFRACTION) != 0;
if (use_refraction) {
/* TODO: Opti: Could be shared. */
DRW_texture_ensure_fullscreen_2d(
&txl->refract_color, GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
GPU_framebuffer_ensure_config(
&fbl->refract_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->refract_color)});
}
const bool is_persp = DRW_view_is_persp_get(NULL);
if (effects->ssr_was_persp != is_persp) {
effects->ssr_was_persp = is_persp;
@ -117,8 +103,7 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
GPU_ATTACHMENT_TEXTURE(effects->ssr_hit_output),
GPU_ATTACHMENT_TEXTURE(effects->ssr_pdf_output)});
/* Enable double buffering to be able to read previous frame color */
return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER |
return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_RADIANCE_BUFFER | EFFECT_DOUBLE_BUFFER |
((use_refraction) ? EFFECT_REFRACT : 0);
}
@ -189,7 +174,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_texture_ref(grp, "planarDepth", &vedata->txl->planar_depth);
DRW_shgroup_uniform_texture_ref(grp, "hitBuffer", &effects->ssr_hit_output);
DRW_shgroup_uniform_texture_ref(grp, "pdfBuffer", &effects->ssr_pdf_output);
DRW_shgroup_uniform_texture_ref(grp, "prevColorBuffer", &txl->color_double_buffer);
DRW_shgroup_uniform_texture_ref(grp, "prevColorBuffer", &txl->filtered_radiance);
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
@ -216,8 +201,7 @@ void EEVEE_refraction_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_REFRACT) != 0) {
GPU_framebuffer_blit(fbl->main_fb, 0, fbl->refract_fb, 0, GPU_COLOR_BIT);
EEVEE_downsample_buffer(vedata, txl->refract_color, 9);
EEVEE_effects_downsample_radiance_buffer(vedata, txl->color);
/* Restore */
GPU_framebuffer_bind(fbl->main_fb);
@ -242,7 +226,7 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
GPU_framebuffer_bind(fbl->screen_tracing_fb);
DRW_draw_pass(psl->ssr_raytrace);
EEVEE_downsample_buffer(vedata, txl->color_double_buffer, 9);
EEVEE_effects_downsample_radiance_buffer(vedata, txl->color_double_buffer);
/* Resolve at fullres */
int samp = (DRW_state_is_image_render()) ? effects->taa_render_sample :

View File

@ -103,7 +103,8 @@ static struct {
struct GPUShader *minz_copydepth_sh;
struct GPUShader *maxz_copydepth_sh;
/* Simple Down-sample */
/* Simple Down-sample. */
struct GPUShader *color_copy_sh;
struct GPUShader *downsample_sh;
struct GPUShader *downsample_cube_sh;
@ -452,10 +453,20 @@ GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void)
/** \name Down-sampling
* \{ */
GPUShader *EEVEE_shaders_effect_color_copy_sh_get(void)
{
if (e_data.color_copy_sh == NULL) {
e_data.color_copy_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_downsample_frag_glsl, e_data.lib, "#define COPY_SRC\n");
}
return e_data.color_copy_sh;
}
GPUShader *EEVEE_shaders_effect_downsample_sh_get(void)
{
if (e_data.downsample_sh == NULL) {
e_data.downsample_sh = DRW_shader_create_fullscreen(datatoc_effect_downsample_frag_glsl, NULL);
e_data.downsample_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_downsample_frag_glsl, e_data.lib, NULL);
}
return e_data.downsample_sh;
}
@ -1537,6 +1548,7 @@ void EEVEE_shaders_free(void)
MEM_SAFE_FREE(e_data.surface_geom_barycentric);
DRW_SHADER_FREE_SAFE(e_data.lookdev_background);
DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_SHADER_FREE_SAFE(e_data.color_copy_sh);
DRW_SHADER_FREE_SAFE(e_data.downsample_sh);
DRW_SHADER_FREE_SAFE(e_data.downsample_cube_sh);
DRW_SHADER_FREE_SAFE(e_data.minz_downlevel_sh);

View File

@ -94,8 +94,7 @@ float search_horizon(vec3 vI,
vec2 uv = uv_start + uv_dir * t;
float lod = min(MAX_LOD, max(i - noise, 0.0) * aoQuality);
int mip = int(lod) + hizMipOffset;
float depth = textureLod(depth_tx, uv * mipRatio[mip].xy, floor(lod)).r;
float depth = textureLod(depth_tx, uv * hizUvScale.xy, floor(lod)).r;
/* Bias depth a bit to avoid self shadowing issues. */
const float bias = 2.0 * 2.4e-7;

View File

@ -2,7 +2,7 @@
layout(std140) uniform common_block
{
mat4 pastViewProjectionMatrix;
vec2 mipRatio[10]; /* To correct mip level texel misalignment */
vec4 hizUvScale; /* To correct mip level texel misalignment */
/* Ambient Occlusion */
vec4 aoParameters[2];
/* Volumetric */
@ -37,15 +37,15 @@ layout(std140) uniform common_block
int prbIrradianceVisSize;
float prbIrradianceSmooth;
float prbLodCubeMax;
float prbLodPlanarMax;
/* Misc*/
int hizMipOffset;
int rayType;
float rayDepth;
float alphaHashOffset;
float alphaHashScale;
float pad6;
float pad7;
float pad8;
float pad9;
};
/* rayType (keep in sync with ray_type) */
@ -69,9 +69,3 @@ layout(std140) uniform common_block
#define ssrQuality ssrParameters.x
#define ssrThickness ssrParameters.y
#define ssrPixelSize ssrParameters.zw
vec2 mip_ratio_interp(float mip)
{
float low_mip = floor(mip);
return mix(mipRatio[int(low_mip)], mipRatio[int(low_mip + 1.0)], mip - low_mip);
}

View File

@ -62,12 +62,6 @@ const vec2 quad_offsets[4] = vec2[4](
#define dof_coc_from_zdepth(d) calculate_coc(linear_depth(d))
vec4 safe_color(vec4 c)
{
/* Clamp to avoid black square artifacts if a pixel goes NaN. */
return clamp(c, vec4(0.0), vec4(1e20)); /* 1e20 arbitrary. */
}
float dof_hdr_color_weight(vec4 color)
{
/* From UE4. Very fast "luma" weighting. */

View File

@ -1,5 +1,9 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
/**
* Simple down-sample shader. Takes the average of the 4 texels of lower mip.
* Simple down-sample shader.
* Do a gaussian filter using 4 bilinear texture samples.
*/
uniform sampler2D source;
@ -14,24 +18,25 @@ float brightness(vec3 c)
void main()
{
#if 0
/* Reconstructing Target uvs like this avoid missing pixels if NPO2 */
vec2 uvs = gl_FragCoord.xy * 2.0 / vec2(textureSize(source, 0));
FragColor = textureLod(source, uvs, 0.0);
#else
vec2 texel_size = 1.0 / vec2(textureSize(source, 0));
vec2 uvs = gl_FragCoord.xy * 2.0 * texel_size;
vec2 uvs = gl_FragCoord.xy * texel_size;
#ifdef COPY_SRC
FragColor = textureLod(source, uvs, 0.0);
FragColor = safe_color(FragColor);
/* Clamped brightness. */
float luma = max(1e-8, brightness(FragColor.rgb));
FragColor *= 1.0 - max(0.0, luma - fireflyFactor) / luma;
#else
vec4 ofs = texel_size.xyxy * vec4(0.75, 0.75, -0.75, -0.75);
uvs *= 2.0;
FragColor = textureLod(source, uvs + ofs.xy, 0.0);
FragColor += textureLod(source, uvs + ofs.xw, 0.0);
FragColor += textureLod(source, uvs + ofs.zy, 0.0);
FragColor += textureLod(source, uvs + ofs.zw, 0.0);
FragColor *= 0.25;
/* Clamped brightness. */
float luma = max(1e-8, brightness(FragColor.rgb));
FragColor *= 1.0 - max(0.0, luma - fireflyFactor) / luma;
#endif
}

View File

@ -2,6 +2,9 @@
* Shader that down-sample depth buffer,
* saving min and max value of each texel in the above mipmaps.
* Adapted from http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/
*
* Major simplification has been made since we pad the buffer to always be bigger than input to
* avoid mipmapping misalignement.
*/
#ifdef LAYERED
@ -12,10 +15,10 @@ uniform sampler2D depthBuffer;
#endif
#ifdef LAYERED
# define sampleLowerMip(t) texelFetch(depthBuffer, ivec3(t, depthLayer), 0).r
# define sampleLowerMip(t) texture(depthBuffer, vec3(t, depthLayer)).r
# define gatherLowerMip(t) textureGather(depthBuffer, vec3(t, depthLayer))
#else
# define sampleLowerMip(t) texelFetch(depthBuffer, t, 0).r
# define sampleLowerMip(t) texture(depthBuffer, t).r
# define gatherLowerMip(t) textureGather(depthBuffer, t)
#endif
@ -37,54 +40,27 @@ out vec4 fragColor;
void main()
{
ivec2 texelPos = ivec2(gl_FragCoord.xy);
ivec2 mipsize = textureSize(depthBuffer, 0).xy;
#ifndef COPY_DEPTH
texelPos *= 2;
#endif
vec2 texel = gl_FragCoord.xy;
vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy);
#ifdef COPY_DEPTH
float val = sampleLowerMip(texelPos);
vec2 uv = texel * texel_size;
float val = sampleLowerMip(uv);
#else
vec2 uv = texel * 2.0 * texel_size;
vec4 samp;
# ifdef GPU_ARB_texture_gather
/* + 1.0 to gather at the center of target 4 texels. */
samp = gatherLowerMip((vec2(texelPos) + 1.0) / vec2(mipsize));
samp = gatherLowerMip(uv);
# else
samp.x = sampleLowerMip(texelPos);
samp.y = sampleLowerMip(texelPos + ivec2(1, 0));
samp.z = sampleLowerMip(texelPos + ivec2(1, 1));
samp.w = sampleLowerMip(texelPos + ivec2(0, 1));
samp.x = sampleLowerMip(uv + vec2(-0.5, -0.5) * texel_size);
samp.y = sampleLowerMip(uv + vec2(-0.5, 0.5) * texel_size);
samp.z = sampleLowerMip(uv + vec2(0.5, -0.5) * texel_size);
samp.w = sampleLowerMip(uv + vec2(0.5, 0.5) * texel_size);
# endif
float val = minmax4(samp.x, samp.y, samp.z, samp.w);
/* if we are reducing an odd-width texture then fetch the edge texels */
if (((mipsize.x & 1) != 0) && (texelPos.x == mipsize.x - 3)) {
/* if both edges are odd, fetch the top-left corner texel */
if (((mipsize.y & 1) != 0) && (texelPos.y == mipsize.y - 3)) {
samp.x = sampleLowerMip(texelPos + ivec2(2, 2));
val = minmax2(val, samp.x);
}
# ifdef GPU_ARB_texture_gather
samp = gatherLowerMip((vec2(texelPos) + vec2(2.0, 1.0)) / vec2(mipsize));
# else
samp.y = sampleLowerMip(texelPos + ivec2(2, 0));
samp.z = sampleLowerMip(texelPos + ivec2(2, 1));
# endif
val = minmax3(val, samp.y, samp.z);
}
/* if we are reducing an odd-height texture then fetch the edge texels */
if (((mipsize.y & 1) != 0) && (texelPos.y == mipsize.y - 3)) {
# ifdef GPU_ARB_texture_gather
samp = gatherLowerMip((vec2(texelPos) + vec2(1.0, 2.0)) / vec2(mipsize));
# else
samp.x = sampleLowerMip(texelPos + ivec2(0, 2));
samp.y = sampleLowerMip(texelPos + ivec2(1, 2));
# endif
val = minmax3(val, samp.x, samp.y);
}
#endif
#if defined(GPU_INTEL) || defined(GPU_ATI)

View File

@ -104,6 +104,11 @@ void do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 vP, float a2, vec4 rand)
pdfData = min(1024e32, pdf_ggx_reflect(NH, a2)); /* Theoretical limit of 16bit float */
/* TODO(fclem) This bias should use depth precision and the dot product between
* ray direction and geom normal. */
float rays_bias = 0.005;
vP = vP + vNg * rays_bias;
vec3 hit_pos = raycast(-1, vP, R * 1e16, ssrThickness, rand.y, ssrQuality, a2, true);
hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), false);
@ -325,10 +330,10 @@ vec3 get_hit_vector(vec3 hit_pos,
vec3 get_scene_color(vec2 ref_uvs, float mip, float planar_index, bool is_planar)
{
if (is_planar) {
return textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, prbLodPlanarMax)).rgb;
return textureLod(probePlanars, vec3(ref_uvs, planar_index), mip).rgb;
}
else {
return textureLod(prevColorBuffer, ref_uvs, mip).rgb;
return textureLod(prevColorBuffer, ref_uvs * hizUvScaleBias.xy + hizUvScaleBias.zw, mip).rgb;
}
}
@ -403,12 +408,6 @@ vec4 get_ssr_samples(vec4 hit_pdf,
vec4 mip = log2(cone_footprint * max_v2(vec2(textureSize(depthBuffer, 0))));
mip = clamp(mip, 0.0, MAX_MIP);
/* Correct UVs for mipmaping mis-alignment */
hit_co[0].xy *= mip_ratio_interp(mip.x);
hit_co[0].zw *= mip_ratio_interp(mip.y);
hit_co[1].xy *= mip_ratio_interp(mip.z);
hit_co[1].zw *= mip_ratio_interp(mip.w);
/* Slide 54 */
vec4 bsdf;
bsdf.x = bsdf_ggx(N, hit_pos[0], V, roughnessSquared);

View File

@ -10,12 +10,6 @@ uniform mat4 prevViewProjectionMatrix;
out vec4 FragColor;
vec4 safe_color(vec4 c)
{
/* Clamp to avoid black square artifacts if a pixel goes NaN. */
return clamp(c, vec4(0.0), vec4(1e20)); /* 1e20 arbitrary. */
}
#ifdef USE_REPROJECTION
/**

View File

@ -16,10 +16,7 @@ float sample_depth(vec2 uv, int index, float lod)
}
else {
#endif
lod = clamp(floor(lod), 0.0, 8.0);
/* Correct UVs for mipmaping mis-alignment */
uv *= mipRatio[int(lod) + hizMipOffset];
return textureLod(maxzBuffer, uv, lod).r;
return textureLod(maxzBuffer, uv * hizUvScale.xy, floor(lod)).r;
#ifdef PLANAR_PROBE_RAYTRACE
}
#endif
@ -37,10 +34,10 @@ vec4 sample_depth_grouped(vec4 uv1, vec4 uv2, int index, float lod)
}
else {
#endif
depths.x = textureLod(maxzBuffer, uv1.xy, lod).r;
depths.y = textureLod(maxzBuffer, uv1.zw, lod).r;
depths.z = textureLod(maxzBuffer, uv2.xy, lod).r;
depths.w = textureLod(maxzBuffer, uv2.zw, lod).r;
depths.x = textureLod(maxzBuffer, uv1.xy * hizUvScale.xy, lod).r;
depths.y = textureLod(maxzBuffer, uv1.zw * hizUvScale.xy, lod).r;
depths.z = textureLod(maxzBuffer, uv2.xy * hizUvScale.xy, lod).r;
depths.w = textureLod(maxzBuffer, uv2.zw * hizUvScale.xy, lod).r;
#ifdef PLANAR_PROBE_RAYTRACE
}
#endif
@ -131,9 +128,6 @@ void prepare_raycast(vec3 ray_origin,
#endif
ss_ray = ss_start * m.xyyy + 0.5;
ss_step *= m.xyyy;
/* take the center of the texel. */
// ss_ray.xy += sign(ss_ray.xy) * m * ssrPixelSize * (1.0 + hizMipOffset);
}
/* See times_and_deltas. */
@ -175,9 +169,7 @@ vec3 raycast(int index,
bool hit = false;
float iter;
for (iter = 1.0; !hit && (ray_time < max_time) && (iter < MAX_STEP); iter++) {
/* Minimum stride of 2 because we are using half res minmax zbuffer. */
/* WORKAROUND: Factor is a bit higher than 2 to avoid some banding. To investigate. */
float stride = max(1.0, iter * trace_quality) * (2.0 + 0.05);
float stride = max(1.01, iter * trace_quality);
float lod = log2(stride * 0.5 * trace_quality) * lod_fac;
ray_time += stride;

View File

@ -68,10 +68,7 @@ vec4 screen_space_refraction(vec3 vP, vec3 N, vec3 V, float ior, float roughness
vec2 texture_size = vec2(textureSize(colorBuffer, 0).xy);
float mip = clamp(log2(cone_footprint * max(texture_size.x, texture_size.y)), 0.0, 9.0);
/* Correct UVs for mipmaping mis-alignment */
hit_uvs *= mip_ratio_interp(mip);
vec3 spec = textureLod(colorBuffer, hit_uvs, mip).xyz;
vec3 spec = textureLod(colorBuffer, hit_uvs * hizUvScale.xy, mip).xyz;
float mask = screen_border_mask(hit_uvs);
return vec4(spec, mask);

View File

@ -128,6 +128,12 @@ vec3 normalize_len(vec3 v, out float len)
return v / len;
}
vec4 safe_color(vec4 c)
{
/* Clamp to avoid black square artifacts if a pixel goes NaN. */
return clamp(c, vec4(0.0), vec4(1e20)); /* 1e20 arbitrary. */
}
/** \} */
/* ---------------------------------------------------------------------- */