Shading Joshua Barczak CMSC 435 UMBC et Olano
Shading Joshua Barczak* CMSC 435 UMBC *et Olano et al
Shader: Artist View • An enchanted orb that magically makes things look pretty – Interesting lighting model – Procedurally generated bump/texture
Shader: Engineer View • A small program that runs at each pixel – Input: • • Position, Normal, UV, etc at surface Various constant values Textures Other information (e. g. Light positions) – Output: • Color and opacity
Shader Authoring • Graph-based editing tools – Artists/Designers • Code directly in specialized language – Engineers/TDs – You Unity 3 D Forums
Render. Man Shading Pipeline Displacement Secondary Rays… Surface Light Volume Imager Closest thing we have to an industry standard for offline rendering…
Displacement • Given – Position – Normal • Compute Displacement – Position – Normal Surface Volume Imager Light
Surface color • Given – Position • Compute Displacement Surface Volume Imager Light – Color – Opacity
Lighting • Given – Surface Position Displacement • Compute Surface Volume Imager Light – Light Direction – Light Color
Volume Effects • Given – Position – Color Displacement Surface Volume Imager Light • Compute – New Color
Image Effects • Given – Pixel Color • Compute Displacement Surface Volume Imager Light – Pixel Color
Renderman Shading Language • Data types – float – color – point/vector/normal – string – matrix This lecture is only an overview…. READ…THE…SPEC…!
Some Variable Declarations float foo = 42; point q = point(x, y, z); point r = point(u, v, w); vector v = q – r; color black = 0; color yellow = color “rgb”(255, 0); float array[42];
Renderman Shading Language • Operators – Usual arithmetic • Component-wise for point/vector/color • Point/vector/normal types can be mixed – But not color – ‘. ’ for dot product, ‘^’ for cross product • C-style flow control – If/while/for/etc…
Points/Vectors • Arithmetic: – Vector/vector or vector/scalar • Point/Vector/Normal Semantics – point-point Vector – Mixing types is allowed but discouraged • Component selection with functions: – xcomp(p), setxcomp(p, x);
Points/Vectors • Named coordinate systems – “current”, “object”, “world”, “screen”, etc… • RTM – Functions exist to transform between them – Points/Vectors can have named coord systems • E. g. point origin = point “object”(0, 0, 0); • RSL does not define a default. Pixie uses camera space
Colors • Arithmetic works like you’d expect – Color to color, color to float • Can’t mix colors and points • Component extraction is similar: – comp(color, index) setcomp(color, index)
Functions point midpoint ( point a; point b ) { return 0. 5*(a+b); } void normalize_inplace ( output vector V ) { V = V/length(V); }
Debugging Tricks • Dump values as color: – if(impossible_condition) color = ugly pink • They have printf…
Annoying RSL Quirks • This compiler is not your friend… – Error messages are cryptic – Write your shaders little by little… • Function parameters are semi-colon delimited – float foo( float a; float b ) • Careful with ‘++’ operators
Special Variables • Inputs (RTM for full list) – Cs Surface color (from Ri. Color) – Os Surface opacity (from Ri. Opacity) – P Surface position – N Surface shading normal – u, v Parametric coordinates – s, t Texture coords – E Position of the eye – I Incident ray direction
Special Variables • Outputs (Surface): – Ci Incident ray color – Oi Incident ray opacity • Outputs (Displacement): – P Displaced position – N Displaced normal
Built-in Functions • All the usual math stuff – sin, cos, tan, abs, mod, pow, exp, log, floor, ceil, – round, sqrt, … • Vector: – length/normalize/distance • min/max/clamp • mix(a, b, t) – Does a lerp
Built-in Functions • • • diffuse(N) specular(N, V, roughness) ambient() texture( string name, uv ) environment( string name, uv ) trace()
Built-In Functions • Du(x)/Dv(x) – Partial derivative of x in parametric space • calculatenormal(P) – Compute normal from derivatives of P • Displacement shaders use this Differencing on Micropolygon grid…
Built-In Functions • step(float min, t) – (t<min) ? 0 : 1 • smoothstep(float min, max, t) – 0 if t<min, 1 if t>max. Hermite interpolation in between…
Example surface plastic( float Ka = 1; float Kd =. 5; float Ks =. 5; float roughness =. 1; color specularcolor = 1; ) { normal Nf = faceforward(normalize(N), I); vector V = -normalize(I); Oi = Os; Ci = Os * (Cs * (Ka*ambient() + Kd*diffuse(Nf)) + specularcolor * Ks*specular(Nf, V, roughness) ); }
Example displacement ripple( float amplitude = 1. 0; float wavelength = 0. 25 ) { P += N * amplitude * sin( 2*PI*(s / wavelength) ); N = calculatenormal(P); }
Procedural Texture Generation • An obscure mix of math, science, and black magic • Takes practice and experimentation – Hence, the assignment • I shall now bombard you with examples… – These are only examples, there is no “right” way
Render. Man Brick mortar brick gap height width gap
Brick Shader surface brick( uniform float width =. 2, uniform float height =. 1, uniform float gap =. 05, color brick = color(1, 0, 0), color mortar = color(. 5, . 5) ) { varying color bc; /* compute brick color */ normal Nf = faceforward(normalize(N), I) Oi = Os; Ci = Oi*bc*(ambient()+diffuse(Nf)); }
Brick Color • Where am I in my brick? – “brick coordinates” bs varying float bs, bt; /* compute brick coordinates */ if (bs < width && bt < height) bc = brick; else bc = mortar; bt
Brick Coordinates bt = mod(t, height+gap); bs = s; if (mod( t/(height+gap), 2) >= 1) bs += (width+gap)/2; // shift odd numbered rows bs = mod(bs, width+gap); 2 bt: 0, 1 t/(h+g) height+gap 1 bs: 0, 1 0
Target Shader • Mix and step can be used as selectors • mix(a, b, step(min, x)) is: – A if min> x – Else B x<min x=min x>min
Target Shader surface target ( float Kd = 0. 8; float Ks=0. 8; float roughness=0. 001; ) { color red = color "rgb"(0. 8, 0, 0); color yellow = color "rgb"(0. 8, 0); color white = color "rgb"(1, 1, 1); color blue = color "rgb"(0, 0, 0. 8); float dist = distance( point(u, v, 0), point(0. 5, 0) ); dist = dist / 0. 4; color c. Diff = mix( Cs, yellow, step(dist, 1) ); c. Diff = mix( c. Diff, blue, step(dist, 0. 8) ); c. Diff = mix( c. Diff, white, step(dist, 0. 6) ); c. Diff = mix( c. Diff, red, step(dist, 0. 4) ); normal Nf = faceforward( normalize(N), I ); Ci = c. Diff*Kd*diffuse(Nf) + Ks*specular(Nf, -normalize(I), roughness); Oi = Os; } Do not expect to earn many points if all you do is copy-paste this code…
Tiles
Tiles • Color pattern floor(u), floor(v) float du = 2*abs( 0. 5 - mod(u*sc, 1) ); float dv = 2*abs( 0. 5 - mod(v*sc, 1) ); dv if( (1 -du)<grout || (1 -dv)<grout ) // use grout color else { tu = mod( floor(u*sc), 2 ); tv = mod( floor(v*sc), 2 ); if( tu == tv ) // blue tile else // white tile } du grout -1 3 2 1 0 0 1 2 3 1
Tiles • Displacement – Parabolic function over tile • F(x)=-h(x-1)(x+1) • Peaks to height h at center – Multiply F(du)F(dv) – Clamp to zero at grout – Certainly not your only option…
Noise • Utility function that is: – – – Deterministic Random-looking Locally continuous Band-limited Range: • 0, 1 (Renderman) • -1, 1 (Perlin’s original)
Noise • Value noise – Cubic interpolation between random values
Noise • Gradient Noise (Perlin Noise) – Random gradient vectors Frequency is higher…
Gradient Noise Blend dot products of gradients with offsets from lattice -Crosses zero at lattice See the literature for more detail…
Comparison *2 x lattice density for comparison
Perlin Noise in Render. Man float noise ( float v ), noise ( float u, v ), noise ( point pt ) noise ( point pt, float t ) 1 -4 dimensions. color/point/vector versions available. . .
Perlin Noise in Render. Man surface noisetest(float sc=1) { Ci = float noise(sc*P); } Increasing frequency (sc) 44
Fractional Brownian Motion (f. Bm) // Combine octaves, increasing frequency, decreasing weight for(i=1; i<=octaves; i++, f*=2) Ci += (float noise(f*scale*P)-. 5)/f; Ci +=. 5; “smokey” pattern Increasing octaves 45
Turbulence // Combine octaves, scaled by 1/f for(i=1; i<=octaves; i++, f*=2) Ci += abs(2*float noise(f*scale*P)-1)/f; “billowy” pattern Increasing scale Increasing octaves 46
Solid Texturing Cs = fbm(P)
Solid Texturing Cs = turbulence(P)
Marble
Marble • Start with a boring white fbm pattern – Bias/rescale to taste
Marble • Add stripes – Blend colors with abs(sin(y*sc)) • In this lecture, “sc” means “arbitrary scaling constant” – “Stripe frequency” in this case – “sc” will change from slide to slide. Don’t get confused…
Marble • Add noise to stripes – abs(sin((y+noise)*s)) – Noisy input to sin noisy sine wave – Hmmm, not noisy enough…
Marble • …Lets try lowfrequency FBM instead – Much better… – Hmm, those stripes are aweful thick…
Marble • Raise stripes to a power – Power > 1 Falls off faster from peak – Power < 1 does the opposite – Tweak until you find the right one…
Wood
Wood • Start with Rings – sin waves – Wayyy too thick… • ? ? ? r r = (x^2+y^2) / sc; Ring=2*abs(0. 5 -mod(r, 1));
Wood • Shrink them – Raise to a power… – I don’t like that fuzzy band around the center…? ? ?
Wood • Scale and saturate – saturate(ring*sc) • Saturate means a clamp to 0: 1 range – Scale then saturate creates plateaus in the function
Wood • Next comes the turbulence…
Wood • Soften rings with high frequency noise ring –= 0. 8*noise(P*100)
Wood • Tweak them a little more…
Wood • Transform P in shader to hide the ring origin – Rotate a few times – Translate really far away – To hide the origin of the ring pattern
Granite?
Granite • Turbulent bottom layer
Lumps float lump( float freq; float size ) { return saturate( turb(freq*P)-(1 -size) )/size; } • Subtract the tail of the function, then renormalize the rest – Keeps the peaks
Turbulence Lumps Size=1 (no change) Size=0. 7 Size=0. 5 Size=0. 3
Increasing Frequency Size=0. 7 4 x Freq. Size=0. 3
Granite • Lumpy white spots… – High frequency turb lumps • Use scale/saturate trick to increase contrast – Not dense enough…
Granite • Add a second, shifted copy of the lumps… lumps(P) + lumps(P+offset)
Granite • Use lumps as blend mask mix( base, grey, lump );
Granite • Second set of lumps… – Lower frequency
Granite • Dark spots…
Planet
Planet • Threshold turbulence to create blotchy shapes – 1 -step(turb(P), sc) • Red: – Low frequency continents • Green: – High frequency islands
Planet • Mask out islands far from continents: – Purple continent – Blue: island_mask • Continents at lower threshold • Spreads out more
Planet • Result: – Mix in green using: • saturate(continent + islands*island_mask)
Clouds • Cloud color – 1 -sc*turbulence(P) • Smallish sc • Cloud mask – Fbm lumps, scaled and saturated
Clouds • Combine mix(planet, clouds, cloud_mask)
Bombing
Bombing • Polka dots – Scale UV coordinates – Check distance to each surrounding corner us = floor(u*sc); // top-left corner vs = floor(v*sc); dist = sqrt((u-us)*(u-us)+(v-vs)*(v-vs)); repeat for: us+1, vs us, vs+1 us+1, vs+1 and find the closest corner… 0 1 2
Cellnoise • Another useful builtin function – Float/color/point versions, just like noise… – Discontinuous at integer values, constant in between
Bombing • Use cellnoise to jitter the corners… spot_x += cellnoise( point(spot_x, spot_y, 0. 5) )*0. 5 – 0. 5; spot_y += cellnoise( point(spot_x, spot_y, 1. 5) )*0. 5 - 0. 5;
Bombing • Use more cellnoise to vary the spot size. . . radius *= mix(0. 6, 1. 4, cellnoise(spot));
Bombing • Yet another use for cellnoise… spotcolor = color cellnoise(spot);
Bombing • Add a drop shadow using smoothstep float d = distance(spot, puv) - radius; if( d < 0) c. Diff = spotcolor; else c. Diff = mix( 0, Cs, smoothstep(0, 0. 015, d) );
Bombing • Throw high-frequency noise on the radius – Make it different for each spotnoise = cellnoise(spot); n = noise( theta*sc, spotnoise )-0. 5; radius += radius*n; theta
Cellular Patterns
Cellular Patterns • Use exact same grid • Find first and second nearest points – Search a 4 x 4 neighborhood and sort by distance
Cellular Patterns • Color Cellnoise • At edges, distance to 1 st/2 nd nearest are equal – Use a fuzzy comparison – Mix in white when close enough
Normal Tricks • Displacement: – FBM scaled by y component of normal • (1 -y)^4 • Color – Mix brown/white based on normal Y • Raised to a power • Then, scaled and saturated
- Slides: 90