diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_engine.c | 2 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 3 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_private.h | 4 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_subsurface.c | 21 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl | 21 | ||||
-rw-r--r-- | source/blender/gpu/GPU_material.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 51 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_layer.c | 18 |
8 files changed, 70 insertions, 52 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 217dc2f0227..4ca59aaa39e 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -323,6 +323,8 @@ static void EEVEE_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPr BKE_collection_engine_property_add_int(props, "taa_samples", 8); BKE_collection_engine_property_add_bool(props, "sss_enable", false); + BKE_collection_engine_property_add_int(props, "sss_samples", 7); + BKE_collection_engine_property_add_float(props, "sss_jitter_threshold", 0.3f); BKE_collection_engine_property_add_bool(props, "ssr_enable", false); BKE_collection_engine_property_add_bool(props, "ssr_refraction", false); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index f7985fb7ddf..23057bd91c0 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -1006,7 +1006,8 @@ static void material_opaque( add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false); if (use_sss) { - struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat); + struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat, + stl->effects->sss_sample_count); if (sss_profile) { DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1); EEVEE_subsurface_add_pass(vedata, e_data.sss_count + 1, sss_profile); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 43540762a52..b1ed108bad0 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -429,6 +429,10 @@ typedef struct EEVEE_EffectsInfo { int enabled_effects; bool swap_double_buffer; + /* SSSS */ + int sss_sample_count; + float sss_jitter_threshold; + /* Volumetrics */ bool use_volumetrics; int volume_current_sample; diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index b2f3d1fee48..2784125ca58 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -19,7 +19,7 @@ * */ -/* Screen space reflections and refractions techniques. +/* Screen space subsurface scattering technique. */ /** \file eevee_subsurface.c @@ -33,16 +33,7 @@ #include "eevee_private.h" #include "GPU_texture.h" -/* SSR shader variations */ -enum { - SSR_SAMPLES = (1 << 0) | (1 << 1), - SSR_RESOLVE = (1 << 2), - SSR_FULL_TRACE = (1 << 3), - SSR_MAX_SHADER = (1 << 4), -}; - static struct { - /* Screen Space SubSurfaceScattering */ struct GPUShader *sss_sh[2]; } e_data = {NULL}; /* Engine data */ @@ -56,6 +47,8 @@ static void eevee_create_shader_subsurface(void) int EEVEE_subsurface_init(EEVEE_SceneLayerData *UNUSED(sldata), EEVEE_Data *vedata) { + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; const float *viewport_size = DRW_viewport_size_get(); @@ -65,6 +58,8 @@ int EEVEE_subsurface_init(EEVEE_SceneLayerData *UNUSED(sldata), EEVEE_Data *veda IDProperty *props = BKE_scene_layer_engine_evaluated_get(scene_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) { + effects->sss_sample_count = 1 + BKE_collection_engine_property_value_get_int(props, "sss_samples") * 2; + effects->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold"); /* Shaders */ if (!e_data.sss_sh[0]) { @@ -119,6 +114,8 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); EEVEE_TextureList *txl = vedata->txl; EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps); @@ -127,6 +124,8 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_data); DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); + DRW_shgroup_uniform_int(grp, "sampleCount", &effects->sss_sample_count, 1); + DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1); DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call_add(grp, quad, NULL); @@ -136,6 +135,8 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur); DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); + DRW_shgroup_uniform_int(grp, "sampleCount", &effects->sss_sample_count, 1); + DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1); DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call_add(grp, quad, NULL); } diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl index 5cc47796ec0..9ee713ab483 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -1,12 +1,14 @@ /* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */ -#define SSS_SAMPLES 25 +#define MAX_SSS_SAMPLES 65 layout(std140) uniform sssProfile { - vec4 kernel[SSS_SAMPLES]; + vec4 kernel[MAX_SSS_SAMPLES]; vec4 radii_max_radius; }; +uniform int sampleCount; +uniform float jitterThreshold; uniform sampler2D depthBuffer; uniform sampler2D sssData; uniform sampler2DArray utilTex; @@ -27,16 +29,6 @@ float get_view_z_from_depth(float depth) } } -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; - } -} - #define LUT_SIZE 64 #define M_PI_2 1.5707963267948966 /* pi/2 */ #define M_2PI 6.2831853071795865 /* 2*pi */ @@ -67,9 +59,8 @@ void main(void) /* Center sample */ vec3 accum = sss_data.rgb * kernel[0].rgb; - for (int i = 1; i < SSS_SAMPLES; i++) { - /* Rotate samples that are near the kernel center. */ - vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > 0.3) ? dir : dir_rand); + for (int i = 1; i < sampleCount && i < MAX_SSS_SAMPLES; i++) { + vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > jitterThreshold) ? dir : dir_rand); vec3 color = texture(sssData, sample_uv).rgb; float sample_depth = texture(depthBuffer, sample_uv).r; sample_depth = get_view_z_from_depth(sample_depth); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 039adc68e6d..4b9f3c1d519 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -236,7 +236,7 @@ GPUBuiltin GPU_get_material_builtins(GPUMaterial *material); GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); void GPU_material_sss_profile_create(GPUMaterial *material, float *radii); -struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material); +struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material, int sample_ct); /* High level functions to create and use GPU materials */ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 1304cfc28a0..a405991002d 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -144,6 +144,7 @@ struct GPUMaterial { GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */ GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */ float *sss_radii; /* UBO containing SSS profile. */ + int sss_samples; bool sss_dirty; }; @@ -485,7 +486,7 @@ void GPU_material_uniform_buffer_tag_dirty(ListBase *gpumaterials) /* Eevee Subsurface scattering. */ /* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */ -#define SSS_SAMPLES 25 +#define SSS_SAMPLES 65 #define SSS_EXPONENT 2.0f /* Importance sampling exponent */ typedef struct GPUSssKernelData { @@ -493,10 +494,10 @@ typedef struct GPUSssKernelData { float radii_n[3], max_radius; } GPUSssKernelData; -static void sss_calculate_offsets(GPUSssKernelData *kd) +static void sss_calculate_offsets(GPUSssKernelData *kd, int count) { - float step = 2.0f / (float)(SSS_SAMPLES - 1); - for (int i = 0; i < SSS_SAMPLES; i++) { + float step = 2.0f / (float)(count - 1); + for (int i = 0; i < count; i++) { float o = ((float)i) * step - 1.0f; float sign = (o < 0.0f) ? -1.0f : 1.0f; float ofs = sign * fabsf(powf(o, SSS_EXPONENT)); @@ -543,7 +544,7 @@ static float gaussian_integral(float x0, float x1) { return gaussian_primitive(x0) - gaussian_primitive(x1); } -static void compute_sss_kernel(GPUSssKernelData *kd, float *radii) +static void compute_sss_kernel(GPUSssKernelData *kd, float *radii, int sample_ct) { /* Normalize size */ copy_v3_v3(kd->radii_n, radii); @@ -551,7 +552,7 @@ static void compute_sss_kernel(GPUSssKernelData *kd, float *radii) mul_v3_fl(kd->radii_n, 1.0f / kd->max_radius); /* Compute samples locations on the 1d kernel */ - sss_calculate_offsets(kd); + sss_calculate_offsets(kd, sample_ct); #if 0 /* Maybe used for other distributions */ /* Calculate areas (using importance-sampling) */ @@ -563,7 +564,7 @@ static void compute_sss_kernel(GPUSssKernelData *kd, float *radii) float sum[3] = {0.0f, 0.0f, 0.0f}; /* Compute interpolated weights */ - for (int i = 0; i < SSS_SAMPLES; i++) { + for (int i = 0; i < sample_ct; i++) { float x0, x1; if (i == 0) { @@ -573,8 +574,8 @@ static void compute_sss_kernel(GPUSssKernelData *kd, float *radii) x0 = (kd->kernel[i - 1][3] + kd->kernel[i][3]) / 2.0f; } - if (i == SSS_SAMPLES - 1) { - x1 = kd->kernel[SSS_SAMPLES - 1][3] + abs(kd->kernel[SSS_SAMPLES - 2][3] - kd->kernel[SSS_SAMPLES - 1][3]) / 2.0f; + if (i == sample_ct - 1) { + x1 = kd->kernel[sample_ct - 1][3] + abs(kd->kernel[sample_ct - 2][3] - kd->kernel[sample_ct - 1][3]) / 2.0f; } else { x1 = (kd->kernel[i][3] + kd->kernel[i + 1][3]) / 2.0f; @@ -590,7 +591,7 @@ static void compute_sss_kernel(GPUSssKernelData *kd, float *radii) } /* Normalize */ - for (int i = 0; i < SSS_SAMPLES; i++) { + for (int i = 0; i < sample_ct; i++) { kd->kernel[i][0] /= sum[0]; kd->kernel[i][1] /= sum[1]; kd->kernel[i][2] /= sum[2]; @@ -598,8 +599,8 @@ static void compute_sss_kernel(GPUSssKernelData *kd, float *radii) /* Put center sample at the start of the array (to sample first) */ float tmpv[4]; - copy_v4_v4(tmpv, kd->kernel[SSS_SAMPLES / 2]); - for (int i = SSS_SAMPLES / 2; i > 0; i--) { + copy_v4_v4(tmpv, kd->kernel[sample_ct / 2]); + for (int i = sample_ct / 2; i > 0; i--) { copy_v4_v4(kd->kernel[i], kd->kernel[i - 1]); } copy_v4_v4(kd->kernel[0], tmpv); @@ -616,24 +617,24 @@ void GPU_material_sss_profile_create(GPUMaterial *material, float *radii) } } -static void GPU_material_sss_profile_update(GPUMaterial *material) +#undef SSS_EXPONENT +#undef SSS_SAMPLES + +struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material, int sample_ct) { - GPUSssKernelData kd; + if (material->sss_radii == NULL) + return NULL; - compute_sss_kernel(&kd, material->sss_radii); + if (material->sss_dirty || (material->sss_samples != sample_ct)) { + GPUSssKernelData kd; - /* Update / Create UBO */ - GPU_uniformbuffer_update(material->sss_profile, &kd); + compute_sss_kernel(&kd, material->sss_radii, sample_ct); - material->sss_dirty = false; -} -#undef SSS_EXPONENT -#undef SSS_SAMPLES + /* Update / Create UBO */ + GPU_uniformbuffer_update(material->sss_profile, &kd); -struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material) -{ - if (material->sss_dirty) { - GPU_material_sss_profile_update(material); + material->sss_samples = sample_ct; + material->sss_dirty = false; } return material->sss_profile; } diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index ec2ff5f1741..b5f031ccaaa 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -368,6 +368,8 @@ RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_shadows) RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(volumetric_shadow_samples) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_colored_transmittance) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(sss_enable) +RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(sss_samples) +RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(sss_jitter_threshold) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_refraction) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_enable) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_halfres) @@ -1204,6 +1206,22 @@ static void rna_def_scene_layer_engine_settings_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update"); + prop = RNA_def_property(srna, "sss_samples", PROP_INT, PROP_NONE); + RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_sss_samples_get", + "rna_LayerEngineSettings_Eevee_sss_samples_set", NULL); + RNA_def_property_ui_text(prop, "Samples", "Number of samples to compute the scattering effect"); + RNA_def_property_range(prop, 1, 32); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update"); + + prop = RNA_def_property(srna, "sss_jitter_threshold", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_sss_jitter_threshold_get", + "rna_LayerEngineSettings_Eevee_sss_jitter_threshold_set", NULL); + RNA_def_property_ui_text(prop, "Jitter Threshold", "Rotate samples that are below this threshold"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update"); + /* Screen Space Reflection */ prop = RNA_def_property(srna, "ssr_enable", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_enable_get", |