-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from quadproduction/enhancement/280-fixbrushed…
…metal-shader Add fixstudio custom arnold shaders for maya
- Loading branch information
Showing
6 changed files
with
1,651 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
[node fixBrushedMetalNormal] | ||
maya.name STRING "fixBrushedMetalNormal" | ||
maya.id INT 0x00010001 | ||
maya.classification STRING "utility/color" | ||
maya.output_name STRING "outNormal" | ||
maya.output_shortname STRING "out" | ||
|
||
[attr map_type] | ||
min INT 0 | ||
max INT 2 | ||
|
||
[attr pattern_type] | ||
min INT 0 | ||
max INT 2 | ||
|
||
[attr scale] | ||
min FLOAT 0 | ||
softmax FLOAT 1000 | ||
|
||
[attr slit_length_min] | ||
min FLOAT 0 | ||
softmax FLOAT 100 | ||
|
||
[attr slit_length_max] | ||
min FLOAT 0 | ||
softmax FLOAT 100 | ||
|
||
[attr slit_depth_min] | ||
min FLOAT 0 | ||
softmax FLOAT 2 | ||
|
||
[attr slit_depth_max] | ||
min FLOAT 0 | ||
softmax FLOAT 1 | ||
|
||
[attr slit_width] | ||
min FLOAT 0 | ||
max FLOAT 1 | ||
|
||
[attr noise_frequency] | ||
min FLOAT 0 | ||
softmax FLOAT 10 | ||
|
||
[attr noise_amplitude] | ||
min FLOAT 0 | ||
softmax FLOAT 1 | ||
|
||
[attr angle_randomness] | ||
min FLOAT 0 | ||
max FLOAT 1 | ||
|
||
[attr layers] | ||
min INT 1 | ||
softmax INT 100 | ||
|
||
[attr slit_profile] | ||
min INT 0 | ||
max INT 2 | ||
|
230 changes: 230 additions & 0 deletions
230
host/maya/custom_arnold_shaders/fixBrushedMetalNormal.osl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
/* | ||
* Brushed metal normal map | ||
* | ||
* This creates an Arnold node that outputs a customizable, procedural brushed | ||
* metal normal map | ||
*/ | ||
|
||
// UTILITY FUNCTIONS | ||
|
||
/* | ||
* normal_to_rgb - convert a unit vector to a valid RGB value | ||
*/ | ||
color normal_to_rgb(normal n) { | ||
return .5 + .5 * color(n); | ||
} | ||
|
||
/* | ||
* depth_to_rgb - transforms range [-depth_max, 0] to [0, 1] for use as an RGB map | ||
*/ | ||
color depth_to_rgb(float d, float depth_max) { | ||
return color(1 + d / depth_max); | ||
} | ||
|
||
// SLIT PROFILE FUNCTIONS | ||
/* | ||
* v_slit_normal - takes in UV values inside a given slit, | ||
* and returns the normal corresponding to a V profile | ||
* with d0 as its maximum depth | ||
* and l0 as its slit length. | ||
*/ | ||
normal v_slit_normal(float u, float v, float l0, float d0) { | ||
normal n = normal(0, v > 0 ? -d0 : d0, 1); | ||
n /= length(n); | ||
return n; | ||
} | ||
|
||
/* | ||
* v_slit_depth - takes in UV values inside a given slit, | ||
* and returns the depth corresponding to a V profile | ||
* with d0 as its maximum depth | ||
* and l0 as its slit length. | ||
*/ | ||
float v_slit_depth(float u, float v, float l0, float d0) { | ||
return (abs(v / l0) - 1) * d0; | ||
} | ||
|
||
/* | ||
* x2_slit_normal - takes in UV values inside a given slit, | ||
* and returns the normal corresponding to a parabola profile | ||
* with d0 as its maximum depth | ||
* and l0 as its slit length. | ||
*/ | ||
normal x2_slit_normal(float u, float v, float l0, float d0) { | ||
float frac = v / l0; | ||
float dfdv = 2 * d0 * frac; | ||
|
||
normal n = normal(0, -dfdv, 1); | ||
n /= length(n); | ||
return n; | ||
} | ||
|
||
/* | ||
* x2_slit_depth - takes in UV values inside a given slit, | ||
* and returns the depth corresponding to a parabola profile | ||
* with d0 as its maximum depth | ||
* and l0 as its slit length. | ||
*/ | ||
float x2_slit_depth(float u, float v, float l0, float d0) { | ||
float frac = v / l0; | ||
return (frac * frac - 1) * d0; | ||
} | ||
|
||
/* | ||
* random_slit_normal - UNUSED; returns a random normal inside a slit | ||
*/ | ||
normal random_slit_normal(float u, float v, float l0, float d0) { | ||
float rnd_angle = noise(v) * M_PI; | ||
return normal(0, cos(rnd_angle), sin(rnd_angle)); | ||
} | ||
|
||
// UV TRANSFORM FUNCTIONS | ||
/* | ||
* use UV as cartesian coordinates, with du and dv representing the local derivatives of UVs | ||
*/ | ||
void transform_uvs_linear(output float u, output float v, | ||
output vector du, output vector dv) { | ||
du = vector(1, 0, 0); | ||
dv = vector(0, 1, 0); | ||
} | ||
|
||
/* | ||
* use UV as polar coordinates, with du and dv representing the local derivatives of UVs | ||
*/ | ||
void transform_uvs_circular(output float u, output float v, | ||
output vector du, output vector dv) { | ||
u = 2 * u - 1; | ||
v = 2 * v - 1; | ||
float r = sqrt(u * u + v * v); | ||
float theta = atan2(v, u); | ||
float inv_r = 1 / r; | ||
float cosTheta = u * inv_r; | ||
float sinTheta = v * inv_r; | ||
|
||
du = vector(-sinTheta, cosTheta, 0); | ||
dv = vector(cosTheta, sinTheta, 0); | ||
|
||
u = theta / M_2PI; | ||
v = r; | ||
} | ||
|
||
// MAIN FUNCTION | ||
shader fixBrushedMetalNormal( | ||
int map_type = 0 [[ string widget = "popup", string options = "Normal|Depth" ]], | ||
int pattern_type = 0 [[ string widget = "popup", string options = "Linear|Circular" ]], | ||
float scale = 500, // scales u and v | ||
float slit_length_min = 5, // scales u only (min) | ||
float slit_length_max = 5, // scales u only (max) | ||
float slit_depth_min = .5, // depth of each slit (min), | ||
float slit_depth_max = .5, // depth of each slit (max), | ||
float slit_width = .5, // width of each slit, 0 < slit_width < 1 | ||
int slit_profile = 0 [[ string widget = "popup", string options = "Parabola|V-shape|Random" ]], // 0: x^2, 1: |x|, 3: random | ||
float noise_frequency = 1, // frequency of the UV perturbation | ||
float noise_amplitude = .1, // amplitude of the UV perturbation | ||
float angle_randomness = 0, | ||
int seed = 0, // random seed | ||
int layers = 1, // scratch passes | ||
string version = "1.1", | ||
// version is not an actual parameter, should be left unchanged by the user (found no cleaner way to do this) | ||
output color Cout = color(.5, .5, 1)) | ||
{ | ||
vector du, dv; // unit vectors that describe the local orientation of u and v | ||
if (pattern_type == 0) { | ||
transform_uvs_linear(u, v, du, dv); | ||
} else if (pattern_type == 1) { | ||
transform_uvs_circular(u, v, du, dv); | ||
} else { | ||
return; | ||
} | ||
|
||
// map u and v to range [-1, 1] | ||
float global_u = scale * (2 * u - 1); | ||
float global_v = scale * (2 * v - 1); | ||
|
||
// add noise to the texture coordinates so as to make the slits less perfect | ||
vector perturbation = noise_amplitude * | ||
noise("perlin", vector(seed, | ||
global_u * noise_frequency, | ||
global_v * noise_frequency)); | ||
|
||
global_u += perturbation[0]; | ||
global_v += perturbation[1]; | ||
|
||
if (map_type == 0) | ||
Cout = normal_to_rgb(normal(0, 0, 1)); | ||
else if (map_type == 1) | ||
Cout = depth_to_rgb(0, 1); | ||
|
||
|
||
// create slit layers | ||
for (int layer_seed = seed * layers; layer_seed < (seed + 1) * layers; layer_seed++) { | ||
/* -- rotate each layer randomly -- */ | ||
|
||
float random_angle = (2 * cellnoise(layer_seed, 0) - 1) * M_PI_2 * angle_randomness; | ||
float random_cos = cos(random_angle); | ||
float random_sin = sin(random_angle); | ||
|
||
float layer_v = global_u * (-random_sin) + global_v * random_cos; | ||
float layer_u = global_u * random_cos + global_v * random_sin; | ||
|
||
vector layer_du = du * random_cos + dv * random_sin; | ||
vector layer_dv = du * (-random_sin) + dv * random_cos; | ||
|
||
/* -- randomly shift columns based on the current layer -- */ | ||
layer_v += scale * cellnoise(layer_seed, 1); | ||
|
||
/* -- randomize slit length -- */ | ||
|
||
// random number based on layer and current row | ||
float rnd = cellnoise(point( | ||
layer_seed, | ||
layer_v, | ||
0) | ||
); | ||
float length_here = slit_length_min + rnd * (slit_length_max - slit_length_min); | ||
layer_u /= length_here; | ||
|
||
/* -- randomly shift rows -- */ | ||
|
||
// shift each row by a random amount in order to avoid having a visible normal discontinuity | ||
float period = 2 * scale / length_here; // the maximum value of layer_u, assuming u is in range[0, 1] | ||
layer_u = mod(layer_u + period * cellnoise(layer_seed, layer_v), | ||
period); | ||
|
||
|
||
float rnd_cells = cellnoise(point(layer_u, layer_v, layer_seed), 1); | ||
float depth_here = slit_depth_min + cellnoise(point(layer_u, layer_v, layer_seed), 2) * (slit_depth_max - slit_depth_min); | ||
|
||
float density = .2; | ||
|
||
if (rnd_cells < density) { // keep "density" % of cells | ||
float slit_u = 2 * mod(layer_u, 1) - 1; | ||
float slit_v = 2 * mod(layer_v, 1) - 1; | ||
|
||
// In radial mode, scale slits to have a uniform width | ||
if (pattern_type == 2) { | ||
slit_v *= u; | ||
} | ||
if (abs(slit_v) < slit_width) { | ||
normal n; | ||
float d = 0; | ||
if (slit_profile == 0) { | ||
n = x2_slit_normal(slit_u, slit_v, slit_width, depth_here); | ||
d = x2_slit_depth(slit_u, slit_v, slit_width, depth_here); | ||
} else if (slit_profile == 1) { | ||
n = v_slit_normal(slit_u, slit_v, slit_width, depth_here); | ||
d = v_slit_depth(slit_u, slit_v, slit_width, depth_here); | ||
} else if (slit_profile == 2) { | ||
n = random_slit_normal(slit_u, slit_v, slit_width, depth_here); | ||
d = x2_slit_depth(slit_u, slit_v, slit_width, depth_here); | ||
} | ||
if (map_type == 0) | ||
Cout = normal_to_rgb( | ||
n[0] * layer_du + n[1] * layer_dv + n[2] * vector(0, 0, 1) | ||
); | ||
else if (map_type == 1) | ||
Cout = depth_to_rgb(d, slit_depth_max); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.