EEVEE Next: Subsurface Scattering #107407
|
@ -156,8 +156,7 @@ void ForwardPipeline::sync()
|
|||
opaque_ps_.bind_ssbo(RBUFS_AOV_BUF_SLOT, &inst_.film.aovs_info);
|
||||
/* Textures. */
|
||||
opaque_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
opaque_ps_.bind_texture(SSS_TRANSMITTANCE_TEX_SLOT,
|
||||
inst_.subsurface.transmittance_ref_get());
|
||||
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());
|
||||
|
@ -185,7 +184,7 @@ 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_ref_get());
|
||||
sub.bind_texture(SSS_TRANSMITTANCE_TEX_SLOT, inst_.subsurface.transmittance_tx_get());
|
||||
/* Uniform Buffer. */
|
||||
sub.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
|
||||
|
||||
|
@ -366,17 +365,14 @@ void DeferredLayer::begin_sync()
|
|||
|
||||
void DeferredLayer::end_sync()
|
||||
{
|
||||
/* Use stencil test to reject pixel not written by this layer. */
|
||||
/* WORKAROUND: Stencil write is only here to avoid rasterizer discard. */
|
||||
DRWState state = DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_EQUAL;
|
||||
/* Allow output to combined pass for the last pass. */
|
||||
DRWState state_write_color = state | DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
|
||||
|
||||
if (closure_bits_ & (CLOSURE_DIFFUSE | CLOSURE_REFLECTION)) {
|
||||
const bool is_last_eval_pass = !(closure_bits_ & CLOSURE_SSS);
|
||||
|
||||
eval_light_ps_.init();
|
||||
eval_light_ps_.state_set(state_write_color);
|
||||
/* Use stencil test to reject pixel not written by this layer. */
|
||||
eval_light_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL |
|
||||
DRW_STATE_BLEND_CUSTOM);
|
||||
eval_light_ps_.state_stencil(0x00u, 0x01u, 0xFFu);
|
||||
eval_light_ps_.shader_set(inst_.shaders.static_shader_get(DEFERRED_LIGHT));
|
||||
eval_light_ps_.bind_image("out_diffuse_light_img", &diffuse_light_tx_);
|
||||
|
@ -387,7 +383,7 @@ void DeferredLayer::end_sync()
|
|||
eval_light_ps_.bind_image(RBUFS_LIGHT_SLOT, &inst_.render_buffers.light_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_ref_get());
|
||||
inst_.subsurface.transmittance_tx_get());
|
||||
|
||||
inst_.lights.bind_resources(&eval_light_ps_);
|
||||
inst_.shadows.bind_resources(&eval_light_ps_);
|
||||
|
|
|
@ -31,7 +31,7 @@ void SubsurfaceModule::end_sync()
|
|||
data_.sample_len = 55;
|
||||
}
|
||||
|
||||
if (transmittance_tx == nullptr) {
|
||||
if (!transmittance_tx.is_valid()) {
|
||||
precompute_transmittance_profile();
|
||||
}
|
||||
|
||||
|
@ -105,12 +105,8 @@ void SubsurfaceModule::precompute_transmittance_profile()
|
|||
profile.first() = 1;
|
||||
profile.last() = 0;
|
||||
|
||||
transmittance_tx = GPU_texture_create_1d("SSSTransmittanceProfile",
|
||||
profile.size(),
|
||||
1,
|
||||
GPU_R16F,
|
||||
GPU_TEXTURE_USAGE_SHADER_READ,
|
||||
profile.data());
|
||||
transmittance_tx.ensure_1d(
|
||||
GPU_R16F, profile.size(), GPU_TEXTURE_USAGE_SHADER_READ, profile.data());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -5,6 +5,15 @@
|
|||
/** \file
|
||||
* \ingroup eevee
|
||||
*
|
||||
* Postprocess diffuse radiance output from the diffuse evaluation pass to mimic subsurface
|
||||
* transmission.
|
||||
*
|
||||
* This implementation follows the technique described in the siggraph presentation:
|
||||
* "Efficient screen space subsurface scattering Siggraph 2018"
|
||||
* by Evgenii Golubev
|
||||
*
|
||||
* But, instead of having all the precomputed weights for all three color primaries,
|
||||
* we precompute a weight profile texture to be able to support per pixel AND per channel radius.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -27,7 +36,7 @@ struct SubsurfaceModule {
|
|||
/** Contains samples locations. */
|
||||
SubsurfaceDataBuf data_;
|
||||
/** Contains translucence profile for a single color channel. */
|
||||
GPUTexture *transmittance_tx = nullptr;
|
||||
Texture transmittance_tx;
|
||||
|
||||
public:
|
||||
SubsurfaceModule(Instance &inst) : inst_(inst)
|
||||
|
@ -48,12 +57,7 @@ struct SubsurfaceModule {
|
|||
pass->bind_ubo("sss_buf", data_);
|
||||
}
|
||||
|
||||
const GPUUniformBuf *ubo_get(void) const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
GPUTexture **transmittance_ref_get(void)
|
||||
GPUTexture **transmittance_tx_get(void)
|
||||
{
|
||||
return &transmittance_tx;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue