[Bf-blender-cvs] [68573757bc5] microfacet_hair: Cycles: initial commit of microfacet hair bsdf
Weizhen Huang
noreply at git.blender.org
Tue Dec 6 18:52:09 CET 2022
Commit: 68573757bc5fb615f6bf2e27056f6e10a556bf70
Author: Weizhen Huang
Date: Tue Dec 6 18:43:56 2022 +0100
Branches: microfacet_hair
https://developer.blender.org/rB68573757bc5fb615f6bf2e27056f6e10a556bf70
Cycles: initial commit of microfacet hair bsdf
This is an implementation of the paper [A Microfacet-based Hair Scattering Model](https://onlinelibrary.wiley.com/doi/full/10.1111/cgf.14588) by Weizhen Huang, Matthias Hullin, and Johannes Hanika.
Original implementation in [Mitsuba 2](https://github.com/RiverIntheSky/roughhair) by Weizhen Huang.
Adapted to Cycles by Olivier Maury D16682 and Christophe Hery.
===================================================================
M intern/cycles/blender/shader.cpp
M intern/cycles/kernel/CMakeLists.txt
M intern/cycles/kernel/closure/bsdf.h
A intern/cycles/kernel/closure/bsdf_hair_microfacet.h
M intern/cycles/kernel/film/denoising_passes.h
M intern/cycles/kernel/osl/shaders/CMakeLists.txt
A intern/cycles/kernel/osl/shaders/node_microfacet_hair_bsdf.osl
M intern/cycles/kernel/osl/shaders/stdcycles.h
M intern/cycles/kernel/svm/closure.h
M intern/cycles/kernel/svm/types.h
M intern/cycles/scene/shader_graph.cpp
M intern/cycles/scene/shader_nodes.cpp
M intern/cycles/scene/shader_nodes.h
M release/datafiles/locale
M release/scripts/addons
M source/blender/blenkernel/BKE_node.h
M source/blender/gpu/shaders/material/gpu_shader_material_hair.glsl
M source/blender/makesdna/DNA_node_types.h
M source/blender/makesrna/intern/rna_nodetree.c
M source/blender/nodes/NOD_static_types.h
M source/blender/nodes/shader/CMakeLists.txt
M source/blender/nodes/shader/node_shader_register.cc
M source/blender/nodes/shader/node_shader_register.hh
M source/blender/nodes/shader/node_shader_tree.cc
A source/blender/nodes/shader/nodes/node_shader_bsdf_hair_microfacet.cc
===================================================================
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index f25e98469fb..43bc5538628 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -660,6 +660,21 @@ static ShaderNode *add_node(Scene *scene,
NODE_PRINCIPLED_HAIR_REFLECTANCE));
node = principled_hair;
}
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfHairMicrofacet)) {
+ BL::ShaderNodeBsdfHairMicrofacet b_microfacet_hair_node(b_node);
+ MicrofacetHairBsdfNode *microfacet_hair = graph->create_node<MicrofacetHairBsdfNode>();
+ microfacet_hair->set_parametrization(
+ (NodeMicrofacetHairParametrization)get_enum(b_microfacet_hair_node.ptr,
+ "parametrization",
+ NODE_MICROFACET_HAIR_NUM,
+ NODE_MICROFACET_HAIR_REFLECTANCE));
+ microfacet_hair->set_model_type(
+ (NodeMicrofacetHairModelType)get_enum(b_microfacet_hair_node.ptr,
+ "model_type",
+ NODE_MICROFACET_HAIR_MODEL_TYPE_NUM,
+ NODE_MICROFACET_HAIR_CIRCULAR_GGX));
+ node = microfacet_hair;
+ }
else if (b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
PrincipledBsdfNode *principled = graph->create_node<PrincipledBsdfNode>();
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 9dc343f597d..a203adda324 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -128,6 +128,7 @@ set(SRC_KERNEL_CLOSURE_HEADERS
closure/bsdf_principled_diffuse.h
closure/bsdf_principled_sheen.h
closure/bsdf_hair_principled.h
+ closure/bsdf_hair_microfacet.h
)
set(SRC_KERNEL_SVM_HEADERS
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 2f5c5d7bd0c..23c64205c70 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -18,6 +18,7 @@
#include "kernel/closure/bsdf_toon.h"
#include "kernel/closure/bsdf_hair.h"
#include "kernel/closure/bsdf_hair_principled.h"
+#include "kernel/closure/bsdf_hair_microfacet.h"
#include "kernel/closure/bsdf_principled_diffuse.h"
#include "kernel/closure/bsdf_principled_sheen.h"
#include "kernel/closure/bssrdf.h"
@@ -243,6 +244,10 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
label = bsdf_principled_hair_sample(
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
break;
+ case CLOSURE_BSDF_HAIR_MICROFACET_ID:
+ label = bsdf_microfacet_hair_sample(
+ kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
+ break;
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
label = bsdf_principled_diffuse_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
*sampled_roughness = one_float2();
@@ -408,6 +413,11 @@ 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_HAIR_MICROFACET_ID:
+ alpha = ((ccl_private MicrofacetHairBSDF *)sc)->roughness;
+ *roughness = make_float2(alpha, alpha);
+ *eta = ((ccl_private MicrofacetHairBSDF *)sc)->eta;
+ break;
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
*roughness = one_float2();
*eta = 1.0f;
@@ -504,6 +514,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
label = LABEL_TRANSMIT | LABEL_GLOSSY;
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ case CLOSURE_BSDF_HAIR_MICROFACET_ID:
if (bsdf_is_transmission(sc, omega_in))
label = LABEL_TRANSMIT | LABEL_GLOSSY;
else
@@ -609,6 +620,9 @@ ccl_device_inline
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
break;
+ case CLOSURE_BSDF_HAIR_MICROFACET_ID:
+ eval = bsdf_microfacet_hair_eval(kg, sd, sc, omega_in, pdf);
+ break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
eval = bsdf_hair_reflection_eval(sc, sd->I, omega_in, pdf);
break;
@@ -676,6 +690,9 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
bsdf_principled_hair_blur(sc, roughness);
break;
+ case CLOSURE_BSDF_HAIR_MICROFACET_ID:
+ bsdf_microfacet_hair_blur(sc, roughness);
+ break;
default:
break;
}
diff --git a/intern/cycles/kernel/closure/bsdf_hair_microfacet.h b/intern/cycles/kernel/closure/bsdf_hair_microfacet.h
new file mode 100644
index 00000000000..6095ebcac41
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_hair_microfacet.h
@@ -0,0 +1,1598 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2018-2022 Blender Foundation */
+
+#pragma once
+
+#ifndef __KERNEL_GPU__
+# include <fenv.h>
+#endif
+
+#include "kernel/util/color.h"
+
+CCL_NAMESPACE_BEGIN
+
+typedef struct MicrofacetHairExtra {
+ float R;
+ float TT;
+ float TRT;
+
+ float eccentricity;
+ float twist_rate;
+ float attr_descr_intercept;
+ float attr_descr_length;
+
+ float axis_rot;
+ float diffraction_weight;
+ float pad1, pad2, pad3;
+
+ /* Geometry data. */
+ float4 geom;
+} MicrofacetHairExtra;
+
+typedef struct MicrofacetHairBSDF {
+ SHADER_CLOSURE_BASE;
+
+ /* Absorption coefficient. */
+ Spectrum sigma;
+ /* Microfacet distribution roughness. */
+ float roughness;
+ /* Cuticle tilt angle. */
+ float alpha;
+ /* IOR. */
+ float eta;
+
+ /* Blur. */
+ float blur;
+
+ /* Circular/Ellipitic and GGX/Beckmann. */
+ int model_type;
+
+ /* Extra closure. */
+ ccl_private MicrofacetHairExtra *extra;
+} MicrofacetHairBSDF;
+
+static_assert(sizeof(ShaderClosure) >= sizeof(MicrofacetHairBSDF),
+ "MicrofacetHairBSDF is too large!");
+static_assert(sizeof(ShaderClosure) >= sizeof(MicrofacetHairExtra),
+ "MicrofacetHairExtra is too large!");
+
+#ifdef __HAIR__
+/* Set up the hair closure. */
+ccl_device int bsdf_microfacet_hair_setup(ccl_private ShaderData *sd,
+ ccl_private MicrofacetHairBSDF *bsdf)
+{
+ bsdf->type = CLOSURE_BSDF_HAIR_MICROFACET_ID;
+
+ bsdf->roughness = clamp(bsdf->roughness, 0.001f, 1.0f);
+
+ /* Compute local frame, aligned to curve tangent and ray direction. */
+ float3 X = safe_normalize(sd->dPdu);
+ float3 Y = safe_normalize(cross(X, sd->I));
+
+ /* h -1..0..1 means the rays goes from grazing the hair, to hitting it at
+ * the center, to grazing the other edge. This is the sine of the angle
+ * between sd->Ng and Z, as seen from the tangent X. */
+
+ /* TODO: we convert this value to a cosine later and discard the sign, so
+ * we could probably save some operations. */
+ float h = (sd->type & PRIMITIVE_CURVE_RIBBON) ? -sd->v : -dot(Y, sd->Ng);
+
+ kernel_assert(fabsf(h) < 1.0f + 1e-4f);
+ kernel_assert(isfinite_safe(Y));
+ kernel_assert(isfinite_safe(h));
+
+ bsdf->extra->geom = make_float4(Y.x, Y.y, Y.z, h);
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG | SD_BSDF_HAS_TRANSMISSION;
+}
+
+#endif /* __HAIR__ */
+
+ccl_device_inline float3 make_float3_from_float(const float f)
+{
+ return make_float3(f, f, f);
+}
+
+ccl_device_inline float3 reflect_vector(const float3 w, const float3 n)
+{
+ return 2.f * dot(w, n) * n - w;
+}
+
+ccl_device float3 refract_vector(const float3 w,
+ const float3 n,
+ const float cos_theta_t,
+ const float eta_ti)
+{
+ return n * (dot(w, n) * eta_ti + cos_theta_t) - w * eta_ti;
+}
+
+ccl_device_inline float3 microfacet_visible_normal_sample(KernelGlobals kg,
+ const bool beckmann,
+ const float roughness,
+ const float3 wi,
+ const float randu,
+ const float randv,
+ ccl_private float *G1i)
+{
+ /* Step 1 : stretch wi */
+ float3 omega_i_ = normalize(make_float3(roughness * wi.x, roughness * wi.y, wi.z));
+
+ /* get polar coordinates of omega_i_ */
+ float costheta_ = 1.f;
+ float sintheta_ = 0.f;
+ float cosphi_ = 1.f;
+ float sinphi_ = 0.f;
+
+ if (omega_i_.z < 0.99999f) {
+ costheta_ = omega_i_.z;
+ sintheta_ = safe_sqrtf(1.f - costheta_ * costheta_);
+
+ float invlen = 1.f / sintheta_;
+ cosphi_ = omega_i_.x * invlen;
+ sinphi_ = omega_i_.y * invlen;
+ }
+
+ /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */
+ float slope_x, slope_y;
+
+ if (beckmann) {
+ microfacet_beckmann_sample_slopes(
+ kg, costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
+ }
+ else {
+ microfacet_ggx_sample_slopes(costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
+ }
+
+ /* 3. rotate */
+ float tmp = cosphi_ * slope_x - sinphi_ * slope_y;
+ slope_y = sinphi_ * slope_x + cosphi_ * slope_y;
+ slope_x = tmp;
+
+ /* 4. unstretch */
+ slope_x = roughness * slope_x;
+ slope_y = roughness * slope_y;
+
+ /* 5. compute normal */
+ return normalize(make_float3(-slope_x, -slope_y, 1.f));
+}
+
+/* returns sin_theta */
+ccl_device_inline float sintheta(const float3 w)
+{
+ return w.y;
+}
+
+/* returns cos_theta */
+ccl_device_inline float costheta(const float3 w)
+{
+ return safe_sqrtf(sqr(w.x) + sqr(w.z));
+}
+
+/* returns tan_theta */
+ccl_device_inline float tantheta(const float3 w)
+{
+ return sintheta(w) / costheta(w);
+}
+
+/* extract theta coordinate from 3D direction
+ * -pi < theta < pi */
+ccl_device_inline float dir_theta(const float3 w)
+{
+ return atan2f(sintheta(w), costheta(w));
+}
+
+/* extract phi coordinate from 3D direction.
+ * -pi < phi < pi
+ * Assuming phi(wi
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list