// Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved. // // NVIDIA CORPORATION and its licensors retain all intellectual property // and proprietary rights in and to this software, related documentation // and any modifications thereto. Any use, reproduction, disclosure or // distribution of this software and related documentation without an express // license agreement from NVIDIA CORPORATION is strictly prohibited. mdl 1.6; import ::anno::*; import ::base::*; import ::math::*; import ::state::*; import ::tex::*; export using ::base import texture_return; // Returns the normal n in tangent space, given n is in internal space. float3 transform_internal_to_tangent(float3 n) { return n.x * float3(state::texture_tangent_u(0).x, state::texture_tangent_v(0).x, state::normal().x) + n.y * float3(state::texture_tangent_u(0).y, state::texture_tangent_v(0).y, state::normal().y) + n.z * float3(state::texture_tangent_u(0).z, state::texture_tangent_v(0).z, state::normal().z); } // 3dsmax Bitmap Transformation Matrix uniform float4x4 max_rotation_translation_scale ( uniform float3 rotation = float3(0.) [[ anno::description("Rotation applied to every UVW coordinate") ]], uniform float3 translation = float3(0.) [[ anno::description("Offset applied to every UVW coordinate") ]], uniform float3 scaling = float3(1.) [[ anno::description("Scale applied to every UVW coordinate") ]], uniform bool u_mirror = false [[ anno::description("Mirror repeat has twice the number of textures in the same space") ]], uniform bool v_mirror = false [[ anno::description("Mirror repeat has twice the number of textures in the same space") ]] ) [[ anno::description("Construct transformation matrix from Euler rotation, translation and scale") ]] { float4x4 scale = float4x4(u_mirror?scaling.x*2.:scaling.x , 0. , 0. , 0., 0. , v_mirror?scaling.y*2.:scaling.y , 0. , 0., 0. , 0. , scaling.z , 0., u_mirror?1.:.5 , v_mirror?1.:.5 , .5 , 1.); float4x4 translate = float4x4(1. , 0. , 0. , 0., 0. , 1. , 0. , 0., 0. , 0. , 1. , 0., -0.5-translation.x, -0.5-translation.y, -0.5-translation.z, 1.); // Euler rotation matrix xyz order float3 s = math::sin(rotation); float3 c = math::cos(rotation); float4x4 rotate = float4x4( c.y*c.z , c.y*s.z , -s.y , 0.0, -c.x*s.z + s.x*s.y*c.z, c.x*c.z + s.x*s.y*s.z , s.x*c.y , 0.0, s.x*s.z + c.x*s.y*c.z , -s.x*c.z + c.x*s.y*s.z, c.x*c.y , 0.0, 0. , 0. , 0. , 1.); return scale *rotate*translate; } export enum vray_color_mode [[ anno::hidden() ]] { mode_color, mode_temperature }; export enum vray_color_primaries [[ anno::hidden() ]] { primaries_none, primaries_sRGB, primaries_ACEScg }; export enum vray_bitmap_primaries [[ anno::hidden() ]] { bm_primaries_default, bm_primaries_sRGB, bm_primaries_ACEScg, bm_primaries_raw }; export enum vray_rgb_output [[ anno::hidden() ]] { rgb_output_rgb_color, rgb_output_alpha_as_grey, rgb_output_intensity_as_grey }; export enum vray_mono_output [[ anno::hidden() ]] { mono_output_rgb_intensity, mono_output_alpha }; export enum vray_alpha_source [[ anno::hidden() ]] { alpha_source_image_alpha, alpha_source_intensity, alpha_source_opaque }; // VRayBitmap map export texture_return VRayBitmap ( // UVW Coordinates uniform int mapChannel=1 [[ anno::in_group("Coordinates"), anno::display_name("Map channel") ]], uniform float U_Offset = 0.f [[ anno::in_group("Coordinates"), anno::display_name("U Offset") ]], uniform float V_Offset = 0.f [[ anno::in_group("Coordinates"), anno::display_name("V Offset") ]], uniform float U_Tiling = 1.f [[ anno::in_group("Coordinates"), anno::display_name("U Tiling") ]], uniform float V_Tiling = 1.f [[ anno::in_group("Coordinates"), anno::display_name("V Tiling") ]], uniform bool U_Tile=true //it is actually an error if both mirror and tile are true [[ anno::in_group("Coordinates"), anno::display_name("U Tile") ]], uniform bool U_Mirror=false [[ anno::in_group("Coordinates"), anno::display_name("U Mirror") ]], uniform bool V_Tile=true [[ anno::in_group("Coordinates"), anno::display_name("V Tile") ]], uniform bool V_Mirror=false [[ anno::in_group("Coordinates"), anno::display_name("V Mirror") ]], uniform float U_angle = 0.f [[ anno::in_group("Coordinates"), anno::display_name("U Angle") ]], uniform float V_angle = 0.f [[ anno::in_group("Coordinates"), anno::display_name("V Angle") ]], uniform float W_angle = 0.f [[ anno::in_group("Coordinates"), anno::display_name("W Angle") ]], uniform int UVW_Type = 0 //enum? [[ anno::in_group("Coordinates"), anno::display_name("UVW Type"), anno::unused(), anno::hidden() ]], // Bitmap uniform texture_2d filename = texture_2d() [[ anno::in_group("Bitmap parameters"), anno::display_name("Bitmap") ]], uniform float multiplier = 1.f [[ anno::in_group("Bitmap parameters"), anno::display_name("Overall multiplier") ]], uniform vray_rgb_output rgb_output = rgb_output_rgb_color [[ anno::in_group("Bitmap parameters"), anno::display_name("RGB output") ]], uniform vray_mono_output mono_output = mono_output_rgb_intensity [[ anno::in_group("Bitmap parameters"), anno::display_name("Mono output") ]], uniform vray_alpha_source alpha_source = alpha_source_image_alpha [[ anno::in_group("Bitmap parameters"), anno::display_name("Alpha source") ]], uniform vray_bitmap_primaries rgb_primaries = bm_primaries_raw [[ anno::in_group("Bitmap parameters"), anno::display_name("RGB primaries"), anno::unused(), anno::hidden() ]], uniform bool crop_enable = false [[ anno::in_group("Bitmap parameters"), anno::display_name("Crop") ]], uniform float crop_u = 0.f //u+w and v+h are always <=1.0 [[ anno::in_group("Bitmap parameters"), anno::display_name("U Crop"), anno::hard_range(0.f, 1.f) ]], uniform float crop_w = 1.f [[ anno::in_group("Bitmap parameters"), anno::display_name("W Crop"), anno::hard_range(0.f, 1.f) ]], uniform float crop_v = 0.f [[ anno::in_group("Bitmap parameters"), anno::display_name("V Crop"), anno::hard_range(0.f, 1.f) ]], uniform float crop_h = 1.f [[ anno::in_group("Bitmap parameters"), anno::display_name("H Crop"), anno::hard_range(0.f, 1.f) ]], // Output uniform float bump_amount = 1.f [[ anno::in_group("Output"), anno::display_name("Bump amount"), anno::unused(), anno::hidden() ]], uniform bool clamp = false [[ anno::in_group("Output"), anno::display_name("Clamp"), anno::unused(), anno::hidden() ]], uniform bool invert = false [[ anno::in_group("Output"), anno::display_name("Invert") ]], uniform bool alphaFromRGB = false [[ anno::in_group("Output"), anno::display_name("Alpha from RGB intensity"), anno::unused(), anno::hidden() ]], uniform float output_amount = 1.f [[ anno::in_group("Output"), anno::display_name("Output amount") ]], uniform float rgb_level = 1.f [[ anno::in_group("Output"), anno::display_name("RGB level") ]], uniform float rgb_offset = 0.f [[ anno::in_group("Output"), anno::display_name("RGB Offset") ]] ) [[ anno::author("NVIDIA Corporation") ]] { uniform float clip_u = crop_enable ? crop_u : 0.f; uniform float clip_w = crop_enable ? crop_w : 1.f; uniform float clip_v = crop_enable ? crop_v : 0.f; uniform float clip_h = crop_enable ? crop_h : 1.f; texture_return bitmap_sample = base::file_texture ( texture : filename, mono_source : (alpha_source == alpha_source_image_alpha) ? base::mono_alpha : base::mono_average, crop_u : float2(clip_u, clip_w + clip_u), crop_v : float2(1.f - clip_v - clip_h, 1.f - clip_v), uvw : base::transform_coordinate ( transform : max_rotation_translation_scale ( scaling : float3(U_Tiling, V_Tiling, 1.f), rotation : float3(U_angle, V_angle, W_angle)/180.f*math::PI , translation : float3(U_Offset, V_Offset, 0.f), u_mirror : U_Mirror, v_mirror : V_Mirror ), coordinate : base::coordinate_source(texture_space: mapChannel-1) ), wrap_u : U_Tile ? tex::wrap_repeat : U_Mirror ? tex::wrap_mirrored_repeat : tex::wrap_clip, wrap_v : V_Tile ? tex::wrap_repeat : V_Mirror ? tex::wrap_mirrored_repeat : tex::wrap_clip ); bitmap_sample.tint = invert ? bitmap_sample.tint * (-rgb_level * output_amount * multiplier ) + (1.f - rgb_offset) : bitmap_sample.tint * (rgb_level * output_amount * multiplier) + rgb_offset; float alpha = (alpha_source != alpha_source_opaque) ? bitmap_sample.mono : 1.f; bitmap_sample.tint = bitmap_sample.tint*alpha; // determinate mono output if(mono_output == mono_output_alpha) bitmap_sample.mono = alpha; else bitmap_sample.mono = math::average(bitmap_sample.tint); // determinate rgb output if(rgb_output == rgb_output_alpha_as_grey) bitmap_sample.tint = color(alpha); else if(rgb_output == rgb_output_intensity_as_grey) bitmap_sample.tint = color(math::average(bitmap_sample.tint)); return bitmap_sample; } // VRayBitmap Map for Bump export float3 VRayBitmap_bump ( // UVW Coordinates uniform int mapChannel=1 [[ anno::in_group("Coordinates"), anno::display_name("Map channel") ]], uniform bool U_Tile=true [[ anno::in_group("Coordinates"), anno::display_name("U Tile") ]], uniform bool U_Mirror=false [[ anno::in_group("Coordinates"), anno::display_name("U Mirror") ]], uniform bool V_Tile=true [[ anno::in_group("Coordinates"), anno::display_name("V Tile") ]], uniform bool V_Mirror=false [[ anno::in_group("Coordinates"), anno::display_name("V Mirror") ]], uniform float U_angle = 0.f [[ anno::in_group("Coordinates"), anno::display_name("U Angle") ]], uniform float V_angle = 0.f [[ anno::in_group("Coordinates"), anno::display_name("V Angle") ]], uniform float W_angle = 0.f [[ anno::in_group("Coordinates"), anno::display_name("W Angle") ]], uniform float U_Offset = 0.f [[ anno::in_group("Coordinates"), anno::display_name("U Offset") ]], uniform float V_Offset = 0.f [[ anno::in_group("Coordinates"), anno::display_name("V Offset") ]], uniform float U_Tiling = 1.f [[ anno::in_group("Coordinates"), anno::display_name("U Tiling") ]], uniform float V_Tiling = 1. [[ anno::in_group("Coordinates"), anno::display_name("V Tiling") ]], uniform int UVW_Type = 0 //enum? [[ anno::in_group("Coordinates"), anno::display_name("UVW Type"), anno::unused() ]], // Bitmap uniform texture_2d filename = texture_2d() [[ anno::in_group("Bitmap parameters"), anno::display_name("Bitmap") ]], uniform bool crop_enable = false [[ anno::in_group("Bitmap parameters"), anno::display_name("Crop") ]], uniform float crop_u = 0.f //u+w and v+h are always <=1.0 [[ anno::in_group("Bitmap parameters"), anno::display_name("U Crop"), anno::hard_range(0.f, 1.f) ]], uniform float crop_w = 1.f [[ anno::in_group("Bitmap parameters"), anno::display_name("W Crop"), anno::hard_range(0.f, 1.f) ]], uniform float crop_v = 0.f [[ anno::in_group("Bitmap parameters"), anno::display_name("V Crop"), anno::hard_range(0.f, 1.f) ]], uniform float crop_h = 1.f [[ anno::in_group("Bitmap parameters"), anno::display_name("H Crop"), anno::hard_range(0.f, 1.f) ]], uniform float factor = 1.f [[ anno::in_group("Bitmap parameters"), anno::display_name("Bump amount") ]], // Output uniform float bump_amount = 1.f [[ anno::in_group("Output"), anno::display_name("Bump output") ]], uniform bool clamp = false [[ anno::in_group("Output"), anno::display_name("Clamp"), anno::unused() ]], uniform bool invert = false [[ anno::in_group("Output"), anno::display_name("Invert") ]], uniform bool alphaFromRGB = false [[ anno::in_group("Output"), anno::display_name("Alpha from RGB intensity"), anno::unused() ]], uniform float output_amount = 1.f [[ anno::in_group("Output"), anno::display_name("Output amount"), anno::unused() ]], uniform float rgb_level = 1.f [[ anno::in_group("Output"), anno::display_name("RGB level"), anno::unused() ]], uniform float rgb_offset = 0.f [[ anno::in_group("Output"), anno::display_name("RGB Offset"), anno::unused() ]] ) [[ anno::author("NVIDIA Corporation") ]] { uniform float clip_u = crop_enable ? crop_u : 0.f; uniform float clip_w = crop_enable ? crop_w : 1.f; uniform float clip_v = crop_enable ? crop_v : 0.f; uniform float clip_h = crop_enable ? crop_h : 1.f; return base::file_bump_texture ( texture : filename, crop_u : float2(clip_u, clip_w + clip_u), crop_v : float2(1.f - clip_v - clip_h, 1.f - clip_v), uvw : base::transform_coordinate ( transform : max_rotation_translation_scale ( scaling : float3(U_Tiling, V_Tiling, 1.f), rotation : float3(U_angle, V_angle,W_angle)/(180.*math::PI), translation : float3(U_Offset, V_Offset, 0.f), u_mirror : U_Mirror, v_mirror : V_Mirror ), coordinate : base::coordinate_source(texture_space: mapChannel - 1) ), wrap_u : U_Tile ? tex::wrap_repeat : U_Mirror ? tex::wrap_mirrored_repeat : tex::wrap_clip, wrap_v : V_Tile ? tex::wrap_repeat : V_Mirror ? tex::wrap_mirrored_repeat : tex::wrap_clip, factor : invert ? -10.f*factor*bump_amount : 10.f*factor*bump_amount ); } // VRayBump2Normal Map for Bump export enum vray_bump2normal_mode [[ anno::hidden() ]] { b2n_tangent_space, b2n_local_XYZ, b2n_screen_space, b2n_world_space }; export texture_return VRayBump2Normal ( float3 bump_map = state::normal() [[ anno::in_group("Parameters"), anno::display_name("Bump map") ]], uniform float bump_map_mult = 100.f [[ anno::in_group("Parameters"), anno::display_name("Bump map multiplier"), anno::hard_range(0.f, 100.f) ]], uniform vray_bump2normal_mode mode = b2n_tangent_space [[ anno::in_group("Parameters"), anno::display_name("Mode"), anno::unused(), anno::hidden() ]], uniform int map_channel=1 [[ anno::in_group("Coordinates"), anno::display_name("Map channel"), anno::unused(), anno::hidden() ]] ) [[ anno::author("NVIDIA Corporation") ]] { texture_return normal_tex; float3 normal_tangent_space = transform_internal_to_tangent(math::normalize(state::normal() + (bump_map - state::normal())*(bump_map_mult*0.01f))); normal_tex.tint = color( (normal_tangent_space + float3(1.f))*0.5f ); normal_tex.mono = 1.f; return normal_tex; } // VRayColor Map export texture_return VRayColor ( uniform vray_color_mode color_mode = mode_color [[ anno::in_group("VRayColor Parameters"), anno::display_name("Color mode") ]], uniform float temperature = 6500.f [[ anno::in_group("VRayColor Parameters"), anno::display_name("Temperature"), anno::hard_range(350.f, 1000000000.f) ]], uniform float red = 0.5f [[ anno::in_group("VRayColor Parameters"), anno::display_name("Red"), anno::soft_range(0.f, 1.f) ]], uniform float green = 0.5f [[ anno::in_group("VRayColor Parameters"), anno::display_name("Green"), anno::soft_range(0.f, 1.f) ]], uniform float blue = 0.5f [[ anno::in_group("VRayColor Parameters"), anno::display_name("Blue"), anno::soft_range(0.f, 1.f) ]], uniform float rgb_multiplier = 1.f [[ anno::in_group("VRayColor Parameters"), anno::display_name("RGB Multiplier") ]], uniform float alpha = 1.f [[ anno::in_group("VRayColor Parameters"), anno::display_name("Alpha"), anno::hard_range(0.f, 1.f) ]], uniform float color_gamma = 1.0f [[ anno::in_group("VRayColor Parameters"), anno::display_name("Color gamma"), anno::hard_range(0.05f, 20.f) ]], uniform vray_color_primaries rgb_primaries = primaries_none [[ anno::in_group("VRayColor Parameters"), anno::display_name("RGB primaries"), anno::unused(), anno::hidden() ]] ) [[ anno::author("NVIDIA Corporation") ]] { float3 rgb(red, green, blue); // using temperature?. Then convert from Kelvin to RGB if(color_mode == mode_temperature) { float k = temperature*0.01f; // red if (temperature < 6600.f) { rgb.x = 1.f; } else { float r = k - 55.f; r = (351.9769f + 0.1142f * r - 40.2537f * math::log(r))/255.f; rgb.x = math::clamp(r, 0.f, 1.f); } // green if (temperature < 6600.f) { float g = k - 2.f; g = (-155.2549f - 0.4460f * g + 104.4922f * math::log(g))/255.f; rgb.y = math::clamp(g, 0.f, 1.f); } else { float g = k - 50.f; g = (325.4494f + 0.0794f * g - 28.0853f * math::log(g))/255.f; rgb.y = math::clamp(g, 0.f, 1.f); } // blue if (temperature >= 6600.f) { rgb.z = 1.f; } else if (temperature <= 2000.f) { rgb.z = 0.f; } else { float b = k - 10.f; b = (-254.7694f + 0.8274f * blue + 115.6799f * math::log(b))/255.f; rgb.z = math::clamp(b, 0.f, 1.f); } } // apply gamma if(color_gamma != 1.f) rgb = math::pow(rgb, 1.f/color_gamma); // apply multiplier rgb *= rgb_multiplier; // fix ranges and return rgb = math::clamp(rgb, 0.f, 1.f); return texture_return(color(rgb), alpha); } // VRayColor Map for Bump export float3 VRayColor_bump ( ) [[ anno::author("NVIDIA Corporation") ]] { return state::normal(); } // VRayColor2Bump Map for Bump export float3 VRayColor2Bump_bump ( float3 map = state::normal() [[ anno::in_group("Parameters"), anno::display_name("Bump map") ]], uniform float height = 2.0f [[ anno::in_group("Parameters"), anno::display_name("Height"), anno::unused(), anno::hidden() ]], uniform float bump_delta_scale = 1.0f [[ anno::in_group("Parameters"), anno::display_name("Bump delta scale"), anno::unused(), anno::hidden(), anno::hard_range(0.f, 1.f) ]] ) [[ anno::author("NVIDIA Corporation") ]] { return map; } // VRay Dirt Map export texture_return VRayDirt ( float radius = 10.f [[ anno::in_group("VRayDirt Parameters"), anno::display_name("Radius"), anno::unused(), anno::hidden() ]], color occluded_color = color(0.f) [[ anno::in_group("VRayDirt Parameters"), anno::display_name("Occluded color"), anno::unused(), anno::hidden() ]], color unoccluded_color = color(1.f) [[ anno::in_group("VRayDirt Parameters"), anno::display_name("Unoccluded color") ]] ) [[ anno::author("NVIDIA Corporation") ]] { return texture_return(unoccluded_color, 1.f); } // VRay Edges Tex Map export texture_return VRayEdgesTex ( color edges_color = color(1.f) [[ anno::in_group("VRayEdgesTex params"), anno::display_name("Color") ]] ) [[ anno::author("NVIDIA Corporation") ]] { return texture_return(edges_color, 1.f); } // VRay Edges Tex Map for bump export float3 VRayEdgesTex_bump ( color edges_color = color(1.f) [[ anno::in_group("VRayEdgesTex params"), anno::display_name("Color"), anno::unused(), anno::hidden() ]], uniform float radius = 0.1f [[ anno::in_group("VRayEdgesTex params"), anno::display_name("Radius"), anno::hard_range(0.f, 100.f) ]], uniform bool same_object_only = true [[ anno::in_group("VRayEdgesTex params"), anno::display_name("Consider same object only") ]], uniform int corners_mode = 0 [[ anno::in_group("VRayEdgesTex params"), anno::display_name("Corners"), anno::unused(), anno::hidden() ]], float multiplier = 1.f [[ anno::in_group("VRayEdgesTex params"), anno::display_name("Multiplier"), anno::unused(), anno::hidden() ]] ) [[ anno::author("NVIDIA Corporation") ]] { return state::rounded_corner_normal(radius*state::meters_per_scene_unit(), !same_object_only); } // VRay Normap Map for bump export float3 VRayNormalMap_bump ( texture_return normal_map = texture_return() [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Normal map") ]], float3 bump_map = state::normal() [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Bump map") ]], uniform float normal_amount = 1.f [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Normal amount"), anno::hard_range(-1000.f, 1000.f) ]], uniform float bump_amount = 1.f [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Bump amount"), anno::hard_range(-1000.f, 1000.f) ]], uniform bool flip_red = false [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Flip red") ]], uniform bool flip_green = false [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Flip green") ]], uniform bool swap_rg = false [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Swap red and green") ]], uniform int map_channel = 1 [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Map channel"), anno::hidden(), anno::unused() ]], uniform float map_rotation = 0.f [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Map rotation"), anno::hard_range(0.f, 360.f), anno::hidden(), anno::unused() ]], uniform float normal_map_amount = 1.0f [[ anno::in_group("VRayNormalMap Parameters"), anno::display_name("Map amount"), anno::hard_range(-10.f, 10.f) ]] ) [[ anno::author("NVIDIA Corporation") ]] { float3 tangent_space_normal = float3(normal_map.tint); if(flip_red) tangent_space_normal.x = 1.f - tangent_space_normal.x; if(flip_green) tangent_space_normal.y = 1.f - tangent_space_normal.y; if(swap_rg) { float tmp = tangent_space_normal.x; tangent_space_normal.x = tangent_space_normal.y; tangent_space_normal.y = tmp; } float normal_factor = normal_amount*(normal_map_amount); tangent_space_normal = (tangent_space_normal - float3(0.5f))*(2.f*normal_factor); float3 mapped_normal = math::normalize( state::texture_tangent_u(0) * tangent_space_normal.x + state::texture_tangent_v(0) * tangent_space_normal.y + state::normal() * (tangent_space_normal.z + (1.f - normal_factor))); float3 bumped_normal = math::normalize(math::lerp(state::normal(), bump_map, bump_amount*normal_map_amount)); return math::normalize(mapped_normal + bumped_normal); }