commit90778901c9Merge:76eebd93bf0026Author: Schoen <schoepas@deher1m1598.emea.adsint.biz> Date: Mon Apr 3 07:52:05 2017 +0200 Merge branch 'master' into cycles_disney_brdf commit76eebd9379Author: Schoen <schoepas@deher1m1598.emea.adsint.biz> Date: Thu Mar 30 15:34:20 2017 +0200 Updated copyright for the new files. commit013f4a152aAuthor: Schoen <schoepas@deher1m1598.emea.adsint.biz> Date: Thu Mar 30 15:32:55 2017 +0200 Switched from multiplication of base and subsurface color to blending between them using the subsurface parameter. commit482ec5d1f2Author: Schoen <schoepas@deher1m1598.emea.adsint.biz> Date: Mon Mar 13 15:47:12 2017 +0100 Fixed a bug that caused an additional white diffuse closure call when using path tracing. commit26e906d162Merge:0593b8c223aff9Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Feb 6 11:32:31 2017 +0100 Merge branch 'master' into cycles_disney_brdf commit0593b8c51bAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Feb 6 11:30:36 2017 +0100 Fixed the broken GLSL shader and implemented the Disney BRDF in the real-time view port. commit8c7e11423bAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Feb 3 14:24:05 2017 +0100 Fix to comply strict compiler flags and some code cleanup commit17724e9d2dMerge:379ba34520afa2Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jan 24 09:59:58 2017 +0100 Merge branch 'master' into cycles_disney_brdf commit379ba346b0Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jan 24 09:28:56 2017 +0100 Renamed the Disney BSDF to Principled BSDF. commitf80dcb4f34Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Dec 2 13:55:12 2016 +0100 Removed reflection call when roughness is low because of artifacts. commit732db8a57fAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Nov 16 09:22:25 2016 +0100 Indication if to use fresnel is now handled via the type of the BSDF. commit0103659f5eAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Nov 11 13:04:11 2016 +0100 Fixed an error in the clearcoat where it appeared too bright for default light sources (like directional lights) commit0aa68f5335Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Nov 7 12:04:38 2016 +0100 Resolved inconsistencies in using tabs and spaces commitf5897a9494Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Nov 7 08:13:41 2016 +0100 Improved the clearcoat part by using GTR1 instead of GTR2 commit3dfc240e61Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 31 11:31:36 2016 +0100 Use reflection BSDF for glossy reflections when roughness is 0.0 to reduce computational expense and some code cleanup Code cleanup includes: - Code style cleanup and removed unused code - Consolidated code in the bsdf_microfacet_multi_impl.h to reduce some computational expense commita2dd0c5fafAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Oct 26 08:51:10 2016 +0200 Fixed glossy reflections and refractions for low roughness values and cleaned up the code. For low roughness values, the reflections had some strange behavior. commit9817375912Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Oct 25 12:37:40 2016 +0200 Removed default values in setup functions and added extra functions for GGX with fresnel. commitbbc5d9d452Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Oct 25 11:09:36 2016 +0200 Switched from uniform to cosine hemisphere sampling for the diffuse and the sheen part. commitd52d8f2813Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 24 16:17:13 2016 +0200 Removed the color parameters from the diffuse and sheen shader and use them as closure weights instead. commit8f3d927385Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 24 09:57:06 2016 +0200 Fixed the issue with artifacts when using anisotropy without linking the tangent input to a tangent node. commitd93f680db9Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 24 09:14:51 2016 +0200 Added subsurface radius parameter to control the per color channel effection radius of the subsurface scattering. commitc708c3e53bAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 24 08:14:10 2016 +0200 Rearranged the inputs of the shader. commitdfbfff9c38Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Oct 21 09:27:05 2016 +0200 Put spaces in the parameter names of the shader node commite5a748ced1Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Oct 21 08:51:20 2016 +0200 Removed code that isn't in use anymore commit75992bebc1Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Oct 21 08:50:07 2016 +0200 Code style cleanup commit4dfcf455f7Merge:243a0e32cd6a89Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Thu Oct 20 10:41:50 2016 +0200 Merge branch 'master' into cycles_disney_brdf commit243a0e3eb8Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Thu Oct 20 10:01:45 2016 +0200 Switching between OSL and SVM is more consistant now when using Disney BSDF. There were some minor differences in the OSL implementation, e.g. the refraction roughness was missing. commit2a5ac50922Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 27 09:17:57 2016 +0200 Fixed a bug that caused transparency to be always white when using OSL and selecting GGX as distribution of the Disney BSDF commite1fa862391Merge:d0530a87f76f6fAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 27 08:59:32 2016 +0200 Merge branch 'master' into cycles_disney_brdf commitd0530a8af0Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 27 08:53:18 2016 +0200 Cleanup the Disney BSDF implementation and removing unneeded files. commit3f4fc826bdAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 27 08:36:07 2016 +0200 Unified the OSL implementation of the Disney clearcoat as a simple microfacet shader like it was previously done in SVM commit4d3a0032ecAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Sep 26 12:35:36 2016 +0200 Enhanced performance for Disney materials without subsurface scattering commit3cd5eb56cfAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Sep 16 08:47:56 2016 +0200 Fixed a bug in the Disney BSDF that caused specular reflections to be too bright and diffuse is now reacting to the roughness again - A normalization for the fresnel was missing which caused the specular reflections to become too bright for the single-scatter GGX - The roughness value for the diffuse BSSRDF part has always been overwritten and thus always 0 - Also the performance for refractive materials with roughness=0.0 has been improved commit7cb37d7119Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Thu Sep 8 12:24:43 2016 +0200 Added selection field to the Disney BSDF node for switching between "Multiscatter GGX" and "GGX" In the "GGX" mode there is an additional parameter for changing the refraction roughness for materials with smooth surfaces and rough interns (e.g. honey). With the "Multiscatter GGX" this effect can't be produced at the moment and so here will be no separation of the two roughness values. commitcdd29d06bbMerge:02c315ab40d1c1Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 6 15:59:05 2016 +0200 Merge branch 'master' into cycles_disney_brdf commit02c315aeb0Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 6 15:16:09 2016 +0200 Implemented the OSL part of the Disney shader commit5f880293aeMerge:630b80eb399a6dAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Sep 2 10:53:36 2016 +0200 Merge branch 'master' into cycles_disney_brdf commit630b80e08bAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Sep 2 10:52:13 2016 +0200 Fresnel in the microfacet multiscatter implementation improved commit0d9f4d7acbAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Aug 26 11:11:05 2016 +0200 Fixed refraction roughness problem (refractions were always 100% rough) and set IOR of clearcoat to 1.5 commit9eed34c7d9Merge:ef29aaeae475e3Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Aug 16 15:22:32 2016 +0200 Merge branch 'master' into cycles_disney_brdf commitef29aaee1aAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Aug 16 15:17:12 2016 +0200 Implemented the fresnel in the multi-scatter GGX for the Disney BSDF - The specular/metallic part uses the multi-scatter GGX - The fresnel of the metallic part is controlled by the specular value - The color of the reflection part when using transparency can be controlled by the specularTint value commit88567af085Merge:cc267e5285e082Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Aug 3 15:05:09 2016 +0200 Merge branch 'master' into cycles_disney_brdf commitcc267e52f2Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Aug 3 15:00:25 2016 +0200 Implemented the Disney clearcoat as a variation of the microfacet bsdf, removed the transparency roughness again and added an input for anisotropic rotations commit81f6c06b1fMerge:ece5a087065022Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Aug 3 11:42:02 2016 +0200 Merge branch 'master' into cycles_disney_brdf commitece5a08e0dAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jul 26 16:29:21 2016 +0200 Base color now applied again to the refraction of transparent Disney materials commite3aff6849eAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jul 26 16:05:19 2016 +0200 Added subsurface color parameter to the Disney shader commitb3ca6d8a2fAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jul 26 12:30:25 2016 +0200 Improvement of the SSS in the Disney shader * Now the bump normal is correctly used for the SSS. * SSS in Disney uses the Disney diffuse shader commitd68729300eAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jul 26 12:23:13 2016 +0200 Better calculation of the Disney diffuse part Now the values for NdotL und NdotV are clamped to 0.0f for a better look when using normal maps commitcb6e500b12Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Jul 25 16:26:42 2016 +0200 Now one can disable specular reflactions again by setting specular and metallic to 0 (cracked this in the previous commit) commitbfb9cb11b5Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Jul 25 16:11:07 2016 +0200 fixed the Disney SSS and cleaned the initialization of the Disney shaders commit642c0fdad1Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Jul 25 16:09:55 2016 +0200 fixed an error that was caused by the missing LABEL_REFLECT in the Disney diffuse shader commitc10b484dcaAuthor: Jens Verwiebe <info@jensverwiebe.de> Date: Fri Jul 22 01:15:21 2016 +0200 Rollback attempt to fix sss crashing, it prevented crash by disabling sss completely, thus useless commit462bba3f97Author: Jens Verwiebe <info@jensverwiebe.de> Date: Thu Jul 21 23:11:59 2016 +0200 Add an undef for sc_next for safety commit32d348577dAuthor: Jens Verwiebe <info@jensverwiebe.de> Date: Thu Jul 21 00:15:48 2016 +0200 Attempt to fix Disney SSS commitdbad91ca6dAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Jul 20 11:13:00 2016 +0200 Added a roughness parameter for refractions (for scattering of the rays within an object) With this, one can create a translucent material with a smooth surface and with a milky look. The final refraction roughness has to be calculated using the surface roughness and the refraction roughness because those two are correlated for refractions. If a ray hits a rough surface of a translucent material, it is scattered while entering the surface. Then it is scattered further within the object. The calculation I'm using is the following: RefrRoughnessFinal = 1.0 - (1.0 - Roughness) * (1.0 - RefrRoughness) commit50ea5e3e34Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jun 7 10:24:50 2016 +0200 Disney BSDF is now supporting CUDA commit10974cc826Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 31 11:18:07 2016 +0200 Added parameters IOR and Transparency for refractions With this, the Disney BRDF/BSSRDF is extended by the BTDF part. commit218202c090Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon May 30 15:08:18 2016 +0200 Added an additional normal for the clearcoat With this normal one can simulate a thin layer of clearcoat by applying a smoother normal map than the original to this input commitdd139ead7eAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon May 30 12:40:56 2016 +0200 Switched to the improved subsurface scattering from Christensen and Burley commit11160fa4e1Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon May 30 10:16:30 2016 +0200 Added Disney Sheen shader as a preparation to get to a BSSRDF commitcee4fe0cc9Merge:4f955d06b5bab6Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon May 30 09:08:09 2016 +0200 Merge branch 'cycles_disney_brdf' of git.blender.org:blender into cycles_disney_brdf Conflicts: intern/cycles/kernel/closure/bsdf_disney_clearcoat.h intern/cycles/kernel/closure/bsdf_disney_diffuse.h intern/cycles/kernel/closure/bsdf_disney_specular.h intern/cycles/kernel/closure/bsdf_util.h intern/cycles/kernel/osl/CMakeLists.txt intern/cycles/kernel/osl/bsdf_disney_clearcoat.cpp intern/cycles/kernel/osl/bsdf_disney_diffuse.cpp intern/cycles/kernel/osl/bsdf_disney_specular.cpp intern/cycles/kernel/osl/osl_closures.h intern/cycles/kernel/shaders/node_disney_bsdf.osl intern/cycles/render/nodes.cpp intern/cycles/render/nodes.h commit4f955d0523Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 24 16:38:23 2016 +0200 SVM and OSL are both working for the simple version of the Disney BRDF commit1f5c41874bAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 24 09:58:50 2016 +0200 Disney node can be used without SVM and started to cleanup the OSL implementation There is still some wrong behavior for SVM for the Schlick Fresnel part at the specular and clearcoat commitd4b814e930Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 18 10:22:29 2016 +0200 Switched from a parameter struct for Disney parameters to ShaderClosure params commitb86a1f5ba5Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 18 10:19:57 2016 +0200 Added additional variables for storing parameters in the ShaderClosure struct commit585b886236Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 17 12:03:17 2016 +0200 added output parameter to the DisneyBsdfNode That has been forgotten after removing the inheritance of BsdfNode commitf91a286398Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 17 10:40:48 2016 +0200 removed BsdfNode class inheritance for DisneyBsdfNode That's due to a naming difference. The Disney BSDF uses the name 'Base Color' while the BsdfNode had a 'Color' input. That caused a text message to be printed while rendering. commit30da91c9c5Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 4 16:08:10 2016 +0200 disney implementation cleaned commit30d41da0f0Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 4 13:23:07 2016 +0200 added the disney brdf as a shader node commit1f099fce24Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 3 16:54:49 2016 +0200 added clearcoat implementation commit00a1378b98Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Apr 29 22:56:49 2016 +0200 disney diffuse und specular implemented commit6baa7a7eb7Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Apr 18 15:21:32 2016 +0200 disney diffuse is working correctly commitd8fa169bf3Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Apr 18 08:41:53 2016 +0200 added vessel for disney diffuse shader commit6b5bab6cecAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 18 10:22:29 2016 +0200 Switched from a parameter struct for Disney parameters to ShaderClosure params commitf6499c2676Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 18 10:19:57 2016 +0200 Added additional variables for storing parameters in the ShaderClosure struct commit7100640b65Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 17 12:03:17 2016 +0200 added output parameter to the DisneyBsdfNode That has been forgotten after removing the inheritance of BsdfNode commit419ee54411Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 17 10:40:48 2016 +0200 removed BsdfNode class inheritance for DisneyBsdfNode That's due to a naming difference. The Disney BSDF uses the name 'Base Color' while the BsdfNode had a 'Color' input. That caused a text message to be printed while rendering. commit6006f91e87Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 4 16:08:10 2016 +0200 disney implementation cleaned commit0ed0895914Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 4 13:23:07 2016 +0200 added the disney brdf as a shader node commit0630b742d7Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 3 16:54:49 2016 +0200 added clearcoat implementation commit9f3d39744bAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Apr 29 22:56:49 2016 +0200 disney diffuse und specular implemented commit9b26206376Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Apr 18 15:21:32 2016 +0200 disney diffuse is working correctly commit4711a3927dAuthor: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Apr 18 08:41:53 2016 +0200 added vessel for disney diffuse shader Differential Revision: https://developer.blender.org/D2313
982 lines
32 KiB
C++
982 lines
32 KiB
C++
/*
|
|
* Copyright 2011-2013 Blender Foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
/* Closure Nodes */
|
|
|
|
ccl_device void svm_node_glass_setup(ShaderData *sd, MicrofacetBsdf *bsdf, int type, float eta, float roughness, bool refract)
|
|
{
|
|
if(type == CLOSURE_BSDF_SHARP_GLASS_ID) {
|
|
if(refract) {
|
|
bsdf->alpha_y = 0.0f;
|
|
bsdf->alpha_x = 0.0f;
|
|
bsdf->ior = eta;
|
|
sd->flag |= bsdf_refraction_setup(bsdf);
|
|
}
|
|
else {
|
|
bsdf->alpha_y = 0.0f;
|
|
bsdf->alpha_x = 0.0f;
|
|
bsdf->ior = 0.0f;
|
|
sd->flag |= bsdf_reflection_setup(bsdf);
|
|
}
|
|
}
|
|
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
|
|
bsdf->alpha_x = roughness;
|
|
bsdf->alpha_y = roughness;
|
|
bsdf->ior = eta;
|
|
|
|
if(refract)
|
|
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
|
|
else
|
|
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
|
}
|
|
else {
|
|
bsdf->alpha_x = roughness;
|
|
bsdf->alpha_y = roughness;
|
|
bsdf->ior = eta;
|
|
|
|
if(refract)
|
|
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
|
else
|
|
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
|
}
|
|
}
|
|
|
|
ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int path_flag, int *offset)
|
|
{
|
|
uint type, param1_offset, param2_offset;
|
|
|
|
uint mix_weight_offset;
|
|
decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, &mix_weight_offset);
|
|
float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
|
|
|
|
/* note we read this extra node before weight check, so offset is added */
|
|
uint4 data_node = read_node(kg, offset);
|
|
|
|
if(mix_weight == 0.0f)
|
|
return;
|
|
|
|
float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): sd->N;
|
|
|
|
float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
|
|
float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
|
|
|
|
switch(type) {
|
|
case CLOSURE_BSDF_PRINCIPLED_ID: {
|
|
uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset,
|
|
sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset, eta_offset, transparency_offset,
|
|
anisotropic_rotation_offset, refraction_roughness_offset;
|
|
uint4 data_node2 = read_node(kg, offset);
|
|
|
|
float3 T = stack_load_float3(stack, data_node.y);
|
|
decode_node_uchar4(data_node.z, &specular_offset, &roughness_offset, &specular_tint_offset, &anisotropic_offset);
|
|
decode_node_uchar4(data_node.w, &sheen_offset, &sheen_tint_offset, &clearcoat_offset, &clearcoat_gloss_offset);
|
|
decode_node_uchar4(data_node2.x, &eta_offset, &transparency_offset, &anisotropic_rotation_offset, &refraction_roughness_offset);
|
|
|
|
// get Disney principled parameters
|
|
float metallic = param1;
|
|
float subsurface = param2;
|
|
float specular = stack_load_float(stack, specular_offset);
|
|
float roughness = stack_load_float(stack, roughness_offset);
|
|
float specular_tint = stack_load_float(stack, specular_tint_offset);
|
|
float anisotropic = stack_load_float(stack, anisotropic_offset);
|
|
float sheen = stack_load_float(stack, sheen_offset);
|
|
float sheen_tint = stack_load_float(stack, sheen_tint_offset);
|
|
float clearcoat = stack_load_float(stack, clearcoat_offset);
|
|
float clearcoat_gloss = stack_load_float(stack, clearcoat_gloss_offset);
|
|
float transparency = stack_load_float(stack, transparency_offset);
|
|
float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
|
|
float refraction_roughness = stack_load_float(stack, refraction_roughness_offset);
|
|
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
|
|
|
|
ClosureType distribution = stack_valid(data_node2.y) ? (ClosureType) data_node2.y : CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
|
|
|
/* rotate tangent */
|
|
if(anisotropic_rotation != 0.0f)
|
|
T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
|
|
|
|
/* calculate ior */
|
|
float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
|
|
|
// calculate fresnel for refraction
|
|
float cosNO = dot(N, sd->I);
|
|
float fresnel = fresnel_dielectric_cos(cosNO, ior);
|
|
|
|
// calculate weights of the diffuse and specular part
|
|
float diffuse_weight = (1.0f - saturate(metallic)) * (1.0f - saturate(transparency));
|
|
|
|
float transp = saturate(transparency) * (1.0f - saturate(metallic));
|
|
float specular_weight = (1.0f - transp);
|
|
|
|
// get the base color
|
|
uint4 data_base_color = read_node(kg, offset);
|
|
float3 base_color = stack_valid(data_base_color.x) ? stack_load_float3(stack, data_base_color.x) :
|
|
make_float3(__uint_as_float(data_base_color.y), __uint_as_float(data_base_color.z), __uint_as_float(data_base_color.w));
|
|
|
|
// get the additional clearcoat normal and subsurface scattering radius
|
|
uint4 data_cn_ssr = read_node(kg, offset);
|
|
float3 clearcoat_normal = stack_valid(data_cn_ssr.x) ? stack_load_float3(stack, data_cn_ssr.x) : sd->N;
|
|
float3 subsurface_radius = stack_valid(data_cn_ssr.y) ? stack_load_float3(stack, data_cn_ssr.y) : make_float3(1.0f, 1.0f, 1.0f);
|
|
|
|
// get the subsurface color
|
|
uint4 data_subsurface_color = read_node(kg, offset);
|
|
float3 subsurface_color = stack_valid(data_subsurface_color.x) ? stack_load_float3(stack, data_subsurface_color.x) :
|
|
make_float3(__uint_as_float(data_subsurface_color.y), __uint_as_float(data_subsurface_color.z), __uint_as_float(data_subsurface_color.w));
|
|
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
|
|
#ifdef __SUBSURFACE__
|
|
float3 albedo = subsurface_color * subsurface + base_color * (1.0f - subsurface);
|
|
float3 subsurf_weight = weight * albedo * diffuse_weight;
|
|
float subsurf_sample_weight = fabsf(average(subsurf_weight));
|
|
|
|
/* disable in case of diffuse ancestor, can't see it well then and
|
|
* adds considerably noise due to probabilities of continuing path
|
|
* getting lower and lower */
|
|
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
|
|
subsurface = 0.0f;
|
|
}
|
|
|
|
/* diffuse */
|
|
if(fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) {
|
|
if(subsurface < CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
|
|
float3 diff_weight = weight * base_color * diffuse_weight;
|
|
|
|
PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
bsdf->roughness = roughness;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bsdf_principled_diffuse_setup(bsdf);
|
|
}
|
|
}
|
|
else if(subsurface > CLOSURE_WEIGHT_CUTOFF && subsurf_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
|
|
/* radius * scale */
|
|
float3 radius = subsurface_radius * subsurface;
|
|
/* sharpness */
|
|
float sharpness = 0.0f;
|
|
/* texture color blur */
|
|
float texture_blur = 0.0f;
|
|
|
|
/* create one closure per color channel */
|
|
Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(subsurf_weight.x, 0.0f, 0.0f));
|
|
if(bssrdf) {
|
|
bssrdf->sample_weight = subsurf_sample_weight;
|
|
bssrdf->radius = radius.x;
|
|
bssrdf->texture_blur = texture_blur;
|
|
bssrdf->albedo = albedo.x;
|
|
bssrdf->sharpness = sharpness;
|
|
bssrdf->N = N;
|
|
bssrdf->roughness = roughness;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_ID);
|
|
}
|
|
|
|
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, subsurf_weight.y, 0.0f));
|
|
if(bssrdf) {
|
|
bssrdf->sample_weight = subsurf_sample_weight;
|
|
bssrdf->radius = radius.y;
|
|
bssrdf->texture_blur = texture_blur;
|
|
bssrdf->albedo = albedo.y;
|
|
bssrdf->sharpness = sharpness;
|
|
bssrdf->N = N;
|
|
bssrdf->roughness = roughness;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_ID);
|
|
}
|
|
|
|
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, subsurf_weight.z));
|
|
if(bssrdf) {
|
|
bssrdf->sample_weight = subsurf_sample_weight;
|
|
bssrdf->radius = radius.z;
|
|
bssrdf->texture_blur = texture_blur;
|
|
bssrdf->albedo = albedo.z;
|
|
bssrdf->sharpness = sharpness;
|
|
bssrdf->N = N;
|
|
bssrdf->roughness = roughness;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_ID);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
/* diffuse */
|
|
if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
|
|
float3 diff_weight = weight * base_color * diffuse_weight;
|
|
|
|
PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
bsdf->roughness = roughness;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bsdf_principled_diffuse_setup(bsdf);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* sheen */
|
|
if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) {
|
|
float m_cdlum = linear_rgb_to_gray(base_color);
|
|
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
|
|
|
|
/* color of the sheen component */
|
|
float3 sheen_color = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sheen_tint) + m_ctint * sheen_tint;
|
|
|
|
float3 sheen_weight = weight * sheen * sheen_color * diffuse_weight;
|
|
|
|
PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf*)bsdf_alloc(sd, sizeof(PrincipledSheenBsdf), sheen_weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bsdf_principled_sheen_setup(bsdf);
|
|
}
|
|
}
|
|
|
|
/* specular reflection */
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
|
|
#endif
|
|
if(specular_weight > CLOSURE_WEIGHT_CUTOFF && (specular > CLOSURE_WEIGHT_CUTOFF || metallic > CLOSURE_WEIGHT_CUTOFF)) {
|
|
float3 spec_weight = weight * specular_weight;
|
|
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight);
|
|
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
|
|
|
if(bsdf && extra) {
|
|
bsdf->N = N;
|
|
bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
|
|
bsdf->T = T;
|
|
bsdf->extra = extra;
|
|
|
|
float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
|
|
float r2 = roughness * roughness;
|
|
|
|
bsdf->alpha_x = fmaxf(0.001f, r2 / aspect);
|
|
bsdf->alpha_y = fmaxf(0.001f, r2 * aspect);
|
|
|
|
float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y + 0.1f * base_color.z; // luminance approx.
|
|
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
|
|
float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) + m_ctint * specular_tint;
|
|
|
|
bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic;
|
|
bsdf->extra->color = base_color;
|
|
|
|
/* setup bsdf */
|
|
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || roughness <= 0.075f) /* use single-scatter GGX */
|
|
sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf);
|
|
else /* use multi-scatter GGX */
|
|
sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf);
|
|
}
|
|
}
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
}
|
|
#endif
|
|
|
|
/* BSDF */
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(kernel_data.integrator.caustics_reflective || kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) {
|
|
#endif
|
|
if(transp > CLOSURE_WEIGHT_CUTOFF) {
|
|
float3 glass_weight = weight * transp;
|
|
float3 cspec0 = base_color * specular_tint + make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint);
|
|
|
|
if(roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) { /* use single-scatter GGX */
|
|
float refl_roughness = roughness;
|
|
|
|
/* reflection */
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
|
|
#endif
|
|
{
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight*fresnel);
|
|
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
|
|
|
if(bsdf && extra) {
|
|
bsdf->N = N;
|
|
bsdf->extra = extra;
|
|
|
|
bsdf->alpha_x = refl_roughness * refl_roughness;
|
|
bsdf->alpha_y = refl_roughness * refl_roughness;
|
|
bsdf->ior = ior;
|
|
|
|
bsdf->extra->color = base_color;
|
|
bsdf->extra->cspec0 = cspec0;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf);
|
|
}
|
|
}
|
|
|
|
/* refraction */
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
|
|
#endif
|
|
{
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), base_color*glass_weight*(1.0f - fresnel));
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
|
|
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
|
|
refraction_roughness = 1.0f - (1.0f - refl_roughness) * (1.0f - refraction_roughness);
|
|
else
|
|
refraction_roughness = refl_roughness;
|
|
|
|
bsdf->alpha_x = refraction_roughness * refraction_roughness;
|
|
bsdf->alpha_y = refraction_roughness * refraction_roughness;
|
|
bsdf->ior = ior;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
|
}
|
|
}
|
|
}
|
|
else { /* use multi-scatter GGX */
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight);
|
|
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
|
|
|
if(bsdf && extra) {
|
|
bsdf->N = N;
|
|
bsdf->extra = extra;
|
|
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
|
|
|
bsdf->alpha_x = roughness * roughness;
|
|
bsdf->alpha_y = roughness * roughness;
|
|
bsdf->ior = ior;
|
|
|
|
bsdf->extra->color = base_color;
|
|
bsdf->extra->cspec0 = cspec0;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf);
|
|
}
|
|
}
|
|
}
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
}
|
|
#endif
|
|
|
|
/* clearcoat */
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
|
|
#endif
|
|
if(clearcoat > CLOSURE_WEIGHT_CUTOFF) {
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
|
|
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
|
|
|
if(bsdf && extra) {
|
|
bsdf->N = clearcoat_normal;
|
|
bsdf->ior = 1.5f;
|
|
bsdf->extra = extra;
|
|
|
|
bsdf->alpha_x = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
|
|
bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
|
|
|
|
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
|
|
bsdf->extra->clearcoat = clearcoat;
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf);
|
|
}
|
|
}
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_DIFFUSE_ID: {
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
OrenNayarBsdf *bsdf = (OrenNayarBsdf*)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
|
|
float roughness = param1;
|
|
|
|
if(roughness == 0.0f) {
|
|
sd->flag |= bsdf_diffuse_setup((DiffuseBsdf*)bsdf);
|
|
}
|
|
else {
|
|
bsdf->roughness = roughness;
|
|
sd->flag |= bsdf_oren_nayar_setup(bsdf);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_TRANSLUCENT_ID: {
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
sd->flag |= bsdf_translucent_setup(bsdf);
|
|
}
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_TRANSPARENT_ID: {
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
|
|
|
|
if(bsdf) {
|
|
sd->flag |= bsdf_transparent_setup(bsdf);
|
|
}
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_REFLECTION_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
|
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: {
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
|
|
break;
|
|
#endif
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
bsdf->alpha_x = param1;
|
|
bsdf->alpha_y = param1;
|
|
bsdf->ior = 0.0f;
|
|
bsdf->extra = NULL;
|
|
|
|
/* setup bsdf */
|
|
if(type == CLOSURE_BSDF_REFLECTION_ID)
|
|
sd->flag |= bsdf_reflection_setup(bsdf);
|
|
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
|
|
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
|
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
|
|
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
|
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
|
|
kernel_assert(stack_valid(data_node.z));
|
|
bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
|
if(bsdf->extra) {
|
|
bsdf->extra->color = stack_load_float3(stack, data_node.z);
|
|
sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
|
|
}
|
|
}
|
|
else
|
|
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_REFRACTION_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
|
|
break;
|
|
#endif
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
bsdf->extra = NULL;
|
|
|
|
float eta = fmaxf(param2, 1e-5f);
|
|
eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
|
|
|
|
/* setup bsdf */
|
|
if(type == CLOSURE_BSDF_REFRACTION_ID) {
|
|
bsdf->alpha_x = 0.0f;
|
|
bsdf->alpha_y = 0.0f;
|
|
bsdf->ior = eta;
|
|
|
|
sd->flag |= bsdf_refraction_setup(bsdf);
|
|
}
|
|
else {
|
|
bsdf->alpha_x = param1;
|
|
bsdf->alpha_y = param1;
|
|
bsdf->ior = eta;
|
|
|
|
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
|
|
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
|
|
else
|
|
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_SHARP_GLASS_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(!kernel_data.integrator.caustics_reflective &&
|
|
!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
|
|
{
|
|
break;
|
|
}
|
|
#endif
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
|
|
/* index of refraction */
|
|
float eta = fmaxf(param2, 1e-5f);
|
|
eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
|
|
|
|
/* fresnel */
|
|
float cosNO = dot(N, sd->I);
|
|
float fresnel = fresnel_dielectric_cos(cosNO, eta);
|
|
float roughness = param1;
|
|
|
|
/* reflection */
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
|
|
#endif
|
|
{
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight*fresnel);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
bsdf->extra = NULL;
|
|
svm_node_glass_setup(sd, bsdf, type, eta, roughness, false);
|
|
}
|
|
}
|
|
|
|
/* refraction */
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
|
|
#endif
|
|
{
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight*(1.0f - fresnel));
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
bsdf->extra = NULL;
|
|
svm_node_glass_setup(sd, bsdf, type, eta, roughness, true);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: {
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(!kernel_data.integrator.caustics_reflective && !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
|
|
break;
|
|
#endif
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
|
|
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
|
|
|
if(bsdf && extra) {
|
|
bsdf->N = N;
|
|
bsdf->extra = extra;
|
|
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
|
|
|
bsdf->alpha_x = param1;
|
|
bsdf->alpha_y = param1;
|
|
float eta = fmaxf(param2, 1e-5f);
|
|
bsdf->ior = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
|
|
|
|
kernel_assert(stack_valid(data_node.z));
|
|
bsdf->extra->color = stack_load_float3(stack, data_node.z);
|
|
|
|
/* setup bsdf */
|
|
sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
|
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID:
|
|
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
|
|
break;
|
|
#endif
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
bsdf->extra = NULL;
|
|
bsdf->T = stack_load_float3(stack, data_node.y);
|
|
|
|
/* rotate tangent */
|
|
float rotation = stack_load_float(stack, data_node.z);
|
|
|
|
if(rotation != 0.0f)
|
|
bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
|
|
|
|
/* compute roughness */
|
|
float roughness = param1;
|
|
float anisotropy = clamp(param2, -0.99f, 0.99f);
|
|
|
|
if(anisotropy < 0.0f) {
|
|
bsdf->alpha_x = roughness/(1.0f + anisotropy);
|
|
bsdf->alpha_y = roughness*(1.0f + anisotropy);
|
|
}
|
|
else {
|
|
bsdf->alpha_x = roughness*(1.0f - anisotropy);
|
|
bsdf->alpha_y = roughness/(1.0f - anisotropy);
|
|
}
|
|
|
|
bsdf->ior = 0.0f;
|
|
|
|
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) {
|
|
sd->flag |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
|
|
}
|
|
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) {
|
|
sd->flag |= bsdf_microfacet_ggx_aniso_setup(bsdf);
|
|
}
|
|
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID) {
|
|
kernel_assert(stack_valid(data_node.w));
|
|
bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
|
if(bsdf->extra) {
|
|
bsdf->extra->color = stack_load_float3(stack, data_node.w);
|
|
sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
|
|
}
|
|
}
|
|
else
|
|
sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
|
|
}
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
VelvetBsdf *bsdf = (VelvetBsdf*)bsdf_alloc(sd, sizeof(VelvetBsdf), weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
|
|
bsdf->sigma = saturate(param1);
|
|
sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf);
|
|
}
|
|
break;
|
|
}
|
|
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
|
#ifdef __CAUSTICS_TRICKS__
|
|
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
|
|
break;
|
|
#endif
|
|
case CLOSURE_BSDF_DIFFUSE_TOON_ID: {
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
ToonBsdf *bsdf = (ToonBsdf*)bsdf_alloc(sd, sizeof(ToonBsdf), weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->N = N;
|
|
bsdf->size = param1;
|
|
bsdf->smooth = param2;
|
|
|
|
if(type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
|
|
sd->flag |= bsdf_diffuse_toon_setup(bsdf);
|
|
else
|
|
sd->flag |= bsdf_glossy_toon_setup(bsdf);
|
|
}
|
|
break;
|
|
}
|
|
#ifdef __HAIR__
|
|
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
|
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
|
|
if(sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
|
|
ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
|
|
|
|
if(bsdf) {
|
|
/* todo: giving a fixed weight here will cause issues when
|
|
* mixing multiple BSDFS. energy will not be conserved and
|
|
* the throughput can blow up after multiple bounces. we
|
|
* better figure out a way to skip backfaces from rays
|
|
* spawned by transmission from the front */
|
|
bsdf->weight = make_float3(1.0f, 1.0f, 1.0f);
|
|
sd->flag |= bsdf_transparent_setup(bsdf);
|
|
}
|
|
}
|
|
else {
|
|
HairBsdf *bsdf = (HairBsdf*)bsdf_alloc(sd, sizeof(HairBsdf), weight);
|
|
|
|
if(bsdf) {
|
|
bsdf->roughness1 = param1;
|
|
bsdf->roughness2 = param2;
|
|
bsdf->offset = -stack_load_float(stack, data_node.z);
|
|
|
|
if(stack_valid(data_node.y)) {
|
|
bsdf->T = normalize(stack_load_float3(stack, data_node.y));
|
|
}
|
|
else if(!(sd->type & PRIMITIVE_ALL_CURVE)) {
|
|
bsdf->T = normalize(sd->dPdv);
|
|
bsdf->offset = 0.0f;
|
|
}
|
|
else
|
|
bsdf->T = normalize(sd->dPdu);
|
|
|
|
if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
|
|
sd->flag |= bsdf_hair_reflection_setup(bsdf);
|
|
}
|
|
else {
|
|
sd->flag |= bsdf_hair_transmission_setup(bsdf);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#ifdef __SUBSURFACE__
|
|
case CLOSURE_BSSRDF_CUBIC_ID:
|
|
case CLOSURE_BSSRDF_GAUSSIAN_ID:
|
|
case CLOSURE_BSSRDF_BURLEY_ID: {
|
|
float3 albedo = sd->svm_closure_weight;
|
|
float3 weight = sd->svm_closure_weight * mix_weight;
|
|
float sample_weight = fabsf(average(weight));
|
|
|
|
/* disable in case of diffuse ancestor, can't see it well then and
|
|
* adds considerably noise due to probabilities of continuing path
|
|
* getting lower and lower */
|
|
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
|
|
param1 = 0.0f;
|
|
|
|
if(sample_weight > CLOSURE_WEIGHT_CUTOFF) {
|
|
/* radius * scale */
|
|
float3 radius = stack_load_float3(stack, data_node.z)*param1;
|
|
/* sharpness */
|
|
float sharpness = stack_load_float(stack, data_node.w);
|
|
/* texture color blur */
|
|
float texture_blur = param2;
|
|
|
|
/* create one closure per color channel */
|
|
Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(weight.x, 0.0f, 0.0f));
|
|
if(bssrdf) {
|
|
bssrdf->sample_weight = sample_weight;
|
|
bssrdf->radius = radius.x;
|
|
bssrdf->texture_blur = texture_blur;
|
|
bssrdf->albedo = albedo.x;
|
|
bssrdf->sharpness = sharpness;
|
|
bssrdf->N = N;
|
|
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
|
|
}
|
|
|
|
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, weight.y, 0.0f));
|
|
if(bssrdf) {
|
|
bssrdf->sample_weight = sample_weight;
|
|
bssrdf->radius = radius.y;
|
|
bssrdf->texture_blur = texture_blur;
|
|
bssrdf->albedo = albedo.y;
|
|
bssrdf->sharpness = sharpness;
|
|
bssrdf->N = N;
|
|
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
|
|
}
|
|
|
|
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, weight.z));
|
|
if(bssrdf) {
|
|
bssrdf->sample_weight = sample_weight;
|
|
bssrdf->radius = radius.z;
|
|
bssrdf->texture_blur = texture_blur;
|
|
bssrdf->albedo = albedo.z;
|
|
bssrdf->sharpness = sharpness;
|
|
bssrdf->N = N;
|
|
sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int path_flag)
|
|
{
|
|
#ifdef __VOLUME__
|
|
uint type, param1_offset, param2_offset;
|
|
|
|
uint mix_weight_offset;
|
|
decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, &mix_weight_offset);
|
|
float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
|
|
|
|
if(mix_weight == 0.0f)
|
|
return;
|
|
|
|
float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
|
|
float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
|
|
float density = fmaxf(param1, 0.0f);
|
|
|
|
switch(type) {
|
|
case CLOSURE_VOLUME_ABSORPTION_ID: {
|
|
float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - sd->svm_closure_weight) * mix_weight * density;
|
|
ShaderClosure *sc = closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_NONE_ID, weight);
|
|
|
|
if(sc) {
|
|
sd->flag |= volume_absorption_setup(sc);
|
|
}
|
|
break;
|
|
}
|
|
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: {
|
|
float3 weight = sd->svm_closure_weight * mix_weight * density;
|
|
HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
|
|
|
|
if(volume) {
|
|
volume->g = param2; /* g */
|
|
sd->flag |= volume_henyey_greenstein_setup(volume);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node)
|
|
{
|
|
uint mix_weight_offset = node.y;
|
|
|
|
if(stack_valid(mix_weight_offset)) {
|
|
float mix_weight = stack_load_float(stack, mix_weight_offset);
|
|
|
|
if(mix_weight == 0.0f)
|
|
return;
|
|
|
|
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, sd->svm_closure_weight * mix_weight);
|
|
}
|
|
else
|
|
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, sd->svm_closure_weight);
|
|
|
|
sd->flag |= SD_EMISSION;
|
|
}
|
|
|
|
ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 node)
|
|
{
|
|
uint mix_weight_offset = node.y;
|
|
|
|
if(stack_valid(mix_weight_offset)) {
|
|
float mix_weight = stack_load_float(stack, mix_weight_offset);
|
|
|
|
if(mix_weight == 0.0f)
|
|
return;
|
|
|
|
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, sd->svm_closure_weight * mix_weight);
|
|
}
|
|
else
|
|
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, sd->svm_closure_weight);
|
|
}
|
|
|
|
ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
|
|
{
|
|
uint mix_weight_offset = node.y;
|
|
|
|
if(stack_valid(mix_weight_offset)) {
|
|
float mix_weight = stack_load_float(stack, mix_weight_offset);
|
|
|
|
if(mix_weight == 0.0f)
|
|
return;
|
|
|
|
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, sd->svm_closure_weight * mix_weight);
|
|
}
|
|
else
|
|
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, sd->svm_closure_weight);
|
|
|
|
sd->flag |= SD_HOLDOUT;
|
|
}
|
|
|
|
ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node)
|
|
{
|
|
uint mix_weight_offset = node.y;
|
|
|
|
if(stack_valid(mix_weight_offset)) {
|
|
float mix_weight = stack_load_float(stack, mix_weight_offset);
|
|
|
|
if(mix_weight == 0.0f)
|
|
return;
|
|
|
|
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, sd->svm_closure_weight * mix_weight);
|
|
}
|
|
else
|
|
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, sd->svm_closure_weight);
|
|
|
|
sd->flag |= SD_AO;
|
|
}
|
|
|
|
/* Closure Nodes */
|
|
|
|
ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
|
|
{
|
|
sd->svm_closure_weight = weight;
|
|
}
|
|
|
|
ccl_device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
|
|
{
|
|
float3 weight = make_float3(__uint_as_float(r), __uint_as_float(g), __uint_as_float(b));
|
|
svm_node_closure_store_weight(sd, weight);
|
|
}
|
|
|
|
ccl_device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset)
|
|
{
|
|
float3 weight = stack_load_float3(stack, weight_offset);
|
|
|
|
svm_node_closure_store_weight(sd, weight);
|
|
}
|
|
|
|
ccl_device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
|
|
{
|
|
uint color_offset = node.y;
|
|
uint strength_offset = node.z;
|
|
|
|
float strength = stack_load_float(stack, strength_offset);
|
|
float3 weight = stack_load_float3(stack, color_offset)*strength;
|
|
|
|
svm_node_closure_store_weight(sd, weight);
|
|
}
|
|
|
|
ccl_device void svm_node_mix_closure(ShaderData *sd, float *stack, uint4 node)
|
|
{
|
|
/* fetch weight from blend input, previous mix closures,
|
|
* and write to stack to be used by closure nodes later */
|
|
uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
|
|
decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
|
|
|
|
float weight = stack_load_float(stack, weight_offset);
|
|
weight = saturate(weight);
|
|
|
|
float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
|
|
|
|
if(stack_valid(weight1_offset))
|
|
stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight));
|
|
if(stack_valid(weight2_offset))
|
|
stack_store_float(stack, weight2_offset, in_weight*weight);
|
|
}
|
|
|
|
/* (Bump) normal */
|
|
|
|
ccl_device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal)
|
|
{
|
|
float3 normal = stack_load_float3(stack, in_direction);
|
|
sd->N = normal;
|
|
stack_store_float3(stack, out_normal, normal);
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|
|
|