Add support for OSL shader to microfacet hair model
This commit is contained in:
parent
e69877c217
commit
f0529cfabc
|
@ -17,8 +17,6 @@ typedef struct MicrofacetHairExtra {
|
|||
float TT;
|
||||
float TRT;
|
||||
|
||||
float aspect_ratio;
|
||||
|
||||
/* Geometry data. */
|
||||
float4 geom;
|
||||
} MicrofacetHairExtra;
|
||||
|
@ -41,6 +39,9 @@ typedef struct MicrofacetHairBSDF {
|
|||
/* Circular/Elliptical */
|
||||
int cross_section;
|
||||
|
||||
/* The ratio of the minor axis to the major axis. */
|
||||
float aspect_ratio;
|
||||
|
||||
/* Extra closure. */
|
||||
ccl_private MicrofacetHairExtra *extra;
|
||||
} MicrofacetHairBSDF;
|
||||
|
@ -74,8 +75,20 @@ ccl_device int bsdf_microfacet_hair_setup(ccl_private ShaderData *sd,
|
|||
kernel_assert(isfinite_safe(h));
|
||||
|
||||
if (bsdf->cross_section == NODE_MICROFACET_HAIR_ELLIPTIC) {
|
||||
/* Local frame is independent of the ray direction for elliptical hairs. */
|
||||
bsdf->extra->geom.w = h;
|
||||
if (bsdf->aspect_ratio > 1.0f) {
|
||||
bsdf->aspect_ratio = 1.0f / bsdf->aspect_ratio;
|
||||
|
||||
/* Switch major and minor axis. */
|
||||
const float3 minor_axis = safe_normalize(cross(
|
||||
sd->dPdu, make_float3(bsdf->extra->geom.x, bsdf->extra->geom.y, bsdf->extra->geom.z)));
|
||||
const float3 major_axis = safe_normalize(cross(minor_axis, sd->dPdu));
|
||||
|
||||
/* Local frame is independent of the ray direction for elliptical hairs. */
|
||||
bsdf->extra->geom = make_float4(major_axis.x, major_axis.y, major_axis.z, h);
|
||||
}
|
||||
else {
|
||||
bsdf->extra->geom.w = h;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bsdf->extra->geom = make_float4(X.x, X.y, X.z, h);
|
||||
|
@ -802,7 +815,7 @@ ccl_device float3 bsdf_microfacet_hair_eval_r_elliptic(ccl_private const ShaderC
|
|||
/* get elliptical cross section characteristic */
|
||||
const float a = 1.0f;
|
||||
/* TODO: rename this as aspect ratio? e is in [0, 0.85], b is in [0.52, 1]. */
|
||||
const float b = bsdf->extra->aspect_ratio;
|
||||
const float b = bsdf->aspect_ratio;
|
||||
const float e2 = 1.0f - sqr(b / a);
|
||||
|
||||
/* this follows blender's convention (unlike the circular case?) */
|
||||
|
@ -898,7 +911,7 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt_elliptic(KernelGlobals kg,
|
|||
return zero_float3();
|
||||
}
|
||||
|
||||
/* this follows blender's convention (unlike the circular case?) */
|
||||
/* TODO: switch wi and wo? */
|
||||
const float3 wo = wi_;
|
||||
const float3 wi = wo_;
|
||||
|
||||
|
@ -923,7 +936,7 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt_elliptic(KernelGlobals kg,
|
|||
|
||||
/* get elliptical cross section characteristic */
|
||||
const float a = 1.0f;
|
||||
const float b = bsdf->extra->aspect_ratio;
|
||||
const float b = bsdf->aspect_ratio;
|
||||
const float e2 = 1.0f - sqr(b / a); /* Squared Eccentricity. */
|
||||
|
||||
const float gamma_m_min = to_gamma(phi_m_min, a, b) + 1e-3f;
|
||||
|
@ -1094,7 +1107,7 @@ ccl_device Spectrum bsdf_microfacet_hair_eval_elliptic(KernelGlobals kg,
|
|||
const float3 wo = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||
|
||||
/* Treat as transparent material if intersection lies outside of the projected radius. */
|
||||
const float e2 = 1.0f - sqr(bsdf->extra->aspect_ratio);
|
||||
const float e2 = 1.0f - sqr(bsdf->aspect_ratio);
|
||||
const float radius = sqrtf(1.0f - e2 * sqr(sin_phi(wi)));
|
||||
if (fabsf(bsdf->extra->geom.w) > radius) {
|
||||
*pdf = 0.0f;
|
||||
|
@ -1136,7 +1149,7 @@ ccl_device int bsdf_microfacet_hair_sample_elliptic(const KernelGlobals kg,
|
|||
|
||||
/* get elliptical cross section characteristic */
|
||||
const float a = 1.0f;
|
||||
const float b = bsdf->extra->aspect_ratio;
|
||||
const float b = bsdf->aspect_ratio;
|
||||
const float e2 = 1.0f - sqr(b / a);
|
||||
|
||||
/* macronormal */
|
||||
|
@ -1345,7 +1358,7 @@ ccl_device Spectrum bsdf_microfacet_hair_eval(KernelGlobals kg,
|
|||
{
|
||||
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)sc;
|
||||
|
||||
if (bsdf->cross_section == NODE_MICROFACET_HAIR_CIRCULAR || bsdf->extra->aspect_ratio == 1.0f) {
|
||||
if (bsdf->cross_section == NODE_MICROFACET_HAIR_CIRCULAR || bsdf->aspect_ratio == 1.0f) {
|
||||
return bsdf_microfacet_hair_eval_circular(kg, sd, sc, omega_in, pdf);
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1378,7 @@ ccl_device int bsdf_microfacet_hair_sample(KernelGlobals kg,
|
|||
{
|
||||
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)sc;
|
||||
|
||||
if (bsdf->cross_section == NODE_MICROFACET_HAIR_CIRCULAR || bsdf->extra->aspect_ratio == 1.0f) {
|
||||
if (bsdf->cross_section == NODE_MICROFACET_HAIR_CIRCULAR || bsdf->aspect_ratio == 1.0f) {
|
||||
return bsdf_microfacet_hair_sample_circular(
|
||||
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,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/volume.h"
|
||||
|
@ -1121,6 +1122,49 @@ ccl_device void osl_closure_principled_hair_setup(KernelGlobals kg,
|
|||
#endif
|
||||
}
|
||||
|
||||
ccl_device void osl_closure_microfacet_hair_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const MicrofacetHairClosure *closure)
|
||||
{
|
||||
#ifdef __HAIR__
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetHairBSDF), rgb_to_spectrum(weight));
|
||||
if (!bsdf) {
|
||||
return;
|
||||
}
|
||||
|
||||
ccl_private MicrofacetHairExtra *extra = (ccl_private MicrofacetHairExtra *)closure_alloc_extra(
|
||||
sd, sizeof(MicrofacetHairExtra));
|
||||
if (!extra) {
|
||||
return;
|
||||
}
|
||||
|
||||
bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
|
||||
bsdf->sigma = closure->sigma;
|
||||
bsdf->roughness = closure->roughness;
|
||||
bsdf->tilt = closure->tilt;
|
||||
bsdf->eta = closure->eta;
|
||||
bsdf->cross_section = closure->cross_section;
|
||||
bsdf->distribution_type = closure->distribution_type;
|
||||
bsdf->aspect_ratio = closure->aspect_ratio;
|
||||
|
||||
bsdf->extra = extra;
|
||||
bsdf->extra->R = closure->reflection;
|
||||
bsdf->extra->TT = closure->transmission;
|
||||
bsdf->extra->TRT = closure->secondary_reflection;
|
||||
bsdf->extra->geom = make_float4(
|
||||
closure->major_axis.x, closure->major_axis.y, closure->major_axis.z, 0.0f);
|
||||
|
||||
sd->flag |= bsdf_microfacet_hair_setup(sd, bsdf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Volume */
|
||||
|
||||
ccl_device void osl_closure_absorption_setup(KernelGlobals kg,
|
||||
|
|
|
@ -245,6 +245,21 @@ OSL_CLOSURE_STRUCT_BEGIN(PrincipledHair, principled_hair)
|
|||
OSL_CLOSURE_STRUCT_MEMBER(PrincipledHair, FLOAT, float, eta, NULL)
|
||||
OSL_CLOSURE_STRUCT_END(PrincipledHair, principled_hair)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(MicrofacetHair, microfacet_hair)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, VECTOR, packed_float3, N, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, VECTOR, packed_float3, sigma, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, roughness, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, tilt, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, eta, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, INT, int, distribution_type, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, INT, int, cross_section, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, aspect_ratio, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, reflection, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, transmission, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, secondary_reflection, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, VECTOR, packed_float3, major_axis, NULL)
|
||||
OSL_CLOSURE_STRUCT_END(MicrofacetHair, microfacet_hair)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(VolumeAbsorption, absorption)
|
||||
OSL_CLOSURE_STRUCT_END(VolumeAbsorption, absorption)
|
||||
|
||||
|
|
|
@ -51,6 +51,10 @@ shader node_microfacet_hair_bsdf(color Color = color(0.017513, 0.005763, 0.00205
|
|||
float IOR = 1.55,
|
||||
string AttrRandom = "geom:curve_random",
|
||||
float Random = 0.0,
|
||||
float AspectRatio = 0.85,
|
||||
float Reflection = 1.0,
|
||||
float Transmission = 1.0,
|
||||
float SecondaryReflection = 1.0,
|
||||
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
|
@ -99,5 +103,26 @@ shader node_microfacet_hair_bsdf(color Color = color(0.017513, 0.005763, 0.00205
|
|||
sigma = m_sigma_from_concentration(0.0, 0.8054375);
|
||||
}
|
||||
|
||||
BSDF = microfacet_hair(Normal, sigma, roughness, Offset, IOR);
|
||||
int distribution_type_enum = (distribution_type == "GGX") ? 0 : 1;
|
||||
int cross_section_enum = 0;
|
||||
normal major_axis = 0.0;
|
||||
|
||||
if (cross_section == "Elliptical") {
|
||||
cross_section_enum = 1;
|
||||
major_axis = 1.0;
|
||||
getattribute("geom:N", major_axis);
|
||||
}
|
||||
|
||||
BSDF = microfacet_hair(Normal,
|
||||
sigma,
|
||||
roughness,
|
||||
Offset,
|
||||
IOR,
|
||||
distribution_type_enum,
|
||||
cross_section_enum,
|
||||
AspectRatio,
|
||||
Reflection,
|
||||
Transmission,
|
||||
SecondaryReflection,
|
||||
major_axis);
|
||||
}
|
||||
|
|
|
@ -60,8 +60,18 @@ closure color principled_hair(normal N,
|
|||
float coat,
|
||||
float alpha,
|
||||
float eta) BUILTIN;
|
||||
closure color
|
||||
microfacet_hair(normal N, color sigma, float roughness, float tilt, float eta) BUILTIN;
|
||||
closure color microfacet_hair(normal N,
|
||||
color sigma,
|
||||
float roughness,
|
||||
float tilt,
|
||||
float eta,
|
||||
int distribution_type,
|
||||
int cross_section,
|
||||
float aspect_ratio,
|
||||
float reflection,
|
||||
float transmission,
|
||||
float secondary_reflection,
|
||||
normal major_axis) BUILTIN;
|
||||
|
||||
// Volume
|
||||
closure color henyey_greenstein(float g) BUILTIN;
|
||||
|
|
|
@ -1002,27 +1002,16 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
}
|
||||
|
||||
if (cross_section == NODE_MICROFACET_HAIR_ELLIPTIC) {
|
||||
|
||||
uint aspect_ratio_ofs, temp;
|
||||
svm_unpack_node_uchar4(data_node5.x, &aspect_ratio_ofs, &temp, &temp, &temp);
|
||||
|
||||
float aspect_ratio = stack_load_float_default(stack, aspect_ratio_ofs, data_node5.y);
|
||||
|
||||
/* Aspect Ratio */
|
||||
bsdf->extra->aspect_ratio = (aspect_ratio > 1.0f) ? 1.0f / aspect_ratio : aspect_ratio;
|
||||
bsdf->aspect_ratio = stack_load_float_default(stack, aspect_ratio_ofs, data_node5.y);
|
||||
|
||||
const AttributeDescriptor attr_descr_normal = find_attribute(kg, sd, data_node5.z);
|
||||
const float3 normal = curve_attribute_float3(kg, sd, attr_descr_normal, NULL, NULL);
|
||||
const float3 binormal = safe_normalize(cross(sd->dPdu, normal));
|
||||
const float3 major_axis = curve_attribute_float3(kg, sd, attr_descr_normal, NULL, NULL);
|
||||
|
||||
/* Align X axis with the ellipse major axis. */
|
||||
if (aspect_ratio > 1.0f) {
|
||||
const float3 normal = safe_normalize(cross(binormal, sd->dPdu));
|
||||
bsdf->extra->geom = make_float4(normal.x, normal.y, normal.z, 0.0f);
|
||||
}
|
||||
else {
|
||||
bsdf->extra->geom = make_float4(binormal.x, binormal.y, binormal.z, 0.0f);
|
||||
}
|
||||
/* Align ellipse major axis with the curve normal direction. */
|
||||
bsdf->extra->geom = make_float4(major_axis.x, major_axis.y, major_axis.z, 0.0f);
|
||||
}
|
||||
|
||||
sd->flag |= bsdf_microfacet_hair_setup(sd, bsdf);
|
||||
|
|
|
@ -3653,8 +3653,8 @@ NODE_DEFINE(MicrofacetHairBsdfNode)
|
|||
|
||||
/* Hair cross-section type specified as enum. */
|
||||
static NodeEnum cross_section_enum;
|
||||
distribution_type_enum.insert("Circular", NODE_MICROFACET_HAIR_CIRCULAR);
|
||||
distribution_type_enum.insert("Elliptical", NODE_MICROFACET_HAIR_ELLIPTIC);
|
||||
cross_section_enum.insert("Circular", NODE_MICROFACET_HAIR_CIRCULAR);
|
||||
cross_section_enum.insert("Elliptical", NODE_MICROFACET_HAIR_ELLIPTIC);
|
||||
SOCKET_ENUM(cross_section, "Cross Section", cross_section_enum, NODE_MICROFACET_HAIR_CIRCULAR);
|
||||
|
||||
/* Initialize sockets to their default values. */
|
||||
|
|
Loading…
Reference in New Issue