UI: Console Text Operations #108626
@ -252,7 +252,9 @@ mark_as_advanced(BUILDINFO_OVERRIDE_TIME)
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16")
|
||||
option(WITH_UNITY_BUILD "\
|
||||
Enable unity build for modules that support it to improve compile times"
|
||||
Enable unity build for modules that support it to improve compile times.\n\
|
||||
WARNING: this option allows files to be built without all necessary headers!\n
|
||||
This option should be disabled before manipulating or removing headers."
|
||||
ON
|
||||
)
|
||||
mark_as_advanced(WITH_UNITY_BUILD)
|
||||
|
@ -79,7 +79,7 @@ SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
USE_ONLY_BUILTIN_RNA_TYPES = True
|
||||
|
||||
# Write a page for each static enum defined in:
|
||||
# `source/blender/makesrna/RNA_enum_items.h` so the enums can be linked to instead of being expanded everywhere.
|
||||
# `source/blender/makesrna/RNA_enum_items.hh` so the enums can be linked to instead of being expanded everywhere.
|
||||
USE_SHARED_RNA_ENUM_ITEMS_STATIC = True
|
||||
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
|
@ -86,6 +86,58 @@ static float precompute_ggx_glass_E(float rough, float mu, float eta, float3 ran
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static float precompute_ggx_gen_schlick_s(
|
||||
float rough, float mu, float eta, float exponent, float3 rand)
|
||||
{
|
||||
MicrofacetBsdf bsdf;
|
||||
bsdf.weight = one_float3();
|
||||
bsdf.sample_weight = 1.0f;
|
||||
bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
|
||||
bsdf.alpha_x = bsdf.alpha_y = sqr(rough);
|
||||
bsdf.ior = eta;
|
||||
bsdf.T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf_microfacet_ggx_setup(&bsdf);
|
||||
|
||||
FresnelGeneralizedSchlick fresnel;
|
||||
fresnel.reflection_tint = one_float3();
|
||||
fresnel.transmission_tint = one_float3();
|
||||
fresnel.f0 = make_float3(0.0f, 1.0f, 0.0f);
|
||||
fresnel.f90 = make_float3(1.0f, 1.0f, 0.0f);
|
||||
fresnel.exponent = exponent;
|
||||
|
||||
bsdf.fresnel_type = MicrofacetFresnel::GENERALIZED_SCHLICK;
|
||||
bsdf.fresnel = &fresnel;
|
||||
|
||||
float3 omega_in;
|
||||
Spectrum eval;
|
||||
float pdf = 0.0f, sampled_eta;
|
||||
float2 sampled_roughness;
|
||||
bsdf_microfacet_ggx_sample((ShaderClosure *)&bsdf,
|
||||
0,
|
||||
make_float3(0.0f, 0.0f, 1.0f),
|
||||
make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
|
||||
rand,
|
||||
&eval,
|
||||
&omega_in,
|
||||
&pdf,
|
||||
&sampled_roughness,
|
||||
&sampled_eta);
|
||||
if (pdf != 0.0f) {
|
||||
/* The idea here is that the resulting Fresnel factor is always bounded by
|
||||
* F0..F90, so it's enough to precompute and store the interpolation factor. */
|
||||
return saturatef(eval.x / eval.y);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
inline float ior_parametrization(float z)
|
||||
{
|
||||
/* This parametrization ensures that the entire [1..inf] range of IORs is covered
|
||||
* and that most precision is allocated to the common areas (1-2). */
|
||||
return ior_from_F0(sqr(sqr(z)));
|
||||
}
|
||||
|
||||
struct PrecomputeTerm {
|
||||
int samples;
|
||||
int nx, ny, nz;
|
||||
@ -95,31 +147,61 @@ struct PrecomputeTerm {
|
||||
static bool cycles_precompute(std::string name)
|
||||
{
|
||||
std::map<string, PrecomputeTerm> precompute_terms;
|
||||
precompute_terms["ggx_E"] = {
|
||||
1 << 23, 32, 32, 1, [](float rough, float mu, float ior, float3 rand) {
|
||||
return precompute_ggx_E(rough, mu, rand);
|
||||
}};
|
||||
/* Overall albedo of the GGX microfacet BRDF, depending on cosI and roughness. */
|
||||
precompute_terms["ggx_E"] = {1 << 23, 32, 32, 1, [](float rough, float mu, float, float3 rand) {
|
||||
return precompute_ggx_E(rough, mu, rand);
|
||||
}};
|
||||
/* Overall albedo of the GGX microfacet BRDF, averaged over cosI */
|
||||
precompute_terms["ggx_Eavg"] = {
|
||||
1 << 26, 32, 1, 1, [](float rough, float mu, float ior, float3 rand) {
|
||||
1 << 26, 32, 1, 1, [](float rough, float mu, float, float3 rand) {
|
||||
return 2.0f * mu * precompute_ggx_E(rough, mu, rand);
|
||||
}};
|
||||
/* Overall albedo of the GGX microfacet BSDF with dielectric Fresnel,
|
||||
* depending on cosI and roughness, for IOR>1. */
|
||||
precompute_terms["ggx_glass_E"] = {
|
||||
1 << 23, 16, 16, 16, [](float rough, float mu, float ior, float3 rand) {
|
||||
1 << 23, 16, 16, 16, [](float rough, float mu, float z, float3 rand) {
|
||||
float ior = ior_parametrization(z);
|
||||
return precompute_ggx_glass_E(rough, mu, ior, rand);
|
||||
}};
|
||||
/* Overall albedo of the GGX microfacet BSDF with dielectric Fresnel,
|
||||
* averaged over cosI, for IOR>1. */
|
||||
precompute_terms["ggx_glass_Eavg"] = {
|
||||
1 << 26, 16, 1, 16, [](float rough, float mu, float ior, float3 rand) {
|
||||
1 << 26, 16, 1, 16, [](float rough, float mu, float z, float3 rand) {
|
||||
float ior = ior_parametrization(z);
|
||||
return 2.0f * mu * precompute_ggx_glass_E(rough, mu, ior, rand);
|
||||
}};
|
||||
/* Overall albedo of the GGX microfacet BSDF with dielectric Fresnel,
|
||||
* depending on cosI and roughness, for IOR<1. */
|
||||
precompute_terms["ggx_glass_inv_E"] = {
|
||||
1 << 23, 16, 16, 16, [](float rough, float mu, float ior, float3 rand) {
|
||||
1 << 23, 16, 16, 16, [](float rough, float mu, float z, float3 rand) {
|
||||
float ior = ior_parametrization(z);
|
||||
return precompute_ggx_glass_E(rough, mu, 1.0f / ior, rand);
|
||||
}};
|
||||
/* Overall albedo of the GGX microfacet BSDF with dielectric Fresnel,
|
||||
* averaged over cosI, for IOR<1. */
|
||||
precompute_terms["ggx_glass_inv_Eavg"] = {
|
||||
1 << 26, 16, 1, 16, [](float rough, float mu, float ior, float3 rand) {
|
||||
1 << 26, 16, 1, 16, [](float rough, float mu, float z, float3 rand) {
|
||||
float ior = ior_parametrization(z);
|
||||
return 2.0f * mu * precompute_ggx_glass_E(rough, mu, 1.0f / ior, rand);
|
||||
}};
|
||||
|
||||
/* Interpolation factor between F0 and F90 for the generalized Schlick Fresnel,
|
||||
* depending on cosI and roughness, for IOR>1, using dielectric Fresnel mode. */
|
||||
precompute_terms["ggx_gen_schlick_ior_s"] = {
|
||||
1 << 20, 16, 16, 16, [](float rough, float mu, float z, float3 rand) {
|
||||
float ior = ior_parametrization(z);
|
||||
return precompute_ggx_gen_schlick_s(rough, mu, ior, -1.0f, rand);
|
||||
}};
|
||||
|
||||
/* Interpolation factor between F0 and F90 for the generalized Schlick Fresnel,
|
||||
* depending on cosI and roughness, for IOR>1. */
|
||||
precompute_terms["ggx_gen_schlick_s"] = {
|
||||
1 << 20, 16, 16, 16, [](float rough, float mu, float z, float3 rand) {
|
||||
/* Remap 0..1 to 0..inf, with 0.5 mapping to 5 (the default value). */
|
||||
float exponent = 5.0f * ((1.0f - z) / z);
|
||||
return precompute_ggx_gen_schlick_s(rough, mu, 1.0f, exponent, rand);
|
||||
}};
|
||||
|
||||
if (precompute_terms.count(name) == 0) {
|
||||
return false;
|
||||
}
|
||||
@ -142,9 +224,6 @@ static bool cycles_precompute(std::string name)
|
||||
float rough = (nx == 1) ? 0.0f : clamp(float(x) / float(nx - 1), 1e-4f, 1.0f);
|
||||
float mu = (ny == 1) ? rand.w : clamp(float(y) / float(ny - 1), 1e-4f, 1.0f);
|
||||
float ior = (nz == 1) ? 0.0f : clamp(float(z) / float(nz - 1), 1e-4f, 0.99f);
|
||||
/* This parametrization ensures that the entire [1..inf] range of IORs is covered
|
||||
* and that most precision is allocated to the common areas (1-2). */
|
||||
ior = ior_from_F0(sqr(sqr(ior)));
|
||||
|
||||
float value = term.evaluation(rough, mu, ior, float4_to_float3(rand));
|
||||
if (isnan(value)) {
|
||||
|
@ -6,9 +6,9 @@
|
||||
#define __BLENDER_DEVICE_H__
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_blender_cpp.h"
|
||||
#include "RNA_types.h"
|
||||
#include "RNA_types.hh"
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
|
@ -52,8 +52,6 @@ void BlenderSync::sync_light(BL::Object &b_parent,
|
||||
case BL::Light::type_SPOT: {
|
||||
BL::SpotLight b_spot_light(b_light);
|
||||
light->set_size(b_spot_light.shadow_soft_size());
|
||||
light->set_axisu(transform_get_column(&tfm, 0));
|
||||
light->set_axisv(transform_get_column(&tfm, 1));
|
||||
light->set_light_type(LIGHT_SPOT);
|
||||
light->set_spot_angle(b_spot_light.spot_size());
|
||||
light->set_spot_smooth(b_spot_light.spot_blend());
|
||||
@ -74,8 +72,6 @@ void BlenderSync::sync_light(BL::Object &b_parent,
|
||||
case BL::Light::type_AREA: {
|
||||
BL::AreaLight b_area_light(b_light);
|
||||
light->set_size(1.0f);
|
||||
light->set_axisu(transform_get_column(&tfm, 0));
|
||||
light->set_axisv(transform_get_column(&tfm, 1));
|
||||
light->set_sizeu(b_area_light.size());
|
||||
light->set_spread(b_area_light.spread());
|
||||
switch (b_area_light.shape()) {
|
||||
@ -106,8 +102,6 @@ void BlenderSync::sync_light(BL::Object &b_parent,
|
||||
light->set_strength(strength);
|
||||
|
||||
/* location and (inverted!) direction */
|
||||
light->set_co(transform_get_column(&tfm, 3));
|
||||
light->set_dir(-transform_get_column(&tfm, 2));
|
||||
light->set_tfm(tfm);
|
||||
|
||||
/* shader */
|
||||
|
@ -6,10 +6,10 @@
|
||||
#define __BLENDER_SYNC_H__
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_blender_cpp.h"
|
||||
#include "RNA_path.h"
|
||||
#include "RNA_types.h"
|
||||
#include "RNA_path.hh"
|
||||
#include "RNA_types.hh"
|
||||
|
||||
#include "blender/id_map.h"
|
||||
#include "blender/util.h"
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_blender_cpp.h"
|
||||
#include "RNA_types.h"
|
||||
#include "RNA_types.hh"
|
||||
|
||||
#include "scene/film.h"
|
||||
|
||||
|
@ -65,14 +65,6 @@ void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
|
||||
.Get<GfMatrix4d>());
|
||||
#endif
|
||||
_light->set_tfm(tfm);
|
||||
|
||||
_light->set_co(transform_get_column(&tfm, 3));
|
||||
_light->set_dir(-transform_get_column(&tfm, 2));
|
||||
|
||||
if (_lightType == HdPrimTypeTokens->diskLight || _lightType == HdPrimTypeTokens->rectLight) {
|
||||
_light->set_axisu(transform_get_column(&tfm, 0));
|
||||
_light->set_axisv(transform_get_column(&tfm, 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyParams) {
|
||||
@ -211,7 +203,23 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
|
||||
outputNode = bgNode;
|
||||
}
|
||||
else {
|
||||
else if (sceneDelegate != nullptr) {
|
||||
VtValue value;
|
||||
const SdfPath &id = GetId();
|
||||
value = sceneDelegate->GetLightParamValue(id, TfToken("falloff"));
|
||||
if (!value.IsEmpty()) {
|
||||
std::string strVal = value.Get<string>();
|
||||
if (strVal == "Constant" || strVal == "Linear" || strVal == "Quadratic") {
|
||||
LightFalloffNode *lfoNode = graph->create_node<LightFalloffNode>();
|
||||
lfoNode->set_strength(1.f);
|
||||
graph->add(lfoNode);
|
||||
graph->connect(lfoNode->output(strVal.c_str()), graph->output()->input("Surface"));
|
||||
outputNode = lfoNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (outputNode == nullptr) {
|
||||
EmissionNode *emissionNode = graph->create_node<EmissionNode>();
|
||||
emissionNode->set_color(one_float3());
|
||||
emissionNode->set_strength(1.0f);
|
||||
|
@ -139,7 +139,6 @@ set(SRC_KERNEL_CLOSURE_HEADERS
|
||||
closure/bssrdf.h
|
||||
closure/emissive.h
|
||||
closure/volume.h
|
||||
closure/bsdf_principled_diffuse.h
|
||||
closure/bsdf_hair_principled.h
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "kernel/closure/bsdf_toon.h"
|
||||
#include "kernel/closure/bsdf_hair.h"
|
||||
#include "kernel/closure/bsdf_hair_principled.h"
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/bssrdf.h"
|
||||
#include "kernel/closure/volume.h"
|
||||
// clang-format on
|
||||
@ -50,11 +49,6 @@ ccl_device_inline float bsdf_get_roughness_squared(ccl_private const ShaderClosu
|
||||
return sqr(sqr(bsdf->roughness));
|
||||
}
|
||||
|
||||
if (sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
|
||||
ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)sc;
|
||||
return sqr(sqr(bsdf->roughness));
|
||||
}
|
||||
|
||||
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
||||
return 0.0f;
|
||||
}
|
||||
@ -204,11 +198,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
label = bsdf_principled_hair_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
label = bsdf_principled_diffuse_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_SHEEN_ID:
|
||||
label = bsdf_sheen_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
@ -341,10 +330,6 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
|
||||
*roughness = make_float2(alpha, alpha);
|
||||
*eta = ((ccl_private PrincipledHairBSDF *)sc)->eta;
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_SHEEN_ID:
|
||||
alpha = ((ccl_private SheenBsdf *)sc)->roughness;
|
||||
*roughness = make_float2(alpha, alpha);
|
||||
@ -426,9 +411,6 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
|
||||
else
|
||||
label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
case CLOSURE_BSDF_SHEEN_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
@ -520,9 +502,6 @@ ccl_device_inline
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
eval = bsdf_hair_transmission_eval(sc, sd->wi, wo, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
eval = bsdf_principled_diffuse_eval(sc, sd->wi, wo, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_SHEEN_ID:
|
||||
eval = bsdf_sheen_eval(sc, sd->wi, wo, pdf);
|
||||
break;
|
||||
@ -581,7 +560,8 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
|
||||
#endif
|
||||
}
|
||||
|
||||
ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd,
|
||||
ccl_device_inline Spectrum bsdf_albedo(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
const bool reflection,
|
||||
const bool transmission)
|
||||
@ -598,8 +578,8 @@ ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd,
|
||||
* extra overhead though. */
|
||||
#if defined(__SVM__) || defined(__OSL__)
|
||||
if (CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
|
||||
albedo *= bsdf_microfacet_estimate_fresnel(
|
||||
sd, (ccl_private const MicrofacetBsdf *)sc, reflection, transmission);
|
||||
albedo *= bsdf_microfacet_estimate_albedo(
|
||||
kg, sd, (ccl_private const MicrofacetBsdf *)sc, reflection, transmission);
|
||||
}
|
||||
else if (sc->type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
|
||||
/* TODO(lukas): Principled Hair could also be split into a glossy and a transmission component,
|
||||
|
@ -241,7 +241,7 @@ ccl_device_forceinline Spectrum microfacet_fresnel(ccl_private const MicrofacetB
|
||||
* Used by Principled v1. */
|
||||
const float F_real = fresnel_dielectric_cos(dot(wi, H), bsdf->ior);
|
||||
const float F0_real = F0_from_ior(bsdf->ior);
|
||||
s = inverse_lerp(F0_real, 1.0f, F_real);
|
||||
s = saturatef(inverse_lerp(F0_real, 1.0f, F_real));
|
||||
}
|
||||
else {
|
||||
/* Regular case: Generalized Schlick term. */
|
||||
@ -329,16 +329,12 @@ ccl_device_inline void microfacet_ggx_preserve_energy(KernelGlobals kg,
|
||||
* code for that), but e.g. a reflection-only closure with Fresnel applied can end up having
|
||||
* a very low overall albedo.
|
||||
* This is used to adjust the sample weight, as well as for the Diff/Gloss/Trans Color pass
|
||||
* and the Denoising Albedo pass.
|
||||
*
|
||||
* NOTE: This code assumes the microfacet surface is fairly smooth. For very high roughness,
|
||||
* the results are much more uniform across the surface.
|
||||
* For better results, we'd be blending between this and Fss based on roughness, but that
|
||||
* would involve storing or recomputing Fss, which is probably not worth it. */
|
||||
ccl_device Spectrum bsdf_microfacet_estimate_fresnel(ccl_private const ShaderData *sd,
|
||||
ccl_private const MicrofacetBsdf *bsdf,
|
||||
const bool reflection,
|
||||
const bool transmission)
|
||||
* and the Denoising Albedo pass. */
|
||||
ccl_device Spectrum bsdf_microfacet_estimate_albedo(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_private const MicrofacetBsdf *bsdf,
|
||||
const bool reflection,
|
||||
const bool transmission)
|
||||
{
|
||||
const bool m_refraction = CLOSURE_IS_REFRACTION(bsdf->type);
|
||||
const bool m_glass = CLOSURE_IS_GLASS(bsdf->type);
|
||||
@ -347,7 +343,29 @@ ccl_device Spectrum bsdf_microfacet_estimate_fresnel(ccl_private const ShaderDat
|
||||
Spectrum albedo = zero_spectrum();
|
||||
if (reflection && (m_reflection || m_glass)) {
|
||||
/* BSDF has a reflective lobe. */
|
||||
albedo += microfacet_fresnel(bsdf, sd->wi, bsdf->N, false);
|
||||
if (bsdf->fresnel_type == MicrofacetFresnel::GENERALIZED_SCHLICK) {
|
||||
ccl_private FresnelGeneralizedSchlick *fresnel = (ccl_private FresnelGeneralizedSchlick *)
|
||||
bsdf->fresnel;
|
||||
float mu = dot(sd->wi, bsdf->N);
|
||||
float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
|
||||
float s;
|
||||
if (fresnel->exponent < 0.0f) {
|
||||
float z = sqrtf(fabsf((bsdf->ior - 1.0f) / (bsdf->ior + 1.0f)));
|
||||
s = lookup_table_read_3D(
|
||||
kg, rough, mu, z, kernel_data.tables.ggx_gen_schlick_ior_s, 16, 16, 16);
|
||||
}
|
||||
else {
|
||||
float z = 1.0f / (0.2f * fresnel->exponent + 1.0f);
|
||||
s = lookup_table_read_3D(
|
||||
kg, rough, mu, z, kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
|
||||
}
|
||||
albedo += mix(fresnel->f0, fresnel->f90, s) * fresnel->reflection_tint;
|
||||
}
|
||||
else {
|
||||
/* If we don't (yet) have a way to estimate albedo in a way that accounts for roughness,
|
||||
* fall back to assuming that the surface is smooth. */
|
||||
albedo += microfacet_fresnel(bsdf, sd->wi, bsdf->N, false);
|
||||
}
|
||||
}
|
||||
if (transmission && (m_refraction || m_glass)) {
|
||||
/* BSDF has a refractive lobe (unless there's TIR). */
|
||||
@ -733,7 +751,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_conductor(KernelGlobals kg,
|
||||
{
|
||||
bsdf->fresnel_type = MicrofacetFresnel::CONDUCTOR;
|
||||
bsdf->fresnel = fresnel;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
|
||||
|
||||
if (preserve_energy) {
|
||||
/* In order to estimate Fss of the conductor, we fit the F82-tint model to it based on the
|
||||
@ -756,7 +774,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_dielectric_tint(
|
||||
{
|
||||
bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC_TINT;
|
||||
bsdf->fresnel = fresnel;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
|
||||
|
||||
if (preserve_energy) {
|
||||
/* Assume that the transmissive tint makes up most of the overall color. */
|
||||
@ -773,7 +791,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(
|
||||
{
|
||||
bsdf->fresnel_type = MicrofacetFresnel::GENERALIZED_SCHLICK;
|
||||
bsdf->fresnel = fresnel;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
|
||||
|
||||
if (preserve_energy) {
|
||||
Spectrum Fss = one_spectrum();
|
||||
@ -851,7 +869,8 @@ ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *bsdf,
|
||||
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(KernelGlobals kg,
|
||||
ccl_private MicrofacetBsdf *bsdf,
|
||||
ccl_private const ShaderData *sd)
|
||||
{
|
||||
bsdf->alpha_x = saturatef(bsdf->alpha_x);
|
||||
@ -860,7 +879,7 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *b
|
||||
bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
|
||||
bsdf->energy_scale = 1.0f;
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true));
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
|
||||
|
||||
return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
@ -1,157 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
/* DISNEY PRINCIPLED DIFFUSE BRDF
|
||||
*
|
||||
* Shading model by Brent Burley (Disney): "Physically Based Shading at Disney" (2012)
|
||||
*
|
||||
* "Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering" (2015)
|
||||
* For the separation of retro-reflection, "2.3 Dielectric BRDF with integrated
|
||||
* subsurface scattering"
|
||||
*/
|
||||
|
||||
#include "kernel/closure/bsdf_util.h"
|
||||
|
||||
#include "kernel/sample/mapping.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
enum PrincipledDiffuseBsdfComponents {
|
||||
PRINCIPLED_DIFFUSE_FULL = 1,
|
||||
PRINCIPLED_DIFFUSE_LAMBERT = 2,
|
||||
PRINCIPLED_DIFFUSE_LAMBERT_EXIT = 4,
|
||||
PRINCIPLED_DIFFUSE_RETRO_REFLECTION = 8,
|
||||
};
|
||||
|
||||
typedef struct PrincipledDiffuseBsdf {
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
float roughness;
|
||||
int components;
|
||||
} PrincipledDiffuseBsdf;
|
||||
|
||||
static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledDiffuseBsdf),
|
||||
"PrincipledDiffuseBsdf is too large!");
|
||||
|
||||
ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf *bsdf)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID;
|
||||
bsdf->components = PRINCIPLED_DIFFUSE_FULL;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum
|
||||
bsdf_principled_diffuse_compute_brdf(ccl_private const PrincipledDiffuseBsdf *bsdf,
|
||||
float3 N,
|
||||
float3 V,
|
||||
float3 L,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
const float NdotL = dot(N, L);
|
||||
|
||||
if (NdotL <= 0) {
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
const float NdotV = dot(N, V);
|
||||
|
||||
const float FV = schlick_fresnel(NdotV);
|
||||
const float FL = schlick_fresnel(NdotL);
|
||||
|
||||
float f = 0.0f;
|
||||
|
||||
/* Lambertian component. */
|
||||
if (bsdf->components & (PRINCIPLED_DIFFUSE_FULL | PRINCIPLED_DIFFUSE_LAMBERT)) {
|
||||
f += (1.0f - 0.5f * FV) * (1.0f - 0.5f * FL);
|
||||
}
|
||||
else if (bsdf->components & PRINCIPLED_DIFFUSE_LAMBERT_EXIT) {
|
||||
f += (1.0f - 0.5f * FL);
|
||||
}
|
||||
|
||||
/* Retro-reflection component. */
|
||||
if (bsdf->components & (PRINCIPLED_DIFFUSE_FULL | PRINCIPLED_DIFFUSE_RETRO_REFLECTION)) {
|
||||
/* H = normalize(L + V); // Bisector of an angle between L and V
|
||||
* LH2 = 2 * dot(L, H)^2 = 2cos(x)^2 = cos(2x) + 1 = dot(L, V) + 1,
|
||||
* half-angle x between L and V is at most 90 deg. */
|
||||
const float LH2 = dot(L, V) + 1;
|
||||
const float RR = bsdf->roughness * LH2;
|
||||
f += RR * (FL + FV + FL * FV * (RR - 1.0f));
|
||||
}
|
||||
|
||||
float value = M_1_PI_F * NdotL * f;
|
||||
|
||||
return make_spectrum(value);
|
||||
}
|
||||
|
||||
/* Compute Fresnel at entry point, to be combined with #PRINCIPLED_DIFFUSE_LAMBERT_EXIT
|
||||
* at the exit point to get the complete BSDF. */
|
||||
ccl_device_inline float bsdf_principled_diffuse_compute_entry_fresnel(const float NdotV)
|
||||
{
|
||||
const float FV = schlick_fresnel(NdotV);
|
||||
return (1.0f - 0.5f * FV);
|
||||
}
|
||||
|
||||
/* Ad-hoc weight adjustment to avoid retro-reflection taking away half the
|
||||
* samples from BSSRDF. */
|
||||
ccl_device_inline float bsdf_principled_diffuse_retro_reflection_sample_weight(
|
||||
ccl_private PrincipledDiffuseBsdf *bsdf, const float3 I)
|
||||
{
|
||||
return bsdf->roughness * schlick_fresnel(dot(bsdf->N, I));
|
||||
}
|
||||
|
||||
ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf *bsdf,
|
||||
int components)
|
||||
{
|
||||
bsdf->type = CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID;
|
||||
bsdf->components = components;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_principled_diffuse_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 wi,
|
||||
const float3 wo,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc;
|
||||
const float3 N = bsdf->N;
|
||||
|
||||
if (dot(N, wo) > 0.0f) {
|
||||
const float3 V = wi;
|
||||
const float3 L = wo;
|
||||
*pdf = fmaxf(dot(N, wo), 0.0f) * M_1_PI_F;
|
||||
return bsdf_principled_diffuse_compute_brdf(bsdf, N, V, L, pdf);
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 Ng,
|
||||
float3 wi,
|
||||
float2 rand,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
|
||||
sample_cos_hemisphere(N, rand, wo, pdf);
|
||||
|
||||
if (dot(Ng, *wo) > 0) {
|
||||
*eval = bsdf_principled_diffuse_compute_brdf(bsdf, N, wi, *wo, pdf);
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
@ -263,6 +263,11 @@ ccl_device_forceinline float bssrdf_pdf(const Spectrum radius, float r)
|
||||
|
||||
ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd, Spectrum weight)
|
||||
{
|
||||
float sample_weight = fabsf(average(weight));
|
||||
if (sample_weight < CLOSURE_WEIGHT_CUTOFF) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ccl_private Bssrdf *bssrdf = (ccl_private Bssrdf *)closure_alloc(
|
||||
sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
|
||||
|
||||
@ -270,9 +275,8 @@ ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd, S
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float sample_weight = fabsf(average(weight));
|
||||
bssrdf->sample_weight = sample_weight;
|
||||
return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? bssrdf : NULL;
|
||||
return bssrdf;
|
||||
}
|
||||
|
||||
ccl_device int bssrdf_setup(ccl_private ShaderData *sd,
|
||||
@ -282,22 +286,6 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd,
|
||||
{
|
||||
int flag = 0;
|
||||
|
||||
/* Add retro-reflection component as separate diffuse BSDF. */
|
||||
if (bssrdf->roughness != FLT_MAX) {
|
||||
ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(PrincipledDiffuseBsdf), bssrdf->weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = bssrdf->N;
|
||||
bsdf->roughness = bssrdf->roughness;
|
||||
flag |= bsdf_principled_diffuse_setup(bsdf, PRINCIPLED_DIFFUSE_RETRO_REFLECTION);
|
||||
|
||||
/* Ad-hoc weight adjustment to avoid retro-reflection taking away half the
|
||||
* samples from BSSRDF. */
|
||||
bsdf->sample_weight *= bsdf_principled_diffuse_retro_reflection_sample_weight(bsdf, sd->wi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify if the radii are large enough to sample without precision issues. */
|
||||
int bssrdf_channels = SPECTRUM_CHANNELS;
|
||||
Spectrum diffuse_weight = zero_spectrum();
|
||||
@ -313,24 +301,12 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd,
|
||||
|
||||
if (bssrdf_channels < SPECTRUM_CHANNELS) {
|
||||
/* Add diffuse BSDF if any radius too small. */
|
||||
if (bssrdf->roughness != FLT_MAX) {
|
||||
ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(PrincipledDiffuseBsdf), diffuse_weight);
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), diffuse_weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = bssrdf->N;
|
||||
bsdf->roughness = bssrdf->roughness;
|
||||
flag |= bsdf_principled_diffuse_setup(bsdf, PRINCIPLED_DIFFUSE_LAMBERT);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), diffuse_weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = bssrdf->N;
|
||||
flag |= bsdf_diffuse_setup(bsdf);
|
||||
}
|
||||
if (bsdf) {
|
||||
bsdf->N = bssrdf->N;
|
||||
flag |= bsdf_diffuse_setup(bsdf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,16 +59,7 @@ ccl_device_forceinline void film_write_denoising_features_surface(KernelGlobals
|
||||
normal += sc->N * sc->sample_weight;
|
||||
sum_weight += sc->sample_weight;
|
||||
|
||||
if (sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
|
||||
/* BSSRDF already accounts for weight, retro-reflection would double up. */
|
||||
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)
|
||||
sc;
|
||||
if (bsdf->components == PRINCIPLED_DIFFUSE_RETRO_REFLECTION) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum closure_albedo = bsdf_albedo(sd, sc, true, true);
|
||||
Spectrum closure_albedo = bsdf_albedo(kg, sd, sc, true, true);
|
||||
if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) {
|
||||
diffuse_albedo += closure_albedo;
|
||||
sum_nonspecular_weight += sc->sample_weight;
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "kernel/closure/alloc.h"
|
||||
#include "kernel/closure/bsdf_diffuse.h"
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/bssrdf.h"
|
||||
#include "kernel/closure/volume.h"
|
||||
|
||||
@ -53,9 +52,6 @@ ccl_device int subsurface_bounce(KernelGlobals kg,
|
||||
|
||||
/* Compute weight, optionally including Fresnel from entry point. */
|
||||
Spectrum weight = surface_shader_bssrdf_sample_weight(sd, sc);
|
||||
if (bssrdf->roughness != FLT_MAX) {
|
||||
path_flag |= PATH_RAY_SUBSURFACE_USE_FRESNEL;
|
||||
}
|
||||
|
||||
if (sd->flag & SD_BACKFACING) {
|
||||
path_flag |= PATH_RAY_SUBSURFACE_BACKFACING;
|
||||
@ -103,24 +99,12 @@ ccl_device void subsurface_shader_data_setup(KernelGlobals kg,
|
||||
|
||||
const Spectrum weight = one_spectrum();
|
||||
|
||||
if (path_flag & PATH_RAY_SUBSURFACE_USE_FRESNEL) {
|
||||
ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(PrincipledDiffuseBsdf), weight);
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->roughness = FLT_MAX;
|
||||
sd->flag |= bsdf_principled_diffuse_setup(bsdf, PRINCIPLED_DIFFUSE_LAMBERT_EXIT);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||
}
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1011,7 +1011,7 @@ ccl_device Spectrum surface_shader_diffuse(KernelGlobals kg, ccl_private const S
|
||||
ccl_private const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSSRDF(sc->type))
|
||||
eval += bsdf_albedo(sd, sc, true, true);
|
||||
eval += bsdf_albedo(kg, sd, sc, true, true);
|
||||
}
|
||||
|
||||
return eval;
|
||||
@ -1025,7 +1025,7 @@ ccl_device Spectrum surface_shader_glossy(KernelGlobals kg, ccl_private const Sh
|
||||
ccl_private const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if (CLOSURE_IS_BSDF_GLOSSY(sc->type) || CLOSURE_IS_GLASS(sc->type))
|
||||
eval += bsdf_albedo(sd, sc, true, false);
|
||||
eval += bsdf_albedo(kg, sd, sc, true, false);
|
||||
}
|
||||
|
||||
return eval;
|
||||
@ -1039,7 +1039,7 @@ ccl_device Spectrum surface_shader_transmission(KernelGlobals kg, ccl_private co
|
||||
ccl_private const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type) || CLOSURE_IS_GLASS(sc->type))
|
||||
eval += bsdf_albedo(sd, sc, false, true);
|
||||
eval += bsdf_albedo(kg, sd, sc, false, true);
|
||||
}
|
||||
|
||||
return eval;
|
||||
|
@ -55,6 +55,14 @@ static_assert(sizeof(ShaderGlobals) == sizeof(OSL::ShaderGlobals) &&
|
||||
|
||||
#include "closures_template.h"
|
||||
|
||||
static OSL::ClosureParam *osl_closure_layer_params()
|
||||
{
|
||||
static OSL::ClosureParam params[] = {CLOSURE_CLOSURE_PARAM(LayerClosure, top),
|
||||
CLOSURE_CLOSURE_PARAM(LayerClosure, base),
|
||||
CLOSURE_FINISH_PARAM(LayerClosure)};
|
||||
return params;
|
||||
}
|
||||
|
||||
void OSLRenderServices::register_closures(OSL::ShadingSystem *ss)
|
||||
{
|
||||
#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
|
||||
@ -62,6 +70,8 @@ void OSLRenderServices::register_closures(OSL::ShadingSystem *ss)
|
||||
#lower, OSL_CLOSURE_##Upper##_ID, osl_closure_##lower##_params(), nullptr, nullptr);
|
||||
|
||||
#include "closures_template.h"
|
||||
ss->register_closure(
|
||||
"layer", OSL_CLOSURE_LAYER_ID, osl_closure_layer_params(), nullptr, nullptr);
|
||||
}
|
||||
|
||||
/* Surface & Background */
|
||||
|
@ -7,26 +7,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// clang-format off
|
||||
#include "kernel/closure/alloc.h"
|
||||
#include "kernel/closure/bsdf_util.h"
|
||||
#include "kernel/closure/bsdf_ashikhmin_velvet.h"
|
||||
#include "kernel/closure/bsdf_diffuse.h"
|
||||
#include "kernel/closure/bsdf_microfacet.h"
|
||||
#include "kernel/closure/bsdf_oren_nayar.h"
|
||||
#include "kernel/closure/bsdf_sheen.h"
|
||||
#include "kernel/closure/bsdf_transparent.h"
|
||||
#include "kernel/closure/bsdf_ashikhmin_shirley.h"
|
||||
#include "kernel/closure/bsdf_toon.h"
|
||||
#include "kernel/closure/bsdf_hair.h"
|
||||
#include "kernel/closure/bsdf_hair_principled.h"
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/volume.h"
|
||||
#include "kernel/closure/bsdf_diffuse_ramp.h"
|
||||
#include "kernel/closure/bsdf_phong_ramp.h"
|
||||
#include "kernel/closure/bssrdf.h"
|
||||
#include "kernel/closure/bsdf.h"
|
||||
#include "kernel/closure/emissive.h"
|
||||
// clang-format on
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@ -42,6 +25,12 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
#include "closures_template.h"
|
||||
|
||||
struct ccl_align(8) LayerClosure
|
||||
{
|
||||
ccl_private const OSLClosure *base;
|
||||
ccl_private const OSLClosure *top;
|
||||
};
|
||||
|
||||
ccl_device_forceinline bool osl_closure_skip(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
@ -65,7 +54,8 @@ ccl_device void osl_closure_diffuse_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const DiffuseClosure *closure)
|
||||
ccl_private const DiffuseClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
|
||||
return;
|
||||
@ -86,7 +76,8 @@ ccl_device void osl_closure_oren_nayar_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const OrenNayarClosure *closure)
|
||||
ccl_private const OrenNayarClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
|
||||
return;
|
||||
@ -108,7 +99,8 @@ ccl_device void osl_closure_translucent_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const TranslucentClosure *closure)
|
||||
ccl_private const TranslucentClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
|
||||
return;
|
||||
@ -129,7 +121,8 @@ ccl_device void osl_closure_reflection_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const ReflectionClosure *closure)
|
||||
ccl_private const ReflectionClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_SINGULAR)) {
|
||||
return;
|
||||
@ -151,7 +144,8 @@ ccl_device void osl_closure_refraction_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const RefractionClosure *closure)
|
||||
ccl_private const RefractionClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_SINGULAR)) {
|
||||
return;
|
||||
@ -174,7 +168,8 @@ ccl_device void osl_closure_transparent_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const TransparentClosure *closure)
|
||||
ccl_private const TransparentClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
bsdf_transparent_setup(sd, rgb_to_spectrum(weight), path_flag);
|
||||
}
|
||||
@ -184,7 +179,8 @@ ccl_device void osl_closure_dielectric_bsdf_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const DielectricBSDFClosure *closure)
|
||||
ccl_private const DielectricBSDFClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
const bool has_reflection = !is_zero(closure->reflection_tint);
|
||||
const bool has_transmission = !is_zero(closure->transmission_tint);
|
||||
@ -243,13 +239,18 @@ ccl_device void osl_closure_dielectric_bsdf_setup(KernelGlobals kg,
|
||||
fresnel->reflection_tint = rgb_to_spectrum(closure->reflection_tint);
|
||||
fresnel->transmission_tint = rgb_to_spectrum(closure->transmission_tint);
|
||||
bsdf_microfacet_setup_fresnel_dielectric_tint(kg, bsdf, sd, fresnel, preserve_energy);
|
||||
|
||||
if (layer_albedo != NULL && has_reflection && !has_transmission) {
|
||||
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device void osl_closure_conductor_bsdf_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const ConductorBSDFClosure *closure)
|
||||
ccl_private const ConductorBSDFClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
|
||||
return;
|
||||
@ -295,7 +296,8 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const GeneralizedSchlickBSDFClosure *closure)
|
||||
ccl_private const GeneralizedSchlickBSDFClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
const bool has_reflection = !is_zero(closure->reflection_tint);
|
||||
const bool has_transmission = !is_zero(closure->transmission_tint);
|
||||
@ -319,11 +321,21 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
|
||||
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
||||
bsdf->alpha_x = closure->alpha_x;
|
||||
bsdf->alpha_y = closure->alpha_y;
|
||||
bsdf->ior = ior_from_F0(average(closure->f0));
|
||||
bsdf->T = closure->T;
|
||||
|
||||
if (closure->exponent < 0.0f) {
|
||||
/* Trick for principled BSDF: Since we use the real Fresnel equation and remap
|
||||
* to the F0...F90 range, this allows us to use the real IOR.
|
||||
* Computing it back from F0 might give a different result in case of specular
|
||||
* tinting. */
|
||||
bsdf->ior = -closure->exponent;
|
||||
}
|
||||
else {
|
||||
bsdf->ior = ior_from_F0(average(closure->f0));
|
||||
}
|
||||
if (sd->flag & SD_BACKFACING) {
|
||||
bsdf->ior = 1.0f / bsdf->ior;
|
||||
}
|
||||
bsdf->T = closure->T;
|
||||
|
||||
bool preserve_energy = false;
|
||||
|
||||
@ -360,6 +372,10 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
|
||||
fresnel->f90 = rgb_to_spectrum(closure->f90);
|
||||
fresnel->exponent = closure->exponent;
|
||||
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, preserve_energy);
|
||||
|
||||
if (layer_albedo != NULL && has_reflection && !has_transmission) {
|
||||
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Standard microfacet closures */
|
||||
@ -368,7 +384,8 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const MicrofacetClosure *closure)
|
||||
ccl_private const MicrofacetClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
const int label = (closure->refract) ? LABEL_TRANSMIT : LABEL_REFLECT;
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | label)) {
|
||||
@ -405,7 +422,7 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
|
||||
}
|
||||
/* Clearcoat */
|
||||
else if (closure->distribution == make_string("clearcoat", 3490136178980547276ull)) {
|
||||
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
|
||||
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(kg, bsdf, sd);
|
||||
}
|
||||
/* GGX (either single- or multi-scattering) */
|
||||
else {
|
||||
@ -424,6 +441,10 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
|
||||
bsdf_microfacet_setup_fresnel_constant(kg, bsdf, sd, rgb_to_spectrum(weight));
|
||||
}
|
||||
}
|
||||
|
||||
if (layer_albedo != NULL && closure->refract == 0) {
|
||||
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Special-purpose Microfacet closures */
|
||||
@ -433,7 +454,8 @@ ccl_device void osl_closure_microfacet_multi_ggx_glass_setup(
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const MicrofacetMultiGGXGlassClosure *closure)
|
||||
ccl_private const MicrofacetMultiGGXGlassClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
/* Technically, the MultiGGX closure may also transmit. However,
|
||||
* since this is set statically and only used for caustic flags, this
|
||||
@ -464,7 +486,8 @@ ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup(
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const MicrofacetMultiGGXClosure *closure)
|
||||
ccl_private const MicrofacetMultiGGXClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
|
||||
return;
|
||||
@ -485,49 +508,10 @@ ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup(
|
||||
|
||||
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
||||
bsdf_microfacet_setup_fresnel_constant(kg, bsdf, sd, rgb_to_spectrum(closure->color));
|
||||
}
|
||||
|
||||
ccl_device void osl_closure_microfacet_aniso_fresnel_setup(
|
||||
KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const MicrofacetAnisoFresnelClosure *closure)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
|
||||
return;
|
||||
if (layer_albedo != NULL) {
|
||||
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
|
||||
}
|
||||
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
|
||||
if (!bsdf) {
|
||||
return;
|
||||
}
|
||||
|
||||
ccl_private FresnelGeneralizedSchlick *fresnel = (ccl_private FresnelGeneralizedSchlick *)
|
||||
closure_alloc_extra(sd, sizeof(FresnelGeneralizedSchlick));
|
||||
if (!fresnel) {
|
||||
return;
|
||||
}
|
||||
|
||||
bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N);
|
||||
bsdf->alpha_x = closure |