Eevee: Initial implementation of Volumetrics.
This commit is contained in:
parent
9d2ee7998a
commit
65b01014b9
|
@ -631,6 +631,7 @@ class RENDER_PT_eevee_poststack_settings(RenderButtonsPanel, Panel):
|
|||
props = scene.layer_properties['BLENDER_EEVEE']
|
||||
|
||||
col = layout.column()
|
||||
col.prop(props, "volumetric_enable")
|
||||
col.prop(props, "gtao_enable")
|
||||
col.prop(props, "motion_blur_enable")
|
||||
col.prop(props, "dof_enable")
|
||||
|
|
|
@ -167,6 +167,7 @@ class RENDERLAYER_PT_eevee_poststack_settings(RenderLayerButtonsPanel, Panel):
|
|||
layer_props = layer.engine_overrides['BLENDER_EEVEE']
|
||||
|
||||
col = layout.column()
|
||||
col.template_override_property(layer_props, scene_props, "volumetric_enable")
|
||||
col.template_override_property(layer_props, scene_props, "gtao_enable")
|
||||
col.template_override_property(layer_props, scene_props, "motion_blur_enable")
|
||||
col.template_override_property(layer_props, scene_props, "dof_enable")
|
||||
|
|
|
@ -157,6 +157,7 @@ data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC)
|
|||
data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/volumetric_frag.glsl SRC)
|
||||
|
||||
data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
|
||||
data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC)
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#include "BKE_animsys.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BLI_dynstr.h"
|
||||
|
||||
#include "eevee_private.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
|
@ -45,11 +47,6 @@ typedef struct EEVEE_LightProbeData {
|
|||
short probe_id, shadow_id;
|
||||
} EEVEE_LightProbeData;
|
||||
|
||||
/* TODO Option */
|
||||
#define ENABLE_EFFECT_MOTION_BLUR 1
|
||||
#define ENABLE_EFFECT_BLOOM 1
|
||||
#define ENABLE_EFFECT_DOF 1
|
||||
|
||||
static struct {
|
||||
/* Downsample Depth */
|
||||
struct GPUShader *minmaxz_downlevel_sh;
|
||||
|
@ -70,7 +67,10 @@ static struct {
|
|||
struct GPUShader *dof_scatter_sh;
|
||||
struct GPUShader *dof_resolve_sh;
|
||||
|
||||
struct GPUTexture *minmmaxz_depth_src;
|
||||
/* Volumetric */
|
||||
struct GPUShader *volumetric_upsample_sh;
|
||||
|
||||
struct GPUTexture *depth_src;
|
||||
} e_data = {NULL}; /* Engine data */
|
||||
|
||||
extern char datatoc_effect_minmaxz_frag_glsl[];
|
||||
|
@ -80,6 +80,7 @@ extern char datatoc_effect_dof_vert_glsl[];
|
|||
extern char datatoc_effect_dof_geom_glsl[];
|
||||
extern char datatoc_effect_dof_frag_glsl[];
|
||||
extern char datatoc_tonemap_frag_glsl[];
|
||||
extern char datatoc_volumetric_frag_glsl[];
|
||||
|
||||
static void eevee_motion_blur_camera_get_matrix_at_time(
|
||||
Scene *scene, ARegion *ar, RegionView3D *rv3d, View3D *v3d, Object *camera, float time, float r_mat[4][4])
|
||||
|
@ -151,6 +152,8 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
|
||||
/* Shaders */
|
||||
if (!e_data.motion_blur_sh) {
|
||||
e_data.volumetric_upsample_sh = DRW_shader_create_fullscreen(datatoc_volumetric_frag_glsl, "#define STEP_UPSAMPLE\n");
|
||||
|
||||
e_data.minmaxz_downlevel_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, NULL);
|
||||
e_data.minmaxz_downdepth_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define INPUT_DEPTH\n");
|
||||
e_data.minmaxz_copydepth_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define INPUT_DEPTH\n"
|
||||
|
@ -190,7 +193,6 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
|
||||
int enabled_effects = 0;
|
||||
|
||||
#if ENABLE_EFFECT_MOTION_BLUR
|
||||
if (BKE_collection_engine_property_value_get_bool(props, "motion_blur_enable")) {
|
||||
/* Update Motion Blur Matrices */
|
||||
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
|
||||
|
@ -221,9 +223,7 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_EFFECT_MOTION_BLUR */
|
||||
|
||||
#if ENABLE_EFFECT_BLOOM
|
||||
if (BKE_collection_engine_property_value_get_bool(props, "bloom_enable")) {
|
||||
/* Bloom */
|
||||
int blitsize[2], texsize[2];
|
||||
|
@ -294,9 +294,7 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
|
||||
enabled_effects |= EFFECT_BLOOM;
|
||||
}
|
||||
#endif /* ENABLE_EFFECT_BLOOM */
|
||||
|
||||
#if ENABLE_EFFECT_DOF
|
||||
if (BKE_collection_engine_property_value_get_bool(props, "dof_enable")) {
|
||||
/* Depth Of Field */
|
||||
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
|
||||
|
@ -375,7 +373,6 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
enabled_effects |= EFFECT_DOF;
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_EFFECT_DOF */
|
||||
|
||||
effects->enabled_effects = enabled_effects;
|
||||
|
||||
|
@ -404,6 +401,16 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
(int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
|
||||
&tex, 1);
|
||||
|
||||
if (BKE_collection_engine_property_value_get_bool(props, "volumetric_enable")) {
|
||||
/* MinMax Pyramid */
|
||||
DRWFboTexture tex_vol = {&stl->g_data->volumetric, DRW_TEX_RGBA_16, DRW_TEX_MIPMAP | DRW_TEX_FILTER | DRW_TEX_TEMP};
|
||||
|
||||
DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
|
||||
(int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
|
||||
&tex_vol, 1);
|
||||
|
||||
effects->enabled_effects |= EFFECT_VOLUMETRIC;
|
||||
}
|
||||
}
|
||||
|
||||
static DRWShadingGroup *eevee_create_bloom_pass(const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample)
|
||||
|
@ -424,7 +431,7 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name, EEVEE_EffectsI
|
|||
return grp;
|
||||
}
|
||||
|
||||
void EEVEE_effects_cache_init(EEVEE_Data *vedata)
|
||||
void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
|
||||
{
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_StorageList *stl = vedata->stl;
|
||||
|
@ -434,6 +441,29 @@ void EEVEE_effects_cache_init(EEVEE_Data *vedata)
|
|||
|
||||
struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
|
||||
|
||||
{
|
||||
struct GPUShader *sh = EEVEE_material_world_volume_get(NULL, NULL);
|
||||
psl->volumetric_integrate_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR);
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->volumetric_integrate_ps);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src);
|
||||
DRW_shgroup_uniform_buffer(grp, "shadowCubes", &sldata->shadow_depth_cube_pool);
|
||||
DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
|
||||
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
|
||||
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
|
||||
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
|
||||
DRW_shgroup_uniform_int(grp, "light_count", &sldata->lamps->num_light, 1);
|
||||
DRW_shgroup_uniform_int(grp, "grid_count", &sldata->probes->num_render_grid, 1);
|
||||
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
|
||||
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSMISSION);
|
||||
grp = DRW_shgroup_create(e_data.volumetric_upsample_sh, psl->volumetric_resolve_ps);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src);
|
||||
DRW_shgroup_uniform_buffer(grp, "volumetricBuffer", &stl->g_data->volumetric);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
}
|
||||
|
||||
{
|
||||
psl->minmaxz_downlevel = DRW_pass_create("HiZ Down Level", DRW_STATE_WRITE_COLOR);
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.minmaxz_downlevel_sh, psl->minmaxz_downlevel);
|
||||
|
@ -442,12 +472,12 @@ void EEVEE_effects_cache_init(EEVEE_Data *vedata)
|
|||
|
||||
psl->minmaxz_downdepth = DRW_pass_create("HiZ Down Depth", DRW_STATE_WRITE_COLOR);
|
||||
grp = DRW_shgroup_create(e_data.minmaxz_downdepth_sh, psl->minmaxz_downdepth);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.minmmaxz_depth_src);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
psl->minmaxz_copydepth = DRW_pass_create("HiZ Copy Depth", DRW_STATE_WRITE_COLOR);
|
||||
grp = DRW_shgroup_create(e_data.minmaxz_copydepth_sh, psl->minmaxz_copydepth);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.minmmaxz_depth_src);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
}
|
||||
|
||||
|
@ -574,7 +604,7 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src)
|
|||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_StorageList *stl = vedata->stl;
|
||||
|
||||
e_data.minmmaxz_depth_src = depth_src;
|
||||
e_data.depth_src = depth_src;
|
||||
|
||||
/* Copy depth buffer to minmax texture top level */
|
||||
DRW_framebuffer_texture_attach(fbl->minmaxz_fb, stl->g_data->minmaxz, 0, 0);
|
||||
|
@ -586,6 +616,33 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src)
|
|||
DRW_framebuffer_recursive_downsample(fbl->minmaxz_fb, stl->g_data->minmaxz, 6, &minmax_downsample_cb, vedata);
|
||||
}
|
||||
|
||||
void EEVEE_effects_do_volumetrics(EEVEE_Data *vedata)
|
||||
{
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_StorageList *stl = vedata->stl;
|
||||
EEVEE_EffectsInfo *effects = stl->effects;
|
||||
|
||||
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
|
||||
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
||||
|
||||
e_data.depth_src = dtxl->depth;
|
||||
|
||||
/* Compute volumetric integration at halfres. */
|
||||
DRW_framebuffer_texture_attach(fbl->volumetric_fb, stl->g_data->volumetric, 0, 0);
|
||||
DRW_framebuffer_bind(fbl->volumetric_fb);
|
||||
DRW_draw_pass(psl->volumetric_integrate_ps);
|
||||
|
||||
/* Resolve at fullres */
|
||||
DRW_framebuffer_texture_detach(dtxl->depth);
|
||||
DRW_framebuffer_bind(fbl->main);
|
||||
DRW_draw_pass(psl->volumetric_resolve_ps);
|
||||
|
||||
/* Restore */
|
||||
DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void EEVEE_draw_effects(EEVEE_Data *vedata)
|
||||
{
|
||||
EEVEE_PassList *psl = vedata->psl;
|
||||
|
@ -709,6 +766,8 @@ void EEVEE_draw_effects(EEVEE_Data *vedata)
|
|||
|
||||
void EEVEE_effects_free(void)
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(e_data.volumetric_upsample_sh);
|
||||
|
||||
DRW_SHADER_FREE_SAFE(e_data.minmaxz_downlevel_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.minmaxz_downdepth_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.minmaxz_copydepth_sh);
|
||||
|
|
|
@ -62,7 +62,7 @@ static void EEVEE_engine_init(void *ved)
|
|||
}
|
||||
stl->g_data->background_alpha = 1.0f;
|
||||
|
||||
EEVEE_materials_init();
|
||||
EEVEE_materials_init(stl);
|
||||
EEVEE_lights_init(sldata);
|
||||
EEVEE_lightprobes_init(sldata, vedata);
|
||||
EEVEE_effects_init(vedata);
|
||||
|
@ -76,7 +76,7 @@ static void EEVEE_cache_init(void *vedata)
|
|||
EEVEE_materials_cache_init(vedata);
|
||||
EEVEE_lights_cache_init(sldata, psl);
|
||||
EEVEE_lightprobes_cache_init(sldata, vedata);
|
||||
EEVEE_effects_cache_init(vedata);
|
||||
EEVEE_effects_cache_init(sldata, vedata);
|
||||
}
|
||||
|
||||
static void EEVEE_cache_populate(void *vedata, Object *ob)
|
||||
|
@ -160,6 +160,9 @@ static void EEVEE_draw_scene(void *vedata)
|
|||
EEVEE_draw_default_passes(psl);
|
||||
DRW_draw_pass(psl->material_pass);
|
||||
|
||||
/* Volumetrics */
|
||||
EEVEE_effects_do_volumetrics(vedata);
|
||||
|
||||
/* Post Process */
|
||||
EEVEE_draw_effects(vedata);
|
||||
}
|
||||
|
@ -187,6 +190,8 @@ static void EEVEE_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPr
|
|||
props->type == IDP_GROUP &&
|
||||
props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
|
||||
|
||||
BKE_collection_engine_property_add_bool(props, "volumetric_enable", false);
|
||||
|
||||
BKE_collection_engine_property_add_bool(props, "gtao_enable", false);
|
||||
BKE_collection_engine_property_add_bool(props, "gtao_use_bent_normals", true);
|
||||
BKE_collection_engine_property_add_float(props, "gtao_distance", 0.2f);
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
static struct {
|
||||
char *frag_shader_lib;
|
||||
|
||||
struct GPUShader *default_volume_sh;
|
||||
struct GPUShader *default_prepass_sh;
|
||||
struct GPUShader *default_prepass_clip_sh;
|
||||
struct GPUShader *default_lit[VAR_MAT_MAX];
|
||||
|
@ -99,6 +100,7 @@ extern char datatoc_shadow_vert_glsl[];
|
|||
extern char datatoc_lightprobe_geom_glsl[];
|
||||
extern char datatoc_lightprobe_vert_glsl[];
|
||||
extern char datatoc_background_vert_glsl[];
|
||||
extern char datatoc_volumetric_frag_glsl[];
|
||||
|
||||
extern Material defmaterial;
|
||||
extern GlobalsUboStorage ts;
|
||||
|
@ -167,6 +169,12 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
|
|||
}
|
||||
#endif
|
||||
|
||||
/* XXX TODO define all shared resources in a shared place without duplication */
|
||||
struct GPUTexture *EEVEE_materials_get_util_tex(void)
|
||||
{
|
||||
return e_data.util_tex;
|
||||
}
|
||||
|
||||
static char *eevee_get_defines(int options)
|
||||
{
|
||||
char *str = NULL;
|
||||
|
@ -222,7 +230,7 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData *
|
|||
DRW_shgroup_uniform_buffer(shgrp, "shadowCubes", &sldata->shadow_depth_cube_pool);
|
||||
DRW_shgroup_uniform_buffer(shgrp, "shadowCascades", &sldata->shadow_depth_cascade_pool);
|
||||
if (vedata->stl->effects->use_ao) {
|
||||
DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)e_data.viewvecs, 2);
|
||||
DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)&vedata->stl->g_data->viewvecs, 2);
|
||||
DRW_shgroup_uniform_buffer(shgrp, "minMaxDepthTex", &vedata->stl->g_data->minmaxz);
|
||||
DRW_shgroup_uniform_vec3(shgrp, "aoParameters", &vedata->stl->effects->ao_dist, 1);
|
||||
}
|
||||
|
@ -244,7 +252,7 @@ static void create_default_shader(int options)
|
|||
MEM_freeN(frag_str);
|
||||
}
|
||||
|
||||
void EEVEE_materials_init(void)
|
||||
void EEVEE_materials_init(EEVEE_StorageList *stl)
|
||||
{
|
||||
if (!e_data.frag_shader_lib) {
|
||||
char *frag_str = NULL;
|
||||
|
@ -282,6 +290,16 @@ void EEVEE_materials_init(void)
|
|||
|
||||
MEM_freeN(frag_str);
|
||||
|
||||
ds_frag = BLI_dynstr_new();
|
||||
BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
|
||||
BLI_dynstr_append(ds_frag, datatoc_volumetric_frag_glsl);
|
||||
frag_str = BLI_dynstr_get_cstring(ds_frag);
|
||||
BLI_dynstr_free(ds_frag);
|
||||
|
||||
e_data.default_volume_sh = DRW_shader_create_fullscreen(frag_str, SHADER_DEFINES "#define STEP_INTEGRATE\n");
|
||||
|
||||
MEM_freeN(frag_str);
|
||||
|
||||
/* Textures */
|
||||
const int layers = 3;
|
||||
float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * 64 * 64 * layers, "utils texels");
|
||||
|
@ -338,19 +356,19 @@ void EEVEE_materials_init(void)
|
|||
viewvecs[i][3] = 1.0;
|
||||
}
|
||||
|
||||
copy_v4_v4(e_data.viewvecs[0], viewvecs[0]);
|
||||
copy_v4_v4(e_data.viewvecs[1], viewvecs[1]);
|
||||
copy_v4_v4(stl->g_data->viewvecs[0], viewvecs[0]);
|
||||
copy_v4_v4(stl->g_data->viewvecs[1], viewvecs[1]);
|
||||
|
||||
/* we need to store the differences */
|
||||
e_data.viewvecs[1][0] -= viewvecs[0][0];
|
||||
e_data.viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
|
||||
stl->g_data->viewvecs[1][0] -= viewvecs[0][0];
|
||||
stl->g_data->viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
|
||||
|
||||
/* calculate a depth offset as well */
|
||||
if (!is_persp) {
|
||||
float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
|
||||
mul_m4_v4(invproj, vec_far);
|
||||
mul_v3_fl(vec_far, 1.0f / vec_far[3]);
|
||||
e_data.viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
|
||||
stl->g_data->viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -385,6 +403,11 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor
|
|||
SHADER_DEFINES "#define WORLD_BACKGROUND\n");
|
||||
}
|
||||
|
||||
struct GPUShader *EEVEE_material_world_volume_get(struct Scene *UNUSED(scene), World *UNUSED(wo))
|
||||
{
|
||||
return e_data.default_volume_sh;
|
||||
}
|
||||
|
||||
struct GPUMaterial *EEVEE_material_mesh_get(
|
||||
struct Scene *scene, Material *ma,
|
||||
bool use_ao, bool use_bent_normals)
|
||||
|
@ -762,6 +785,7 @@ void EEVEE_materials_free(void)
|
|||
DRW_SHADER_FREE_SAFE(e_data.default_lit[i]);
|
||||
}
|
||||
MEM_SAFE_FREE(e_data.frag_shader_lib);
|
||||
DRW_SHADER_FREE_SAFE(e_data.default_volume_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.default_background);
|
||||
|
|
|
@ -93,6 +93,8 @@ typedef struct EEVEE_PassList {
|
|||
struct DRWPass *minmaxz_downlevel;
|
||||
struct DRWPass *minmaxz_downdepth;
|
||||
struct DRWPass *minmaxz_copydepth;
|
||||
struct DRWPass *volumetric_integrate_ps;
|
||||
struct DRWPass *volumetric_resolve_ps;
|
||||
|
||||
struct DRWPass *depth_pass;
|
||||
struct DRWPass *depth_pass_cull;
|
||||
|
@ -106,17 +108,18 @@ typedef struct EEVEE_PassList {
|
|||
typedef struct EEVEE_FramebufferList {
|
||||
/* Effects */
|
||||
struct GPUFrameBuffer *minmaxz_fb;
|
||||
struct GPUFrameBuffer *effect_fb; /* HDR */
|
||||
struct GPUFrameBuffer *bloom_blit_fb; /* HDR */
|
||||
struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP]; /* HDR */
|
||||
struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP-1]; /* HDR */
|
||||
struct GPUFrameBuffer *effect_fb;
|
||||
struct GPUFrameBuffer *bloom_blit_fb;
|
||||
struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP];
|
||||
struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP-1];
|
||||
struct GPUFrameBuffer *dof_down_fb;
|
||||
struct GPUFrameBuffer *dof_scatter_far_fb;
|
||||
struct GPUFrameBuffer *dof_scatter_near_fb;
|
||||
struct GPUFrameBuffer *volumetric_fb;
|
||||
|
||||
struct GPUFrameBuffer *planarref_fb;
|
||||
|
||||
struct GPUFrameBuffer *main; /* HDR */
|
||||
struct GPUFrameBuffer *main;
|
||||
} EEVEE_FramebufferList;
|
||||
|
||||
typedef struct EEVEE_TextureList {
|
||||
|
@ -312,6 +315,7 @@ enum {
|
|||
EFFECT_MOTION_BLUR = (1 << 0),
|
||||
EFFECT_BLOOM = (1 << 1),
|
||||
EFFECT_DOF = (1 << 2),
|
||||
EFFECT_VOLUMETRIC = (1 << 3),
|
||||
};
|
||||
|
||||
/* ************** SCENE LAYER DATA ************** */
|
||||
|
@ -399,7 +403,9 @@ typedef struct EEVEE_PrivateData {
|
|||
struct GHash *material_hash;
|
||||
struct GHash *hair_material_hash;
|
||||
struct GPUTexture *minmaxz;
|
||||
struct GPUTexture *volumetric;
|
||||
float background_alpha; /* TODO find a better place for this. */
|
||||
float viewvecs[2][4];
|
||||
/* For planar probes */
|
||||
float texel_size[2];
|
||||
} EEVEE_PrivateData; /* Transient data */
|
||||
|
@ -411,12 +417,14 @@ EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob);
|
|||
EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob);
|
||||
|
||||
/* eevee_materials.c */
|
||||
void EEVEE_materials_init(void);
|
||||
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
|
||||
void EEVEE_materials_init(EEVEE_StorageList *stl);
|
||||
void EEVEE_materials_cache_init(EEVEE_Data *vedata);
|
||||
void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sldata, Object *ob, struct Gwn_Batch *geom);
|
||||
void EEVEE_materials_cache_finish(EEVEE_Data *vedata);
|
||||
struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
|
||||
struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
|
||||
struct GPUShader *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
|
||||
struct GPUMaterial *EEVEE_material_mesh_lightprobe_get(struct Scene *scene, Material *ma);
|
||||
struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene, Material *ma, bool use_ao, bool use_bent_normals);
|
||||
struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, bool use_ao, bool use_bent_normals);
|
||||
|
@ -443,8 +451,9 @@ void EEVEE_lightprobes_free(void);
|
|||
|
||||
/* eevee_effects.c */
|
||||
void EEVEE_effects_init(EEVEE_Data *vedata);
|
||||
void EEVEE_effects_cache_init(EEVEE_Data *vedata);
|
||||
void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata);
|
||||
void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src);
|
||||
void EEVEE_effects_do_volumetrics(EEVEE_Data *vedata);
|
||||
void EEVEE_draw_effects(EEVEE_Data *vedata);
|
||||
void EEVEE_effects_free(void);
|
||||
|
||||
|
|
|
@ -225,12 +225,21 @@ float buffer_depth(bool is_persp, float z, float zf, float zn)
|
|||
}
|
||||
}
|
||||
|
||||
vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
|
||||
float get_view_z_from_depth(float depth)
|
||||
{
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
float d = 2.0 * depth - 1.0;
|
||||
float zview = -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
|
||||
return (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz) * zview;
|
||||
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
|
||||
}
|
||||
else {
|
||||
return viewvecs[0].z + depth * viewvecs[1].z;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
|
||||
{
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
return (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz) * get_view_z_from_depth(depth);
|
||||
}
|
||||
else {
|
||||
return viewvecs[0].xyz + vec3(uvcoords, depth) * viewvecs[1].xyz;
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
|
||||
out vec4 FragColor;
|
||||
|
||||
#ifdef STEP_INTEGRATE
|
||||
|
||||
uniform sampler2D depthFull;
|
||||
|
||||
float find_next_step(float near, float far, float noise, int iter, int iter_count)
|
||||
{
|
||||
const float lambda = 0.8f; /* TODO : Parameter */
|
||||
|
||||
float progress = (float(iter) + noise) / float(iter_count);
|
||||
|
||||
float linear_split = mix(near, far, progress);
|
||||
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
float exp_split = near * pow(far / near, progress);
|
||||
return mix(linear_split, exp_split, lambda);
|
||||
}
|
||||
else {
|
||||
return linear_split;
|
||||
}
|
||||
}
|
||||
|
||||
void participating_media_properties(vec3 wpos, out vec3 absorption, out vec3 scattering, out float anisotropy)
|
||||
{
|
||||
/* TODO Call nodetree from here. */
|
||||
absorption = vec3(0.00);
|
||||
scattering = vec3(1.0) * step(-1.0, -wpos.z);
|
||||
|
||||
anisotropy = -0.8;
|
||||
}
|
||||
|
||||
float phase_function_isotropic()
|
||||
{
|
||||
return 1.0 / (4.0 * M_PI);
|
||||
}
|
||||
|
||||
float phase_function(vec3 v, vec3 l, float g)
|
||||
{
|
||||
#if 0
|
||||
/* Henyey-Greenstein */
|
||||
float cos_theta = dot(v, l);
|
||||
float sqr_g = g * g;
|
||||
return (1- sqr_g) / (4.0 * M_PI * pow(1 + sqr_g - 2 * g * cos_theta, 3.0 / 2.0));
|
||||
#else
|
||||
return phase_function_isotropic();
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 light_volume(LightData ld, vec4 l_vector, vec3 l_col)
|
||||
{
|
||||
float dist = max(1e-4, abs(l_vector.w - ld.l_radius));
|
||||
return l_col * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI) / (dist * dist);
|
||||
}
|
||||
|
||||
/* Based on Frosbite Unified Volumetric.
|
||||
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
|
||||
void main()
|
||||
{
|
||||
vec2 uv = (gl_FragCoord.xy * 2.0) / ivec2(textureSize(depthFull, 0));
|
||||
float scene_depth = texelFetch(depthFull, ivec2(gl_FragCoord.xy) * 2, 0).r; /* use the same depth as in the upsample step */
|
||||
vec3 vpos = get_view_space_from_depth(uv, scene_depth);
|
||||
vec3 wpos = (ViewMatrixInverse * vec4(vpos, 1.0)).xyz;
|
||||
vec3 wdir = (ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - wpos) : cameraForward;
|
||||
|
||||
/* Note: this is NOT the distance to the camera. */
|
||||
float max_z = vpos.z;
|
||||
|
||||
/* project ray to clip plane so we can integrate in even steps in clip space. */
|
||||
vec3 wdir_proj = wdir / abs(dot(cameraForward, wdir));
|
||||
float wlen = length(wdir_proj);
|
||||
|
||||
/* Transmittance: How much light can get through. */
|
||||
vec3 transmittance = vec3(1.0);
|
||||
|
||||
/* Scattering: Light that has been accumulated from scattered light sources. */
|
||||
vec3 scattering = vec3(0.0);
|
||||
|
||||
vec3 ray_origin = (ProjectionMatrix[3][3] == 0.0)
|
||||
? cameraPos
|
||||
: (ViewMatrixInverse * vec4(get_view_space_from_depth(uv, 0.5), 1.0)).xyz;
|
||||
|
||||
/* Start from near clip. TODO make start distance an option. */
|
||||
float rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).r;
|
||||
/* Less noisy but noticeable patterns, could work better with temporal AA. */
|
||||
// float rand = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
|
||||
float near = get_view_z_from_depth(0.0);
|
||||
float far = get_view_z_from_depth(1.0);
|
||||
float dist = near;
|
||||
for (int i = 1; i < 64; ++i) {
|
||||
float new_dist = find_next_step(near, far, rand, i, 64);
|
||||
float step = dist - new_dist; /* Marching step */
|
||||
dist = new_dist;
|
||||
|
||||
vec3 ray_wpos = ray_origin + wdir_proj * dist;
|
||||
|
||||
/* Volume Sample */
|
||||
vec3 s_absorption, s_scattering; /* mu_a, mu_s */
|
||||
float s_anisotropy;
|
||||
participating_media_properties(ray_wpos, s_absorption, s_scattering, s_anisotropy);
|
||||
|
||||
vec3 s_extinction = max(vec3(1e-8), s_absorption + s_scattering); /* mu_t */
|
||||
|
||||
/* Evaluate each light */
|
||||
vec3 Lscat = vec3(0.0);
|
||||
|
||||
#if 1 /* Lights */
|
||||
for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
|
||||
LightData ld = lights_data[i];
|
||||
|
||||
vec4 l_vector;
|
||||
l_vector.xyz = ld.l_position - ray_wpos;
|
||||
l_vector.w = length(l_vector.xyz);
|
||||
|
||||
#if 1 /* Shadows & Spots */
|
||||
float Vis = light_visibility(ld, ray_wpos, l_vector);
|
||||
#else
|
||||
float Vis = 1.0;
|
||||
#endif
|
||||
vec3 Li = light_volume(ld, l_vector, ld.l_color);
|
||||
|
||||
Lscat += Li * Vis * s_scattering * phase_function(-wdir, l_vector.xyz / l_vector.w, s_anisotropy);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Environment : Average color. */
|
||||
IrradianceData ir_data = load_irradiance_cell(0, vec3(1.0));
|
||||
Lscat += (ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2]) * 0.333333 * s_scattering * phase_function_isotropic();
|
||||
|
||||
ir_data = load_irradiance_cell(0, vec3(-1.0));
|
||||
Lscat += (ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2]) * 0.333333 * s_scattering * phase_function_isotropic();
|
||||
|
||||
/* Evaluate Scattering */
|
||||
float s_len = wlen * step;
|
||||
vec3 Tr = exp(-s_extinction * s_len);
|
||||
|
||||
/* integrate along the current step segment */
|
||||
Lscat = (Lscat - Lscat * Tr) / s_extinction;
|
||||
/* accumulate and also take into account the transmittance from previous steps */
|
||||
scattering += transmittance * Lscat;
|
||||
|
||||
/* Evaluate transmittance to view independantely */
|
||||
transmittance *= Tr;
|
||||
|
||||
if (dist < max_z)
|
||||
break;
|
||||
}
|
||||
|
||||
float mono_transmittance = dot(transmittance, vec3(1.0)) / 3.0;
|
||||
|
||||
FragColor = vec4(scattering, mono_transmittance);
|
||||
}
|
||||
|
||||
#else /* STEP_UPSAMPLE */
|
||||
|
||||
uniform sampler2D depthFull;
|
||||
uniform sampler2D volumetricBuffer;
|
||||
|
||||
uniform mat4 ProjectionMatrix;
|
||||
|
||||
vec4 get_view_z_from_depth(vec4 depth)
|
||||
{
|
||||
vec4 d = 2.0 * depth - 1.0;
|
||||
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
#if 0 /* 2 x 2 with bilinear */
|
||||
|
||||
const vec4 bilinear_weights[4] = vec4[4](
|
||||
vec4(9.0 / 16.0, 3.0 / 16.0, 3.0 / 16.0, 1.0 / 16.0 ),
|
||||
vec4(3.0 / 16.0, 9.0 / 16.0, 1.0 / 16.0, 3.0 / 16.0 ),
|
||||
vec4(3.0 / 16.0, 1.0 / 16.0, 9.0 / 16.0, 3.0 / 16.0 ),
|
||||
vec4(1.0 / 16.0, 3.0 / 16.0, 3.0 / 16.0, 9.0 / 16.0 )
|
||||
);
|
||||
|
||||
/* Depth aware upsampling */
|
||||
vec4 depths;
|
||||
ivec2 texel_co = ivec2(gl_FragCoord.xy * 0.5) * 2;
|
||||
|
||||
/* TODO use textureGather on glsl 4.0 */
|
||||
depths.x = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 0)).r;
|
||||
depths.y = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 0)).r;
|
||||
depths.z = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 2)).r;
|
||||
depths.w = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 2)).r;
|
||||
|
||||
vec4 target_depth = texelFetch(depthFull, ivec2(gl_FragCoord.xy), 0).rrrr;
|
||||
|
||||
depths = get_view_z_from_depth(depths);
|
||||
target_depth = get_view_z_from_depth(target_depth);
|
||||
|
||||
vec4 weights = 1.0 - step(0.05, abs(depths - target_depth));
|
||||
|
||||
/* Index in range [0-3] */
|
||||
int pix_id = int(dot(mod(ivec2(gl_FragCoord.xy), 2), ivec2(1, 2)));
|
||||
weights *= bilinear_weights[pix_id];
|
||||
|
||||
float weight_sum = dot(weights, vec4(1.0));
|
||||
|
||||
if (weight_sum == 0.0) {
|
||||
weights.x = 1.0;
|
||||
weight_sum = 1.0;
|
||||
}
|
||||
|
||||
texel_co = ivec2(gl_FragCoord.xy * 0.5);
|
||||
|
||||
vec4 integration_result;
|
||||
integration_result = texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 0)) * weights.x;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 0)) * weights.y;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 1)) * weights.z;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 1)) * weights.w;
|
||||
|
||||
#else /* 4 x 4 */
|
||||
|
||||
/* Depth aware upsampling */
|
||||
vec4 depths[4];
|
||||
ivec2 texel_co = ivec2(gl_FragCoord.xy * 0.5) * 2;
|
||||
|
||||
/* TODO use textureGather on glsl 4.0 */
|
||||
texel_co += ivec2(-2, -2);
|
||||
depths[0].x = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 0)).r;
|
||||
depths[0].y = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 0)).r;
|
||||
depths[0].z = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 2)).r;
|
||||
depths[0].w = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 2)).r;
|
||||
|
||||
texel_co += ivec2(4, 0);
|
||||
depths[1].x = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 0)).r;
|
||||
depths[1].y = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 0)).r;
|
||||
depths[1].z = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 2)).r;
|
||||
depths[1].w = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 2)).r;
|
||||
|
||||
texel_co += ivec2(-4, 4);
|
||||
depths[2].x = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 0)).r;
|
||||
depths[2].y = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 0)).r;
|
||||
depths[2].z = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 2)).r;
|
||||
depths[2].w = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 2)).r;
|
||||
|
||||
texel_co += ivec2(4, 0);
|
||||
depths[3].x = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 0)).r;
|
||||
depths[3].y = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 0)).r;
|
||||
depths[3].z = texelFetchOffset(depthFull, texel_co, 0, ivec2(0, 2)).r;
|
||||
depths[3].w = texelFetchOffset(depthFull, texel_co, 0, ivec2(2, 2)).r;
|
||||
|
||||
vec4 target_depth = texelFetch(depthFull, ivec2(gl_FragCoord.xy), 0).rrrr;
|
||||
|
||||
depths[0] = get_view_z_from_depth(depths[0]);
|
||||
depths[1] = get_view_z_from_depth(depths[1]);
|
||||
depths[2] = get_view_z_from_depth(depths[2]);
|
||||
depths[3] = get_view_z_from_depth(depths[3]);
|
||||
|
||||
target_depth = get_view_z_from_depth(target_depth);
|
||||
|
||||
vec4 weights[4];
|
||||
weights[0] = 1.0 - step(0.05, abs(depths[0] - target_depth));
|
||||
weights[1] = 1.0 - step(0.05, abs(depths[1] - target_depth));
|
||||
weights[2] = 1.0 - step(0.05, abs(depths[2] - target_depth));
|
||||
weights[3] = 1.0 - step(0.05, abs(depths[3] - target_depth));
|
||||
|
||||
float weight_sum;
|
||||
weight_sum = dot(weights[0], vec4(1.0));
|
||||
weight_sum += dot(weights[1], vec4(1.0));
|
||||
weight_sum += dot(weights[2], vec4(1.0));
|
||||
weight_sum += dot(weights[3], vec4(1.0));
|
||||
|
||||
if (weight_sum == 0.0) {
|
||||
weights[0].x = 1.0;
|
||||
weight_sum = 1.0;
|
||||
}
|
||||
|
||||
texel_co = ivec2(gl_FragCoord.xy * 0.5);
|
||||
|
||||
vec4 integration_result;
|
||||
|
||||
texel_co += ivec2(-1, -1);
|
||||
integration_result = texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 0)) * weights[0].x;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 0)) * weights[0].y;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 1)) * weights[0].z;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 1)) * weights[0].w;
|
||||
|
||||
texel_co += ivec2(2, 0);
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 0)) * weights[1].x;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 0)) * weights[1].y;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 1)) * weights[1].z;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 1)) * weights[1].w;
|
||||
|
||||
texel_co += ivec2(-2, 2);
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 0)) * weights[2].x;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 0)) * weights[2].y;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 1)) * weights[2].z;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 1)) * weights[2].w;
|
||||
|
||||
texel_co += ivec2(2, 0);
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 0)) * weights[3].x;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 0)) * weights[3].y;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(0, 1)) * weights[3].z;
|
||||
integration_result += texelFetchOffset(volumetricBuffer, texel_co, 0, ivec2(1, 1)) * weights[3].w;
|
||||
#endif
|
||||
|
||||
FragColor = integration_result / weight_sum;
|
||||
}
|
||||
#endif
|
|
@ -2612,6 +2612,7 @@ RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(bloom_intensity)
|
|||
RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(motion_blur_enable)
|
||||
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(motion_blur_samples)
|
||||
RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(motion_blur_shutter)
|
||||
RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_enable)
|
||||
|
||||
/* object engine */
|
||||
RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_wire)
|
||||
|
@ -6166,6 +6167,14 @@ static void rna_def_scene_layer_engine_settings_eevee(BlenderRNA *brna)
|
|||
|
||||
/* see RNA_LAYER_ENGINE_GET_SET macro */
|
||||
|
||||
/* Volumetrics */
|
||||
prop = RNA_def_property(srna, "volumetric_enable", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_enable_get",
|
||||
"rna_LayerEngineSettings_Eevee_volumetric_enable_set");
|
||||
RNA_def_property_ui_text(prop, "Volumetrics", "Enable scattering and absorbance of volumetric material");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
|
||||
|
||||
/* Ambient Occlusion */
|
||||
prop = RNA_def_property(srna, "gtao_enable", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_enable_get",
|
||||
|
|
Loading…
Reference in New Issue