EEVEE-Next: Move the transmittance LUT to the Utility Texture #111535

Merged
Miguel Pozo merged 1 commits from pragma37/blender:pull-eevee-next-transmittance-to-utils into main 2023-08-28 21:01:15 +02:00
12 changed files with 52 additions and 56 deletions

View File

@ -130,11 +130,10 @@
/* Only during surface shading (forward and deferred eval). */
#define SHADOW_TILEMAPS_TEX_SLOT 4
#define SHADOW_ATLAS_TEX_SLOT 5
#define SSS_TRANSMITTANCE_TEX_SLOT 6
#define IRRADIANCE_ATLAS_TEX_SLOT 7
#define REFLECTION_PROBE_TEX_SLOT 8
#define VOLUME_SCATTERING_TEX_SLOT 9
#define VOLUME_TRANSMITTANCE_TEX_SLOT 10
#define IRRADIANCE_ATLAS_TEX_SLOT 6
#define REFLECTION_PROBE_TEX_SLOT 7
#define VOLUME_SCATTERING_TEX_SLOT 8
#define VOLUME_TRANSMITTANCE_TEX_SLOT 9
/* Images. */
#define RBUFS_COLOR_SLOT 0

View File

@ -223,7 +223,6 @@ void ForwardPipeline::sync()
opaque_ps_.bind_image(RBUFS_CRYPTOMATTE_SLOT, &inst_.render_buffers.cryptomatte_tx);
/* Textures. */
opaque_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
opaque_ps_.bind_texture(SSS_TRANSMITTANCE_TEX_SLOT, inst_.subsurface.transmittance_tx_get());
/* Uniform Buffer. */
opaque_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
@ -254,7 +253,6 @@ void ForwardPipeline::sync()
/* Textures. */
sub.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
sub.bind_texture(SSS_TRANSMITTANCE_TEX_SLOT, inst_.subsurface.transmittance_tx_get());
/* Uniform Buffer. */
sub.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
@ -457,8 +455,6 @@ void DeferredLayer::end_sync()
eval_light_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
eval_light_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
eval_light_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
eval_light_ps_.bind_texture(SSS_TRANSMITTANCE_TEX_SLOT,
inst_.subsurface.transmittance_tx_get());
eval_light_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
inst_.lights.bind_resources(&eval_light_ps_);
@ -732,8 +728,6 @@ void DeferredProbeLayer::end_sync()
eval_light_ps_.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
eval_light_ps_.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
eval_light_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
eval_light_ps_.bind_texture(SSS_TRANSMITTANCE_TEX_SLOT,
inst_.subsurface.transmittance_tx_get());
eval_light_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data);
inst_.lights.bind_resources(&eval_light_ps_);

View File

@ -18,6 +18,8 @@
/* TODO(fclem): Move it to GPU/DRAW. */
#include "../eevee/eevee_lut.h"
#include "eevee_subsurface.hh"
namespace blender::eevee {
class Instance;
@ -355,7 +357,7 @@ class UtilityTexture : public Texture {
static constexpr int lut_size = UTIL_TEX_SIZE;
static constexpr int lut_size_sqr = lut_size * lut_size;
static constexpr int layer_count = 4 + UTIL_BTDF_LAYER_COUNT;
static constexpr int layer_count = UTIL_BTDF_LAYER + 1 + UTIL_BTDF_LAYER_COUNT;
public:
UtilityTexture()
@ -380,6 +382,18 @@ class UtilityTexture : public Texture {
Layer &layer = data[UTIL_BLUE_NOISE_LAYER];
memcpy(layer.data, blue_noise, sizeof(layer));
}
{
Layer &layer = data[UTIL_SSS_TRANSMITTANCE_PROFILE_LAYER];
const Vector<float> &transmittance_profile = SubsurfaceModule::transmittance_profile();
BLI_assert(transmittance_profile.size() == UTIL_TEX_SIZE);
/* Repeatedly stored on every row for correct interpolation. */
for (auto y : IndexRange(UTIL_TEX_SIZE)) {
for (auto x : IndexRange(UTIL_TEX_SIZE)) {
/* Only the first channel is used. */
layer.data[y * UTIL_TEX_SIZE + x][0] = transmittance_profile[x];
}
}
}
{
Layer &layer = data[UTIL_LTC_MAT_LAYER];
memcpy(layer.data, ltc_mat_ggx, sizeof(layer));
@ -402,7 +416,7 @@ class UtilityTexture : public Texture {
}
{
for (auto layer_id : IndexRange(16)) {
Layer &layer = data[3 + layer_id];
Layer &layer = data[UTIL_BTDF_LAYER + layer_id];
for (auto i : IndexRange(lut_size_sqr)) {
layer.data[i][0] = btdf_ggx_lut[layer_id][i * 2 + 0];
layer.data[i][1] = btdf_ggx_lut[layer_id][i * 2 + 1];

View File

@ -339,7 +339,7 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
}
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_SUBSURFACE) && pipeline_type == MAT_PIPE_FORWARD) {
info.additional_info("eevee_transmittance_data");
info.define("SSS_TRANSMITTANCE");
}
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_BARYCENTRIC)) {

View File

@ -1240,12 +1240,13 @@ BLI_STATIC_ASSERT_ALIGN(ReflectionProbeData, 16)
#define UTIL_TEX_UV_BIAS (0.5f / UTIL_TEX_SIZE)
#define UTIL_BLUE_NOISE_LAYER 0
#define UTIL_LTC_MAT_LAYER 1
#define UTIL_LTC_MAG_LAYER 2
#define UTIL_BSDF_LAYER 2
#define UTIL_BTDF_LAYER 3
#define UTIL_DISK_INTEGRAL_LAYER 3
#define UTIL_DISK_INTEGRAL_COMP 2
#define UTIL_SSS_TRANSMITTANCE_PROFILE_LAYER 1
#define UTIL_LTC_MAT_LAYER 2
#define UTIL_LTC_MAG_LAYER 3
#define UTIL_BSDF_LAYER 3
#define UTIL_BTDF_LAYER 4
#define UTIL_DISK_INTEGRAL_LAYER 4
#define UTIL_DISK_INTEGRAL_COMP 3
/* __cplusplus is true when compiling with MSL, so include if inside a shader. */
#if !defined(__cplusplus) || defined(GPU_SHADER)

View File

@ -31,10 +31,6 @@ void SubsurfaceModule::end_sync()
data_.sample_len = 55;
}
if (!transmittance_tx_.is_valid()) {
precompute_transmittance_profile();
}
precompute_samples_location();
data_.push_update();
@ -85,9 +81,13 @@ void SubsurfaceModule::precompute_samples_location()
}
}
void SubsurfaceModule::precompute_transmittance_profile()
const Vector<float> &SubsurfaceModule::transmittance_profile()
{
Vector<float> profile(SSS_TRANSMIT_LUT_SIZE);
static Vector<float> profile;
if (!profile.is_empty()) {
return profile;
}
profile.resize(SSS_TRANSMIT_LUT_SIZE);
/* Precompute sample position with white albedo. */
float radius = 1.0f;
@ -137,8 +137,7 @@ void SubsurfaceModule::precompute_transmittance_profile()
profile.first() = 1;
profile.last() = 0;
transmittance_tx_.ensure_1d(
GPU_R16F, profile.size(), GPU_TEXTURE_USAGE_SHADER_READ, profile.data());
return profile;
}
/** \} */

View File

@ -35,8 +35,6 @@ struct SubsurfaceModule {
Instance &inst_;
/** Contains samples locations. */
SubsurfaceDataBuf data_;
/** Contains translucence profile for a single color channel. */
Texture transmittance_tx_;
/** Scene diffuse irradiance. Pointer binded at sync time, set at render time. */
GPUTexture *diffuse_light_tx_;
/** Subsurface eval pass. Runs after the deferred pass. */
@ -51,6 +49,9 @@ struct SubsurfaceModule {
~SubsurfaceModule(){};
/** Contains translucence profile for a single color channel. */
static const Vector<float> &transmittance_profile();
void end_sync();
void render(View &view, Framebuffer &fb, Texture &diffuse_light_tx);
@ -60,14 +61,8 @@ struct SubsurfaceModule {
pass->bind_ubo("sss_buf", data_);
}
GPUTexture **transmittance_tx_get()
{
return &transmittance_tx_;
}
private:
void precompute_samples_location();
void precompute_transmittance_profile();
/** Christensen-Burley implementation. */
static float burley_setup(float radius, float albedo);

View File

@ -10,7 +10,6 @@
* - light_tile_buf
* - shadow_atlas_tx
* - shadow_tilemaps_tx
* - sss_transmittance_tx
* - utility_tx
*/
@ -53,14 +52,8 @@ void light_eval_ex(ClosureDiffuse diffuse,
float delta = max(thickness, -(samp.occluder_delta + samp.bias));
vec3 intensity = visibility * light.transmit_power *
light_translucent(sss_transmittance_tx,
is_directional,
light,
diffuse.N,
L,
dist,
diffuse.sss_radius,
delta);
light_translucent(
is_directional, light, diffuse.N, L, dist, diffuse.sss_radius, delta);
out_diffuse += light.color * intensity;
}
#endif

View File

@ -242,8 +242,13 @@ float light_ltc(sampler2DArray utility_tx,
}
}
vec3 light_translucent(sampler1D transmittance_tx,
const bool is_directional,
#ifdef SSS_TRANSMITTANCE
float sample_transmittance_profile(float u)
{
return utility_tx_sample(utility_tx, vec2(u, 0.0), UTIL_SSS_TRANSMITTANCE_PROFILE_LAYER).r;
}
vec3 light_translucent(const bool is_directional,
LightData ld,
vec3 N,
vec3 L,
@ -262,10 +267,11 @@ vec3 light_translucent(sampler1D transmittance_tx,
vec3 channels_co = saturate(delta / sss_radius) * SSS_TRANSMIT_LUT_SCALE + SSS_TRANSMIT_LUT_BIAS;
vec3 translucency;
translucency.x = (sss_radius.x > 0.0) ? texture(transmittance_tx, channels_co.x).r : 0.0;
translucency.y = (sss_radius.y > 0.0) ? texture(transmittance_tx, channels_co.y).r : 0.0;
translucency.z = (sss_radius.z > 0.0) ? texture(transmittance_tx, channels_co.z).r : 0.0;
translucency.x = (sss_radius.x > 0.0) ? sample_transmittance_profile(channels_co.x) : 0.0;
translucency.y = (sss_radius.y > 0.0) ? sample_transmittance_profile(channels_co.y) : 0.0;
translucency.z = (sss_radius.z > 0.0) ? sample_transmittance_profile(channels_co.z) : 0.0;
return translucency * power;
}
#endif
/** \} */

View File

@ -44,6 +44,7 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light_base)
Qualifier::READ,
ImageType::FLOAT_2D,
"indirect_refraction_img")
.define("SSS_TRANSMITTANCE")
.additional_info("eevee_shared",
"eevee_utility_texture",
"eevee_sampling_data",
@ -52,7 +53,6 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light_base)
"eevee_lightprobe_data",
"eevee_shadow_data",
"eevee_deferred_base",
"eevee_transmittance_data",
"eevee_hiz_data",
"eevee_render_pass_out",
"draw_view",

View File

@ -157,7 +157,6 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward)
// "eevee_render_pass_out",
// "eevee_cryptomatte_out",
// "eevee_raytrace_data",
// "eevee_transmittance_data",
);
GPU_SHADER_CREATE_INFO(eevee_surf_capture)

View File

@ -5,10 +5,6 @@
#include "eevee_defines.hh"
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(eevee_transmittance_data)
.define("SSS_TRANSMITTANCE")
.sampler(SSS_TRANSMITTANCE_TEX_SLOT, ImageType::FLOAT_1D, "sss_transmittance_tx");
GPU_SHADER_CREATE_INFO(eevee_subsurface_eval)
.do_static_compilation(true)
.additional_info("eevee_shared", "eevee_render_pass_out")