forked from bartvdbraak/blender
Cycles: option to make background visible through glass transparent.
This can be enabled in the Film panel, with an option to control the transmisison roughness below which glass becomes transparent. Differential Revision: https://developer.blender.org/D2904
This commit is contained in:
parent
cce280dd67
commit
322f0223d0
@ -413,9 +413,20 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
)
|
||||
cls.film_transparent = BoolProperty(
|
||||
name="Transparent",
|
||||
description="World background is transparent with premultiplied alpha",
|
||||
description="World background is transparent, for compositing the render over another background",
|
||||
default=False,
|
||||
)
|
||||
cls.film_transparent_glass = BoolProperty(
|
||||
name="Transparent Glass",
|
||||
description="Render transmissive surfaces as transparent, for compositing glass over another background",
|
||||
default=False,
|
||||
)
|
||||
cls.film_transparent_roughness = FloatProperty(
|
||||
name="Transparent Roughness Threshold",
|
||||
description="For transparent transmission, keep surfaces with roughness above the threshold opaque",
|
||||
min=0.0, max=1.0,
|
||||
default=0.1,
|
||||
)
|
||||
|
||||
# Really annoyingly, we have to keep it around for a few releases,
|
||||
# otherwise forward compatibility breaks in really bad manner: CRASH!
|
||||
|
@ -367,14 +367,21 @@ class CYCLES_RENDER_PT_film(CyclesButtonsPanel, Panel):
|
||||
|
||||
col = split.column()
|
||||
col.prop(cscene, "film_exposure")
|
||||
col.prop(cscene, "film_transparent")
|
||||
|
||||
col = split.column()
|
||||
col.separator()
|
||||
sub = col.column(align=True)
|
||||
sub.prop(cscene, "pixel_filter_type", text="")
|
||||
if cscene.pixel_filter_type != 'BOX':
|
||||
sub.prop(cscene, "filter_width", text="Width")
|
||||
|
||||
col = split.column()
|
||||
col.prop(cscene, "film_transparent")
|
||||
sub = col.row()
|
||||
sub.prop(cscene, "film_transparent_glass", text="Transparent Glass")
|
||||
sub.active = cscene.film_transparent
|
||||
sub = col.row()
|
||||
sub.prop(cscene, "film_transparent_roughness", text="Roughness Threshold")
|
||||
sub.active = cscene.film_transparent and cscene.film_transparent_glass
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Performance"
|
||||
|
@ -1333,6 +1333,15 @@ void BlenderSync::sync_world(bool update_all)
|
||||
else
|
||||
background->transparent = b_scene.render().alpha_mode() == BL::RenderSettings::alpha_mode_TRANSPARENT;
|
||||
|
||||
if(background->transparent) {
|
||||
background->transparent_glass = get_boolean(cscene, "film_transparent_glass");
|
||||
background->transparent_roughness_threshold = get_float(cscene, "film_transparent_roughness");
|
||||
}
|
||||
else {
|
||||
background->transparent_glass = false;
|
||||
background->transparent_roughness_threshold = 0.0f;
|
||||
}
|
||||
|
||||
background->use_shader = render_layer.use_background_shader;
|
||||
background->use_ao = background->use_ao && render_layer.use_background_ao;
|
||||
|
||||
|
@ -38,7 +38,7 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Returns the square of the roughness of the closure if it has roughness,
|
||||
* 0 for singular closures and 1 otherwise. */
|
||||
ccl_device_inline float bsdf_get_roughness_sqr(const ShaderClosure *sc)
|
||||
ccl_device_inline float bsdf_get_roughness_squared(const ShaderClosure *sc)
|
||||
{
|
||||
if(CLOSURE_IS_BSDF_SINGULAR(sc->type)) {
|
||||
return 0.0f;
|
||||
@ -173,6 +173,17 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Test if BSDF sample should be treated as transparent for background. */
|
||||
if(label & LABEL_TRANSMIT) {
|
||||
float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold;
|
||||
|
||||
if(threshold_squared >= 0.0f) {
|
||||
if(bsdf_get_roughness_squared(sc) <= threshold_squared) {
|
||||
label |= LABEL_TRANSMIT_TRANSPARENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
|
@ -455,7 +455,7 @@ ccl_device_inline void path_radiance_accum_background(
|
||||
|
||||
#ifdef __PASSES__
|
||||
if(L->use_light_pass) {
|
||||
if(state->bounce == 0)
|
||||
if(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)
|
||||
L->background += throughput*value;
|
||||
else if(state->bounce == 1)
|
||||
L->direct_emission += throughput*value;
|
||||
|
@ -140,7 +140,7 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
|
||||
/* All closures contribute to the normal feature, but only diffuse-like ones to the albedo. */
|
||||
normal += sc->N * sc->sample_weight;
|
||||
sum_weight += sc->sample_weight;
|
||||
if(bsdf_get_roughness_sqr(sc) > sqr(0.075f)) {
|
||||
if(bsdf_get_roughness_squared(sc) > sqr(0.075f)) {
|
||||
albedo += sc->weight;
|
||||
sum_nonspecular_weight += sc->sample_weight;
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ ccl_device_forceinline void kernel_path_background(
|
||||
PathRadiance *L)
|
||||
{
|
||||
/* eval background shader if nothing hit */
|
||||
if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) {
|
||||
if(kernel_data.background.transparent && (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
|
||||
L->transparent += average(throughput);
|
||||
|
||||
#ifdef __PASSES__
|
||||
@ -280,7 +280,7 @@ ccl_device_forceinline bool kernel_path_shader_apply(
|
||||
{
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
|
||||
if(state->flag & PATH_RAY_CAMERA) {
|
||||
if(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) {
|
||||
state->flag |= (PATH_RAY_SHADOW_CATCHER |
|
||||
PATH_RAY_STORE_SHADOW_INFO);
|
||||
|
||||
@ -302,7 +302,7 @@ ccl_device_forceinline bool kernel_path_shader_apply(
|
||||
#ifdef __HOLDOUT__
|
||||
if(((sd->flag & SD_HOLDOUT) ||
|
||||
(sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
|
||||
(state->flag & PATH_RAY_CAMERA))
|
||||
(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND))
|
||||
{
|
||||
if(kernel_data.background.transparent) {
|
||||
float3 holdout_weight;
|
||||
|
@ -23,7 +23,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg,
|
||||
int sample,
|
||||
ccl_addr_space Ray *ray)
|
||||
{
|
||||
state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP;
|
||||
state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP|PATH_RAY_TRANSPARENT_BACKGROUND;
|
||||
|
||||
state->rng_hash = rng_hash;
|
||||
state->rng_offset = PRNG_BASE_NUM;
|
||||
@ -86,12 +86,13 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
|
||||
}
|
||||
|
||||
state->bounce++;
|
||||
state->flag &= ~(PATH_RAY_ALL_VISIBILITY|PATH_RAY_MIS_SKIP);
|
||||
|
||||
#ifdef __VOLUME__
|
||||
if(label & LABEL_VOLUME_SCATTER) {
|
||||
/* volume scatter */
|
||||
state->flag |= PATH_RAY_VOLUME_SCATTER;
|
||||
state->flag &= ~(PATH_RAY_REFLECT|PATH_RAY_TRANSMIT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT|PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
|
||||
state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
|
||||
|
||||
state->volume_bounce++;
|
||||
}
|
||||
@ -101,7 +102,7 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
|
||||
/* surface reflection/transmission */
|
||||
if(label & LABEL_REFLECT) {
|
||||
state->flag |= PATH_RAY_REFLECT;
|
||||
state->flag &= ~(PATH_RAY_TRANSMIT|PATH_RAY_VOLUME_SCATTER|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
|
||||
state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
|
||||
|
||||
if(label & LABEL_DIFFUSE)
|
||||
state->diffuse_bounce++;
|
||||
@ -112,7 +113,10 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
|
||||
kernel_assert(label & LABEL_TRANSMIT);
|
||||
|
||||
state->flag |= PATH_RAY_TRANSMIT;
|
||||
state->flag &= ~(PATH_RAY_REFLECT|PATH_RAY_VOLUME_SCATTER|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
|
||||
|
||||
if(!(label & LABEL_TRANSMIT_TRANSPARENT)) {
|
||||
state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
|
||||
}
|
||||
|
||||
state->transmission_bounce++;
|
||||
}
|
||||
@ -120,17 +124,13 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
|
||||
/* diffuse/glossy/singular */
|
||||
if(label & LABEL_DIFFUSE) {
|
||||
state->flag |= PATH_RAY_DIFFUSE|PATH_RAY_DIFFUSE_ANCESTOR;
|
||||
state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
|
||||
}
|
||||
else if(label & LABEL_GLOSSY) {
|
||||
state->flag |= PATH_RAY_GLOSSY;
|
||||
state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
|
||||
}
|
||||
else {
|
||||
kernel_assert(label & LABEL_SINGULAR);
|
||||
|
||||
state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP;
|
||||
state->flag &= ~PATH_RAY_DIFFUSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,11 +346,12 @@ enum PathRayFlag {
|
||||
|
||||
PATH_RAY_ALL_VISIBILITY = ((1 << 14)-1),
|
||||
|
||||
PATH_RAY_MIS_SKIP = (1 << 15),
|
||||
PATH_RAY_DIFFUSE_ANCESTOR = (1 << 16),
|
||||
PATH_RAY_SINGLE_PASS_DONE = (1 << 17),
|
||||
PATH_RAY_SHADOW_CATCHER = (1 << 18),
|
||||
PATH_RAY_STORE_SHADOW_INFO = (1 << 19),
|
||||
PATH_RAY_MIS_SKIP = (1 << 15),
|
||||
PATH_RAY_DIFFUSE_ANCESTOR = (1 << 16),
|
||||
PATH_RAY_SINGLE_PASS_DONE = (1 << 17),
|
||||
PATH_RAY_SHADOW_CATCHER = (1 << 18),
|
||||
PATH_RAY_STORE_SHADOW_INFO = (1 << 19),
|
||||
PATH_RAY_TRANSPARENT_BACKGROUND = (1 << 20),
|
||||
};
|
||||
|
||||
/* Closure Label */
|
||||
@ -364,6 +365,7 @@ typedef enum ClosureLabel {
|
||||
LABEL_SINGULAR = 16,
|
||||
LABEL_TRANSPARENT = 32,
|
||||
LABEL_VOLUME_SCATTER = 64,
|
||||
LABEL_TRANSMIT_TRANSPARENT = 128,
|
||||
} ClosureLabel;
|
||||
|
||||
/* Render Passes */
|
||||
@ -1259,7 +1261,7 @@ typedef struct KernelBackground {
|
||||
int surface_shader;
|
||||
int volume_shader;
|
||||
int transparent;
|
||||
int pad;
|
||||
float transparent_roughness_squared_threshold;
|
||||
|
||||
/* ambient occlusion */
|
||||
float ao_factor;
|
||||
|
@ -38,7 +38,10 @@ NODE_DEFINE(Background)
|
||||
SOCKET_BOOLEAN(use_shader, "Use Shader", true);
|
||||
SOCKET_BOOLEAN(use_ao, "Use AO", false);
|
||||
SOCKET_UINT(visibility, "Visibility", PATH_RAY_ALL_VISIBILITY);
|
||||
|
||||
SOCKET_BOOLEAN(transparent, "Transparent", false);
|
||||
SOCKET_BOOLEAN(transparent_glass, "Transparent Glass", false);
|
||||
SOCKET_FLOAT(transparent_roughness_threshold, "Transparent Roughness Threshold", 0.0f);
|
||||
|
||||
SOCKET_NODE(shader, "Shader", &Shader::node_type);
|
||||
|
||||
@ -81,6 +84,15 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
|
||||
kbackground->transparent = transparent;
|
||||
kbackground->surface_shader = scene->shader_manager->get_shader_id(bg_shader);
|
||||
|
||||
if(transparent && transparent_glass) {
|
||||
/* Square twice, once for principled BSDF convention, and once for
|
||||
* faster comparison in kernel with anisotropic roughness. */
|
||||
kbackground->transparent_roughness_squared_threshold = sqr(sqr(transparent_roughness_threshold));
|
||||
}
|
||||
else {
|
||||
kbackground->transparent_roughness_squared_threshold = -1.0f;
|
||||
}
|
||||
|
||||
if(bg_shader->has_volume)
|
||||
kbackground->volume_shader = kbackground->surface_shader;
|
||||
else
|
||||
|
@ -42,6 +42,9 @@ public:
|
||||
Shader *shader;
|
||||
|
||||
bool transparent;
|
||||
bool transparent_glass;
|
||||
float transparent_roughness_threshold;
|
||||
|
||||
bool need_update;
|
||||
|
||||
Background();
|
||||
|
Loading…
Reference in New Issue
Block a user