From 98f6ddcd60f181a54864d0bcf86e7026e093648e Mon Sep 17 00:00:00 2001 From: Pavlo Penenko Date: Mon, 24 Aug 2026 17:01:08 -0400 Subject: [PATCH 1/2] Use Qualitative Oren-Nayar to match Standard Surface spec Update Metashade SS to set energy_compensation=false on the diffuse BSDF, aligning with the stock Standard Surface nodegraph. Remove masonry from the test exclusion list now that the FLIP threshold failure is resolved. --- contrib/metashade | 2 +- .../mx_metashade_standard_surface_bsdf_genglsl_impl.glsl | 4 +++- contrib/tests/test_render_metashade.py | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/contrib/metashade b/contrib/metashade index feccb46fc5..4b3b38fd61 160000 --- a/contrib/metashade +++ b/contrib/metashade @@ -1 +1 @@ -Subproject commit feccb46fc5903b53fed6f0e6bc3be71eb9d19e92 +Subproject commit 4b3b38fd612f7ca42d37e44d0ee3ec3c8fa1633e diff --git a/contrib/tests/metashade_ref/libraries/standard_surface/mx_metashade_standard_surface_bsdf_genglsl_impl.glsl b/contrib/tests/metashade_ref/libraries/standard_surface/mx_metashade_standard_surface_bsdf_genglsl_impl.glsl index 47357a2600..f24b9931c1 100644 --- a/contrib/tests/metashade_ref/libraries/standard_surface/mx_metashade_standard_surface_bsdf_genglsl_impl.glsl +++ b/contrib/tests/metashade_ref/libraries/standard_surface/mx_metashade_standard_surface_bsdf_genglsl_impl.glsl @@ -46,10 +46,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/test_render_metashade.py b/contrib/tests/test_render_metashade.py index 7ec0a7e25e..6b9c3796fd 100644 --- a/contrib/tests/test_render_metashade.py +++ b/contrib/tests/test_render_metashade.py @@ -304,7 +304,6 @@ def test_render(self, case: RenderTestCase, subtests, override_env): "speckle.mtlx", # mx_rotate_vector3 duplicate "waves.mtlx", # mx_rotate_vector3 duplicate "wood.mtlx", # mx_rotate_vector3 duplicate - "masonry.mtlx", # FLIP threshold (0.073 > 0.05) }) From 9d4c9782952dbf0bfbc1e3fa82cdcb5fb0511ba9 Mon Sep 17 00:00:00 2001 From: Pavlo Penenko Date: Mon, 24 Aug 2026 18:01:56 -0400 Subject: [PATCH 2/2] Regenerate shader baselines and bump metashade submodule Update all rendered shader baselines to reflect the Qualitative Oren-Nayar change (energy_compensation=false). Bump metashade submodule to metashade/metashade#229 (merged on main). Signed-off-by: Pavlo Penenko --- contrib/metashade | 2 +- .../Fusion/bitmap/bitmapoutput_glsl_ps.glsl | 177 ++ .../Fusion/bitmap/bitmapoutput_glsl_vs.glsl | 71 + .../Fusion/glazing/Glazing_test_ps.glsl | 4 +- .../Fusion/heightmap/Gold_pass_ps.glsl | 4 +- .../Fusion/layered/Granite_Blue_Pearl_ps.glsl | 4 +- .../layered/Paint_Metallic_Green_ps.glsl | 4 +- .../Fusion/layered/Paint_Metallic_Red_ps.glsl | 4 +- .../Examples/Fusion/normalmap/Gold_ps.glsl | 4 +- .../opaque/Plastic_Glossy_White_ps.glsl | 4 +- .../Fusion/opaque/Walnut_Semigloss_ps.glsl | 4 +- .../Examples/Fusion/opaque/Walnut_ps.glsl | 4 +- .../transparent/Gemstone_Diamond_ps.glsl | 4 +- .../Fusion/transparent/Gemstone_Ruby_ps.glsl | 4 +- .../Revit/ceramic/M_legacy_ceramic_ps.glsl | 4 +- .../Revit/checker/M_legacy_checker_ps.glsl | 4 +- .../Revit/concrete/M_legacy_concrete_ps.glsl | 4 +- .../Revit/generic/M_legacy_generic_ps.glsl | 4 +- .../Revit/glass/M_legacy_glass_ps.glsl | 4 +- .../Revit/glazing/M_legacy_glazing_ps.glsl | 4 +- .../Revit/gradient/M_legacy_gradient_ps.glsl | 4 +- .../Revit/hardwood/M_legacy_hardwood_ps.glsl | 4 +- .../Revit/masonry/M_legacy_masonry_ps.glsl | 1978 +++++++++++++++++ .../Revit/masonry/M_legacy_masonry_vs.glsl | 82 + .../Revit/mirror/M_legacy_mirror_ps.glsl | 4 +- .../turbulence2d_object_out_glsl_ps.glsl | 966 ++++++++ .../turbulence2d_object_out_glsl_vs.glsl | 71 + .../turbulence3d_object_out_glsl_ps.glsl | 966 ++++++++ .../turbulence3d_object_out_glsl_vs.glsl | 70 + .../Revit/plastic/M_legacy_plastic_ps.glsl | 4 +- .../Revit/stone/M_legacy_stone_ps.glsl | 4 +- .../Revit/tiles/M_legacy_tiles_ps.glsl | 4 +- .../wallpaint/M_legacy_wallpaint_ps.glsl | 4 +- .../Revit/water/M_legacy_water_ps.glsl | 4 +- .../Tiled_Brass_ps.glsl | 4 +- .../M_BrickPattern_ps.glsl | 4 +- .../Car_Paint_ps.glsl | 4 +- .../M_Bishop_B_ps.glsl | 4 +- .../M_Bishop_W_ps.glsl | 4 +- .../M_Castle_B_ps.glsl | 4 +- .../M_Castle_W_ps.glsl | 4 +- .../M_Chessboard_ps.glsl | 4 +- .../M_King_B_ps.glsl | 4 +- .../M_King_W_ps.glsl | 4 +- .../M_Knight_B_ps.glsl | 4 +- .../M_Knight_W_ps.glsl | 4 +- .../M_Pawn_Body_B_ps.glsl | 4 +- .../M_Pawn_Body_W_ps.glsl | 4 +- .../M_Pawn_Top_B_ps.glsl | 4 +- .../M_Pawn_Top_W_ps.glsl | 4 +- .../M_Queen_B_ps.glsl | 4 +- .../M_Queen_W_ps.glsl | 4 +- .../standard_surface_chrome/Chrome_ps.glsl | 4 +- .../standard_surface_copper/Copper_ps.glsl | 4 +- .../standard_surface_default/Default_ps.glsl | 4 +- .../aswf/standard_surface_glass/Glass_ps.glsl | 4 +- .../GlassTinted_ps.glsl | 4 +- .../aswf/standard_surface_gold/Gold_ps.glsl | 4 +- .../Greysphere_ps.glsl | 4 +- .../Greysphere_Calibration_ps.glsl | 4 +- .../aswf/standard_surface_jade/Jade_ps.glsl | 4 +- .../Greysphere_Calibration_ps.glsl | 4 +- .../Tiled_Brass_ps.glsl | 4 +- .../Greysphere_Calibration_ps.glsl | 4 +- .../Tiled_Wood_ps.glsl | 4 +- .../Marble_3D_ps.glsl | 4 +- .../Metal_Brushed_ps.glsl | 4 +- .../M_OnyxHextiled_ps.glsl | 4 +- .../standard_surface_plastic/Plastic_ps.glsl | 4 +- .../ThinFilm_ps.glsl | 4 +- .../standard_surface_velvet/Velvet_ps.glsl | 4 +- .../Tiled_Wood_ps.glsl | 4 +- 72 files changed, 4571 insertions(+), 64 deletions(-) create mode 100644 contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/bitmap/bitmapoutput_glsl_ps.glsl create mode 100644 contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/bitmap/bitmapoutput_glsl_vs.glsl create mode 100644 contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/masonry/M_legacy_masonry_ps.glsl create mode 100644 contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/masonry/M_legacy_masonry_vs.glsl create mode 100644 contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence2d_object_out_glsl_ps.glsl create mode 100644 contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence2d_object_out_glsl_vs.glsl create mode 100644 contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence3d_object_out_glsl_ps.glsl create mode 100644 contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence3d_object_out_glsl_vs.glsl diff --git a/contrib/metashade b/contrib/metashade index 4b3b38fd61..0ce571b68d 160000 --- a/contrib/metashade +++ b/contrib/metashade @@ -1 +1 @@ -Subproject commit 4b3b38fd612f7ca42d37e44d0ee3ec3c8fa1633e +Subproject commit 0ce571b68d63f2feed3297f842be1502027bfdd6 diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/bitmap/bitmapoutput_glsl_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/bitmap/bitmapoutput_glsl_ps.glsl new file mode 100644 index 0000000000..28b850a836 --- /dev/null +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/bitmap/bitmapoutput_glsl_ps.glsl @@ -0,0 +1,177 @@ +#version 400 + + +struct BSDF { vec3 response; vec3 throughput; }; +#define EDF vec3 +struct VDF { vec3 response; vec3 throughput; }; +struct surfaceshader { vec3 color; vec3 transparency; }; +struct volumeshader { vec3 color; vec3 transparency; }; +struct displacementshader { vec3 offset; float scale; }; +struct lightshader { vec3 intensity; vec3 direction; }; +#define material surfaceshader + +// Uniform block: PublicUniforms +uniform int geomprop_UV0_index = 0; +uniform vec2 simplebitmap_realworld_offset_unit_in1 = vec2(0.000000, 0.000000); +uniform float simplebitmap_realworld_offset_unit_in2 = 2.540000; +uniform vec2 simplebitmap_realworld_scale_unit_in1 = vec2(2.000000, 2.000000); +uniform float simplebitmap_realworld_scale_unit_in2 = 2.540000; +uniform sampler2D simplebitmap_file; +uniform vec2 simplebitmap_uv_offset = vec2(0.000000, 0.000000); +uniform vec2 simplebitmap_uv_scale = vec2(1.000000, 1.000000); +uniform float simplebitmap_rotation_angle = 0.000000; +uniform float simplebitmap_rgbamount = 1.000000; +uniform bool simplebitmap_invert = false; +uniform int simplebitmap_uaddressmode = 2; +uniform int simplebitmap_vaddressmode = 2; + +in VertexData +{ + vec2 texcoord_0; +} vd; + +// Pixel shader outputs +out vec4 bitmapoutput1; + +#define M_FLOAT_EPS 1e-8 +#define M_PI 3.1415926535897932 + +#define mx_mod mod +#define mx_inverse inverse +#define mx_inversesqrt inversesqrt +#define mx_sin sin +#define mx_cos cos +#define mx_tan tan +#define mx_asin asin +#define mx_acos acos +#define mx_atan atan +#define mx_radians radians +#define mx_float_bits_to_int floatBitsToInt + +vec2 mx_matrix_mul(vec2 v, mat2 m) { return v * m; } +vec3 mx_matrix_mul(vec3 v, mat3 m) { return v * m; } +vec4 mx_matrix_mul(vec4 v, mat4 m) { return v * m; } +vec2 mx_matrix_mul(mat2 m, vec2 v) { return m * v; } +vec3 mx_matrix_mul(mat3 m, vec3 v) { return m * v; } +vec4 mx_matrix_mul(mat4 m, vec4 v) { return m * v; } +mat2 mx_matrix_mul(mat2 m1, mat2 m2) { return m1 * m2; } +mat3 mx_matrix_mul(mat3 m1, mat3 m2) { return m1 * m2; } +mat4 mx_matrix_mul(mat4 m1, mat4 m2) { return m1 * m2; } + +float mx_square(float x) +{ + return x*x; +} + +vec2 mx_square(vec2 x) +{ + return x*x; +} + +vec3 mx_square(vec3 x) +{ + return x*x; +} + +vec3 mx_srgb_encode(vec3 color) +{ + bvec3 isAbove = greaterThan(color, vec3(0.0031308)); + vec3 linSeg = color * 12.92; + vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; + return mix(linSeg, powSeg, isAbove); +} + +#define AIRY_FRESNEL_ITERATIONS 2 + +void mx_rotate_vector2(vec2 _in, float amount, out vec2 result) +{ + float rotationRadians = mx_radians(amount); + float sa = mx_sin(rotationRadians); + float ca = mx_cos(rotationRadians); + result = vec2(ca*_in.x + sa*_in.y, -sa*_in.x + ca*_in.y); +} + +void NG_switch_vector2I(vec2 in1, vec2 in2, vec2 in3, vec2 in4, vec2 in5, vec2 in6, vec2 in7, vec2 in8, vec2 in9, vec2 in10, int which, out vec2 out1) +{ + const int ifgreater_10_value1_tmp = 10; + const vec2 ifgreater_10_in2_tmp = vec2(0.000000, 0.000000); + vec2 ifgreater_10_out = (ifgreater_10_value1_tmp > which) ? in10 : ifgreater_10_in2_tmp; + const int ifgreater_9_value1_tmp = 9; + vec2 ifgreater_9_out = (ifgreater_9_value1_tmp > which) ? in9 : ifgreater_10_out; + const int ifgreater_8_value1_tmp = 8; + vec2 ifgreater_8_out = (ifgreater_8_value1_tmp > which) ? in8 : ifgreater_9_out; + const int ifgreater_7_value1_tmp = 7; + vec2 ifgreater_7_out = (ifgreater_7_value1_tmp > which) ? in7 : ifgreater_8_out; + const int ifgreater_6_value1_tmp = 6; + vec2 ifgreater_6_out = (ifgreater_6_value1_tmp > which) ? in6 : ifgreater_7_out; + const int ifgreater_5_value1_tmp = 5; + vec2 ifgreater_5_out = (ifgreater_5_value1_tmp > which) ? in5 : ifgreater_6_out; + const int ifgreater_4_value1_tmp = 4; + vec2 ifgreater_4_out = (ifgreater_4_value1_tmp > which) ? in4 : ifgreater_5_out; + const int ifgreater_3_value1_tmp = 3; + vec2 ifgreater_3_out = (ifgreater_3_value1_tmp > which) ? in3 : ifgreater_4_out; + const int ifgreater_2_value1_tmp = 2; + vec2 ifgreater_2_out = (ifgreater_2_value1_tmp > which) ? in2 : ifgreater_3_out; + const int ifgreater_1_value1_tmp = 1; + vec2 ifgreater_1_out = (ifgreater_1_value1_tmp > which) ? in1 : ifgreater_2_out; + out1 = ifgreater_1_out; +} + +void NG_place2d_vector2(vec2 texcoord, vec2 pivot, vec2 scale, float rotate, vec2 offset, int operationorder, out vec2 out1) +{ + vec2 N_subpivot_out = texcoord - pivot; + vec2 N_applyscale_out = N_subpivot_out / scale; + vec2 N_applyoffset2_out = N_subpivot_out - offset; + vec2 N_applyrot_out = vec2(0.0); + mx_rotate_vector2(N_applyscale_out, rotate, N_applyrot_out); + vec2 N_applyrot2_out = vec2(0.0); + mx_rotate_vector2(N_applyoffset2_out, rotate, N_applyrot2_out); + vec2 N_applyoffset_out = N_applyrot_out - offset; + vec2 N_applyscale2_out = N_applyrot2_out / scale; + vec2 N_addpivot_out = N_applyoffset_out + pivot; + vec2 N_addpivot2_out = N_applyscale2_out + pivot; + vec2 N_switch_operationorder_out = vec2(0.0); + NG_switch_vector2I(N_addpivot_out, N_addpivot2_out, vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), operationorder, N_switch_operationorder_out); + out1 = N_switch_operationorder_out; +} + +vec2 mx_transform_uv(vec2 uv, vec2 uv_scale, vec2 uv_offset) +{ + uv = uv * uv_scale + uv_offset; + return vec2(uv.x, 1.0 - uv.y); +} + +void mx_image_color3(sampler2D tex_sampler, int layer, vec3 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec3 result) +{ + vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); + result = texture(tex_sampler, uv).rgb; +} + +void adsk_NG_adsk_bitmap_color3(sampler2D file, vec2 realworld_offset, vec2 realworld_scale, vec2 uv_offset, vec2 uv_scale, float rotation_angle, float rgbamount, bool invert, int uaddressmode, int vaddressmode, vec2 texcoord, out vec3 out1) +{ + vec2 total_offset_out = realworld_offset + uv_offset; + vec2 total_scale_out = realworld_scale / uv_scale; + const float rotation_angle_param_in2_tmp = -1.000000; + float rotation_angle_param_out = rotation_angle * rotation_angle_param_in2_tmp; + vec2 a_place2d_out = vec2(0.0); + NG_place2d_vector2(texcoord, vec2(0.000000, 0.000000), total_scale_out, rotation_angle_param_out, total_offset_out, 1, a_place2d_out); + vec3 b_image_out = vec3(0.0); + mx_image_color3(file, 0, vec3(0.000000, 0.000000, 0.000000), a_place2d_out, uaddressmode, vaddressmode, 1, 0, 0, 0, vec2(1.000000, 1.000000), vec2(0.000000, 0.000000), b_image_out); + vec3 image_brightness_out = b_image_out * rgbamount; + const vec3 image_invert_amount_tmp = vec3(1.000000, 1.000000, 1.000000); + vec3 image_invert_out = image_invert_amount_tmp - image_brightness_out; + const bool image_convert_value2_tmp = true; + vec3 image_convert_out = (invert == image_convert_value2_tmp) ? image_invert_out : image_brightness_out; + out1 = image_convert_out; +} + +void main() +{ + vec2 geomprop_UV0_out1 = vd.texcoord_0.xy; + vec2 simplebitmap_realworld_offset_unit_out = simplebitmap_realworld_offset_unit_in1 * simplebitmap_realworld_offset_unit_in2; + vec2 simplebitmap_realworld_scale_unit_out = simplebitmap_realworld_scale_unit_in1 * simplebitmap_realworld_scale_unit_in2; + vec3 simplebitmap_out = vec3(0.0); + adsk_NG_adsk_bitmap_color3(simplebitmap_file, simplebitmap_realworld_offset_unit_out, simplebitmap_realworld_scale_unit_out, simplebitmap_uv_offset, simplebitmap_uv_scale, simplebitmap_rotation_angle, simplebitmap_rgbamount, simplebitmap_invert, simplebitmap_uaddressmode, simplebitmap_vaddressmode, geomprop_UV0_out1, simplebitmap_out); + bitmapoutput1 = vec4(simplebitmap_out, 1.0); +} + diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/bitmap/bitmapoutput_glsl_vs.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/bitmap/bitmapoutput_glsl_vs.glsl new file mode 100644 index 0000000000..c43d3a752f --- /dev/null +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/bitmap/bitmapoutput_glsl_vs.glsl @@ -0,0 +1,71 @@ +#version 400 + + +// Uniform block: PrivateUniforms +uniform mat4 u_worldMatrix = mat4(1.0); +uniform mat4 u_viewProjectionMatrix = mat4(1.0); + +// Inputs block: VertexInputs +in vec3 i_position; +in vec2 i_texcoord_0; + +out VertexData +{ + vec2 texcoord_0; +} vd; + +#define M_FLOAT_EPS 1e-8 +#define M_PI 3.1415926535897932 + +#define mx_mod mod +#define mx_inverse inverse +#define mx_inversesqrt inversesqrt +#define mx_sin sin +#define mx_cos cos +#define mx_tan tan +#define mx_asin asin +#define mx_acos acos +#define mx_atan atan +#define mx_radians radians +#define mx_float_bits_to_int floatBitsToInt + +vec2 mx_matrix_mul(vec2 v, mat2 m) { return v * m; } +vec3 mx_matrix_mul(vec3 v, mat3 m) { return v * m; } +vec4 mx_matrix_mul(vec4 v, mat4 m) { return v * m; } +vec2 mx_matrix_mul(mat2 m, vec2 v) { return m * v; } +vec3 mx_matrix_mul(mat3 m, vec3 v) { return m * v; } +vec4 mx_matrix_mul(mat4 m, vec4 v) { return m * v; } +mat2 mx_matrix_mul(mat2 m1, mat2 m2) { return m1 * m2; } +mat3 mx_matrix_mul(mat3 m1, mat3 m2) { return m1 * m2; } +mat4 mx_matrix_mul(mat4 m1, mat4 m2) { return m1 * m2; } + +float mx_square(float x) +{ + return x*x; +} + +vec2 mx_square(vec2 x) +{ + return x*x; +} + +vec3 mx_square(vec3 x) +{ + return x*x; +} + +vec3 mx_srgb_encode(vec3 color) +{ + bvec3 isAbove = greaterThan(color, vec3(0.0031308)); + vec3 linSeg = color * 12.92; + vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; + return mix(linSeg, powSeg, isAbove); +} + +void main() +{ + vec4 hPositionWorld = u_worldMatrix * vec4(i_position, 1.0); + gl_Position = u_viewProjectionMatrix * hPositionWorld; + vd.texcoord_0 = i_texcoord_0; +} + diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/glazing/Glazing_test_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/glazing/Glazing_test_ps.glsl index cc0d2c6c55..aea869522b 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/glazing/Glazing_test_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/glazing/Glazing_test_ps.glsl @@ -1620,10 +1620,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/heightmap/Gold_pass_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/heightmap/Gold_pass_ps.glsl index 5b2ff1c847..e457154046 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/heightmap/Gold_pass_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/heightmap/Gold_pass_ps.glsl @@ -1778,10 +1778,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Granite_Blue_Pearl_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Granite_Blue_Pearl_ps.glsl index a5aa2be335..47a1355c43 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Granite_Blue_Pearl_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Granite_Blue_Pearl_ps.glsl @@ -1818,10 +1818,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Paint_Metallic_Green_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Paint_Metallic_Green_ps.glsl index 142cc22d9a..90a1886257 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Paint_Metallic_Green_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Paint_Metallic_Green_ps.glsl @@ -1617,10 +1617,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Paint_Metallic_Red_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Paint_Metallic_Red_ps.glsl index 50a6d058a1..15ba6602d2 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Paint_Metallic_Red_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/layered/Paint_Metallic_Red_ps.glsl @@ -1617,10 +1617,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/normalmap/Gold_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/normalmap/Gold_ps.glsl index 2c02560b48..fdb3ef1d32 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/normalmap/Gold_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/normalmap/Gold_ps.glsl @@ -1750,10 +1750,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Plastic_Glossy_White_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Plastic_Glossy_White_ps.glsl index 55f1df336c..1661a9c1bc 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Plastic_Glossy_White_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Plastic_Glossy_White_ps.glsl @@ -1612,10 +1612,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Walnut_Semigloss_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Walnut_Semigloss_ps.glsl index 3d049784f6..b173458204 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Walnut_Semigloss_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Walnut_Semigloss_ps.glsl @@ -1818,10 +1818,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Walnut_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Walnut_ps.glsl index 99b531a66c..9bd047d9da 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Walnut_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/opaque/Walnut_ps.glsl @@ -1819,10 +1819,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/transparent/Gemstone_Diamond_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/transparent/Gemstone_Diamond_ps.glsl index 49afc0afc5..ee868005b5 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/transparent/Gemstone_Diamond_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/transparent/Gemstone_Diamond_ps.glsl @@ -1608,10 +1608,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/transparent/Gemstone_Ruby_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/transparent/Gemstone_Ruby_ps.glsl index 48a2d104d0..23e59782c1 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/transparent/Gemstone_Ruby_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Fusion/transparent/Gemstone_Ruby_ps.glsl @@ -1608,10 +1608,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/ceramic/M_legacy_ceramic_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/ceramic/M_legacy_ceramic_ps.glsl index ac9981f8a5..9972460320 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/ceramic/M_legacy_ceramic_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/ceramic/M_legacy_ceramic_ps.glsl @@ -1806,10 +1806,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/checker/M_legacy_checker_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/checker/M_legacy_checker_ps.glsl index fcacb0535b..d8fecb750a 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/checker/M_legacy_checker_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/checker/M_legacy_checker_ps.glsl @@ -1819,10 +1819,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/concrete/M_legacy_concrete_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/concrete/M_legacy_concrete_ps.glsl index b780838475..fb932d8e8c 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/concrete/M_legacy_concrete_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/concrete/M_legacy_concrete_ps.glsl @@ -1876,10 +1876,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/generic/M_legacy_generic_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/generic/M_legacy_generic_ps.glsl index 75d2e472a6..41a7997cc5 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/generic/M_legacy_generic_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/generic/M_legacy_generic_ps.glsl @@ -1780,10 +1780,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/glass/M_legacy_glass_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/glass/M_legacy_glass_ps.glsl index 2dc0b939f9..7a0f4f3c18 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/glass/M_legacy_glass_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/glass/M_legacy_glass_ps.glsl @@ -2732,10 +2732,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/glazing/M_legacy_glazing_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/glazing/M_legacy_glazing_ps.glsl index e9a7ac37f9..66a259c24e 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/glazing/M_legacy_glazing_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/glazing/M_legacy_glazing_ps.glsl @@ -1680,10 +1680,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/gradient/M_legacy_gradient_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/gradient/M_legacy_gradient_ps.glsl index ee2f036656..9b11a4f4d1 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/gradient/M_legacy_gradient_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/gradient/M_legacy_gradient_ps.glsl @@ -2883,10 +2883,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/hardwood/M_legacy_hardwood_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/hardwood/M_legacy_hardwood_ps.glsl index e0bbdcb09d..23996a024f 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/hardwood/M_legacy_hardwood_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/hardwood/M_legacy_hardwood_ps.glsl @@ -1897,10 +1897,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/masonry/M_legacy_masonry_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/masonry/M_legacy_masonry_ps.glsl new file mode 100644 index 0000000000..ecc7c8b053 --- /dev/null +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/masonry/M_legacy_masonry_ps.glsl @@ -0,0 +1,1978 @@ +#version 400 + + +struct BSDF { vec3 response; vec3 throughput; }; +#define EDF vec3 +struct VDF { vec3 response; vec3 throughput; }; +struct surfaceshader { vec3 color; vec3 transparency; }; +struct volumeshader { vec3 color; vec3 transparency; }; +struct displacementshader { vec3 offset; float scale; }; +struct lightshader { vec3 intensity; vec3 direction; }; +#define material surfaceshader + +// Uniform block: PrivateUniforms +uniform mat4 u_envMatrix = mat4(-1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000); +uniform sampler2D u_envRadiance; +uniform float u_envLightIntensity = 1.000000; +uniform int u_envRadianceMips = 1; +uniform int u_envRadianceSamples = 16; +uniform sampler2D u_envIrradiance; +uniform bool u_refractionTwoSided = false; +uniform vec3 u_viewPosition = vec3(0.0); + +// Uniform block: PublicUniforms +uniform surfaceshader backsurfaceshader; +uniform displacementshader displacementshader1; +uniform int geomprop_UV0_index = 0; +uniform sampler2D test_bump_masonry_file; +uniform vec2 test_bump_masonry_realworld_offset = vec2(0.000000, 0.000000); +uniform vec2 test_bump_masonry_realworld_scale = vec2(0.250000, 0.250000); +uniform vec2 test_bump_masonry_uv_offset = vec2(0.000000, 0.000000); +uniform vec2 test_bump_masonry_uv_scale = vec2(1.000000, 1.000000); +uniform float test_bump_masonry_rotation_angle = 0.000000; +uniform float test_bump_masonry_depth = 0.500000; +uniform int test_bump_masonry_uaddressmode = 2; +uniform int test_bump_masonry_vaddressmode = 2; +uniform int SR_legacy_masonry_type = 0; +uniform vec3 SR_legacy_masonry_color = vec3(0.500000, 0.500000, 0.500000); +uniform bool SR_legacy_masonry_tint_enable = false; +uniform vec3 SR_legacy_masonry_tint_color = vec3(0.950000, 0.500000, 0.500000); +uniform int SR_legacy_masonry_finish = 1; +uniform bool SR_legacy_masonry_relief_enable = true; + +in VertexData +{ + vec2 texcoord_0; + vec3 normalWorld; + vec3 tangentWorld; + vec3 bitangentWorld; + vec3 positionWorld; +} vd; + +// Pixel shader outputs +out vec4 out1; + +#define M_FLOAT_EPS 1e-8 +#define M_PI 3.1415926535897932 + +#define mx_mod mod +#define mx_inverse inverse +#define mx_inversesqrt inversesqrt +#define mx_sin sin +#define mx_cos cos +#define mx_tan tan +#define mx_asin asin +#define mx_acos acos +#define mx_atan atan +#define mx_radians radians +#define mx_float_bits_to_int floatBitsToInt + +vec2 mx_matrix_mul(vec2 v, mat2 m) { return v * m; } +vec3 mx_matrix_mul(vec3 v, mat3 m) { return v * m; } +vec4 mx_matrix_mul(vec4 v, mat4 m) { return v * m; } +vec2 mx_matrix_mul(mat2 m, vec2 v) { return m * v; } +vec3 mx_matrix_mul(mat3 m, vec3 v) { return m * v; } +vec4 mx_matrix_mul(mat4 m, vec4 v) { return m * v; } +mat2 mx_matrix_mul(mat2 m1, mat2 m2) { return m1 * m2; } +mat3 mx_matrix_mul(mat3 m1, mat3 m2) { return m1 * m2; } +mat4 mx_matrix_mul(mat4 m1, mat4 m2) { return m1 * m2; } + +float mx_square(float x) +{ + return x*x; +} + +vec2 mx_square(vec2 x) +{ + return x*x; +} + +vec3 mx_square(vec3 x) +{ + return x*x; +} + +vec3 mx_srgb_encode(vec3 color) +{ + bvec3 isAbove = greaterThan(color, vec3(0.0031308)); + vec3 linSeg = color * 12.92; + vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; + return mix(linSeg, powSeg, isAbove); +} + +#define DIRECTIONAL_ALBEDO_METHOD 0 + +#define AIRY_FRESNEL_ITERATIONS 2 + +#define M_PI 3.1415926535897932 +#define M_PI_INV (1.0 / M_PI) + +float mx_pow5(float x) +{ + return mx_square(mx_square(x)) * x; +} + +float mx_pow6(float x) +{ + float x2 = mx_square(x); + return mx_square(x2) * x2; +} + +// Standard Schlick Fresnel +float mx_fresnel_schlick(float cosTheta, float F0) +{ + float x = clamp(1.0 - cosTheta, 0.0, 1.0); + float x5 = mx_pow5(x); + return F0 + (1.0 - F0) * x5; +} +vec3 mx_fresnel_schlick(float cosTheta, vec3 F0) +{ + float x = clamp(1.0 - cosTheta, 0.0, 1.0); + float x5 = mx_pow5(x); + return F0 + (1.0 - F0) * x5; +} + +// Generalized Schlick Fresnel +float mx_fresnel_schlick(float cosTheta, float F0, float F90) +{ + float x = clamp(1.0 - cosTheta, 0.0, 1.0); + float x5 = mx_pow5(x); + return mix(F0, F90, x5); +} +vec3 mx_fresnel_schlick(float cosTheta, vec3 F0, vec3 F90) +{ + float x = clamp(1.0 - cosTheta, 0.0, 1.0); + float x5 = mx_pow5(x); + return mix(F0, F90, x5); +} + +// Generalized Schlick Fresnel with a variable exponent +float mx_fresnel_schlick(float cosTheta, float F0, float F90, float exponent) +{ + float x = clamp(1.0 - cosTheta, 0.0, 1.0); + return mix(F0, F90, pow(x, exponent)); +} +vec3 mx_fresnel_schlick(float cosTheta, vec3 F0, vec3 F90, float exponent) +{ + float x = clamp(1.0 - cosTheta, 0.0, 1.0); + return mix(F0, F90, pow(x, exponent)); +} + +// Enforce that the given normal is forward-facing from the specified view direction. +vec3 mx_forward_facing_normal(vec3 N, vec3 V) +{ + return (dot(N, V) < 0.0) ? -N : N; +} + +// https://www.graphics.rwth-aachen.de/publication/2/jgt.pdf +float mx_golden_ratio_sequence(int i) +{ + const float GOLDEN_RATIO = 1.6180339887498948; + return fract((float(i) + 1.0) * GOLDEN_RATIO); +} + +// https://people.irisa.fr/Ricardo.Marques/articles/2013/SF_CGF.pdf +vec2 mx_spherical_fibonacci(int i, int numSamples) +{ + return vec2((float(i) + 0.5) / float(numSamples), mx_golden_ratio_sequence(i)); +} + +// Generate a uniform-weighted sample on the unit hemisphere. +vec3 mx_uniform_sample_hemisphere(vec2 Xi) +{ + float phi = 2.0 * M_PI * Xi.x; + float cosTheta = 1.0 - Xi.y; + float sinTheta = sqrt(1.0 - mx_square(cosTheta)); + return vec3(mx_cos(phi) * sinTheta, + mx_sin(phi) * sinTheta, + cosTheta); +} + +// Generate a cosine-weighted sample on the unit hemisphere. +vec3 mx_cosine_sample_hemisphere(vec2 Xi) +{ + float phi = 2.0 * M_PI * Xi.x; + float cosTheta = sqrt(Xi.y); + float sinTheta = sqrt(1.0 - Xi.y); + return vec3(mx_cos(phi) * sinTheta, + mx_sin(phi) * sinTheta, + cosTheta); +} + +// PDF of a cosine-weighted hemisphere sample. +float mx_cosine_hemisphere_PDF(float cosTheta) +{ + return max(cosTheta, 0.0) * M_PI_INV; +} + +// PDF of a uniform hemisphere sample. +float mx_uniform_hemisphere_PDF() +{ + return 0.5 * M_PI_INV; +} + +// Construct an orthonormal basis from a unit vector. +// https://graphics.pixar.com/library/OrthonormalB/paper.pdf +mat3 mx_orthonormal_basis(vec3 N) +{ + float sign = (N.z < 0.0) ? -1.0 : 1.0; + float a = -1.0 / (sign + N.z); + float b = N.x * N.y * a; + vec3 X = vec3(1.0 + sign * N.x * N.x * a, sign * b, -sign * N.x); + vec3 Y = vec3(b, sign + N.y * N.y * a, -N.y); + return mat3(X, Y, N); +} + +const int FRESNEL_MODEL_DIELECTRIC = 0; +const int FRESNEL_MODEL_CONDUCTOR = 1; +const int FRESNEL_MODEL_SCHLICK = 2; + +// Parameters for Fresnel calculations +struct FresnelData +{ + // Fresnel model + int model; + bool airy; + + // Physical Fresnel + vec3 ior; + vec3 extinction; + + // Generalized Schlick Fresnel + vec3 F0; + vec3 F82; + vec3 F90; + float exponent; + + // Thin film + float tf_thickness; + float tf_ior; + + // Refraction + bool refraction; +}; + +// https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf +// Appendix B.2 Equation 13 +float mx_ggx_NDF(vec3 H, vec2 alpha) +{ + vec2 He = H.xy / alpha; + float denom = dot(He, He) + mx_square(H.z); + return 1.0 / (M_PI * alpha.x * alpha.y * mx_square(denom)); +} + +// https://ggx-research.github.io/publication/2023/06/09/publication-ggx.html +vec3 mx_ggx_importance_sample_VNDF(vec2 Xi, vec3 V, vec2 alpha) +{ + // Transform the view direction to the hemisphere configuration. + V = normalize(vec3(V.xy * alpha, V.z)); + + // Sample a spherical cap in (-V.z, 1]. + float phi = 2.0 * M_PI * Xi.x; + float z = (1.0 - Xi.y) * (1.0 + V.z) - V.z; + float sinTheta = sqrt(clamp(1.0 - z * z, 0.0, 1.0)); + float x = sinTheta * mx_cos(phi); + float y = sinTheta * mx_sin(phi); + vec3 c = vec3(x, y, z); + + // Compute the microfacet normal. + vec3 H = c + V; + + // Transform the microfacet normal back to the ellipsoid configuration. + H = normalize(vec3(H.xy * alpha, max(H.z, 0.0))); + + return H; +} + +// PDF of a reflection direction sampled from the GGX VNDF. +float mx_ggx_VNDF_reflection_PDF(vec3 H, vec2 alpha, float G1V, float NdotV) +{ + return mx_ggx_NDF(H, alpha) * G1V / (4.0 * NdotV); +} + +// https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf +// Equation 34 +float mx_ggx_smith_G1(float cosTheta, float alpha) +{ + float cosTheta2 = mx_square(cosTheta); + float tanTheta2 = (1.0 - cosTheta2) / cosTheta2; + return 2.0 / (1.0 + sqrt(1.0 + mx_square(alpha) * tanTheta2)); +} + +// Height-correlated Smith masking-shadowing +// http://jcgt.org/published/0003/02/03/paper.pdf +// Equations 72 and 99 +float mx_ggx_smith_G2(float NdotL, float NdotV, float alpha) +{ + float alpha2 = mx_square(alpha); + float lambdaL = sqrt(alpha2 + (1.0 - alpha2) * mx_square(NdotL)); + float lambdaV = sqrt(alpha2 + (1.0 - alpha2) * mx_square(NdotV)); + return 2.0 * NdotL * NdotV / (lambdaL * NdotV + lambdaV * NdotL); +} + +// Rational quadratic fit to Monte Carlo data for GGX directional albedo. +vec3 mx_ggx_dir_albedo_analytic(float NdotV, float alpha, vec3 F0, vec3 F90) +{ + float x = NdotV; + float y = alpha; + float x2 = mx_square(x); + float y2 = mx_square(y); + vec4 r = vec4(0.1003, 0.9345, 1.0, 1.0) + + vec4(-0.6303, -2.323, -1.765, 0.2281) * x + + vec4(9.748, 2.229, 8.263, 15.94) * y + + vec4(-2.038, -3.748, 11.53, -55.83) * x * y + + vec4(29.34, 1.424, 28.96, 13.08) * x2 + + vec4(-8.245, -0.7684, -7.507, 41.26) * y2 + + vec4(-26.44, 1.436, -36.11, 54.9) * x2 * y + + vec4(19.99, 0.2913, 15.86, 300.2) * x * y2 + + vec4(-5.448, 0.6286, 33.37, -285.1) * x2 * y2; + vec2 AB = clamp(r.xy / r.zw, 0.0, 1.0); + return F0 * AB.x + F90 * AB.y; +} + +vec3 mx_ggx_dir_albedo_table_lookup(float NdotV, float alpha, vec3 F0, vec3 F90) +{ +#if DIRECTIONAL_ALBEDO_METHOD == 1 + if (textureSize(u_albedoTable, 0).x > 1) + { + vec2 AB = texture(u_albedoTable, vec2(NdotV, alpha)).rg; + return F0 * AB.x + F90 * AB.y; + } +#endif + return vec3(0.0); +} + +// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf +vec3 mx_ggx_dir_albedo_monte_carlo(float NdotV, float alpha, vec3 F0, vec3 F90) +{ + NdotV = clamp(NdotV, M_FLOAT_EPS, 1.0); + vec3 V = vec3(sqrt(1.0 - mx_square(NdotV)), 0, NdotV); + + vec2 AB = vec2(0.0); + const int SAMPLE_COUNT = 64; + for (int i = 0; i < SAMPLE_COUNT; i++) + { + vec2 Xi = mx_spherical_fibonacci(i, SAMPLE_COUNT); + + // Compute the half vector and incoming light direction. + vec3 H = mx_ggx_importance_sample_VNDF(Xi, V, vec2(alpha)); + vec3 L = -reflect(V, H); + + // Compute dot products for this sample. + float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); + float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); + + // Compute the Fresnel term. + float Fc = mx_fresnel_schlick(VdotH, 0.0, 1.0); + + // Compute the per-sample geometric term. + // https://hal.inria.fr/hal-00996995v2/document, Algorithm 2 + float G2 = mx_ggx_smith_G2(NdotL, NdotV, alpha); + + // Add the contribution of this sample. + AB += vec2(G2 * (1.0 - Fc), G2 * Fc); + } + + // Apply the global component of the geometric term and normalize. + AB /= mx_ggx_smith_G1(NdotV, alpha) * float(SAMPLE_COUNT); + + // Return the final directional albedo. + return F0 * AB.x + F90 * AB.y; +} + +vec3 mx_ggx_dir_albedo(float NdotV, float alpha, vec3 F0, vec3 F90) +{ +#if DIRECTIONAL_ALBEDO_METHOD == 0 + return mx_ggx_dir_albedo_analytic(NdotV, alpha, F0, F90); +#elif DIRECTIONAL_ALBEDO_METHOD == 1 + return mx_ggx_dir_albedo_table_lookup(NdotV, alpha, F0, F90); +#else + return mx_ggx_dir_albedo_monte_carlo(NdotV, alpha, F0, F90); +#endif +} + +float mx_ggx_dir_albedo(float NdotV, float alpha, float F0, float F90) +{ + return mx_ggx_dir_albedo(NdotV, alpha, vec3(F0), vec3(F90)).x; +} + +// https://blog.selfshadow.com/publications/turquin/ms_comp_final.pdf +// Equations 14 and 16 +vec3 mx_ggx_energy_compensation(float NdotV, float alpha, vec3 Fss) +{ + float Ess = mx_ggx_dir_albedo(NdotV, alpha, 1.0, 1.0); + return 1.0 + Fss * (1.0 - Ess) / Ess; +} + +float mx_ggx_energy_compensation(float NdotV, float alpha, float Fss) +{ + return mx_ggx_energy_compensation(NdotV, alpha, vec3(Fss)).x; +} + +// Compute the average of an anisotropic alpha pair. +float mx_average_alpha(vec2 alpha) +{ + return sqrt(alpha.x * alpha.y); +} + +// Convert a real-valued index of refraction to normal-incidence reflectivity. +float mx_ior_to_f0(float ior) +{ + return mx_square((ior - 1.0) / (ior + 1.0)); +} + +// Convert normal-incidence reflectivity to real-valued index of refraction. +float mx_f0_to_ior(float F0) +{ + float sqrtF0 = sqrt(clamp(F0, 0.01, 0.99)); + return (1.0 + sqrtF0) / (1.0 - sqrtF0); +} +vec3 mx_f0_to_ior(vec3 F0) +{ + vec3 sqrtF0 = sqrt(clamp(F0, 0.01, 0.99)); + return (vec3(1.0) + sqrtF0) / (vec3(1.0) - sqrtF0); +} + +// https://renderwonk.com/publications/wp-generalization-adobe/gen-adobe.pdf +vec3 mx_fresnel_hoffman_schlick(float cosTheta, FresnelData fd) +{ + const float COS_THETA_MAX = 1.0 / 7.0; + const float COS_THETA_FACTOR = 1.0 / (COS_THETA_MAX * pow(1.0 - COS_THETA_MAX, 6.0)); + + float x = clamp(cosTheta, 0.0, 1.0); + vec3 a = mix(fd.F0, fd.F90, pow(1.0 - COS_THETA_MAX, fd.exponent)) * (vec3(1.0) - fd.F82) * COS_THETA_FACTOR; + return mix(fd.F0, fd.F90, pow(1.0 - x, fd.exponent)) - a * x * mx_pow6(1.0 - x); +} + +// https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ +float mx_fresnel_dielectric(float cosTheta, float ior) +{ + float c = cosTheta; + float g2 = ior*ior + c*c - 1.0; + if (g2 < 0.0) + { + // Total internal reflection + return 1.0; + } + + float g = sqrt(g2); + return 0.5 * mx_square((g - c) / (g + c)) * + (1.0 + mx_square(((g + c) * c - 1.0) / ((g - c) * c + 1.0))); +} + +// https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ +vec2 mx_fresnel_dielectric_polarized(float cosTheta, float ior) +{ + float cosTheta2 = mx_square(clamp(cosTheta, 0.0, 1.0)); + float sinTheta2 = 1.0 - cosTheta2; + + float t0 = max(ior * ior - sinTheta2, 0.0); + float t1 = t0 + cosTheta2; + float t2 = 2.0 * sqrt(t0) * cosTheta; + float Rs = (t1 - t2) / (t1 + t2); + + float t3 = cosTheta2 * t0 + sinTheta2 * sinTheta2; + float t4 = t2 * sinTheta2; + float Rp = Rs * (t3 - t4) / (t3 + t4); + + return vec2(Rp, Rs); +} + +// https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/ +void mx_fresnel_conductor_polarized(float cosTheta, vec3 n, vec3 k, out vec3 Rp, out vec3 Rs) +{ + float cosTheta2 = mx_square(clamp(cosTheta, 0.0, 1.0)); + float sinTheta2 = 1.0 - cosTheta2; + vec3 n2 = n * n; + vec3 k2 = k * k; + + vec3 t0 = n2 - k2 - vec3(sinTheta2); + vec3 a2plusb2 = sqrt(t0 * t0 + 4.0 * n2 * k2); + vec3 t1 = a2plusb2 + vec3(cosTheta2); + vec3 a = sqrt(max(0.5 * (a2plusb2 + t0), 0.0)); + vec3 t2 = 2.0 * a * cosTheta; + Rs = (t1 - t2) / (t1 + t2); + + vec3 t3 = cosTheta2 * a2plusb2 + vec3(sinTheta2 * sinTheta2); + vec3 t4 = t2 * sinTheta2; + Rp = Rs * (t3 - t4) / (t3 + t4); +} + +vec3 mx_fresnel_conductor(float cosTheta, vec3 n, vec3 k) +{ + vec3 Rp, Rs; + mx_fresnel_conductor_polarized(cosTheta, n, k, Rp, Rs); + return 0.5 * (Rp + Rs); +} + +// https://belcour.github.io/blog/research/publication/2017/05/01/brdf-thin-film.html +void mx_fresnel_conductor_phase_polarized(float cosTheta, float eta1, vec3 eta2, vec3 kappa2, out vec3 phiP, out vec3 phiS) +{ + vec3 k2 = kappa2 / eta2; + vec3 sinThetaSqr = vec3(1.0) - cosTheta * cosTheta; + vec3 A = eta2*eta2*(vec3(1.0)-k2*k2) - eta1*eta1*sinThetaSqr; + vec3 B = sqrt(A*A + mx_square(2.0*eta2*eta2*k2)); + vec3 U = sqrt((A+B)/2.0); + vec3 V = max(vec3(0.0), sqrt((B-A)/2.0)); + + phiS = mx_atan(2.0*eta1*V*cosTheta, U*U + V*V - mx_square(eta1*cosTheta)); + phiP = mx_atan(2.0*eta1*eta2*eta2*cosTheta * (2.0*k2*U - (vec3(1.0)-k2*k2) * V), + mx_square(eta2*eta2*(vec3(1.0)+k2*k2)*cosTheta) - eta1*eta1*(U*U+V*V)); +} + +// https://belcour.github.io/blog/research/publication/2017/05/01/brdf-thin-film.html +vec3 mx_eval_sensitivity(float opd, vec3 shift) +{ + // Use Gaussian fits, given by 3 parameters: val, pos and var + float phase = 2.0*M_PI * opd; + vec3 val = vec3(5.4856e-13, 4.4201e-13, 5.2481e-13); + vec3 pos = vec3(1.6810e+06, 1.7953e+06, 2.2084e+06); + vec3 var = vec3(4.3278e+09, 9.3046e+09, 6.6121e+09); + vec3 xyz = val * sqrt(2.0*M_PI * var) * mx_cos(pos * phase + shift) * exp(- var * phase*phase); + xyz.x += 9.7470e-14 * sqrt(2.0*M_PI * 4.5282e+09) * mx_cos(2.2399e+06 * phase + shift[0]) * exp(- 4.5282e+09 * phase*phase); + return xyz / 1.0685e-7; +} + +// A Practical Extension to Microfacet Theory for the Modeling of Varying Iridescence +// https://belcour.github.io/blog/research/publication/2017/05/01/brdf-thin-film.html +vec3 mx_fresnel_airy(float cosTheta, FresnelData fd) +{ + // XYZ to CIE 1931 RGB color space (using neutral E illuminant) + const mat3 XYZ_TO_RGB = mat3(2.3706743, -0.5138850, 0.0052982, -0.9000405, 1.4253036, -0.0146949, -0.4706338, 0.0885814, 1.0093968); + + // Assume vacuum on the outside + float eta1 = 1.0; + float eta2 = max(fd.tf_ior, eta1); + vec3 eta3 = (fd.model == FRESNEL_MODEL_SCHLICK) ? mx_f0_to_ior(fd.F0) : fd.ior; + vec3 kappa3 = (fd.model == FRESNEL_MODEL_SCHLICK) ? vec3(0.0) : fd.extinction; + float cosThetaT = sqrt(1.0 - (1.0 - mx_square(cosTheta)) * mx_square(eta1 / eta2)); + + // First interface + vec2 R12 = mx_fresnel_dielectric_polarized(cosTheta, eta2 / eta1); + if (cosThetaT <= 0.0) + { + // Total internal reflection + R12 = vec2(1.0); + } + vec2 T121 = vec2(1.0) - R12; + + // Second interface + vec3 R23p, R23s; + if (fd.model == FRESNEL_MODEL_SCHLICK) + { + vec3 f = mx_fresnel_hoffman_schlick(cosThetaT, fd); + R23p = 0.5 * f; + R23s = 0.5 * f; + } + else + { + mx_fresnel_conductor_polarized(cosThetaT, eta3 / eta2, kappa3 / eta2, R23p, R23s); + } + + // Phase shift + float cosB = mx_cos(mx_atan(eta2 / eta1)); + vec2 phi21 = vec2(cosTheta < cosB ? 0.0 : M_PI, M_PI); + vec3 phi23p, phi23s; + if (fd.model == FRESNEL_MODEL_SCHLICK) + { + phi23p = vec3((eta3[0] < eta2) ? M_PI : 0.0, + (eta3[1] < eta2) ? M_PI : 0.0, + (eta3[2] < eta2) ? M_PI : 0.0); + phi23s = phi23p; + } + else + { + mx_fresnel_conductor_phase_polarized(cosThetaT, eta2, eta3, kappa3, phi23p, phi23s); + } + vec3 r123p = max(sqrt(R12.x*R23p), 0.0); + vec3 r123s = max(sqrt(R12.y*R23s), 0.0); + + // Iridescence term + vec3 I = vec3(0.0); + vec3 Cm, Sm; + + // Optical path difference + float distMeters = fd.tf_thickness * 1.0e-9; + float opd = 2.0 * eta2 * cosThetaT * distMeters; + + // Iridescence term using spectral antialiasing for Parallel polarization + + // Reflectance term for m=0 (DC term amplitude) + vec3 Rs = (mx_square(T121.x) * R23p) / (vec3(1.0) - R12.x*R23p); + I += R12.x + Rs; + + // Reflectance term for m>0 (pairs of diracs) + Cm = Rs - T121.x; + for (int m = 1; m <= AIRY_FRESNEL_ITERATIONS; m++) + { + Cm *= r123p; + Sm = 2.0 * mx_eval_sensitivity(float(m) * opd, float(m)*(phi23p+vec3(phi21.x))); + I += Cm*Sm; + } + + // Iridescence term using spectral antialiasing for Perpendicular polarization + + // Reflectance term for m=0 (DC term amplitude) + vec3 Rp = (mx_square(T121.y) * R23s) / (vec3(1.0) - R12.y*R23s); + I += R12.y + Rp; + + // Reflectance term for m>0 (pairs of diracs) + Cm = Rp - T121.y; + for (int m = 1; m <= AIRY_FRESNEL_ITERATIONS; m++) + { + Cm *= r123s; + Sm = 2.0 * mx_eval_sensitivity(float(m) * opd, float(m)*(phi23s+vec3(phi21.y))); + I += Cm*Sm; + } + + // Average parallel and perpendicular polarization + I *= 0.5; + + // Convert back to RGB reflectance + I = clamp(mx_matrix_mul(XYZ_TO_RGB, I), 0.0, 1.0); + + return I; +} + +FresnelData mx_init_fresnel_dielectric(float ior, float tf_thickness, float tf_ior) +{ + FresnelData fd; + fd.model = FRESNEL_MODEL_DIELECTRIC; + fd.airy = tf_thickness > 0.0; + fd.ior = vec3(ior); + fd.extinction = vec3(0.0); + fd.F0 = vec3(0.0); + fd.F82 = vec3(0.0); + fd.F90 = vec3(0.0); + fd.exponent = 0.0; + fd.tf_thickness = tf_thickness; + fd.tf_ior = tf_ior; + fd.refraction = false; + return fd; +} + +FresnelData mx_init_fresnel_conductor(vec3 ior, vec3 extinction, float tf_thickness, float tf_ior) +{ + FresnelData fd; + fd.model = FRESNEL_MODEL_CONDUCTOR; + fd.airy = tf_thickness > 0.0; + fd.ior = ior; + fd.extinction = extinction; + fd.F0 = vec3(0.0); + fd.F82 = vec3(0.0); + fd.F90 = vec3(0.0); + fd.exponent = 0.0; + fd.tf_thickness = tf_thickness; + fd.tf_ior = tf_ior; + fd.refraction = false; + return fd; +} + +FresnelData mx_init_fresnel_schlick(vec3 F0, vec3 F82, vec3 F90, float exponent, float tf_thickness, float tf_ior) +{ + FresnelData fd; + fd.model = FRESNEL_MODEL_SCHLICK; + fd.airy = tf_thickness > 0.0; + fd.ior = vec3(0.0); + fd.extinction = vec3(0.0); + fd.F0 = F0; + fd.F82 = F82; + fd.F90 = F90; + fd.exponent = exponent; + fd.tf_thickness = tf_thickness; + fd.tf_ior = tf_ior; + fd.refraction = false; + return fd; +} + +vec3 mx_compute_fresnel(float cosTheta, FresnelData fd) +{ + if (fd.airy) + { + return mx_fresnel_airy(cosTheta, fd); + } + else if (fd.model == FRESNEL_MODEL_DIELECTRIC) + { + return vec3(mx_fresnel_dielectric(cosTheta, fd.ior.x)); + } + else if (fd.model == FRESNEL_MODEL_CONDUCTOR) + { + return mx_fresnel_conductor(cosTheta, fd.ior, fd.extinction); + } + else // FRESNEL_MODEL_SCHLICK + { + return mx_fresnel_hoffman_schlick(cosTheta, fd); + } +} + +// Directional albedo accounting for different Fresnel functions. +vec3 mx_ggx_dir_albedo(float NdotV, float alpha, FresnelData fd) +{ + if (fd.airy) + { + // Approximation using a blend between mirror (alpha = 0) + // and rougher cases. This helps to maintain angular + // color variation at lower roughness values. + vec3 mirrorDirAlbedo = mx_compute_fresnel(NdotV, fd); + vec3 F0 = mx_fresnel_airy(1.0, fd); + vec3 roughDirAlbedo = mx_ggx_dir_albedo(NdotV, alpha, F0, vec3(1.0)); + return mix(mirrorDirAlbedo, roughDirAlbedo, sqrt(alpha)); + } + else if (fd.model == FRESNEL_MODEL_DIELECTRIC) + { + float F0 = mx_ior_to_f0(fd.ior.x); + return mx_ggx_dir_albedo(NdotV, alpha, vec3(F0), vec3(1.0)); + } + else if (fd.model == FRESNEL_MODEL_CONDUCTOR) + { + vec3 F0 = mx_fresnel_conductor(1.0, fd.ior, fd.extinction); + return mx_ggx_dir_albedo(NdotV, alpha, F0, vec3(1.0)); + } + else // FRESNEL_MODEL_SCHLICK + { + return mx_ggx_dir_albedo(NdotV, alpha, fd.F0, fd.F90); + } +} + +// Compute the refraction of a ray through a solid sphere. +vec3 mx_refraction_solid_sphere(vec3 R, vec3 N, float ior) +{ + R = refract(R, N, 1.0 / ior); + vec3 N1 = normalize(R * dot(R, N) - N * 0.5); + return refract(R, N1, ior); +} + +vec2 mx_latlong_projection(vec3 dir) +{ + float latitude = -mx_asin(dir.y) * M_PI_INV + 0.5; + float longitude = mx_atan(dir.x, -dir.z) * M_PI_INV * 0.5 + 0.5; + return vec2(longitude, latitude); +} + +vec3 mx_latlong_map_lookup(vec3 dir, mat4 transform, float lod, sampler2D tex_sampler) +{ + vec3 envDir = normalize(mx_matrix_mul(transform, vec4(dir,0.0)).xyz); + vec2 uv = mx_latlong_projection(envDir); + return textureLod(tex_sampler, uv, lod).rgb; +} + +// Return the mip level with the appropriate coverage for a filtered importance sample. +// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch20.html +// Section 20.4 Equation 13 +float mx_latlong_compute_lod(vec3 dir, float pdf, float maxMipLevel, int envSamples) +{ + const float MIP_LEVEL_OFFSET = 1.5; + float effectiveMaxMipLevel = maxMipLevel - MIP_LEVEL_OFFSET; + float distortion = sqrt(1.0 - mx_square(dir.y)); + return max(effectiveMaxMipLevel - 0.5 * log2(float(envSamples) * pdf * distortion), 0.0); +} + +vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd) +{ + // Generate tangent frame. + X = normalize(X - dot(X, N) * N); + vec3 Y = cross(N, X); + mat3 tangentToWorld = mat3(X, Y, N); + + // Transform the view vector to tangent space. + V = vec3(dot(V, X), dot(V, Y), dot(V, N)); + + // Compute derived properties. + float NdotV = clamp(V.z, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(alpha); + float G1V = mx_ggx_smith_G1(NdotV, avgAlpha); + + // Integrate outgoing radiance using filtered importance sampling. + // http://cgg.mff.cuni.cz/~jaroslav/papers/2008-egsr-fis/2008-egsr-fis-final-embedded.pdf + vec3 radiance = vec3(0.0); + int envRadianceSamples = u_envRadianceSamples; + for (int i = 0; i < envRadianceSamples; i++) + { + vec2 Xi = mx_spherical_fibonacci(i, envRadianceSamples); + + // Compute the half vector and incoming light direction. + vec3 H = mx_ggx_importance_sample_VNDF(Xi, V, alpha); + vec3 L = fd.refraction ? mx_refraction_solid_sphere(-V, H, fd.ior.x) : -reflect(V, H); + + // Compute dot products for this sample. + float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); + float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); + + // Sample the environment light from the given direction. + vec3 Lw = mx_matrix_mul(tangentToWorld, L); + float pdf = mx_ggx_VNDF_reflection_PDF(H, alpha, G1V, NdotV); + float lod = mx_latlong_compute_lod(Lw, pdf, float(u_envRadianceMips - 1), envRadianceSamples); + vec3 sampleColor = mx_latlong_map_lookup(Lw, u_envMatrix, lod, u_envRadiance); + + // Compute the Fresnel term. + vec3 F = mx_compute_fresnel(VdotH, fd); + + // Compute the geometric term. + float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); + + // Compute the combined FG term, which simplifies to inverted Fresnel for refraction. + vec3 FG = fd.refraction ? vec3(1.0) - F : F * G; + + // Add the radiance contribution of this sample. + // From https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf + // incidentLight = sampleColor * NdotL + // microfacetSpecular = D * F * G / (4 * NdotL * NdotV) + // pdf = D * G1V / (4 * NdotV); + // radiance = incidentLight * microfacetSpecular / pdf + radiance += sampleColor * FG; + } + + // Apply the global component of the geometric term and normalize. + radiance /= G1V * float(envRadianceSamples); + + // Return the final radiance. + return (u_envRadianceSamples == 0 ? vec3(0.0) : radiance) * u_envLightIntensity; +} + +vec3 mx_environment_irradiance(vec3 N) +{ + vec3 Li = mx_latlong_map_lookup(N, u_envMatrix, 0.0, u_envIrradiance); + return Li * u_envLightIntensity; +} + + +vec3 mx_surface_transmission(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd, vec3 tint) +{ + // Approximate the appearance of surface transmission as glossy + // environment map refraction, ignoring any scene geometry that might + // be visible through the surface. + fd.refraction = true; + if (u_refractionTwoSided) + { + tint = mx_square(tint); + } + return mx_environment_radiance(N, V, X, alpha, distribution, fd) * tint; +} + +void mx_rotate_vector2(vec2 _in, float amount, out vec2 result) +{ + float rotationRadians = mx_radians(amount); + float sa = mx_sin(rotationRadians); + float ca = mx_cos(rotationRadians); + result = vec2(ca*_in.x + sa*_in.y, -sa*_in.x + ca*_in.y); +} + +void NG_switch_vector2I(vec2 in1, vec2 in2, vec2 in3, vec2 in4, vec2 in5, vec2 in6, vec2 in7, vec2 in8, vec2 in9, vec2 in10, int which, out vec2 out1) +{ + const int ifgreater_10_value1_tmp = 10; + const vec2 ifgreater_10_in2_tmp = vec2(0.000000, 0.000000); + vec2 ifgreater_10_out = (ifgreater_10_value1_tmp > which) ? in10 : ifgreater_10_in2_tmp; + const int ifgreater_9_value1_tmp = 9; + vec2 ifgreater_9_out = (ifgreater_9_value1_tmp > which) ? in9 : ifgreater_10_out; + const int ifgreater_8_value1_tmp = 8; + vec2 ifgreater_8_out = (ifgreater_8_value1_tmp > which) ? in8 : ifgreater_9_out; + const int ifgreater_7_value1_tmp = 7; + vec2 ifgreater_7_out = (ifgreater_7_value1_tmp > which) ? in7 : ifgreater_8_out; + const int ifgreater_6_value1_tmp = 6; + vec2 ifgreater_6_out = (ifgreater_6_value1_tmp > which) ? in6 : ifgreater_7_out; + const int ifgreater_5_value1_tmp = 5; + vec2 ifgreater_5_out = (ifgreater_5_value1_tmp > which) ? in5 : ifgreater_6_out; + const int ifgreater_4_value1_tmp = 4; + vec2 ifgreater_4_out = (ifgreater_4_value1_tmp > which) ? in4 : ifgreater_5_out; + const int ifgreater_3_value1_tmp = 3; + vec2 ifgreater_3_out = (ifgreater_3_value1_tmp > which) ? in3 : ifgreater_4_out; + const int ifgreater_2_value1_tmp = 2; + vec2 ifgreater_2_out = (ifgreater_2_value1_tmp > which) ? in2 : ifgreater_3_out; + const int ifgreater_1_value1_tmp = 1; + vec2 ifgreater_1_out = (ifgreater_1_value1_tmp > which) ? in1 : ifgreater_2_out; + out1 = ifgreater_1_out; +} + +void NG_place2d_vector2(vec2 texcoord, vec2 pivot, vec2 scale, float rotate, vec2 offset, int operationorder, out vec2 out1) +{ + vec2 N_subpivot_out = texcoord - pivot; + vec2 N_applyscale_out = N_subpivot_out / scale; + vec2 N_applyoffset2_out = N_subpivot_out - offset; + vec2 N_applyrot_out = vec2(0.0); + mx_rotate_vector2(N_applyscale_out, rotate, N_applyrot_out); + vec2 N_applyrot2_out = vec2(0.0); + mx_rotate_vector2(N_applyoffset2_out, rotate, N_applyrot2_out); + vec2 N_applyoffset_out = N_applyrot_out - offset; + vec2 N_applyscale2_out = N_applyrot2_out / scale; + vec2 N_addpivot_out = N_applyoffset_out + pivot; + vec2 N_addpivot2_out = N_applyscale2_out + pivot; + vec2 N_switch_operationorder_out = vec2(0.0); + NG_switch_vector2I(N_addpivot_out, N_addpivot2_out, vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), vec2(0.000000, 0.000000), operationorder, N_switch_operationorder_out); + out1 = N_switch_operationorder_out; +} + +vec2 mx_transform_uv(vec2 uv, vec2 uv_scale, vec2 uv_offset) +{ + uv = uv * uv_scale + uv_offset; + return vec2(uv.x, 1.0 - uv.y); +} + +void mx_image_float(sampler2D tex_sampler, int layer, float defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out float result) +{ + vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); + result = texture(tex_sampler, uv).r; +} + +void mx_heighttonormal_vector3(float height, float scale, vec2 texcoord, out vec3 result) +{ + // Scale factor for parity with traditional Sobel filtering. + const float SOBEL_SCALE_FACTOR = 1.0 / 16.0; + + // Compute screen-space gradients of the heightfield and texture coordinates. + vec2 dHdS = vec2(dFdx(height), dFdy(height)) * scale * SOBEL_SCALE_FACTOR; + vec2 dUdS = vec2(dFdx(texcoord.x), dFdy(texcoord.x)); + vec2 dVdS = vec2(dFdx(texcoord.y), dFdy(texcoord.y)); + + // Construct a screen-space tangent frame. + vec3 tangent = vec3(dUdS.x, dVdS.x, dHdS.x); + vec3 bitangent = vec3(dUdS.y, dVdS.y, dHdS.y); + vec3 n = cross(tangent, bitangent); + + // Handle invalid and mirrored texture coordinates. + if (dot(n, n) < M_FLOAT_EPS * M_FLOAT_EPS) + { + n = vec3(0, 0, 1); + } + else if (n.z < 0.0) + { + n *= -1.0; + } + + // Normalize and encode the results. + result = normalize(n) * 0.5 + 0.5; +} + +void mx_normalmap_vector2(vec3 value, vec2 normal_scale, vec3 N, vec3 T, vec3 B, out vec3 result) +{ + value = (dot(value, value) == 0.0) ? vec3(0.0, 0.0, 1.0) : value * 2.0 - 1.0; + value = T * value.x * normal_scale.x + + B * value.y * normal_scale.y + + N * value.z; + result = normalize(value); +} + +void mx_normalmap_float(vec3 value, float normal_scale, vec3 N, vec3 T, vec3 B, out vec3 result) +{ + mx_normalmap_vector2(value, vec2(normal_scale), N, T, B, result); +} + +void adsk_NG_adsk_height_map(sampler2D file, vec2 realworld_offset, vec2 realworld_scale, vec2 uv_offset, vec2 uv_scale, float rotation_angle, float depth, int uaddressmode, int vaddressmode, vec2 texcoord, vec3 normal, vec3 tangent, out vec3 out1) +{ + vec2 total_offset_out = realworld_offset + uv_offset; + vec2 total_scale_out = realworld_scale / uv_scale; + const float rotation_angle_param_in2_tmp = -1.000000; + float rotation_angle_param_out = rotation_angle * rotation_angle_param_in2_tmp; + vec3 normalmap_cross_out = cross(normal, tangent); + vec2 a_place2d_out = vec2(0.0); + NG_place2d_vector2(texcoord, vec2(0.000000, 0.000000), total_scale_out, rotation_angle_param_out, total_offset_out, 1, a_place2d_out); + vec3 normalmap_cross_norm_out = normalize(normalmap_cross_out); + float b_image_out = 0.0; + mx_image_float(file, 0, 0.000000, a_place2d_out, uaddressmode, vaddressmode, 1, 0, 0, 0, vec2(1.000000, 1.000000), vec2(0.000000, 0.000000), b_image_out); + vec3 impl_heighttonormalmap_out = vec3(0.0); + mx_heighttonormal_vector3(b_image_out, 1.000000, a_place2d_out, impl_heighttonormalmap_out); + vec3 impl_normalmap_out = vec3(0.0); + mx_normalmap_float(impl_heighttonormalmap_out, depth, normal, tangent, normalmap_cross_norm_out, impl_normalmap_out); + out1 = impl_normalmap_out; +} + +void NG_switch_floatI(float in1, float in2, float in3, float in4, float in5, float in6, float in7, float in8, float in9, float in10, int which, out float out1) +{ + const int ifgreater_10_value1_tmp = 10; + const float ifgreater_10_in2_tmp = 0.000000; + float ifgreater_10_out = (ifgreater_10_value1_tmp > which) ? in10 : ifgreater_10_in2_tmp; + const int ifgreater_9_value1_tmp = 9; + float ifgreater_9_out = (ifgreater_9_value1_tmp > which) ? in9 : ifgreater_10_out; + const int ifgreater_8_value1_tmp = 8; + float ifgreater_8_out = (ifgreater_8_value1_tmp > which) ? in8 : ifgreater_9_out; + const int ifgreater_7_value1_tmp = 7; + float ifgreater_7_out = (ifgreater_7_value1_tmp > which) ? in7 : ifgreater_8_out; + const int ifgreater_6_value1_tmp = 6; + float ifgreater_6_out = (ifgreater_6_value1_tmp > which) ? in6 : ifgreater_7_out; + const int ifgreater_5_value1_tmp = 5; + float ifgreater_5_out = (ifgreater_5_value1_tmp > which) ? in5 : ifgreater_6_out; + const int ifgreater_4_value1_tmp = 4; + float ifgreater_4_out = (ifgreater_4_value1_tmp > which) ? in4 : ifgreater_5_out; + const int ifgreater_3_value1_tmp = 3; + float ifgreater_3_out = (ifgreater_3_value1_tmp > which) ? in3 : ifgreater_4_out; + const int ifgreater_2_value1_tmp = 2; + float ifgreater_2_out = (ifgreater_2_value1_tmp > which) ? in2 : ifgreater_3_out; + const int ifgreater_1_value1_tmp = 1; + float ifgreater_1_out = (ifgreater_1_value1_tmp > which) ? in1 : ifgreater_2_out; + out1 = ifgreater_1_out; +} + +void mx_roughness_anisotropy(float roughness, float anisotropy, out vec2 result) +{ + float roughness_sqr = clamp(roughness*roughness, M_FLOAT_EPS, 1.0); + if (anisotropy > 0.0) + { + float aspect = sqrt(1.0 - clamp(anisotropy, 0.0, 0.98)); + result.x = min(roughness_sqr / aspect, 1.0); + result.y = roughness_sqr * aspect; + } + else + { + result.x = roughness_sqr; + result.y = roughness_sqr; + } +} +void mx_rotate_vector3(vec3 _in, float amount, vec3 axis, out vec3 result) +{ + // Based on https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula, where the + // Wikipedia formula follows v' = M * v and MaterialX follows v' = v * M, thus the + // order of parameters to cross are reversed. + + axis = normalize(axis); + float rotationRadians = mx_radians(amount); + float s = mx_sin(rotationRadians); + float c = mx_cos(rotationRadians); + float oc = 1.0 - c; + result = _in * c + cross(_in, axis) * s + axis * dot(axis, _in) * oc; +} +// These are defined based on the HwShaderGenerator::ClosureContextType enum +// if that changes - these need to be updated accordingly. + +#define CLOSURE_TYPE_DEFAULT 0 +#define CLOSURE_TYPE_REFLECTION 1 +#define CLOSURE_TYPE_TRANSMISSION 2 +#define CLOSURE_TYPE_INDIRECT 3 +#define CLOSURE_TYPE_EMISSION 4 + +struct ClosureData { + int closureType; + vec3 L; + vec3 V; + vec3 N; + vec3 P; + float occlusion; +}; + +ClosureData makeClosureData(int closureType, vec3 L, vec3 V, vec3 N, vec3 P, float occlusion) +{ + return ClosureData(closureType, L, V, N, P, occlusion); +} + +const float FUJII_CONSTANT_1 = 0.5 - 2.0 / (3.0 * M_PI); +const float FUJII_CONSTANT_2 = 2.0 / 3.0 - 28.0 / (15.0 * M_PI); + +// Qualitative Oren-Nayar diffuse with simplified math: +// https://www1.cs.columbia.edu/CAVE/publications/pdfs/Oren_SIGGRAPH94.pdf +float mx_oren_nayar_diffuse(float NdotV, float NdotL, float LdotV, float roughness) +{ + float s = LdotV - NdotL * NdotV; + float stinv = (s > 0.0) ? s / max(NdotL, NdotV) : 0.0; + + float sigma2 = mx_square(roughness); + float A = 1.0 - 0.5 * (sigma2 / (sigma2 + 0.33)); + float B = 0.45 * sigma2 / (sigma2 + 0.09); + + return A + B * stinv; +} + +// Rational quadratic fit to Monte Carlo data for Oren-Nayar directional albedo. +float mx_oren_nayar_diffuse_dir_albedo_analytic(float NdotV, float roughness) +{ + vec2 r = vec2(1.0, 1.0) + + vec2(-0.4297, -0.6076) * roughness + + vec2(-0.7632, -0.4993) * NdotV * roughness + + vec2(1.4385, 2.0315) * mx_square(roughness); + return r.x / r.y; +} + +float mx_oren_nayar_diffuse_dir_albedo_table_lookup(float NdotV, float roughness) +{ +#if DIRECTIONAL_ALBEDO_METHOD == 1 + if (textureSize(u_albedoTable, 0).x > 1) + { + return texture(u_albedoTable, vec2(NdotV, roughness)).b; + } +#endif + return 0.0; +} + +float mx_oren_nayar_diffuse_dir_albedo_monte_carlo(float NdotV, float roughness) +{ + NdotV = clamp(NdotV, M_FLOAT_EPS, 1.0); + vec3 V = vec3(sqrt(1.0 - mx_square(NdotV)), 0, NdotV); + + float radiance = 0.0; + const int SAMPLE_COUNT = 64; + for (int i = 0; i < SAMPLE_COUNT; i++) + { + vec2 Xi = mx_spherical_fibonacci(i, SAMPLE_COUNT); + + // Compute the incoming light direction. + vec3 L = mx_uniform_sample_hemisphere(Xi); + + // Compute dot products for this sample. + float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); + float LdotV = clamp(dot(L, V), M_FLOAT_EPS, 1.0); + + // Compute diffuse reflectance. + float reflectance = mx_oren_nayar_diffuse(NdotV, NdotL, LdotV, roughness); + + // Add the radiance contribution of this sample. + // uniform_pdf = 1 / (2 * PI) + // radiance = (reflectance * NdotL) / (uniform_pdf * PI); + radiance += reflectance * NdotL; + } + + // Apply global components and normalize. + radiance *= 2.0 / float(SAMPLE_COUNT); + + // Return the final directional albedo. + return radiance; +} + +float mx_oren_nayar_diffuse_dir_albedo(float NdotV, float roughness) +{ +#if DIRECTIONAL_ALBEDO_METHOD == 2 + float dirAlbedo = mx_oren_nayar_diffuse_dir_albedo_monte_carlo(NdotV, roughness); +#else + float dirAlbedo = mx_oren_nayar_diffuse_dir_albedo_analytic(NdotV, roughness); +#endif + return clamp(dirAlbedo, 0.0, 1.0); +} + +// Improved Oren-Nayar diffuse from Fujii: +// https://mimosa-pudica.net/improved-oren-nayar.html +float mx_oren_nayar_fujii_diffuse_dir_albedo(float cosTheta, float roughness) +{ + float A = 1.0 / (1.0 + FUJII_CONSTANT_1 * roughness); + float B = roughness * A; + float Si = sqrt(max(0.0, 1.0 - mx_square(cosTheta))); + float G = Si * (mx_acos(clamp(cosTheta, -1.0, 1.0)) - Si * cosTheta) + + 2.0 * ((Si / cosTheta) * (1.0 - Si * Si * Si) - Si) / 3.0; + return A + (B * G * M_PI_INV); +} + +float mx_oren_nayar_fujii_diffuse_avg_albedo(float roughness) +{ + float A = 1.0 / (1.0 + FUJII_CONSTANT_1 * roughness); + return A * (1.0 + FUJII_CONSTANT_2 * roughness); +} + +// Energy-compensated Oren-Nayar diffuse from OpenPBR Surface: +// https://academysoftwarefoundation.github.io/OpenPBR/ +vec3 mx_oren_nayar_compensated_diffuse(float NdotV, float NdotL, float LdotV, float roughness, vec3 color) +{ + float s = LdotV - NdotL * NdotV; + float stinv = (s > 0.0) ? s / max(NdotL, NdotV) : s; + + // Compute the single-scatter lobe. + float A = 1.0 / (1.0 + FUJII_CONSTANT_1 * roughness); + vec3 lobeSingleScatter = color * A * (1.0 + roughness * stinv); + + // Compute the multi-scatter lobe. + float dirAlbedoV = mx_oren_nayar_fujii_diffuse_dir_albedo(NdotV, roughness); + float dirAlbedoL = mx_oren_nayar_fujii_diffuse_dir_albedo(NdotL, roughness); + float avgAlbedo = mx_oren_nayar_fujii_diffuse_avg_albedo(roughness); + vec3 colorMultiScatter = mx_square(color) * avgAlbedo / + (vec3(1.0) - color * max(0.0, 1.0 - avgAlbedo)); + vec3 lobeMultiScatter = colorMultiScatter * + max(M_FLOAT_EPS, 1.0 - dirAlbedoV) * + max(M_FLOAT_EPS, 1.0 - dirAlbedoL) / + max(M_FLOAT_EPS, 1.0 - avgAlbedo); + + // Return the sum. + return lobeSingleScatter + lobeMultiScatter; +} + +vec3 mx_oren_nayar_compensated_diffuse_dir_albedo(float cosTheta, float roughness, vec3 color) +{ + float dirAlbedo = mx_oren_nayar_fujii_diffuse_dir_albedo(cosTheta, roughness); + float avgAlbedo = mx_oren_nayar_fujii_diffuse_avg_albedo(roughness); + vec3 colorMultiScatter = mx_square(color) * avgAlbedo / + (vec3(1.0) - color * max(0.0, 1.0 - avgAlbedo)); + return mix(colorMultiScatter, color, dirAlbedo); +} + +// https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf +// Section 5.3 +float mx_burley_diffuse(float NdotV, float NdotL, float LdotH, float roughness) +{ + float F90 = 0.5 + (2.0 * roughness * mx_square(LdotH)); + float refL = mx_fresnel_schlick(NdotL, 1.0, F90); + float refV = mx_fresnel_schlick(NdotV, 1.0, F90); + return refL * refV; +} + +// Compute the directional albedo component of Burley diffuse for the given +// view angle and roughness. Curve fit provided by Stephen Hill. +float mx_burley_diffuse_dir_albedo(float NdotV, float roughness) +{ + float x = NdotV; + float fit0 = 0.97619 - 0.488095 * mx_pow5(1.0 - x); + float fit1 = 1.55754 + (-2.02221 + (2.56283 - 1.06244 * x) * x) * x; + return mix(fit0, fit1, roughness); +} + +// Evaluate the Burley diffusion profile for the given distance and diffusion shape. +// Based on https://graphics.pixar.com/library/ApproxBSSRDF/ +vec3 mx_burley_diffusion_profile(float dist, vec3 shape) +{ + vec3 num1 = exp(-shape * dist); + vec3 num2 = exp(-shape * dist / 3.0); + float denom = max(dist, M_FLOAT_EPS); + return (num1 + num2) / denom; +} + +// Integrate the Burley diffusion profile over a sphere of the given radius. +// Inspired by Eric Penner's presentation in http://advances.realtimerendering.com/s2011/ +vec3 mx_integrate_burley_diffusion(vec3 N, vec3 L, float radius, vec3 mfp) +{ + float theta = mx_acos(dot(N, L)); + + // Estimate the Burley diffusion shape from mean free path. + vec3 shape = vec3(1.0) / max(mfp, 0.1); + + // Integrate the profile over the sphere. + vec3 sumD = vec3(0.0); + vec3 sumR = vec3(0.0); + const int SAMPLE_COUNT = 32; + const float SAMPLE_WIDTH = (2.0 * M_PI) / float(SAMPLE_COUNT); + for (int i = 0; i < SAMPLE_COUNT; i++) + { + float x = -M_PI + (float(i) + 0.5) * SAMPLE_WIDTH; + float dist = radius * abs(2.0 * mx_sin(x * 0.5)); + vec3 R = mx_burley_diffusion_profile(dist, shape); + sumD += R * max(mx_cos(theta + x), 0.0); + sumR += R; + } + + return sumD / sumR; +} + +vec3 mx_subsurface_scattering_approx(vec3 N, vec3 L, vec3 P, vec3 albedo, vec3 mfp) +{ + float curvature = length(fwidth(N)) / length(fwidth(P)); + float radius = 1.0 / max(curvature, 0.01); + return albedo * mx_integrate_burley_diffusion(N, L, radius, mfp) / vec3(M_PI); +} + +void mx_oren_nayar_diffuse_bsdf(ClosureData closureData, float weight, vec3 color, float roughness, vec3 N, bool energy_compensation, inout BSDF bsdf) +{ + bsdf.throughput = vec3(0.0); + + if (weight < M_FLOAT_EPS) + { + return; + } + + vec3 V = closureData.V; + vec3 L = closureData.L; + + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + if (closureData.closureType == CLOSURE_TYPE_REFLECTION) + { + float NdotL = clamp(dot(N, L), M_FLOAT_EPS, 1.0); + float LdotV = clamp(dot(L, V), M_FLOAT_EPS, 1.0); + + vec3 diffuse = energy_compensation ? + mx_oren_nayar_compensated_diffuse(NdotV, NdotL, LdotV, roughness, color) : + mx_oren_nayar_diffuse(NdotV, NdotL, LdotV, roughness) * color; + bsdf.response = diffuse * closureData.occlusion * weight * NdotL * M_PI_INV; + } + else if (closureData.closureType == CLOSURE_TYPE_INDIRECT) + { + vec3 diffuse = energy_compensation ? + mx_oren_nayar_compensated_diffuse_dir_albedo(NdotV, roughness, color) : + mx_oren_nayar_diffuse_dir_albedo(NdotV, roughness) * color; + vec3 Li = mx_environment_irradiance(N); + bsdf.response = Li * diffuse * weight; + } +} + +void mx_translucent_bsdf(ClosureData closureData, float weight, vec3 color, vec3 N, inout BSDF bsdf) +{ + bsdf.throughput = vec3(0.0); + + if (weight < M_FLOAT_EPS) + { + return; + } + + vec3 V = closureData.V; + vec3 L = closureData.L; + + // Invert normal since we're transmitting light from the other side + N = -N; + + if (closureData.closureType == CLOSURE_TYPE_REFLECTION) + { + float NdotL = clamp(dot(N, L), 0.0, 1.0); + bsdf.response = color * weight * NdotL * M_PI_INV; + } + else if (closureData.closureType == CLOSURE_TYPE_INDIRECT) + { + vec3 Li = mx_environment_irradiance(N); + bsdf.response = Li * color * weight; + } +} + +void mx_subsurface_bsdf(ClosureData closureData, float weight, vec3 color, vec3 radius, float anisotropy, vec3 N, inout BSDF bsdf) +{ + bsdf.throughput = vec3(0.0); + + if (weight < M_FLOAT_EPS) + { + return; + } + + vec3 V = closureData.V; + vec3 L = closureData.L; + vec3 P = closureData.P; + float occlusion = closureData.occlusion; + + N = mx_forward_facing_normal(N, V); + + if (closureData.closureType == CLOSURE_TYPE_REFLECTION) + { + vec3 sss = mx_subsurface_scattering_approx(N, L, P, color, radius); + float NdotL = clamp(dot(N, L), M_FLOAT_EPS, 1.0); + float visibleOcclusion = 1.0 - NdotL * (1.0 - occlusion); + bsdf.response = sss * visibleOcclusion * weight; + } + else if (closureData.closureType == CLOSURE_TYPE_INDIRECT) + { + // For now, we render indirect subsurface as simple indirect diffuse. + vec3 Li = mx_environment_irradiance(N); + bsdf.response = Li * color * weight; + } +} + +// https://fpsunflower.github.io/ckulla/data/s2017_pbs_imageworks_sheen.pdf +// Equation 2 +float mx_imageworks_sheen_NDF(float NdotH, float roughness) +{ + float invRoughness = 1.0 / max(roughness, 0.005); + float cos2 = NdotH * NdotH; + float sin2 = 1.0 - cos2; + return (2.0 + invRoughness) * pow(sin2, invRoughness * 0.5) / (2.0 * M_PI); +} + +float mx_imageworks_sheen_brdf(float NdotL, float NdotV, float NdotH, float roughness) +{ + // Microfacet distribution. + float D = mx_imageworks_sheen_NDF(NdotH, roughness); + + // Fresnel and geometry terms are ignored. + float F = 1.0; + float G = 1.0; + + // We use a smoother denominator, as in: + // https://blog.selfshadow.com/publications/s2013-shading-course/rad/s2013_pbs_rad_notes.pdf + return D * F * G / (4.0 * (NdotL + NdotV - NdotL*NdotV)); +} + +// Rational quadratic fit to Monte Carlo data for Imageworks sheen directional albedo. +float mx_imageworks_sheen_dir_albedo_analytic(float NdotV, float roughness) +{ + vec2 r = vec2(13.67300, 1.0) + + vec2(-68.78018, 61.57746) * NdotV + + vec2(799.08825, 442.78211) * roughness + + vec2(-905.00061, 2597.49308) * NdotV * roughness + + vec2(60.28956, 121.81241) * mx_square(NdotV) + + vec2(1086.96473, 3045.55075) * mx_square(roughness); + return r.x / r.y; +} + +float mx_imageworks_sheen_dir_albedo_table_lookup(float NdotV, float roughness) +{ +#if DIRECTIONAL_ALBEDO_METHOD == 1 + if (textureSize(u_albedoTable, 0).x > 1) + { + return texture(u_albedoTable, vec2(NdotV, roughness)).b; + } +#endif + return 0.0; +} + +float mx_imageworks_sheen_dir_albedo_monte_carlo(float NdotV, float roughness) +{ + NdotV = clamp(NdotV, M_FLOAT_EPS, 1.0); + vec3 V = vec3(sqrt(1.0f - mx_square(NdotV)), 0, NdotV); + + float radiance = 0.0; + const int SAMPLE_COUNT = 64; + for (int i = 0; i < SAMPLE_COUNT; i++) + { + vec2 Xi = mx_spherical_fibonacci(i, SAMPLE_COUNT); + + // Compute the incoming light direction and half vector. + vec3 L = mx_uniform_sample_hemisphere(Xi); + vec3 H = normalize(L + V); + + // Compute dot products for this sample. + float NdotL = clamp(L.z, M_FLOAT_EPS, 1.0); + float NdotH = clamp(H.z, M_FLOAT_EPS, 1.0); + + // Compute sheen reflectance. + float reflectance = mx_imageworks_sheen_brdf(NdotL, NdotV, NdotH, roughness); + + // Add the radiance contribution of this sample. + // radiance = reflectance * NdotL / uniform_pdf; + radiance += reflectance * NdotL / mx_uniform_hemisphere_PDF(); + } + + // Return the final directional albedo. + return radiance / float(SAMPLE_COUNT); +} + +float mx_imageworks_sheen_dir_albedo(float NdotV, float roughness) +{ +#if DIRECTIONAL_ALBEDO_METHOD == 0 + float dirAlbedo = mx_imageworks_sheen_dir_albedo_analytic(NdotV, roughness); +#elif DIRECTIONAL_ALBEDO_METHOD == 1 + float dirAlbedo = mx_imageworks_sheen_dir_albedo_table_lookup(NdotV, roughness); +#else + float dirAlbedo = mx_imageworks_sheen_dir_albedo_monte_carlo(NdotV, roughness); +#endif + return clamp(dirAlbedo, 0.0, 1.0); +} + +// The following functions are adapted from https://github.com/tizian/ltc-sheen. +// "Practical Multiple-Scattering Sheen Using Linearly Transformed Cosines", Zeltner et al. + +// Gaussian fit to directional albedo table. +float mx_zeltner_sheen_dir_albedo(float x, float y) +{ + float s = y*(0.0206607 + 1.58491*y)/(0.0379424 + y*(1.32227 + y)); + float m = y*(-0.193854 + y*(-1.14885 + y*(1.7932 - 0.95943*y*y)))/(0.046391 + y); + float o = y*(0.000654023 + (-0.0207818 + 0.119681*y)*y)/(1.26264 + y*(-1.92021 + y)); + return exp(-0.5*mx_square((x - m)/s))/(s*sqrt(2.0*M_PI)) + o; +} + +// Rational fits to LTC matrix coefficients. +float mx_zeltner_sheen_ltc_aInv(float x, float y) +{ + return (2.58126*x + 0.813703*y)*y/(1.0 + 0.310327*x*x + 2.60994*x*y); +} + +float mx_zeltner_sheen_ltc_bInv(float x, float y) +{ + return sqrt(1.0 - x)*(y - 1.0)*y*y*y/(0.0000254053 + 1.71228*x - 1.71506*x*y + 1.34174*y*y); +} + +// V and N are assumed to be unit vectors. +mat3 mx_orthonormal_basis_ltc(vec3 V, vec3 N, float NdotV) +{ + // Generate a tangent vector in the plane of V and N. + // This required to correctly orient the LTC lobe. + vec3 X = V - N*NdotV; + float lenSqr = dot(X, X); + if (lenSqr > 0.0) + { + X *= mx_inversesqrt(lenSqr); + vec3 Y = cross(N, X); + return mat3(X, Y, N); + } + + // If lenSqr == 0, then V == N, so any orthonormal basis will do. + return mx_orthonormal_basis(N); +} + +// Multiplication by directional albedo is handled by the calling function. +float mx_zeltner_sheen_brdf(vec3 L, vec3 V, vec3 N, float NdotV, float roughness) +{ + mat3 toLTC = transpose(mx_orthonormal_basis_ltc(V, N, NdotV)); + vec3 w = mx_matrix_mul(toLTC, L); + + float aInv = mx_zeltner_sheen_ltc_aInv(NdotV, roughness); + float bInv = mx_zeltner_sheen_ltc_bInv(NdotV, roughness); + + // Transform w to original configuration (clamped cosine). + // |aInv 0 bInv| + // wo = M^-1 . w = | 0 aInv 0| . w + // | 0 0 1| + vec3 wo = vec3(aInv*w.x + bInv*w.z, aInv * w.y, w.z); + float lenSqr = dot(wo, wo); + + // D(w) = Do(M^-1.w / ||M^-1.w||) . |M^-1| / ||M^-1.w||^3 + // = Do(M^-1.w) . |M^-1| / ||M^-1.w||^4 + // = Do(wo) . |M^-1| / dot(wo, wo)^2 + // = Do(wo) . aInv^2 / dot(wo, wo)^2 + // = Do(wo) . (aInv / dot(wo, wo))^2 + return mx_cosine_hemisphere_PDF(wo.z) * mx_square(aInv / lenSqr); +} + +vec3 mx_zeltner_sheen_importance_sample(vec2 Xi, vec3 V, vec3 N, float roughness, out float pdf) +{ + float NdotV = clamp(dot(N, V), 0.0, 1.0); + roughness = clamp(roughness, 0.01, 1.0); // Clamp to range of original impl. + + vec3 wo = mx_cosine_sample_hemisphere(Xi); + + float aInv = mx_zeltner_sheen_ltc_aInv(NdotV, roughness); + float bInv = mx_zeltner_sheen_ltc_bInv(NdotV, roughness); + + // Transform wo from original configuration (clamped cosine). + // |1/aInv 0 -bInv/aInv| + // w = M . wo = | 0 1/aInv 0| . wo + // | 0 0 1| + vec3 w = vec3(wo.x/aInv - wo.z*bInv/aInv, wo.y / aInv, wo.z); + + float lenSqr = dot(w, w); + w *= mx_inversesqrt(lenSqr); + + // D(w) = Do(wo) . ||M.wo||^3 / |M| + // = Do(wo / ||M.wo||) . ||M.wo||^4 / |M| + // = Do(w) . ||M.wo||^4 / |M| (possible because M doesn't change z component) + // = Do(w) . dot(w, w)^2 * aInv^2 + // = Do(w) . (aInv * dot(w, w))^2 + pdf = mx_cosine_hemisphere_PDF(w.z) * mx_square(aInv * lenSqr); + + mat3 fromLTC = mx_orthonormal_basis_ltc(V, N, NdotV); + w = mx_matrix_mul(fromLTC, w); + + return w; +} + +void mx_sheen_bsdf(ClosureData closureData, float weight, vec3 color, float roughness, vec3 N, int mode, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + + vec3 V = closureData.V; + vec3 L = closureData.L; + + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + if (closureData.closureType == CLOSURE_TYPE_REFLECTION) + { + float dirAlbedo; + if (mode == 0) + { + vec3 H = normalize(L + V); + + float NdotL = clamp(dot(N, L), M_FLOAT_EPS, 1.0); + float NdotH = clamp(dot(N, H), M_FLOAT_EPS, 1.0); + + vec3 fr = color * mx_imageworks_sheen_brdf(NdotL, NdotV, NdotH, roughness); + dirAlbedo = mx_imageworks_sheen_dir_albedo(NdotV, roughness); + + // We need to include NdotL from the light integral here + // as in this case it's not cancelled out by the BRDF denominator. + bsdf.response = fr * NdotL * closureData.occlusion * weight; + } + else + { + roughness = clamp(roughness, 0.01, 1.0); // Clamp to range of original impl. + + vec3 fr = color * mx_zeltner_sheen_brdf(L, V, N, NdotV, roughness); + dirAlbedo = mx_zeltner_sheen_dir_albedo(NdotV, roughness); + bsdf.response = dirAlbedo * fr * closureData.occlusion * weight; + } + bsdf.throughput = vec3(1.0 - dirAlbedo * weight); + } + else if (closureData.closureType == CLOSURE_TYPE_INDIRECT) + { + float dirAlbedo; + if (mode == 0) + { + dirAlbedo = mx_imageworks_sheen_dir_albedo(NdotV, roughness); + } + else + { + roughness = clamp(roughness, 0.01, 1.0); // Clamp to range of original impl. + dirAlbedo = mx_zeltner_sheen_dir_albedo(NdotV, roughness); + } + + vec3 Li = mx_environment_irradiance(N); + bsdf.response = Li * color * dirAlbedo * weight; + bsdf.throughput = vec3(1.0 - dirAlbedo * weight); + } +} + +void mx_dielectric_bsdf(ClosureData closureData, float weight, vec3 tint, float ior, vec2 roughness, bool retroreflective, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +{ + if (weight < M_FLOAT_EPS) + { + return; + } + if (closureData.closureType != CLOSURE_TYPE_TRANSMISSION && scatter_mode == 1) + { + return; + } + + vec3 V = closureData.V; + vec3 L = closureData.L; + + // Retroreflective mode is only supported for reflection and indirect + if (retroreflective && (closureData.closureType != CLOSURE_TYPE_TRANSMISSION)) + V = reflect(-V, N); + + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + FresnelData fd = mx_init_fresnel_dielectric(ior, thinfilm_thickness, thinfilm_ior); + float F0 = mx_ior_to_f0(ior); + + vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(safeAlpha); + vec3 safeTint = max(tint, 0.0); + + if (closureData.closureType == CLOSURE_TYPE_REFLECTION) + { + X = normalize(X - dot(X, N) * N); + vec3 Y = cross(N, X); + vec3 H = normalize(L + V); + + float NdotL = clamp(dot(N, L), M_FLOAT_EPS, 1.0); + float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); + + vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); + + vec3 F = mx_compute_fresnel(VdotH, fd); + float D = mx_ggx_NDF(Ht, safeAlpha); + float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); + + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, F0, 1.0) * comp; + bsdf.throughput = 1.0 - dirAlbedo * weight; + + bsdf.response = D * F * G * comp * safeTint * closureData.occlusion * weight / (4.0 * NdotV); + } + else if (closureData.closureType == CLOSURE_TYPE_TRANSMISSION) + { + vec3 F = mx_compute_fresnel(NdotV, fd); + + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, F0, 1.0) * comp; + bsdf.throughput = 1.0 - dirAlbedo * weight; + + if (scatter_mode != 0) + { + bsdf.response = mx_surface_transmission(N, V, X, safeAlpha, distribution, fd, safeTint) * weight; + } + } + else if (closureData.closureType == CLOSURE_TYPE_INDIRECT) + { + vec3 F = mx_compute_fresnel(NdotV, fd); + + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 dirAlbedo = mx_ggx_dir_albedo(NdotV, avgAlpha, F0, 1.0) * comp; + bsdf.throughput = 1.0 - dirAlbedo * weight; + + vec3 Li = mx_environment_radiance(N, V, X, safeAlpha, distribution, fd); + bsdf.response = Li * safeTint * comp * weight; + } +} + +void mx_conductor_bsdf(ClosureData closureData, float weight, vec3 ior_n, vec3 ior_k, vec2 roughness, bool retroreflective, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, inout BSDF bsdf) +{ + bsdf.throughput = vec3(0.0); + + if (weight < M_FLOAT_EPS) + { + return; + } + + vec3 V = closureData.V; + vec3 L = closureData.L; + + V = retroreflective ? reflect(-V, N) : V; + N = mx_forward_facing_normal(N, V); + float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); + + FresnelData fd = mx_init_fresnel_conductor(ior_n, ior_k, thinfilm_thickness, thinfilm_ior); + + vec2 safeAlpha = clamp(roughness, M_FLOAT_EPS, 1.0); + float avgAlpha = mx_average_alpha(safeAlpha); + + if (closureData.closureType == CLOSURE_TYPE_REFLECTION) + { + X = normalize(X - dot(X, N) * N); + vec3 Y = cross(N, X); + vec3 H = normalize(L + V); + + float NdotL = clamp(dot(N, L), M_FLOAT_EPS, 1.0); + float VdotH = clamp(dot(V, H), M_FLOAT_EPS, 1.0); + + vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); + + vec3 F = mx_compute_fresnel(VdotH, fd); + float D = mx_ggx_NDF(Ht, safeAlpha); + float G = mx_ggx_smith_G2(NdotL, NdotV, avgAlpha); + + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + + // Note: NdotL is cancelled out + bsdf.response = D * F * G * comp * closureData.occlusion * weight / (4.0 * NdotV); + } + else if (closureData.closureType == CLOSURE_TYPE_INDIRECT) + { + vec3 F = mx_compute_fresnel(NdotV, fd); + vec3 comp = mx_ggx_energy_compensation(NdotV, avgAlpha, F); + vec3 Li = mx_environment_radiance(N, V, X, safeAlpha, distribution, fd); + bsdf.response = Li * comp * weight; + } +} +void mx_artistic_ior(vec3 reflectivity, vec3 edge_color, out vec3 ior, out vec3 extinction) +{ + // "Artist Friendly Metallic Fresnel", Ole Gulbrandsen, 2014 + // http://jcgt.org/published/0003/04/03/paper.pdf + + vec3 r = clamp(reflectivity, 0.0, 0.99); + vec3 r_sqrt = sqrt(r); + vec3 n_min = (1.0 - r) / (1.0 + r); + vec3 n_max = (1.0 + r_sqrt) / (1.0 - r_sqrt); + ior = mix(n_max, n_min, edge_color); + + vec3 np1 = ior + 1.0; + vec3 nm1 = ior - 1.0; + vec3 k2 = (np1*np1 * r - nm1*nm1) / (1.0 - r); + k2 = max(k2, 0.0); + extinction = sqrt(k2); +} +void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec3 base_color, float diffuse_roughness, float metalness, float specular, vec3 specular_color, float specular_roughness, float specular_IOR, float specular_anisotropy, float specular_rotation, float transmission, vec3 transmission_color, float transmission_extra_roughness, float subsurface, vec3 subsurface_color, vec3 subsurface_radius, float subsurface_scale, float subsurface_anisotropy, float sheen, vec3 sheen_color, float sheen_roughness, float coat, vec3 coat_color, float coat_roughness, float coat_anisotropy, float coat_rotation, float coat_IOR, vec3 coat_normal, float coat_affect_color, float coat_affect_roughness, float thin_film_thickness, float thin_film_IOR, bool thin_walled, vec3 normal, vec3 tangent, inout BSDF bsdf) +{ + // + // Coat affect roughness: blend specular roughness toward 1.0 + float coat_roughness_factor = (coat_affect_roughness * coat) * coat_roughness; + float coat_affected_specular_roughness = (specular_roughness * (1 - coat_roughness_factor)) + coat_roughness_factor; + // + // Roughness + vec2 main_roughness; + mx_roughness_anisotropy(coat_affected_specular_roughness, specular_anisotropy, main_roughness); + // + // Tangent rotation + vec3 main_tangent = tangent; + if (specular_anisotropy > 0.0) + { + float tangent_rotate_degree = specular_rotation * 360.0; + vec3 tangent_rotated; + mx_rotate_vector3(tangent, tangent_rotate_degree, normal, tangent_rotated); + main_tangent = normalize(tangent_rotated); + } + // + // Coat tangent rotation + vec3 coat_tangent = tangent; + if (coat_anisotropy > 0.0) + { + float coat_tangent_rotate_degree = coat_rotation * 360.0; + vec3 coat_tangent_rotated; + mx_rotate_vector3(tangent, coat_tangent_rotate_degree, coat_normal, coat_tangent_rotated); + coat_tangent = normalize(coat_tangent_rotated); + } + // + // Coat affect color: darken diffuse under the coat + vec3 coat_gamma = vec3((clamp(coat, 0.0, 1.0) * coat_affect_color) + 1.0); + vec3 coat_affected_diffuse_color = pow(clamp(base_color, 0.0, 1.0), coat_gamma); + // + // Coat affect subsurface color + vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); + // + // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR + BSDF diffuse_bsdf; + diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); + diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); + // + // Subsurface scattering + vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; + BSDF sss_bsdf; + sss_bsdf.response = vec3(0.0, 0.0, 0.0); + sss_bsdf.throughput = vec3(1.0, 1.0, 1.0); + if (thin_walled) + { + mx_translucent_bsdf(closureData, 1.0, coat_affected_subsurface_color, normal, sss_bsdf); + } + else + { + mx_subsurface_bsdf(closureData, 1.0, coat_affected_subsurface_color, subsurface_radius_scaled, subsurface_anisotropy, normal, sss_bsdf); + } + // + // Subsurface mix: blend SSS with diffuse + BSDF subsurface_mix; + subsurface_mix.response = mix(diffuse_bsdf.response, sss_bsdf.response, subsurface); + subsurface_mix.throughput = mix(diffuse_bsdf.throughput, sss_bsdf.throughput, subsurface); + // + // Sheen BSDF + BSDF sheen_bsdf_out; + sheen_bsdf_out.response = vec3(0.0, 0.0, 0.0); + sheen_bsdf_out.throughput = vec3(1.0, 1.0, 1.0); + mx_sheen_bsdf(closureData, sheen, sheen_color, sheen_roughness, normal, 0, sheen_bsdf_out); + // + // Sheen layer: sheen over subsurface mix + bsdf.response = sheen_bsdf_out.response + (subsurface_mix.response * sheen_bsdf_out.throughput); + bsdf.throughput = sheen_bsdf_out.throughput * subsurface_mix.throughput; + // + // Transmission roughness (coat-affected) + float transmission_roughness_clamped = clamp(specular_roughness + transmission_extra_roughness, 0.0, 1.0); + float transmission_roughness_scalar = (transmission_roughness_clamped * (1 - coat_roughness_factor)) + coat_roughness_factor; + vec2 transmission_roughness; + mx_roughness_anisotropy(transmission_roughness_scalar, specular_anisotropy, transmission_roughness); + // + // Transmission BSDF (dielectric transmission) + BSDF transmission_bsdf; + transmission_bsdf.response = vec3(0.0, 0.0, 0.0); + transmission_bsdf.throughput = vec3(1.0, 1.0, 1.0); + mx_dielectric_bsdf(closureData, 1.0, transmission_color, specular_IOR, transmission_roughness, false, 0.0, 1.5, normal, main_tangent, 0, 1, transmission_bsdf); + // + // Transmission mix: blend transmission with sheen layer + bsdf.response = mix(bsdf.response, transmission_bsdf.response, transmission); + bsdf.throughput = mix(bsdf.throughput, transmission_bsdf.throughput, transmission); + // + // Specular BSDF (dielectric reflection) + BSDF specular_bsdf; + specular_bsdf.response = vec3(0.0, 0.0, 0.0); + specular_bsdf.throughput = vec3(1.0, 1.0, 1.0); + mx_dielectric_bsdf(closureData, specular, specular_color, specular_IOR, main_roughness, false, thin_film_thickness, thin_film_IOR, normal, main_tangent, 0, 0, specular_bsdf); + // + // Layer: specular over transmission mix + bsdf.response = specular_bsdf.response + (bsdf.response * specular_bsdf.throughput); + bsdf.throughput = specular_bsdf.throughput * bsdf.throughput; + // + // Artistic IOR (reflectivity/edge-color -> physical IOR/extinction) + vec3 metal_reflectivity = base_color * base; + vec3 metal_edgecolor = specular_color * specular; + vec3 ior_n; + vec3 ior_k; + mx_artistic_ior(metal_reflectivity, metal_edgecolor, ior_n, ior_k); + // + // Conductor BSDF (metal reflection) + BSDF metal_bsdf; + metal_bsdf.response = vec3(0.0, 0.0, 0.0); + metal_bsdf.throughput = vec3(1.0, 1.0, 1.0); + mx_conductor_bsdf(closureData, metalness, ior_n, ior_k, main_roughness, false, thin_film_thickness, thin_film_IOR, normal, main_tangent, 0, metal_bsdf); + // + // Metalness mix: conductor (fg) vs specular layer (bg) + // Conductor response is already scaled by metalness (the weight), + // so we just add it to the attenuated specular layer. + float one_minus_metalness = 1 - metalness; + bsdf.response = metal_bsdf.response + (bsdf.response * one_minus_metalness); + bsdf.throughput = metal_bsdf.throughput + (bsdf.throughput * one_minus_metalness); + // + // Coat attenuation: tint underlying layers by coat color + // Float3 coercion needed: RgbF lerp result -> Float3 for BSDF multiply + vec3 coat_attenuation = mix(vec3(1.0), coat_color, coat); + bsdf.response = bsdf.response * coat_attenuation; + bsdf.throughput = bsdf.throughput * coat_attenuation; + // + // Coat roughness + vec2 coat_roughness_vec; + mx_roughness_anisotropy(coat_roughness, coat_anisotropy, coat_roughness_vec); + // + // Coat BSDF (dielectric reflection) + BSDF coat_bsdf; + coat_bsdf.response = vec3(0.0, 0.0, 0.0); + coat_bsdf.throughput = vec3(1.0, 1.0, 1.0); + mx_dielectric_bsdf(closureData, coat, vec3(1.0, 1.0, 1.0), coat_IOR, coat_roughness_vec, false, 0.0, 1.5, coat_normal, coat_tangent, 0, 0, coat_bsdf); + // + // Coat layer: coat over attenuated base + bsdf.response = coat_bsdf.response + (bsdf.response * coat_bsdf.throughput); + bsdf.throughput = coat_bsdf.throughput * bsdf.throughput; +} + + +void mx_luminance_color3(vec3 _in, vec3 lumacoeffs, out vec3 result) +{ + result = vec3(dot(_in, lumacoeffs)); +} + + +void mx_uniform_edf(ClosureData closureData, vec3 color, out EDF result) +{ + if (closureData.closureType == CLOSURE_TYPE_EMISSION) + { + result = color; + } +} + +void NG_metashade_standard_surface(float base, vec3 base_color, float diffuse_roughness, float metalness, float specular, vec3 specular_color, float specular_roughness, float specular_IOR, float specular_anisotropy, float specular_rotation, float transmission, vec3 transmission_color, float transmission_depth, vec3 transmission_scatter, float transmission_scatter_anisotropy, float transmission_dispersion, float transmission_extra_roughness, float subsurface, vec3 subsurface_color, vec3 subsurface_radius, float subsurface_scale, float subsurface_anisotropy, float sheen, vec3 sheen_color, float sheen_roughness, float coat, vec3 coat_color, float coat_roughness, float coat_anisotropy, float coat_rotation, float coat_IOR, vec3 coat_normal, float coat_affect_color, float coat_affect_roughness, float thin_film_thickness, float thin_film_IOR, float emission, vec3 emission_color, vec3 opacity, bool thin_walled, vec3 normal, vec3 tangent, out surfaceshader out1) +{ + vec3 emission_weight_out = emission_color * emission; + vec3 opacity_luminance_out = vec3(0.0); + mx_luminance_color3(opacity, vec3(0.272229, 0.674082, 0.053689), opacity_luminance_out); + const int opacity_luminance_float_index_tmp = 0; + float opacity_luminance_float_out = opacity_luminance_out[opacity_luminance_float_index_tmp]; + surfaceshader surface_ctor_out = surfaceshader(vec3(0.0),vec3(0.0)); + { + vec3 N = normalize(vd.normalWorld); + vec3 V = normalize(u_viewPosition - vd.positionWorld); + vec3 P = vd.positionWorld; + vec3 L = vec3(0.000000, 0.000000, 0.000000); + float occlusion = 1.0; + + float surfaceOpacity = opacity_luminance_float_out; + + // Shadow occlusion + + // Ambient occlusion + occlusion = 1.0; + + // Add environment contribution + { + ClosureData closureData = makeClosureData(CLOSURE_TYPE_INDIRECT, L, V, N, P, occlusion); + BSDF ss_bsdf_bsdf = BSDF(vec3(0.0),vec3(1.0)); + mx_metashade_standard_surface_bsdf(closureData, base, base_color, diffuse_roughness, metalness, specular, specular_color, specular_roughness, specular_IOR, specular_anisotropy, specular_rotation, transmission, transmission_color, transmission_extra_roughness, subsurface, subsurface_color, subsurface_radius, subsurface_scale, subsurface_anisotropy, sheen, sheen_color, sheen_roughness, coat, coat_color, coat_roughness, coat_anisotropy, coat_rotation, coat_IOR, coat_normal, coat_affect_color, coat_affect_roughness, thin_film_thickness, thin_film_IOR, thin_walled, normal, tangent, ss_bsdf_bsdf); + + surface_ctor_out.color += occlusion * ss_bsdf_bsdf.response; + } + + // Add surface emission + { + ClosureData closureData = makeClosureData(CLOSURE_TYPE_EMISSION, L, V, N, P, occlusion); + EDF emission_edf_out = EDF(0.0); + mx_uniform_edf(closureData, emission_weight_out, emission_edf_out); + surface_ctor_out.color += emission_edf_out; + } + + // Calculate the BSDF transmission for viewing direction + ClosureData closureData = makeClosureData(CLOSURE_TYPE_TRANSMISSION, L, V, N, P, occlusion); + BSDF ss_bsdf_bsdf = BSDF(vec3(0.0),vec3(1.0)); + mx_metashade_standard_surface_bsdf(closureData, base, base_color, diffuse_roughness, metalness, specular, specular_color, specular_roughness, specular_IOR, specular_anisotropy, specular_rotation, transmission, transmission_color, transmission_extra_roughness, subsurface, subsurface_color, subsurface_radius, subsurface_scale, subsurface_anisotropy, sheen, sheen_color, sheen_roughness, coat, coat_color, coat_roughness, coat_anisotropy, coat_rotation, coat_IOR, coat_normal, coat_affect_color, coat_affect_roughness, thin_film_thickness, thin_film_IOR, thin_walled, normal, tangent, ss_bsdf_bsdf); + surface_ctor_out.color += ss_bsdf_bsdf.response; + + // Compute and apply surface opacity + { + surface_ctor_out.color *= surfaceOpacity; + surface_ctor_out.transparency = mix(vec3(1.000000, 1.000000, 1.000000), surface_ctor_out.transparency, surfaceOpacity); + } + } + + out1 = surface_ctor_out; +} + +void NG_legacy_masonry(int type, vec3 color, bool tint_enable, vec3 tint_color, int finish, bool relief_enable, vec3 normal_relief, out surfaceshader out1) +{ + vec3 tint_mult_out = color * tint_color; + float switch_type_rough_out = 0.0; + NG_switch_floatI(0.500000, 0.200000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, type, switch_type_rough_out); + float switch_finish_out = 0.0; + NG_switch_floatI(0.100000, 0.400000, 0.700000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, finish, switch_finish_out); + vec3 geomprop_Nworld_out1 = normalize(vd.normalWorld); + vec3 geomprop_Tworld_out1 = normalize(vd.tangentWorld); + vec3 geomprop_Bworld_out1 = normalize(vd.bitangentWorld); + const bool tint_selection_value2_tmp = true; + vec3 tint_selection_out = (tint_enable == tint_selection_value2_tmp) ? tint_mult_out : color; + vec3 normalmap_out = vec3(0.0); + mx_normalmap_float(vec3(0.500000, 0.500000, 1.000000), 1.000000, geomprop_Nworld_out1, geomprop_Tworld_out1, geomprop_Bworld_out1, normalmap_out); + const bool relief_selection_value2_tmp = true; + vec3 relief_selection_out = (relief_enable == relief_selection_value2_tmp) ? normal_relief : normalmap_out; + surfaceshader standard_surface_out = surfaceshader(vec3(0.0),vec3(0.0)); + NG_metashade_standard_surface(1.000000, tint_selection_out, switch_type_rough_out, 0.000000, 1.000000, vec3(1.000000, 1.000000, 1.000000), switch_finish_out, 1.500000, 0.000000, 0.000000, 0.000000, vec3(1.000000, 1.000000, 1.000000), 0.000000, vec3(0.000000, 0.000000, 0.000000), 0.000000, 0.000000, 0.000000, 0.000000, vec3(1.000000, 1.000000, 1.000000), vec3(1.000000, 1.000000, 1.000000), 1.000000, 0.000000, 0.000000, vec3(1.000000, 1.000000, 1.000000), 0.300000, 0.000000, vec3(1.000000, 1.000000, 1.000000), 0.100000, 0.000000, 0.000000, 1.500000, geomprop_Nworld_out1, 0.000000, 0.000000, 0.000000, 1.500000, 0.000000, vec3(1.000000, 1.000000, 1.000000), vec3(1.000000, 1.000000, 1.000000), false, relief_selection_out, geomprop_Tworld_out1, standard_surface_out); + out1 = standard_surface_out; +} + +void main() +{ + vec2 geomprop_UV0_out1 = vd.texcoord_0.xy; + vec3 geomprop_Nworld_out1 = normalize(vd.normalWorld); + vec3 geomprop_Tworld_out1 = normalize(vd.tangentWorld); + vec3 test_bump_masonry_out = vec3(0.0); + adsk_NG_adsk_height_map(test_bump_masonry_file, test_bump_masonry_realworld_offset, test_bump_masonry_realworld_scale, test_bump_masonry_uv_offset, test_bump_masonry_uv_scale, test_bump_masonry_rotation_angle, test_bump_masonry_depth, test_bump_masonry_uaddressmode, test_bump_masonry_vaddressmode, geomprop_UV0_out1, geomprop_Nworld_out1, geomprop_Tworld_out1, test_bump_masonry_out); + surfaceshader SR_legacy_masonry_out = surfaceshader(vec3(0.0),vec3(0.0)); + NG_legacy_masonry(SR_legacy_masonry_type, SR_legacy_masonry_color, SR_legacy_masonry_tint_enable, SR_legacy_masonry_tint_color, SR_legacy_masonry_finish, SR_legacy_masonry_relief_enable, test_bump_masonry_out, SR_legacy_masonry_out); + material M_legacy_masonry_out = SR_legacy_masonry_out; + out1 = vec4(M_legacy_masonry_out.color, 1.0); +} + diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/masonry/M_legacy_masonry_vs.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/masonry/M_legacy_masonry_vs.glsl new file mode 100644 index 0000000000..45a9757647 --- /dev/null +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/masonry/M_legacy_masonry_vs.glsl @@ -0,0 +1,82 @@ +#version 400 + + +// Uniform block: PrivateUniforms +uniform mat4 u_worldMatrix = mat4(1.0); +uniform mat4 u_viewProjectionMatrix = mat4(1.0); +uniform mat4 u_worldInverseTransposeMatrix = mat4(1.0); + +// Inputs block: VertexInputs +in vec3 i_position; +in vec2 i_texcoord_0; +in vec3 i_normal; +in vec3 i_tangent; + +out VertexData +{ + vec2 texcoord_0; + vec3 normalWorld; + vec3 tangentWorld; + vec3 bitangentWorld; + vec3 positionWorld; +} vd; + +#define M_FLOAT_EPS 1e-8 +#define M_PI 3.1415926535897932 + +#define mx_mod mod +#define mx_inverse inverse +#define mx_inversesqrt inversesqrt +#define mx_sin sin +#define mx_cos cos +#define mx_tan tan +#define mx_asin asin +#define mx_acos acos +#define mx_atan atan +#define mx_radians radians +#define mx_float_bits_to_int floatBitsToInt + +vec2 mx_matrix_mul(vec2 v, mat2 m) { return v * m; } +vec3 mx_matrix_mul(vec3 v, mat3 m) { return v * m; } +vec4 mx_matrix_mul(vec4 v, mat4 m) { return v * m; } +vec2 mx_matrix_mul(mat2 m, vec2 v) { return m * v; } +vec3 mx_matrix_mul(mat3 m, vec3 v) { return m * v; } +vec4 mx_matrix_mul(mat4 m, vec4 v) { return m * v; } +mat2 mx_matrix_mul(mat2 m1, mat2 m2) { return m1 * m2; } +mat3 mx_matrix_mul(mat3 m1, mat3 m2) { return m1 * m2; } +mat4 mx_matrix_mul(mat4 m1, mat4 m2) { return m1 * m2; } + +float mx_square(float x) +{ + return x*x; +} + +vec2 mx_square(vec2 x) +{ + return x*x; +} + +vec3 mx_square(vec3 x) +{ + return x*x; +} + +vec3 mx_srgb_encode(vec3 color) +{ + bvec3 isAbove = greaterThan(color, vec3(0.0031308)); + vec3 linSeg = color * 12.92; + vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; + return mix(linSeg, powSeg, isAbove); +} + +void main() +{ + vec4 hPositionWorld = u_worldMatrix * vec4(i_position, 1.0); + gl_Position = u_viewProjectionMatrix * hPositionWorld; + vd.texcoord_0 = i_texcoord_0; + vd.normalWorld = normalize(mx_matrix_mul(u_worldInverseTransposeMatrix, vec4(i_normal, 0.0)).xyz); + vd.tangentWorld = normalize(mx_matrix_mul(u_worldMatrix, vec4(i_tangent, 0.0)).xyz); + vd.bitangentWorld = cross(vd.normalWorld, vd.tangentWorld); + vd.positionWorld = hPositionWorld.xyz; +} + diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/mirror/M_legacy_mirror_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/mirror/M_legacy_mirror_ps.glsl index ee763efbce..c9a8242f82 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/mirror/M_legacy_mirror_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/mirror/M_legacy_mirror_ps.glsl @@ -1602,10 +1602,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence2d_object_out_glsl_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence2d_object_out_glsl_ps.glsl new file mode 100644 index 0000000000..ef5d93d6d7 --- /dev/null +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence2d_object_out_glsl_ps.glsl @@ -0,0 +1,966 @@ +#version 400 + + +struct BSDF { vec3 response; vec3 throughput; }; +#define EDF vec3 +struct VDF { vec3 response; vec3 throughput; }; +struct surfaceshader { vec3 color; vec3 transparency; }; +struct volumeshader { vec3 color; vec3 transparency; }; +struct displacementshader { vec3 offset; float scale; }; +struct lightshader { vec3 intensity; vec3 direction; }; +#define material surfaceshader + +in VertexData +{ + vec2 texcoord_0; +} vd; + +// Pixel shader outputs +out vec4 out11; + +#define M_FLOAT_EPS 1e-8 +#define M_PI 3.1415926535897932 + +#define mx_mod mod +#define mx_inverse inverse +#define mx_inversesqrt inversesqrt +#define mx_sin sin +#define mx_cos cos +#define mx_tan tan +#define mx_asin asin +#define mx_acos acos +#define mx_atan atan +#define mx_radians radians +#define mx_float_bits_to_int floatBitsToInt + +vec2 mx_matrix_mul(vec2 v, mat2 m) { return v * m; } +vec3 mx_matrix_mul(vec3 v, mat3 m) { return v * m; } +vec4 mx_matrix_mul(vec4 v, mat4 m) { return v * m; } +vec2 mx_matrix_mul(mat2 m, vec2 v) { return m * v; } +vec3 mx_matrix_mul(mat3 m, vec3 v) { return m * v; } +vec4 mx_matrix_mul(mat4 m, vec4 v) { return m * v; } +mat2 mx_matrix_mul(mat2 m1, mat2 m2) { return m1 * m2; } +mat3 mx_matrix_mul(mat3 m1, mat3 m2) { return m1 * m2; } +mat4 mx_matrix_mul(mat4 m1, mat4 m2) { return m1 * m2; } + +float mx_square(float x) +{ + return x*x; +} + +vec2 mx_square(vec2 x) +{ + return x*x; +} + +vec3 mx_square(vec3 x) +{ + return x*x; +} + +vec3 mx_srgb_encode(vec3 color) +{ + bvec3 isAbove = greaterThan(color, vec3(0.0031308)); + vec3 linSeg = color * 12.92; + vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; + return mix(linSeg, powSeg, isAbove); +} + +#define AIRY_FRESNEL_ITERATIONS 2 + +/* +Noise Library. + +This library is a modified version of the noise library found in +Open Shading Language: +github.com/imageworks/OpenShadingLanguage/blob/master/src/include/OSL/oslnoise.h + +It contains the subset of noise types needed to implement the MaterialX +standard library. The modifications are mainly conversions from C++ to GLSL. +Produced results should be identical to the OSL noise functions. + +Original copyright notice: +------------------------------------------------------------------------ +Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of Sony Pictures Imageworks nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------------ +*/ + +float mx_select(bool b, float t, float f) +{ + return b ? t : f; +} + +float mx_negate_if(float val, bool b) +{ + return b ? -val : val; +} + +int mx_floor(float x) +{ + return int(floor(x)); +} + +// return mx_floor as well as the fractional remainder +float mx_floorfrac(float x, out int i) +{ + i = mx_floor(x); + return x - float(i); +} + +float mx_bilerp(float v0, float v1, float v2, float v3, float s, float t) +{ + float s1 = 1.0 - s; + return (1.0 - t) * (v0*s1 + v1*s) + t * (v2*s1 + v3*s); +} +vec3 mx_bilerp(vec3 v0, vec3 v1, vec3 v2, vec3 v3, float s, float t) +{ + float s1 = 1.0 - s; + return (1.0 - t) * (v0*s1 + v1*s) + t * (v2*s1 + v3*s); +} +float mx_trilerp(float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float s, float t, float r) +{ + float s1 = 1.0 - s; + float t1 = 1.0 - t; + float r1 = 1.0 - r; + return (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) + + r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s))); +} +vec3 mx_trilerp(vec3 v0, vec3 v1, vec3 v2, vec3 v3, vec3 v4, vec3 v5, vec3 v6, vec3 v7, float s, float t, float r) +{ + float s1 = 1.0 - s; + float t1 = 1.0 - t; + float r1 = 1.0 - r; + return (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) + + r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s))); +} + +// 2 and 3 dimensional gradient functions - perform a dot product against a +// randomly chosen vector. Note that the gradient vector is not normalized, but +// this only affects the overall "scale" of the result, so we simply account for +// the scale by multiplying in the corresponding "perlin" function. +float mx_gradient_float(uint hash, float x, float y) +{ + // 8 possible directions (+-1,+-2) and (+-2,+-1) + uint h = hash & 7u; + float u = mx_select(h<4u, x, y); + float v = 2.0 * mx_select(h<4u, y, x); + // compute the dot product with (x,y). + return mx_negate_if(u, bool(h&1u)) + mx_negate_if(v, bool(h&2u)); +} +float mx_gradient_float(uint hash, float x, float y, float z) +{ + // use vectors pointing to the edges of the cube + uint h = hash & 15u; + float u = mx_select(h<8u, x, y); + float v = mx_select(h<4u, y, mx_select((h==12u)||(h==14u), x, z)); + return mx_negate_if(u, bool(h&1u)) + mx_negate_if(v, bool(h&2u)); +} +vec3 mx_gradient_vec3(uvec3 hash, float x, float y) +{ + return vec3(mx_gradient_float(hash.x, x, y), mx_gradient_float(hash.y, x, y), mx_gradient_float(hash.z, x, y)); +} +vec3 mx_gradient_vec3(uvec3 hash, float x, float y, float z) +{ + return vec3(mx_gradient_float(hash.x, x, y, z), mx_gradient_float(hash.y, x, y, z), mx_gradient_float(hash.z, x, y, z)); +} +// Scaling factors to normalize the result of gradients above. +// These factors were experimentally calculated to be: +// 2D: 0.6616 +// 3D: 0.9820 +float mx_gradient_scale2d(float v) { return 0.6616 * v; } +float mx_gradient_scale3d(float v) { return 0.9820 * v; } +vec3 mx_gradient_scale2d(vec3 v) { return 0.6616 * v; } +vec3 mx_gradient_scale3d(vec3 v) { return 0.9820 * v; } + +/// Bitwise circular rotation left by k bits (for 32 bit unsigned integers) +uint mx_rotl32(uint x, int k) +{ + return (x<>(32-k)); +} + +void mx_bjmix(inout uint a, inout uint b, inout uint c) +{ + a -= c; a ^= mx_rotl32(c, 4); c += b; + b -= a; b ^= mx_rotl32(a, 6); a += c; + c -= b; c ^= mx_rotl32(b, 8); b += a; + a -= c; a ^= mx_rotl32(c,16); c += b; + b -= a; b ^= mx_rotl32(a,19); a += c; + c -= b; c ^= mx_rotl32(b, 4); b += a; +} + +// Mix up and combine the bits of a, b, and c (doesn't change them, but +// returns a hash of those three original values). +uint mx_bjfinal(uint a, uint b, uint c) +{ + c ^= b; c -= mx_rotl32(b,14); + a ^= c; a -= mx_rotl32(c,11); + b ^= a; b -= mx_rotl32(a,25); + c ^= b; c -= mx_rotl32(b,16); + a ^= c; a -= mx_rotl32(c,4); + b ^= a; b -= mx_rotl32(a,14); + c ^= b; c -= mx_rotl32(b,24); + return c; +} + +// Convert a 32 bit integer into a floating point number in [0,1] +float mx_bits_to_01(uint bits) +{ + return float(bits) / float(uint(0xffffffff)); +} + +float mx_fade(float t) +{ + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +uint mx_hash_int(int x) +{ + uint len = 1u; + uint seed = uint(0xdeadbeef) + (len << 2u) + 13u; + return mx_bjfinal(seed+uint(x), seed, seed); +} + +uint mx_hash_int(int x, int y) +{ + uint len = 2u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z) +{ + uint len = 3u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z, int xx) +{ + uint len = 4u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + mx_bjmix(a, b, c); + a += uint(xx); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z, int xx, int yy) +{ + uint len = 5u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + mx_bjmix(a, b, c); + a += uint(xx); + b += uint(yy); + return mx_bjfinal(a, b, c); +} + +uvec3 mx_hash_vec3(int x, int y) +{ + uint h = mx_hash_int(x, y); + // we only need the low-order bits to be random, so split out + // the 32 bit result into 3 parts for each channel + uvec3 result; + result.x = (h ) & 0xFFu; + result.y = (h >> 8 ) & 0xFFu; + result.z = (h >> 16) & 0xFFu; + return result; +} + +uvec3 mx_hash_vec3(int x, int y, int z) +{ + uint h = mx_hash_int(x, y, z); + // we only need the low-order bits to be random, so split out + // the 32 bit result into 3 parts for each channel + uvec3 result; + result.x = (h ) & 0xFFu; + result.y = (h >> 8 ) & 0xFFu; + result.z = (h >> 16) & 0xFFu; + return result; +} + +float mx_perlin_noise_float(vec2 p) +{ + int X, Y; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float u = mx_fade(fx); + float v = mx_fade(fy); + float result = mx_bilerp( + mx_gradient_float(mx_hash_int(X , Y ), fx , fy ), + mx_gradient_float(mx_hash_int(X+1, Y ), fx-1.0, fy ), + mx_gradient_float(mx_hash_int(X , Y+1), fx , fy-1.0), + mx_gradient_float(mx_hash_int(X+1, Y+1), fx-1.0, fy-1.0), + u, v); + return mx_gradient_scale2d(result); +} + +float mx_perlin_noise_float(vec3 p) +{ + int X, Y, Z; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float fz = mx_floorfrac(p.z, Z); + float u = mx_fade(fx); + float v = mx_fade(fy); + float w = mx_fade(fz); + float result = mx_trilerp( + mx_gradient_float(mx_hash_int(X , Y , Z ), fx , fy , fz ), + mx_gradient_float(mx_hash_int(X+1, Y , Z ), fx-1.0, fy , fz ), + mx_gradient_float(mx_hash_int(X , Y+1, Z ), fx , fy-1.0, fz ), + mx_gradient_float(mx_hash_int(X+1, Y+1, Z ), fx-1.0, fy-1.0, fz ), + mx_gradient_float(mx_hash_int(X , Y , Z+1), fx , fy , fz-1.0), + mx_gradient_float(mx_hash_int(X+1, Y , Z+1), fx-1.0, fy , fz-1.0), + mx_gradient_float(mx_hash_int(X , Y+1, Z+1), fx , fy-1.0, fz-1.0), + mx_gradient_float(mx_hash_int(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0), + u, v, w); + return mx_gradient_scale3d(result); +} + +vec3 mx_perlin_noise_vec3(vec2 p) +{ + int X, Y; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float u = mx_fade(fx); + float v = mx_fade(fy); + vec3 result = mx_bilerp( + mx_gradient_vec3(mx_hash_vec3(X , Y ), fx , fy ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y ), fx-1.0, fy ), + mx_gradient_vec3(mx_hash_vec3(X , Y+1), fx , fy-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1), fx-1.0, fy-1.0), + u, v); + return mx_gradient_scale2d(result); +} + +vec3 mx_perlin_noise_vec3(vec3 p) +{ + int X, Y, Z; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float fz = mx_floorfrac(p.z, Z); + float u = mx_fade(fx); + float v = mx_fade(fy); + float w = mx_fade(fz); + vec3 result = mx_trilerp( + mx_gradient_vec3(mx_hash_vec3(X , Y , Z ), fx , fy , fz ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y , Z ), fx-1.0, fy , fz ), + mx_gradient_vec3(mx_hash_vec3(X , Y+1, Z ), fx , fy-1.0, fz ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1, Z ), fx-1.0, fy-1.0, fz ), + mx_gradient_vec3(mx_hash_vec3(X , Y , Z+1), fx , fy , fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y , Z+1), fx-1.0, fy , fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X , Y+1, Z+1), fx , fy-1.0, fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0), + u, v, w); + return mx_gradient_scale3d(result); +} + +float mx_cell_noise_float(float p) +{ + int ix = mx_floor(p); + return mx_bits_to_01(mx_hash_int(ix)); +} + +float mx_cell_noise_float(vec2 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + return mx_bits_to_01(mx_hash_int(ix, iy)); +} + +float mx_cell_noise_float(vec3 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + return mx_bits_to_01(mx_hash_int(ix, iy, iz)); +} + +float mx_cell_noise_float(vec4 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + int iw = mx_floor(p.w); + return mx_bits_to_01(mx_hash_int(ix, iy, iz, iw)); +} + +vec3 mx_cell_noise_vec3(float p) +{ + int ix = mx_floor(p); + return vec3( + mx_bits_to_01(mx_hash_int(ix, 0)), + mx_bits_to_01(mx_hash_int(ix, 1)), + mx_bits_to_01(mx_hash_int(ix, 2)) + ); +} + +vec3 mx_cell_noise_vec3(vec2 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + return vec3( + mx_bits_to_01(mx_hash_int(ix, iy, 0)), + mx_bits_to_01(mx_hash_int(ix, iy, 1)), + mx_bits_to_01(mx_hash_int(ix, iy, 2)) + ); +} + +vec3 mx_cell_noise_vec3(vec3 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (4u << 2u) + 13u; + a += uint(ix); + b += uint(iy); + c += uint(iz); + mx_bjmix(a, b, c); + return vec3( + mx_bits_to_01(mx_bjfinal(a, b, c)), + mx_bits_to_01(mx_bjfinal(a + 1u, b, c)), + mx_bits_to_01(mx_bjfinal(a + 2u, b, c)) + ); +} + +vec3 mx_cell_noise_vec3(vec4 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + int iw = mx_floor(p.w); + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (5u << 2u) + 13u; + a += uint(ix); + b += uint(iy); + c += uint(iz); + mx_bjmix(a, b, c); + a += uint(iw); + return vec3( + mx_bits_to_01(mx_bjfinal(a, b, c)), + mx_bits_to_01(mx_bjfinal(a, b + 1u, c)), + mx_bits_to_01(mx_bjfinal(a, b + 2u, c)) + ); +} + +float mx_fractal2d_noise_float(vec2 p, int octaves, float lacunarity, float diminish) +{ + float result = 0.0; + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_float(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec3 mx_fractal2d_noise_vec3(vec2 p, int octaves, float lacunarity, float diminish) +{ + vec3 result = vec3(0.0); + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_vec3(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec2 mx_fractal2d_noise_vec2(vec2 p, int octaves, float lacunarity, float diminish) +{ + return vec2(mx_fractal2d_noise_float(p, octaves, lacunarity, diminish), + mx_fractal2d_noise_float(p+vec2(19, 193), octaves, lacunarity, diminish)); +} + +vec4 mx_fractal2d_noise_vec4(vec2 p, int octaves, float lacunarity, float diminish) +{ + vec3 c = mx_fractal2d_noise_vec3(p, octaves, lacunarity, diminish); + float f = mx_fractal2d_noise_float(p+vec2(19, 193), octaves, lacunarity, diminish); + return vec4(c, f); +} + +float mx_fractal3d_noise_float(vec3 p, int octaves, float lacunarity, float diminish) +{ + float result = 0.0; + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_float(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec3 mx_fractal3d_noise_vec3(vec3 p, int octaves, float lacunarity, float diminish) +{ + vec3 result = vec3(0.0); + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_vec3(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec2 mx_fractal3d_noise_vec2(vec3 p, int octaves, float lacunarity, float diminish) +{ + return vec2(mx_fractal3d_noise_float(p, octaves, lacunarity, diminish), + mx_fractal3d_noise_float(p+vec3(19, 193, 17), octaves, lacunarity, diminish)); +} + +vec4 mx_fractal3d_noise_vec4(vec3 p, int octaves, float lacunarity, float diminish) +{ + vec3 c = mx_fractal3d_noise_vec3(p, octaves, lacunarity, diminish); + float f = mx_fractal3d_noise_float(p+vec3(19, 193, 17), octaves, lacunarity, diminish); + return vec4(c, f); +} + +vec2 mx_worley_cell_position(int x, int y, int xoff, int yoff, float jitter) +{ + vec3 tmp = mx_cell_noise_vec3(vec2(x+xoff, y+yoff)); + vec2 off = vec2(tmp.x, tmp.y); + + off -= 0.5f; + off *= jitter; + off += 0.5f; + + return vec2(float(x), float(y)) + off; +} + +vec3 mx_worley_cell_position(int x, int y, int z, int xoff, int yoff, int zoff, float jitter) +{ + vec3 off = mx_cell_noise_vec3(vec3(x+xoff, y+yoff, z+zoff)); + + off -= 0.5f; + off *= jitter; + off += 0.5f; + + return vec3(float(x), float(y), float(z)) + off; +} + +float mx_worley_distance(vec2 p, int x, int y, int xoff, int yoff, float jitter, int metric) +{ + vec2 cellpos = mx_worley_cell_position(x, y, xoff, yoff, jitter); + vec2 diff = cellpos - p; + if (metric == 2) + return abs(diff.x) + abs(diff.y); // Manhattan distance + if (metric == 3) + return max(abs(diff.x), abs(diff.y)); // Chebyshev distance + // Either Euclidean or Distance^2 + return dot(diff, diff); +} + +float mx_worley_distance(vec3 p, int x, int y, int z, int xoff, int yoff, int zoff, float jitter, int metric) +{ + vec3 cellpos = mx_worley_cell_position(x, y, z, xoff, yoff, zoff, jitter); + vec3 diff = cellpos - p; + if (metric == 2) + return abs(diff.x) + abs(diff.y) + abs(diff.z); // Manhattan distance + if (metric == 3) + return max(max(abs(diff.x), abs(diff.y)), abs(diff.z)); // Chebyshev distance + // Either Euclidean or Distance^2 + return dot(diff, diff); +} + +float mx_worley_noise_float(vec2 p, float jitter, int style, int metric) +{ + int X, Y; + float dist; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + float sqdist = 1e6f; // Some big number for jitter > 1 (not all GPUs may be IEEE) + vec2 minpos = vec2(0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + vec2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos; + if(dist < sqdist) + { + sqdist = dist; + minpos = cellpos; + } + } + } + if (style == 1) + return mx_cell_noise_float(minpos + p); + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +vec2 mx_worley_noise_vec2(vec2 p, float jitter, int style, int metric) +{ + int X, Y; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + vec2 sqdist = vec2(1e6f, 1e6f); + vec2 minpos = vec2(0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + vec2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos; + if (dist < sqdist.x) + { + sqdist.y = sqdist.x; + sqdist.x = dist; + minpos = cellpos; + } + else if (dist < sqdist.y) + { + sqdist.y = dist; + } + } + } + if (style == 1) + { + vec3 tmp = mx_cell_noise_vec3(minpos + p); + return vec2(tmp.x,tmp.y); + } + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +vec3 mx_worley_noise_vec3(vec2 p, float jitter, int style, int metric) +{ + int X, Y; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + vec3 sqdist = vec3(1e6f, 1e6f, 1e6f); + vec2 minpos = vec2(0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + vec2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos; + if (dist < sqdist.x) + { + sqdist.z = sqdist.y; + sqdist.y = sqdist.x; + sqdist.x = dist; + minpos = cellpos; + } + else if (dist < sqdist.y) + { + sqdist.z = sqdist.y; + sqdist.y = dist; + } + else if (dist < sqdist.z) + { + sqdist.z = dist; + } + } + } + if (style == 1) + return mx_cell_noise_vec3(minpos + p); + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +float mx_worley_noise_float(vec3 p, float jitter, int style, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + float sqdist = 1e6f; + vec3 minpos = vec3(0,0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + vec3 cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos; + if(dist < sqdist) + { + sqdist = dist; + minpos = cellpos; + } + } + } + } + if (style == 1) + return mx_cell_noise_float(minpos + p); + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +vec2 mx_worley_noise_vec2(vec3 p, float jitter, int style, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + vec2 sqdist = vec2(1e6f, 1e6f); + vec3 minpos = vec3(0,0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + vec3 cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos; + if (dist < sqdist.x) + { + sqdist.y = sqdist.x; + sqdist.x = dist; + minpos = cellpos; + } + else if (dist < sqdist.y) + { + sqdist.y = dist; + } + } + } + } + if (style == 1) + { + vec3 tmp = mx_cell_noise_vec3(minpos + p); + return vec2(tmp.x,tmp.y); + } + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +vec3 mx_worley_noise_vec3(vec3 p, float jitter, int style, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + vec3 sqdist = vec3(1e6f, 1e6f, 1e6f); + vec3 minpos = vec3(0,0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + vec3 cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos; + if (dist < sqdist.x) + { + sqdist.z = sqdist.y; + sqdist.y = sqdist.x; + sqdist.x = dist; + minpos = cellpos; + } + else if (dist < sqdist.y) + { + sqdist.z = sqdist.y; + sqdist.y = dist; + } + else if (dist < sqdist.z) + { + sqdist.z = dist; + } + } + } + } + if (style == 1) + return mx_cell_noise_vec3(minpos + p); + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +void mx_noise2d_float(float amplitude, float pivot, vec2 texcoord, out float result) +{ + float value = mx_perlin_noise_float(texcoord); + result = value * amplitude + pivot; +} + +void NG_switch_float(float in1, float in2, float in3, float in4, float in5, float in6, float in7, float in8, float in9, float in10, float which, out float out1) +{ + const float ifgreater_10_value1_tmp = 10.000000; + const float ifgreater_10_in2_tmp = 0.000000; + float ifgreater_10_out = (ifgreater_10_value1_tmp > which) ? in10 : ifgreater_10_in2_tmp; + const float ifgreater_9_value1_tmp = 9.000000; + float ifgreater_9_out = (ifgreater_9_value1_tmp > which) ? in9 : ifgreater_10_out; + const float ifgreater_8_value1_tmp = 8.000000; + float ifgreater_8_out = (ifgreater_8_value1_tmp > which) ? in8 : ifgreater_9_out; + const float ifgreater_7_value1_tmp = 7.000000; + float ifgreater_7_out = (ifgreater_7_value1_tmp > which) ? in7 : ifgreater_8_out; + const float ifgreater_6_value1_tmp = 6.000000; + float ifgreater_6_out = (ifgreater_6_value1_tmp > which) ? in6 : ifgreater_7_out; + const float ifgreater_5_value1_tmp = 5.000000; + float ifgreater_5_out = (ifgreater_5_value1_tmp > which) ? in5 : ifgreater_6_out; + const float ifgreater_4_value1_tmp = 4.000000; + float ifgreater_4_out = (ifgreater_4_value1_tmp > which) ? in4 : ifgreater_5_out; + const float ifgreater_3_value1_tmp = 3.000000; + float ifgreater_3_out = (ifgreater_3_value1_tmp > which) ? in3 : ifgreater_4_out; + const float ifgreater_2_value1_tmp = 2.000000; + float ifgreater_2_out = (ifgreater_2_value1_tmp > which) ? in2 : ifgreater_3_out; + const float ifgreater_1_value1_tmp = 1.000000; + float ifgreater_1_out = (ifgreater_1_value1_tmp > which) ? in1 : ifgreater_2_out; + out1 = ifgreater_1_out; +} + +void NG_turbulence2d_max8_float(vec2 texcoord, float octaves, float amplitude, out float out1) +{ + const float multiply8_in2_tmp = 128.000000; + vec2 multiply8_out = texcoord * multiply8_in2_tmp; + const float multiply7_in2_tmp = 64.000000; + vec2 multiply7_out = texcoord * multiply7_in2_tmp; + const float multiply6_in2_tmp = 32.000000; + vec2 multiply6_out = texcoord * multiply6_in2_tmp; + const float multiply5_in2_tmp = 16.000000; + vec2 multiply5_out = texcoord * multiply5_in2_tmp; + const float multiply4_in2_tmp = 8.000000; + vec2 multiply4_out = texcoord * multiply4_in2_tmp; + const float multiply3_in2_tmp = 4.000000; + vec2 multiply3_out = texcoord * multiply3_in2_tmp; + const float multiply2_in2_tmp = 2.000000; + vec2 multiply2_out = texcoord * multiply2_in2_tmp; + float noise2d1_out = 0.0; + mx_noise2d_float(1.000000, 0.000000, texcoord, noise2d1_out); + const float modulo_octave_in2_tmp = 5.000000; + float modulo_octave_out = mx_mod(octaves, modulo_octave_in2_tmp); + const float divide_octave_in2_tmp = 5.000000; + float divide_octave_out = octaves / divide_octave_in2_tmp; + const float modulo_fractional_in2_tmp = 1.000000; + float modulo_fractional_out = mx_mod(octaves, modulo_fractional_in2_tmp); + float noise2d8_out = 0.0; + mx_noise2d_float(1.000000, 0.000000, multiply8_out, noise2d8_out); + float noise2d7_out = 0.0; + mx_noise2d_float(1.000000, 0.000000, multiply7_out, noise2d7_out); + float noise2d6_out = 0.0; + mx_noise2d_float(1.000000, 0.000000, multiply6_out, noise2d6_out); + float noise2d5_out = 0.0; + mx_noise2d_float(1.000000, 0.000000, multiply5_out, noise2d5_out); + float noise2d4_out = 0.0; + mx_noise2d_float(1.000000, 0.000000, multiply4_out, noise2d4_out); + float noise2d3_out = 0.0; + mx_noise2d_float(1.000000, 0.000000, multiply3_out, noise2d3_out); + float noise2d2_out = 0.0; + mx_noise2d_float(1.000000, 0.000000, multiply2_out, noise2d2_out); + float absval1_out = abs(noise2d1_out); + const float divide8_in2_tmp = 128.000000; + float divide8_out = noise2d8_out / divide8_in2_tmp; + const float divide7_in2_tmp = 64.000000; + float divide7_out = noise2d7_out / divide7_in2_tmp; + const float divide6_in2_tmp = 32.000000; + float divide6_out = noise2d6_out / divide6_in2_tmp; + const float divide5_in2_tmp = 16.000000; + float divide5_out = noise2d5_out / divide5_in2_tmp; + const float divide4_in2_tmp = 8.000000; + float divide4_out = noise2d4_out / divide4_in2_tmp; + const float divide3_in2_tmp = 4.000000; + float divide3_out = noise2d3_out / divide3_in2_tmp; + const float divide2_in2_tmp = 2.000000; + float divide2_out = noise2d2_out / divide2_in2_tmp; + float multiply9_out = absval1_out * modulo_fractional_out; + float absval8_out = abs(divide8_out); + float absval7_out = abs(divide7_out); + float absval6_out = abs(divide6_out); + float absval5_out = abs(divide5_out); + float absval4_out = abs(divide4_out); + float absval3_out = abs(divide3_out); + float absval2_out = abs(divide2_out); + float multiply16_out = absval8_out * modulo_fractional_out; + float multiply15_out = absval7_out * modulo_fractional_out; + float multiply14_out = absval6_out * modulo_fractional_out; + float multiply13_out = absval5_out * modulo_fractional_out; + float multiply12_out = absval4_out * modulo_fractional_out; + float multiply11_out = absval3_out * modulo_fractional_out; + float add2_out = absval1_out + absval2_out; + float multiply10_out = absval2_out * modulo_fractional_out; + float switch4_out = 0.0; + NG_switch_float(multiply14_out, multiply15_out, multiply16_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, modulo_octave_out, switch4_out); + float add3_out = add2_out + absval3_out; + float switch3_out = 0.0; + NG_switch_float(multiply9_out, multiply10_out, multiply11_out, multiply12_out, multiply13_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, modulo_octave_out, switch3_out); + float add4_out = add3_out + absval4_out; + float switch_fractional_out = 0.0; + NG_switch_float(switch3_out, switch4_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, divide_octave_out, switch_fractional_out); + float add5_out = add4_out + absval5_out; + float switch1_out = 0.0; + NG_switch_float(0.000000, absval1_out, add2_out, add3_out, add4_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, modulo_octave_out, switch1_out); + float add6_out = add5_out + absval6_out; + float add7_out = add6_out + absval7_out; + float add8_out = add7_out + absval8_out; + float switch2_out = 0.0; + NG_switch_float(add5_out, add6_out, add7_out, add8_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, modulo_octave_out, switch2_out); + float switch_octave_out = 0.0; + NG_switch_float(switch1_out, switch2_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, divide_octave_out, switch_octave_out); + float add_fractional_out = switch_octave_out + switch_fractional_out; + const float ifgreatereq_octave_value2_tmp = 8.000000; + float ifgreatereq_octave_out = (octaves >= ifgreatereq_octave_value2_tmp) ? add8_out : add_fractional_out; + float multiply_amplitude_out = ifgreatereq_octave_out * amplitude; + out1 = multiply_amplitude_out; +} + +void main() +{ + vec2 texcoord1_out = vd.texcoord_0.xy; + const vec2 multiply1_in2_tmp = vec2(20.000000, 20.000000); + vec2 multiply1_out = texcoord1_out * multiply1_in2_tmp; + float turbulence2d1_out = 0.0; + NG_turbulence2d_max8_float(multiply1_out, 2.000000, 10.000000, turbulence2d1_out); + out11 = vec4(turbulence2d1_out, turbulence2d1_out, turbulence2d1_out, 1.0); +} + diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence2d_object_out_glsl_vs.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence2d_object_out_glsl_vs.glsl new file mode 100644 index 0000000000..c43d3a752f --- /dev/null +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence2d_object_out_glsl_vs.glsl @@ -0,0 +1,71 @@ +#version 400 + + +// Uniform block: PrivateUniforms +uniform mat4 u_worldMatrix = mat4(1.0); +uniform mat4 u_viewProjectionMatrix = mat4(1.0); + +// Inputs block: VertexInputs +in vec3 i_position; +in vec2 i_texcoord_0; + +out VertexData +{ + vec2 texcoord_0; +} vd; + +#define M_FLOAT_EPS 1e-8 +#define M_PI 3.1415926535897932 + +#define mx_mod mod +#define mx_inverse inverse +#define mx_inversesqrt inversesqrt +#define mx_sin sin +#define mx_cos cos +#define mx_tan tan +#define mx_asin asin +#define mx_acos acos +#define mx_atan atan +#define mx_radians radians +#define mx_float_bits_to_int floatBitsToInt + +vec2 mx_matrix_mul(vec2 v, mat2 m) { return v * m; } +vec3 mx_matrix_mul(vec3 v, mat3 m) { return v * m; } +vec4 mx_matrix_mul(vec4 v, mat4 m) { return v * m; } +vec2 mx_matrix_mul(mat2 m, vec2 v) { return m * v; } +vec3 mx_matrix_mul(mat3 m, vec3 v) { return m * v; } +vec4 mx_matrix_mul(mat4 m, vec4 v) { return m * v; } +mat2 mx_matrix_mul(mat2 m1, mat2 m2) { return m1 * m2; } +mat3 mx_matrix_mul(mat3 m1, mat3 m2) { return m1 * m2; } +mat4 mx_matrix_mul(mat4 m1, mat4 m2) { return m1 * m2; } + +float mx_square(float x) +{ + return x*x; +} + +vec2 mx_square(vec2 x) +{ + return x*x; +} + +vec3 mx_square(vec3 x) +{ + return x*x; +} + +vec3 mx_srgb_encode(vec3 color) +{ + bvec3 isAbove = greaterThan(color, vec3(0.0031308)); + vec3 linSeg = color * 12.92; + vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; + return mix(linSeg, powSeg, isAbove); +} + +void main() +{ + vec4 hPositionWorld = u_worldMatrix * vec4(i_position, 1.0); + gl_Position = u_viewProjectionMatrix * hPositionWorld; + vd.texcoord_0 = i_texcoord_0; +} + diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence3d_object_out_glsl_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence3d_object_out_glsl_ps.glsl new file mode 100644 index 0000000000..5d683df9b8 --- /dev/null +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence3d_object_out_glsl_ps.glsl @@ -0,0 +1,966 @@ +#version 400 + + +struct BSDF { vec3 response; vec3 throughput; }; +#define EDF vec3 +struct VDF { vec3 response; vec3 throughput; }; +struct surfaceshader { vec3 color; vec3 transparency; }; +struct volumeshader { vec3 color; vec3 transparency; }; +struct displacementshader { vec3 offset; float scale; }; +struct lightshader { vec3 intensity; vec3 direction; }; +#define material surfaceshader + +in VertexData +{ + vec3 positionWorld; +} vd; + +// Pixel shader outputs +out vec4 out11; + +#define M_FLOAT_EPS 1e-8 +#define M_PI 3.1415926535897932 + +#define mx_mod mod +#define mx_inverse inverse +#define mx_inversesqrt inversesqrt +#define mx_sin sin +#define mx_cos cos +#define mx_tan tan +#define mx_asin asin +#define mx_acos acos +#define mx_atan atan +#define mx_radians radians +#define mx_float_bits_to_int floatBitsToInt + +vec2 mx_matrix_mul(vec2 v, mat2 m) { return v * m; } +vec3 mx_matrix_mul(vec3 v, mat3 m) { return v * m; } +vec4 mx_matrix_mul(vec4 v, mat4 m) { return v * m; } +vec2 mx_matrix_mul(mat2 m, vec2 v) { return m * v; } +vec3 mx_matrix_mul(mat3 m, vec3 v) { return m * v; } +vec4 mx_matrix_mul(mat4 m, vec4 v) { return m * v; } +mat2 mx_matrix_mul(mat2 m1, mat2 m2) { return m1 * m2; } +mat3 mx_matrix_mul(mat3 m1, mat3 m2) { return m1 * m2; } +mat4 mx_matrix_mul(mat4 m1, mat4 m2) { return m1 * m2; } + +float mx_square(float x) +{ + return x*x; +} + +vec2 mx_square(vec2 x) +{ + return x*x; +} + +vec3 mx_square(vec3 x) +{ + return x*x; +} + +vec3 mx_srgb_encode(vec3 color) +{ + bvec3 isAbove = greaterThan(color, vec3(0.0031308)); + vec3 linSeg = color * 12.92; + vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; + return mix(linSeg, powSeg, isAbove); +} + +#define AIRY_FRESNEL_ITERATIONS 2 + +/* +Noise Library. + +This library is a modified version of the noise library found in +Open Shading Language: +github.com/imageworks/OpenShadingLanguage/blob/master/src/include/OSL/oslnoise.h + +It contains the subset of noise types needed to implement the MaterialX +standard library. The modifications are mainly conversions from C++ to GLSL. +Produced results should be identical to the OSL noise functions. + +Original copyright notice: +------------------------------------------------------------------------ +Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of Sony Pictures Imageworks nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------------ +*/ + +float mx_select(bool b, float t, float f) +{ + return b ? t : f; +} + +float mx_negate_if(float val, bool b) +{ + return b ? -val : val; +} + +int mx_floor(float x) +{ + return int(floor(x)); +} + +// return mx_floor as well as the fractional remainder +float mx_floorfrac(float x, out int i) +{ + i = mx_floor(x); + return x - float(i); +} + +float mx_bilerp(float v0, float v1, float v2, float v3, float s, float t) +{ + float s1 = 1.0 - s; + return (1.0 - t) * (v0*s1 + v1*s) + t * (v2*s1 + v3*s); +} +vec3 mx_bilerp(vec3 v0, vec3 v1, vec3 v2, vec3 v3, float s, float t) +{ + float s1 = 1.0 - s; + return (1.0 - t) * (v0*s1 + v1*s) + t * (v2*s1 + v3*s); +} +float mx_trilerp(float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float s, float t, float r) +{ + float s1 = 1.0 - s; + float t1 = 1.0 - t; + float r1 = 1.0 - r; + return (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) + + r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s))); +} +vec3 mx_trilerp(vec3 v0, vec3 v1, vec3 v2, vec3 v3, vec3 v4, vec3 v5, vec3 v6, vec3 v7, float s, float t, float r) +{ + float s1 = 1.0 - s; + float t1 = 1.0 - t; + float r1 = 1.0 - r; + return (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) + + r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s))); +} + +// 2 and 3 dimensional gradient functions - perform a dot product against a +// randomly chosen vector. Note that the gradient vector is not normalized, but +// this only affects the overall "scale" of the result, so we simply account for +// the scale by multiplying in the corresponding "perlin" function. +float mx_gradient_float(uint hash, float x, float y) +{ + // 8 possible directions (+-1,+-2) and (+-2,+-1) + uint h = hash & 7u; + float u = mx_select(h<4u, x, y); + float v = 2.0 * mx_select(h<4u, y, x); + // compute the dot product with (x,y). + return mx_negate_if(u, bool(h&1u)) + mx_negate_if(v, bool(h&2u)); +} +float mx_gradient_float(uint hash, float x, float y, float z) +{ + // use vectors pointing to the edges of the cube + uint h = hash & 15u; + float u = mx_select(h<8u, x, y); + float v = mx_select(h<4u, y, mx_select((h==12u)||(h==14u), x, z)); + return mx_negate_if(u, bool(h&1u)) + mx_negate_if(v, bool(h&2u)); +} +vec3 mx_gradient_vec3(uvec3 hash, float x, float y) +{ + return vec3(mx_gradient_float(hash.x, x, y), mx_gradient_float(hash.y, x, y), mx_gradient_float(hash.z, x, y)); +} +vec3 mx_gradient_vec3(uvec3 hash, float x, float y, float z) +{ + return vec3(mx_gradient_float(hash.x, x, y, z), mx_gradient_float(hash.y, x, y, z), mx_gradient_float(hash.z, x, y, z)); +} +// Scaling factors to normalize the result of gradients above. +// These factors were experimentally calculated to be: +// 2D: 0.6616 +// 3D: 0.9820 +float mx_gradient_scale2d(float v) { return 0.6616 * v; } +float mx_gradient_scale3d(float v) { return 0.9820 * v; } +vec3 mx_gradient_scale2d(vec3 v) { return 0.6616 * v; } +vec3 mx_gradient_scale3d(vec3 v) { return 0.9820 * v; } + +/// Bitwise circular rotation left by k bits (for 32 bit unsigned integers) +uint mx_rotl32(uint x, int k) +{ + return (x<>(32-k)); +} + +void mx_bjmix(inout uint a, inout uint b, inout uint c) +{ + a -= c; a ^= mx_rotl32(c, 4); c += b; + b -= a; b ^= mx_rotl32(a, 6); a += c; + c -= b; c ^= mx_rotl32(b, 8); b += a; + a -= c; a ^= mx_rotl32(c,16); c += b; + b -= a; b ^= mx_rotl32(a,19); a += c; + c -= b; c ^= mx_rotl32(b, 4); b += a; +} + +// Mix up and combine the bits of a, b, and c (doesn't change them, but +// returns a hash of those three original values). +uint mx_bjfinal(uint a, uint b, uint c) +{ + c ^= b; c -= mx_rotl32(b,14); + a ^= c; a -= mx_rotl32(c,11); + b ^= a; b -= mx_rotl32(a,25); + c ^= b; c -= mx_rotl32(b,16); + a ^= c; a -= mx_rotl32(c,4); + b ^= a; b -= mx_rotl32(a,14); + c ^= b; c -= mx_rotl32(b,24); + return c; +} + +// Convert a 32 bit integer into a floating point number in [0,1] +float mx_bits_to_01(uint bits) +{ + return float(bits) / float(uint(0xffffffff)); +} + +float mx_fade(float t) +{ + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +uint mx_hash_int(int x) +{ + uint len = 1u; + uint seed = uint(0xdeadbeef) + (len << 2u) + 13u; + return mx_bjfinal(seed+uint(x), seed, seed); +} + +uint mx_hash_int(int x, int y) +{ + uint len = 2u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z) +{ + uint len = 3u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z, int xx) +{ + uint len = 4u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + mx_bjmix(a, b, c); + a += uint(xx); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z, int xx, int yy) +{ + uint len = 5u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + mx_bjmix(a, b, c); + a += uint(xx); + b += uint(yy); + return mx_bjfinal(a, b, c); +} + +uvec3 mx_hash_vec3(int x, int y) +{ + uint h = mx_hash_int(x, y); + // we only need the low-order bits to be random, so split out + // the 32 bit result into 3 parts for each channel + uvec3 result; + result.x = (h ) & 0xFFu; + result.y = (h >> 8 ) & 0xFFu; + result.z = (h >> 16) & 0xFFu; + return result; +} + +uvec3 mx_hash_vec3(int x, int y, int z) +{ + uint h = mx_hash_int(x, y, z); + // we only need the low-order bits to be random, so split out + // the 32 bit result into 3 parts for each channel + uvec3 result; + result.x = (h ) & 0xFFu; + result.y = (h >> 8 ) & 0xFFu; + result.z = (h >> 16) & 0xFFu; + return result; +} + +float mx_perlin_noise_float(vec2 p) +{ + int X, Y; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float u = mx_fade(fx); + float v = mx_fade(fy); + float result = mx_bilerp( + mx_gradient_float(mx_hash_int(X , Y ), fx , fy ), + mx_gradient_float(mx_hash_int(X+1, Y ), fx-1.0, fy ), + mx_gradient_float(mx_hash_int(X , Y+1), fx , fy-1.0), + mx_gradient_float(mx_hash_int(X+1, Y+1), fx-1.0, fy-1.0), + u, v); + return mx_gradient_scale2d(result); +} + +float mx_perlin_noise_float(vec3 p) +{ + int X, Y, Z; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float fz = mx_floorfrac(p.z, Z); + float u = mx_fade(fx); + float v = mx_fade(fy); + float w = mx_fade(fz); + float result = mx_trilerp( + mx_gradient_float(mx_hash_int(X , Y , Z ), fx , fy , fz ), + mx_gradient_float(mx_hash_int(X+1, Y , Z ), fx-1.0, fy , fz ), + mx_gradient_float(mx_hash_int(X , Y+1, Z ), fx , fy-1.0, fz ), + mx_gradient_float(mx_hash_int(X+1, Y+1, Z ), fx-1.0, fy-1.0, fz ), + mx_gradient_float(mx_hash_int(X , Y , Z+1), fx , fy , fz-1.0), + mx_gradient_float(mx_hash_int(X+1, Y , Z+1), fx-1.0, fy , fz-1.0), + mx_gradient_float(mx_hash_int(X , Y+1, Z+1), fx , fy-1.0, fz-1.0), + mx_gradient_float(mx_hash_int(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0), + u, v, w); + return mx_gradient_scale3d(result); +} + +vec3 mx_perlin_noise_vec3(vec2 p) +{ + int X, Y; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float u = mx_fade(fx); + float v = mx_fade(fy); + vec3 result = mx_bilerp( + mx_gradient_vec3(mx_hash_vec3(X , Y ), fx , fy ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y ), fx-1.0, fy ), + mx_gradient_vec3(mx_hash_vec3(X , Y+1), fx , fy-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1), fx-1.0, fy-1.0), + u, v); + return mx_gradient_scale2d(result); +} + +vec3 mx_perlin_noise_vec3(vec3 p) +{ + int X, Y, Z; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float fz = mx_floorfrac(p.z, Z); + float u = mx_fade(fx); + float v = mx_fade(fy); + float w = mx_fade(fz); + vec3 result = mx_trilerp( + mx_gradient_vec3(mx_hash_vec3(X , Y , Z ), fx , fy , fz ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y , Z ), fx-1.0, fy , fz ), + mx_gradient_vec3(mx_hash_vec3(X , Y+1, Z ), fx , fy-1.0, fz ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1, Z ), fx-1.0, fy-1.0, fz ), + mx_gradient_vec3(mx_hash_vec3(X , Y , Z+1), fx , fy , fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y , Z+1), fx-1.0, fy , fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X , Y+1, Z+1), fx , fy-1.0, fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0), + u, v, w); + return mx_gradient_scale3d(result); +} + +float mx_cell_noise_float(float p) +{ + int ix = mx_floor(p); + return mx_bits_to_01(mx_hash_int(ix)); +} + +float mx_cell_noise_float(vec2 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + return mx_bits_to_01(mx_hash_int(ix, iy)); +} + +float mx_cell_noise_float(vec3 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + return mx_bits_to_01(mx_hash_int(ix, iy, iz)); +} + +float mx_cell_noise_float(vec4 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + int iw = mx_floor(p.w); + return mx_bits_to_01(mx_hash_int(ix, iy, iz, iw)); +} + +vec3 mx_cell_noise_vec3(float p) +{ + int ix = mx_floor(p); + return vec3( + mx_bits_to_01(mx_hash_int(ix, 0)), + mx_bits_to_01(mx_hash_int(ix, 1)), + mx_bits_to_01(mx_hash_int(ix, 2)) + ); +} + +vec3 mx_cell_noise_vec3(vec2 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + return vec3( + mx_bits_to_01(mx_hash_int(ix, iy, 0)), + mx_bits_to_01(mx_hash_int(ix, iy, 1)), + mx_bits_to_01(mx_hash_int(ix, iy, 2)) + ); +} + +vec3 mx_cell_noise_vec3(vec3 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (4u << 2u) + 13u; + a += uint(ix); + b += uint(iy); + c += uint(iz); + mx_bjmix(a, b, c); + return vec3( + mx_bits_to_01(mx_bjfinal(a, b, c)), + mx_bits_to_01(mx_bjfinal(a + 1u, b, c)), + mx_bits_to_01(mx_bjfinal(a + 2u, b, c)) + ); +} + +vec3 mx_cell_noise_vec3(vec4 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + int iw = mx_floor(p.w); + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (5u << 2u) + 13u; + a += uint(ix); + b += uint(iy); + c += uint(iz); + mx_bjmix(a, b, c); + a += uint(iw); + return vec3( + mx_bits_to_01(mx_bjfinal(a, b, c)), + mx_bits_to_01(mx_bjfinal(a, b + 1u, c)), + mx_bits_to_01(mx_bjfinal(a, b + 2u, c)) + ); +} + +float mx_fractal2d_noise_float(vec2 p, int octaves, float lacunarity, float diminish) +{ + float result = 0.0; + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_float(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec3 mx_fractal2d_noise_vec3(vec2 p, int octaves, float lacunarity, float diminish) +{ + vec3 result = vec3(0.0); + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_vec3(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec2 mx_fractal2d_noise_vec2(vec2 p, int octaves, float lacunarity, float diminish) +{ + return vec2(mx_fractal2d_noise_float(p, octaves, lacunarity, diminish), + mx_fractal2d_noise_float(p+vec2(19, 193), octaves, lacunarity, diminish)); +} + +vec4 mx_fractal2d_noise_vec4(vec2 p, int octaves, float lacunarity, float diminish) +{ + vec3 c = mx_fractal2d_noise_vec3(p, octaves, lacunarity, diminish); + float f = mx_fractal2d_noise_float(p+vec2(19, 193), octaves, lacunarity, diminish); + return vec4(c, f); +} + +float mx_fractal3d_noise_float(vec3 p, int octaves, float lacunarity, float diminish) +{ + float result = 0.0; + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_float(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec3 mx_fractal3d_noise_vec3(vec3 p, int octaves, float lacunarity, float diminish) +{ + vec3 result = vec3(0.0); + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_vec3(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec2 mx_fractal3d_noise_vec2(vec3 p, int octaves, float lacunarity, float diminish) +{ + return vec2(mx_fractal3d_noise_float(p, octaves, lacunarity, diminish), + mx_fractal3d_noise_float(p+vec3(19, 193, 17), octaves, lacunarity, diminish)); +} + +vec4 mx_fractal3d_noise_vec4(vec3 p, int octaves, float lacunarity, float diminish) +{ + vec3 c = mx_fractal3d_noise_vec3(p, octaves, lacunarity, diminish); + float f = mx_fractal3d_noise_float(p+vec3(19, 193, 17), octaves, lacunarity, diminish); + return vec4(c, f); +} + +vec2 mx_worley_cell_position(int x, int y, int xoff, int yoff, float jitter) +{ + vec3 tmp = mx_cell_noise_vec3(vec2(x+xoff, y+yoff)); + vec2 off = vec2(tmp.x, tmp.y); + + off -= 0.5f; + off *= jitter; + off += 0.5f; + + return vec2(float(x), float(y)) + off; +} + +vec3 mx_worley_cell_position(int x, int y, int z, int xoff, int yoff, int zoff, float jitter) +{ + vec3 off = mx_cell_noise_vec3(vec3(x+xoff, y+yoff, z+zoff)); + + off -= 0.5f; + off *= jitter; + off += 0.5f; + + return vec3(float(x), float(y), float(z)) + off; +} + +float mx_worley_distance(vec2 p, int x, int y, int xoff, int yoff, float jitter, int metric) +{ + vec2 cellpos = mx_worley_cell_position(x, y, xoff, yoff, jitter); + vec2 diff = cellpos - p; + if (metric == 2) + return abs(diff.x) + abs(diff.y); // Manhattan distance + if (metric == 3) + return max(abs(diff.x), abs(diff.y)); // Chebyshev distance + // Either Euclidean or Distance^2 + return dot(diff, diff); +} + +float mx_worley_distance(vec3 p, int x, int y, int z, int xoff, int yoff, int zoff, float jitter, int metric) +{ + vec3 cellpos = mx_worley_cell_position(x, y, z, xoff, yoff, zoff, jitter); + vec3 diff = cellpos - p; + if (metric == 2) + return abs(diff.x) + abs(diff.y) + abs(diff.z); // Manhattan distance + if (metric == 3) + return max(max(abs(diff.x), abs(diff.y)), abs(diff.z)); // Chebyshev distance + // Either Euclidean or Distance^2 + return dot(diff, diff); +} + +float mx_worley_noise_float(vec2 p, float jitter, int style, int metric) +{ + int X, Y; + float dist; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + float sqdist = 1e6f; // Some big number for jitter > 1 (not all GPUs may be IEEE) + vec2 minpos = vec2(0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + vec2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos; + if(dist < sqdist) + { + sqdist = dist; + minpos = cellpos; + } + } + } + if (style == 1) + return mx_cell_noise_float(minpos + p); + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +vec2 mx_worley_noise_vec2(vec2 p, float jitter, int style, int metric) +{ + int X, Y; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + vec2 sqdist = vec2(1e6f, 1e6f); + vec2 minpos = vec2(0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + vec2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos; + if (dist < sqdist.x) + { + sqdist.y = sqdist.x; + sqdist.x = dist; + minpos = cellpos; + } + else if (dist < sqdist.y) + { + sqdist.y = dist; + } + } + } + if (style == 1) + { + vec3 tmp = mx_cell_noise_vec3(minpos + p); + return vec2(tmp.x,tmp.y); + } + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +vec3 mx_worley_noise_vec3(vec2 p, float jitter, int style, int metric) +{ + int X, Y; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + vec3 sqdist = vec3(1e6f, 1e6f, 1e6f); + vec2 minpos = vec2(0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + vec2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos; + if (dist < sqdist.x) + { + sqdist.z = sqdist.y; + sqdist.y = sqdist.x; + sqdist.x = dist; + minpos = cellpos; + } + else if (dist < sqdist.y) + { + sqdist.z = sqdist.y; + sqdist.y = dist; + } + else if (dist < sqdist.z) + { + sqdist.z = dist; + } + } + } + if (style == 1) + return mx_cell_noise_vec3(minpos + p); + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +float mx_worley_noise_float(vec3 p, float jitter, int style, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + float sqdist = 1e6f; + vec3 minpos = vec3(0,0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + vec3 cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos; + if(dist < sqdist) + { + sqdist = dist; + minpos = cellpos; + } + } + } + } + if (style == 1) + return mx_cell_noise_float(minpos + p); + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +vec2 mx_worley_noise_vec2(vec3 p, float jitter, int style, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + vec2 sqdist = vec2(1e6f, 1e6f); + vec3 minpos = vec3(0,0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + vec3 cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos; + if (dist < sqdist.x) + { + sqdist.y = sqdist.x; + sqdist.x = dist; + minpos = cellpos; + } + else if (dist < sqdist.y) + { + sqdist.y = dist; + } + } + } + } + if (style == 1) + { + vec3 tmp = mx_cell_noise_vec3(minpos + p); + return vec2(tmp.x,tmp.y); + } + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +vec3 mx_worley_noise_vec3(vec3 p, float jitter, int style, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + vec3 sqdist = vec3(1e6f, 1e6f, 1e6f); + vec3 minpos = vec3(0,0,0); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + vec3 cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos; + if (dist < sqdist.x) + { + sqdist.z = sqdist.y; + sqdist.y = sqdist.x; + sqdist.x = dist; + minpos = cellpos; + } + else if (dist < sqdist.y) + { + sqdist.z = sqdist.y; + sqdist.y = dist; + } + else if (dist < sqdist.z) + { + sqdist.z = dist; + } + } + } + } + if (style == 1) + return mx_cell_noise_vec3(minpos + p); + else + { + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; + } +} + +void mx_noise3d_float(float amplitude, float pivot, vec3 position, out float result) +{ + float value = mx_perlin_noise_float(position); + result = value * amplitude + pivot; +} + +void NG_switch_float(float in1, float in2, float in3, float in4, float in5, float in6, float in7, float in8, float in9, float in10, float which, out float out1) +{ + const float ifgreater_10_value1_tmp = 10.000000; + const float ifgreater_10_in2_tmp = 0.000000; + float ifgreater_10_out = (ifgreater_10_value1_tmp > which) ? in10 : ifgreater_10_in2_tmp; + const float ifgreater_9_value1_tmp = 9.000000; + float ifgreater_9_out = (ifgreater_9_value1_tmp > which) ? in9 : ifgreater_10_out; + const float ifgreater_8_value1_tmp = 8.000000; + float ifgreater_8_out = (ifgreater_8_value1_tmp > which) ? in8 : ifgreater_9_out; + const float ifgreater_7_value1_tmp = 7.000000; + float ifgreater_7_out = (ifgreater_7_value1_tmp > which) ? in7 : ifgreater_8_out; + const float ifgreater_6_value1_tmp = 6.000000; + float ifgreater_6_out = (ifgreater_6_value1_tmp > which) ? in6 : ifgreater_7_out; + const float ifgreater_5_value1_tmp = 5.000000; + float ifgreater_5_out = (ifgreater_5_value1_tmp > which) ? in5 : ifgreater_6_out; + const float ifgreater_4_value1_tmp = 4.000000; + float ifgreater_4_out = (ifgreater_4_value1_tmp > which) ? in4 : ifgreater_5_out; + const float ifgreater_3_value1_tmp = 3.000000; + float ifgreater_3_out = (ifgreater_3_value1_tmp > which) ? in3 : ifgreater_4_out; + const float ifgreater_2_value1_tmp = 2.000000; + float ifgreater_2_out = (ifgreater_2_value1_tmp > which) ? in2 : ifgreater_3_out; + const float ifgreater_1_value1_tmp = 1.000000; + float ifgreater_1_out = (ifgreater_1_value1_tmp > which) ? in1 : ifgreater_2_out; + out1 = ifgreater_1_out; +} + +void NG_turbulence3d_max8_float(vec3 position, float octaves, float amplitude, out float out1) +{ + const float multiply8_in2_tmp = 128.000000; + vec3 multiply8_out = position * multiply8_in2_tmp; + const float multiply7_in2_tmp = 64.000000; + vec3 multiply7_out = position * multiply7_in2_tmp; + const float multiply6_in2_tmp = 32.000000; + vec3 multiply6_out = position * multiply6_in2_tmp; + const float multiply5_in2_tmp = 16.000000; + vec3 multiply5_out = position * multiply5_in2_tmp; + const float multiply4_in2_tmp = 8.000000; + vec3 multiply4_out = position * multiply4_in2_tmp; + const float multiply3_in2_tmp = 4.000000; + vec3 multiply3_out = position * multiply3_in2_tmp; + const float multiply2_in2_tmp = 2.000000; + vec3 multiply2_out = position * multiply2_in2_tmp; + float noise3d1_out = 0.0; + mx_noise3d_float(1.000000, 0.000000, position, noise3d1_out); + const float modulo_octave_in2_tmp = 5.000000; + float modulo_octave_out = mx_mod(octaves, modulo_octave_in2_tmp); + const float divide_octave_in2_tmp = 5.000000; + float divide_octave_out = octaves / divide_octave_in2_tmp; + const float modulo_fractional_in2_tmp = 1.000000; + float modulo_fractional_out = mx_mod(octaves, modulo_fractional_in2_tmp); + float noise3d8_out = 0.0; + mx_noise3d_float(1.000000, 0.000000, multiply8_out, noise3d8_out); + float noise3d7_out = 0.0; + mx_noise3d_float(1.000000, 0.000000, multiply7_out, noise3d7_out); + float noise3d6_out = 0.0; + mx_noise3d_float(1.000000, 0.000000, multiply6_out, noise3d6_out); + float noise3d5_out = 0.0; + mx_noise3d_float(1.000000, 0.000000, multiply5_out, noise3d5_out); + float noise3d4_out = 0.0; + mx_noise3d_float(1.000000, 0.000000, multiply4_out, noise3d4_out); + float noise3d3_out = 0.0; + mx_noise3d_float(1.000000, 0.000000, multiply3_out, noise3d3_out); + float noise3d2_out = 0.0; + mx_noise3d_float(1.000000, 0.000000, multiply2_out, noise3d2_out); + float absval1_out = abs(noise3d1_out); + const float divide8_in2_tmp = 128.000000; + float divide8_out = noise3d8_out / divide8_in2_tmp; + const float divide7_in2_tmp = 64.000000; + float divide7_out = noise3d7_out / divide7_in2_tmp; + const float divide6_in2_tmp = 32.000000; + float divide6_out = noise3d6_out / divide6_in2_tmp; + const float divide5_in2_tmp = 16.000000; + float divide5_out = noise3d5_out / divide5_in2_tmp; + const float divide4_in2_tmp = 8.000000; + float divide4_out = noise3d4_out / divide4_in2_tmp; + const float divide3_in2_tmp = 4.000000; + float divide3_out = noise3d3_out / divide3_in2_tmp; + const float divide2_in2_tmp = 2.000000; + float divide2_out = noise3d2_out / divide2_in2_tmp; + float multiply9_out = absval1_out * modulo_fractional_out; + float absval8_out = abs(divide8_out); + float absval7_out = abs(divide7_out); + float absval6_out = abs(divide6_out); + float absval5_out = abs(divide5_out); + float absval4_out = abs(divide4_out); + float absval3_out = abs(divide3_out); + float absval2_out = abs(divide2_out); + float multiply16_out = absval8_out * modulo_fractional_out; + float multiply15_out = absval7_out * modulo_fractional_out; + float multiply14_out = absval6_out * modulo_fractional_out; + float multiply13_out = absval5_out * modulo_fractional_out; + float multiply12_out = absval4_out * modulo_fractional_out; + float multiply11_out = absval3_out * modulo_fractional_out; + float add2_out = absval1_out + absval2_out; + float multiply10_out = absval2_out * modulo_fractional_out; + float switch4_out = 0.0; + NG_switch_float(multiply14_out, multiply15_out, multiply16_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, modulo_octave_out, switch4_out); + float add3_out = add2_out + absval3_out; + float switch3_out = 0.0; + NG_switch_float(multiply9_out, multiply10_out, multiply11_out, multiply12_out, multiply13_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, modulo_octave_out, switch3_out); + float add4_out = add3_out + absval4_out; + float switch_fractional_out = 0.0; + NG_switch_float(switch3_out, switch4_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, divide_octave_out, switch_fractional_out); + float add5_out = add4_out + absval5_out; + float switch1_out = 0.0; + NG_switch_float(0.000000, absval1_out, add2_out, add3_out, add4_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, modulo_octave_out, switch1_out); + float add6_out = add5_out + absval6_out; + float add7_out = add6_out + absval7_out; + float add8_out = add7_out + absval8_out; + float switch2_out = 0.0; + NG_switch_float(add5_out, add6_out, add7_out, add8_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, modulo_octave_out, switch2_out); + float switch_octave_out = 0.0; + NG_switch_float(switch1_out, switch2_out, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, divide_octave_out, switch_octave_out); + float add_fractional_out = switch_octave_out + switch_fractional_out; + const float ifgreatereq_octave_value2_tmp = 8.000000; + float ifgreatereq_octave_out = (octaves >= ifgreatereq_octave_value2_tmp) ? add8_out : add_fractional_out; + float multiply_amplitude_out = ifgreatereq_octave_out * amplitude; + out1 = multiply_amplitude_out; +} + +void main() +{ + vec3 position1_out = vd.positionWorld; + const vec3 multiply1_in2_tmp = vec3(20.000000, 20.000000, 20.000000); + vec3 multiply1_out = position1_out * multiply1_in2_tmp; + float turbulence3d1_out = 0.0; + NG_turbulence3d_max8_float(multiply1_out, 2.000000, 10.000000, turbulence3d1_out); + out11 = vec4(turbulence3d1_out, turbulence3d1_out, turbulence3d1_out, 1.0); +} + diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence3d_object_out_glsl_vs.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence3d_object_out_glsl_vs.glsl new file mode 100644 index 0000000000..30f3dc3371 --- /dev/null +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/other/turbulence3d_object_out_glsl_vs.glsl @@ -0,0 +1,70 @@ +#version 400 + + +// Uniform block: PrivateUniforms +uniform mat4 u_worldMatrix = mat4(1.0); +uniform mat4 u_viewProjectionMatrix = mat4(1.0); + +// Inputs block: VertexInputs +in vec3 i_position; + +out VertexData +{ + vec3 positionWorld; +} vd; + +#define M_FLOAT_EPS 1e-8 +#define M_PI 3.1415926535897932 + +#define mx_mod mod +#define mx_inverse inverse +#define mx_inversesqrt inversesqrt +#define mx_sin sin +#define mx_cos cos +#define mx_tan tan +#define mx_asin asin +#define mx_acos acos +#define mx_atan atan +#define mx_radians radians +#define mx_float_bits_to_int floatBitsToInt + +vec2 mx_matrix_mul(vec2 v, mat2 m) { return v * m; } +vec3 mx_matrix_mul(vec3 v, mat3 m) { return v * m; } +vec4 mx_matrix_mul(vec4 v, mat4 m) { return v * m; } +vec2 mx_matrix_mul(mat2 m, vec2 v) { return m * v; } +vec3 mx_matrix_mul(mat3 m, vec3 v) { return m * v; } +vec4 mx_matrix_mul(mat4 m, vec4 v) { return m * v; } +mat2 mx_matrix_mul(mat2 m1, mat2 m2) { return m1 * m2; } +mat3 mx_matrix_mul(mat3 m1, mat3 m2) { return m1 * m2; } +mat4 mx_matrix_mul(mat4 m1, mat4 m2) { return m1 * m2; } + +float mx_square(float x) +{ + return x*x; +} + +vec2 mx_square(vec2 x) +{ + return x*x; +} + +vec3 mx_square(vec3 x) +{ + return x*x; +} + +vec3 mx_srgb_encode(vec3 color) +{ + bvec3 isAbove = greaterThan(color, vec3(0.0031308)); + vec3 linSeg = color * 12.92; + vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; + return mix(linSeg, powSeg, isAbove); +} + +void main() +{ + vec4 hPositionWorld = u_worldMatrix * vec4(i_position, 1.0); + gl_Position = u_viewProjectionMatrix * hPositionWorld; + vd.positionWorld = hPositionWorld.xyz; +} + diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/plastic/M_legacy_plastic_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/plastic/M_legacy_plastic_ps.glsl index e82889170c..2b477139e7 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/plastic/M_legacy_plastic_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/plastic/M_legacy_plastic_ps.glsl @@ -1806,10 +1806,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/stone/M_legacy_stone_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/stone/M_legacy_stone_ps.glsl index bc61ac26bc..8cbfda9279 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/stone/M_legacy_stone_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/stone/M_legacy_stone_ps.glsl @@ -1854,10 +1854,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/tiles/M_legacy_tiles_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/tiles/M_legacy_tiles_ps.glsl index 07db6a016a..9c9bb69053 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/tiles/M_legacy_tiles_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/tiles/M_legacy_tiles_ps.glsl @@ -2875,10 +2875,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/wallpaint/M_legacy_wallpaint_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/wallpaint/M_legacy_wallpaint_ps.glsl index 5a0a544831..f3258ac459 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/wallpaint/M_legacy_wallpaint_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/wallpaint/M_legacy_wallpaint_ps.glsl @@ -1810,10 +1810,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/water/M_legacy_water_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/water/M_legacy_water_ps.glsl index b1c401ca68..e7e99220ec 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/water/M_legacy_water_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/adsk/Examples/Revit/water/M_legacy_water_ps.glsl @@ -1911,10 +1911,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_brass_tiled/Tiled_Brass_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_brass_tiled/Tiled_Brass_ps.glsl index c2bf52b2ce..4dfddf21ed 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_brass_tiled/Tiled_Brass_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_brass_tiled/Tiled_Brass_ps.glsl @@ -1744,10 +1744,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_brick_procedural/M_BrickPattern_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_brick_procedural/M_BrickPattern_ps.glsl index 1173799049..984e093227 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_brick_procedural/M_BrickPattern_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_brick_procedural/M_BrickPattern_ps.glsl @@ -1872,10 +1872,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_carpaint/Car_Paint_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_carpaint/Car_Paint_ps.glsl index f814326288..6c29d114d9 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_carpaint/Car_Paint_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_carpaint/Car_Paint_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Bishop_B_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Bishop_B_ps.glsl index e9085bf47e..f290a15c8f 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Bishop_B_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Bishop_B_ps.glsl @@ -1767,10 +1767,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Bishop_W_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Bishop_W_ps.glsl index fc204047b5..8dca64843c 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Bishop_W_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Bishop_W_ps.glsl @@ -1767,10 +1767,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Castle_B_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Castle_B_ps.glsl index 6e8f877e74..9a1a76be79 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Castle_B_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Castle_B_ps.glsl @@ -1767,10 +1767,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Castle_W_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Castle_W_ps.glsl index d65db20eac..7984b843d7 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Castle_W_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Castle_W_ps.glsl @@ -1767,10 +1767,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Chessboard_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Chessboard_ps.glsl index ace5da19fb..1e14265257 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Chessboard_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Chessboard_ps.glsl @@ -1767,10 +1767,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_King_B_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_King_B_ps.glsl index 60c36edb4b..dcb7dab625 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_King_B_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_King_B_ps.glsl @@ -1777,10 +1777,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_King_W_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_King_W_ps.glsl index 3a5b92c695..8b138d1dee 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_King_W_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_King_W_ps.glsl @@ -1777,10 +1777,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Knight_B_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Knight_B_ps.glsl index 5a16a82eb6..514baeafe3 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Knight_B_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Knight_B_ps.glsl @@ -1757,10 +1757,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Knight_W_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Knight_W_ps.glsl index e6439f84c2..bba335d918 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Knight_W_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Knight_W_ps.glsl @@ -1757,10 +1757,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Body_B_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Body_B_ps.glsl index 825d247ea2..ac41c74642 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Body_B_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Body_B_ps.glsl @@ -1767,10 +1767,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Body_W_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Body_W_ps.glsl index b7a7f438c5..9666dc7af2 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Body_W_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Body_W_ps.glsl @@ -1767,10 +1767,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Top_B_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Top_B_ps.glsl index 7a788c45ef..03a9594787 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Top_B_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Top_B_ps.glsl @@ -1697,10 +1697,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Top_W_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Top_W_ps.glsl index 63d54a8dbe..09ec08006d 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Top_W_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Pawn_Top_W_ps.glsl @@ -1697,10 +1697,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Queen_B_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Queen_B_ps.glsl index 49bf553a10..10f861125a 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Queen_B_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Queen_B_ps.glsl @@ -1777,10 +1777,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Queen_W_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Queen_W_ps.glsl index 627f57e9eb..89ce77e223 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Queen_W_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chess_set/M_Queen_W_ps.glsl @@ -1777,10 +1777,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chrome/Chrome_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chrome/Chrome_ps.glsl index 20e29b1f43..c9a28867bc 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chrome/Chrome_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_chrome/Chrome_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_copper/Copper_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_copper/Copper_ps.glsl index 539983bcda..3285e28955 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_copper/Copper_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_copper/Copper_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_default/Default_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_default/Default_ps.glsl index 79d7d9c03d..1fb628f80a 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_default/Default_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_default/Default_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_glass/Glass_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_glass/Glass_ps.glsl index 11000f54d2..0067143706 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_glass/Glass_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_glass/Glass_ps.glsl @@ -1639,10 +1639,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_glass_tinted/GlassTinted_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_glass_tinted/GlassTinted_ps.glsl index 406b405e14..7076fd4d58 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_glass_tinted/GlassTinted_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_glass_tinted/GlassTinted_ps.glsl @@ -1639,10 +1639,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_gold/Gold_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_gold/Gold_ps.glsl index d94aad9293..84213c3c52 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_gold/Gold_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_gold/Gold_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_greysphere/Greysphere_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_greysphere/Greysphere_ps.glsl index cc799e8e75..b78fba63ea 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_greysphere/Greysphere_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_greysphere/Greysphere_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_greysphere_calibration/Greysphere_Calibration_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_greysphere_calibration/Greysphere_Calibration_ps.glsl index 7317776041..f227f0403d 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_greysphere_calibration/Greysphere_Calibration_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_greysphere_calibration/Greysphere_Calibration_ps.glsl @@ -1765,10 +1765,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_jade/Jade_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_jade/Jade_ps.glsl index c6f5ee982c..243c41fe47 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_jade/Jade_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_jade/Jade_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_brass_tiled/Greysphere_Calibration_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_brass_tiled/Greysphere_Calibration_ps.glsl index 7317776041..f227f0403d 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_brass_tiled/Greysphere_Calibration_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_brass_tiled/Greysphere_Calibration_ps.glsl @@ -1765,10 +1765,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_brass_tiled/Tiled_Brass_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_brass_tiled/Tiled_Brass_ps.glsl index c2bf52b2ce..4dfddf21ed 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_brass_tiled/Tiled_Brass_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_brass_tiled/Tiled_Brass_ps.glsl @@ -1744,10 +1744,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_wood_tiled/Greysphere_Calibration_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_wood_tiled/Greysphere_Calibration_ps.glsl index 7317776041..f227f0403d 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_wood_tiled/Greysphere_Calibration_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_wood_tiled/Greysphere_Calibration_ps.glsl @@ -1765,10 +1765,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_wood_tiled/Tiled_Wood_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_wood_tiled/Tiled_Wood_ps.glsl index a7410ef4a6..85b51f6a21 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_wood_tiled/Tiled_Wood_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_look_wood_tiled/Tiled_Wood_ps.glsl @@ -1745,10 +1745,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_marble_solid/Marble_3D_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_marble_solid/Marble_3D_ps.glsl index dd36078d24..98b0abf425 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_marble_solid/Marble_3D_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_marble_solid/Marble_3D_ps.glsl @@ -2416,10 +2416,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_metal_brushed/Metal_Brushed_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_metal_brushed/Metal_Brushed_ps.glsl index 924862274c..e88d46bf59 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_metal_brushed/Metal_Brushed_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_metal_brushed/Metal_Brushed_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_onyx_hextiled/M_OnyxHextiled_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_onyx_hextiled/M_OnyxHextiled_ps.glsl index babdddf9c1..3d0d1a5d40 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_onyx_hextiled/M_OnyxHextiled_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_onyx_hextiled/M_OnyxHextiled_ps.glsl @@ -1934,10 +1934,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_plastic/Plastic_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_plastic/Plastic_ps.glsl index 80755eb5f1..265faae321 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_plastic/Plastic_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_plastic/Plastic_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_thin_film/ThinFilm_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_thin_film/ThinFilm_ps.glsl index 9cae6b3246..af9b1ab421 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_thin_film/ThinFilm_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_thin_film/ThinFilm_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_velvet/Velvet_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_velvet/Velvet_ps.glsl index 6048c5687a..f5fa219307 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_velvet/Velvet_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_velvet/Velvet_ps.glsl @@ -1638,10 +1638,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale; diff --git a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_wood_tiled/Tiled_Wood_ps.glsl b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_wood_tiled/Tiled_Wood_ps.glsl index a7410ef4a6..85b51f6a21 100644 --- a/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_wood_tiled/Tiled_Wood_ps.glsl +++ b/contrib/tests/metashade_ref/renders/standard_surface/aswf/standard_surface_wood_tiled/Tiled_Wood_ps.glsl @@ -1745,10 +1745,12 @@ void mx_metashade_standard_surface_bsdf(ClosureData closureData, float base, vec vec3 coat_affected_subsurface_color = pow(clamp(subsurface_color, 0.0, 1.0), coat_gamma); // // Diffuse BSDF (Oren-Nayar) + // `energy_compensation=false` to match the Standard Surface spec, + // instead of the more physically-correct `true` in OpenPBR BSDF diffuse_bsdf; diffuse_bsdf.response = vec3(0.0, 0.0, 0.0); diffuse_bsdf.throughput = vec3(1.0, 1.0, 1.0); - mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, true, diffuse_bsdf); + mx_oren_nayar_diffuse_bsdf(closureData, base, coat_affected_diffuse_color, diffuse_roughness, normal, false, diffuse_bsdf); // // Subsurface scattering vec3 subsurface_radius_scaled = subsurface_radius * subsurface_scale;