EEVEE-Next: Move the transmittance LUT to the Utility Texture #111535
|
@ -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
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue