1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405 |
- /*
- Copyright (c) 2006 soho vfx inc.
- Copyright (c) 2006 The 3Delight Team.
- */
- #ifndef _shading_utils_h
- #define _shading_utils_h
- #include "utils.h"
- #include "global_illumination.h"
- #define NEW_BUMP
- #define SQR(i) ( (i) * (i) )
- #define GET_CL( CL ) { CL = Cl; if( unshadowed != 0 ) \
- lightsource("__3dfm_unshadowed_cl", CL); }
- /*
- ShadingNormal
- A wrapper for faceforward which avoids faceforward for single-sided
- primitives or when using double-sided shading. This is to prevent artefacts
- around silhouette edges caused by the way "Sides 2" is usually shaded. Note
- that we don't explicitely check for double-sided shading as it also sets
- Sides to 1.
- */
- normal ShadingNormal( normal i_N )
- {
- extern vector I;
- normal Nf = i_N;
- uniform float sides = 2;
- attribute("Sides", sides);
- if( sides == 2 )
- {
- Nf = faceforward(Nf, I);
- }
- else
- {
- /* This mess is to flip the normals of polygon meshes with reversed
- orientation. We only want it when 'N' is attached to the primitive. */
- uniform float geometricnormal = 1;
- attribute( "geometry:geometricnormal", geometricnormal );
- if( geometricnormal == 0 )
- {
- uniform string orientation;
- attribute( "Ri:Orientation", orientation );
- if( orientation == "outside" )
- Nf = -Nf;
- }
- }
- return Nf;
- }
- /*
- Maya's ambient function
- */
- color getAmbient( normal i_N; )
- {
- return ambient();
- }
- color getAmbientUnshadowed( normal i_N )
- {
- extern point P;
- color amb = 0;
- illuminance( P )
- {
- if( L == 0 )
- {
- color unshadowed_cl = 0;
- lightsource("__3dfm_unshadowed_cl", unshadowed_cl);
- amb += unshadowed_cl;
- }
- }
- return amb;
- }
- /*
- Maya's diffuse function
- */
- color getDiffuse(
- normal i_N;
- uniform float keyLightsOnly;
- uniform float unshadowed; )
- {
- extern point P;
- color C = 0;
- illuminance( P, i_N, PI/2 )
- {
- float isKeyLight = 1;
-
- if( keyLightsOnly != 0 )
- {
- isKeyLight = 0;
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nondiffuse = 0;
- lightsource( "__nondiffuse", nondiffuse );
-
- if( nondiffuse < 1 )
- {
- varying color cur_cl;
- GET_CL(cur_cl);
- C += cur_cl * normalize(L).i_N * (1-nondiffuse);
- }
- }
- }
- if( keyLightsOnly == 0 && unshadowed == 0 )
- {
- float samples = 16;
- option( "user:_3dfm_arealight_samples", samples );
- color clight;
- trace(
- P, i_N,
- "type", "transmission",
- "hitsides", "reversed",
- "samplearealights", 1,
- "samples", samples,
- "arealightcontribution", clight,
- "bsdf", "cosine" );
- C += clight;
- }
- return C;
- }
- color getTranslucence(
- normal i_N;
- float i_translucence, i_translucenceDepth, i_translucenceFocus;)
- {
- extern point P;
- extern vector I;
- /*
- A translucence focus of 1 leads to a division by zero and an effective
- focus of 0. Clamping it like this yields about the same result as maya.
- */
- float focus = min( i_translucenceFocus, 0.99999 );
-
- color C = 0;
- if( i_translucence > 0.0 )
- {
- illuminance( P )
- {
- float nondiffuse = 0;
- lightsource( "__nondiffuse", nondiffuse );
- if( nondiffuse < 1 )
- {
- float costheta = normalize(L).normalize(I);
- float a = (1 + costheta) * 0.5;
- float trs = pow( pow(a, focus), 1/(1-focus) );
-
- C += Cl * trs * (1-nondiffuse);
- }
- }
- }
- return C * i_translucence;
- }
- color
- getBlinn(
- normal i_Nf;
- float i_eccentricity;
- float i_specularRollOff;
- uniform float i_keyLightsOnly;
- uniform float unshadowed;
- )
- {
- float E;
- color C = 0;
- vector H, Ln, V, Nn;
- float NH, NH2, NHSQR, Dd, Gg, VN, VH, LN, Ff, tmp;
- extern point P;
- extern vector L, I;
- extern color Cl;
- if(i_eccentricity != 1)
- E = 1 / (SQR(i_eccentricity) - 1);
- else
- E = -1e5;
- V = normalize(-I);
- VN = V . i_Nf;
- illuminance( P, i_Nf, PI / 2)
- {
- float isKeyLight = 1;
-
- if( i_keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
- if( nonspecular < 1 )
- {
- Ln = normalize(L);
- H = normalize(Ln + V);
- NH = i_Nf . H;
- NHSQR = SQR(NH);
- NH2 = NH * 2;
- Dd = (E + 1) / (NHSQR + E);
- Dd *= Dd;
- VH = V . H;
- LN = Ln . i_Nf;
- if(VN < LN)
- {
- if(VN * NH2 < VH)
- Gg = NH2 / VH;
- else
- Gg = 1 / VN;
- }
- else
- {
- if(LN * NH2 < VH)
- Gg = (LN * NH2) / (VH * VN);
- else
- Gg = 1 / VN;
- }
- /* poor man's Fresnel */
- tmp = pow((1 - VH), 3);
- Ff = tmp + (1 - tmp) * i_specularRollOff;
- varying color cur_cl;
- GET_CL(cur_cl);
- C += cur_cl * Dd * Gg * Ff * (1-nonspecular);
- }
- }
- }
- if( i_keyLightsOnly == 0 && unshadowed == 0 )
- {
- float samples = 16;
- option( "user:_3dfm_arealight_samples", samples );
- float eta = 0;
- if( i_specularRollOff < 0.99 )
- {
- float sr = max( 0.0001, i_specularRollOff );
- /* Similar attenuation for highlights seen head-on. */
- eta = -((sr+1+2*sqrt(sr))/(sr-1));
- }
- float e = 1 / pow( i_eccentricity, 2.75 /* guesswork */ );
- float denormalize = 2 * PI / (e + 2);
- /* Do I look like I know what I'm doing? Yes? Awesome! */
- denormalize *= 1.27;
- color clight;
- trace(
- P, i_Nf,
- "type", "transmission",
- "hitsides", "reversed",
- "samplearealights", 1,
- "samples", samples,
- "arealightcontribution", clight,
- "bsdf", "blinn",
- "wo", V,
- "eta", eta,
- "roughness", pow( e + 1, -2/7 ) );
- C += denormalize * clight;
- }
- return C;
- }
- color getAnisotropic(
- vector i_N, i_I, i_xdir;
- float i_fresnel, i_roughness, i_spreadx, i_spready;
- uniform float i_keyLightsOnly, unshadowed;)
- {
- /* Stam's anisotropic BRDF */
- float stam_anisotropy( float u, v, w, rx, ry )
- {
- float w2 = w * w;
- float bt = 4 * PI * w2 * w2 * rx * ry;
- float ex = exp(- u * u / (4 * w2 * rx * rx)) * exp( - v * v / (4 * w2 * ry * ry));
- return ex / bt;
- }
- extern point P;
- vector ydir = i_N ^ i_xdir;
- float costheta2 = i_I.i_N;
- /*float sintheta2 = sin(acos(costheta2));*/
- float rx = i_roughness / i_spreadx;
- float ry = i_roughness / i_spready;
- float exists, emitspec = 0;
- color ClnoShadow = 0;
- color spec = 0;
- illuminance( P, i_N, PI / 2 )
- {
- float isKeyLight = 1;
-
- if( i_keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
- if( nonspecular<1 && i_N.L>0 )
- {
- vector Ln = normalize(L);
- float costheta1 = Ln.i_N;
- vector V = Ln + i_I;
- float v = V.i_xdir;
- float u = V.ydir;
- float w = V.i_N;
- float G = (1 + Ln.i_I);
- G = clamp( G * G / (costheta1*costheta2), 0, 1);
- float D = stam_anisotropy( u, v, w, rx, ry );
- float factor = G * D;
- float HdotI = V.i_I / length(V);
- HdotI = 1.0 - HdotI;
- HdotI = HdotI * HdotI * HdotI;
- factor *= HdotI + (1.0 - HdotI);
- factor = clamp(factor, 0, 1) * i_fresnel;
- varying color cur_cl;
- GET_CL(cur_cl);
- spec += factor * cur_cl * (1-nonspecular);
- }
- }
- }
- return spec/4;
- }
- void
- computeSurfaceTransparency(
- float i_matteOpacityMode;
- float i_matteOpacity;
- color i_transparency;
- output color o_outTransparency )
- {
- if(i_matteOpacityMode == 0)
- {
- // This is the "Black Hole" Maya setting
- o_outTransparency = 0;
- }
- else if(i_matteOpacityMode == 1)
- {
- // This is the "Solid Matte" Maya setting
- o_outTransparency = i_matteOpacity;
- }
- else
- {
- // This is the "Opacity Gain" Maya setting (and the default value)
- o_outTransparency = (1 - i_transparency) * i_matteOpacity;
- }
- o_outTransparency = 1.0 - o_outTransparency;
- }
- void computeSurface(
- color i_surfaceColor;
- color i_transparency;
- float i_matteOpacityMode;
- float i_matteOpacity;
- output color o_outColor;
- output color o_outTransparency;
- )
- {
- computeSurfaceTransparency(
- i_matteOpacityMode, i_matteOpacity, i_transparency, o_outTransparency );
- o_outColor = i_surfaceColor * (1 - o_outTransparency);
- o_outColor = clamp(o_outColor, 0, 1e30);
- }
- float raySpecularDepth()
- {
- uniform float depth = 0;
- rayinfo( "speculardepth", depth );
- return depth;
- }
- color getReflection(
- normal i_N;
- vector i_I;
- color i_specularColor;
- float i_reflectivity;
- color i_reflectedColor;
- uniform float i_maxDistance;
- uniform float i_samples;
- uniform float i_blur;
- uniform float i_noiseAmp;
- uniform float i_noiseFreq;
- uniform float i_reflectionLimit )
- {
- extern point P;
- extern uniform float __reflects;
-
- #if defined(USE_AOV_aov_env_reflection) || \
- defined(USE_AOV_aov_rt_reflection) || \
- defined(USE_AOV_aov_rt_reflection_alpha) || \
- defined(USE_AOV_aov_reflection) || \
- defined(USE_AOV_aov_env_specular)
- extern color __transparency;
- #endif
- color ray_coloration = i_specularColor * i_reflectivity;
- // Color from the "reflectedColor" attr meant for env maps.
- color env_color = i_reflectedColor;
- color reflected = env_color;
- if( ray_coloration != color(0) &&
- raySpecularDepth() < i_reflectionLimit &&
- __reflects != 0)
- {
- vector R = reflect( i_I, i_N );
- if( i_noiseAmp != 0 && i_noiseFreq != 0)
- {
- point Pobj = transform("object", P);
- R = mix( R, R * noise( Pobj * i_noiseFreq ), i_noiseAmp );
- }
-
- color trs;
- color rc = trace(
- P, R,
- "subset", "-_3dfm_not_visible_in_reflections",
- "maxdist", i_maxDistance,
- "samplecone", i_blur,
- "samples", i_samples,
- "transmission", trs,
- "weight", ray_coloration );
- #ifdef USE_AOV_aov_rt_reflection
- extern color aov_rt_reflection;
- aov_rt_reflection += __transparency * rc * ray_coloration;
- #endif
- #ifdef USE_AOV_aov_rt_reflection_alpha
- extern float aov_rt_reflection_alpha;
- aov_rt_reflection_alpha += luminance(__transparency * (1 - trs));
- #endif
- if( trs != 0 )
- {
- varying color gi_env_color = getGiEnvironmentSpecular(R, i_samples, i_blur);
- #ifdef USE_AOV_aov_env_specular
- extern varying color aov_env_specular;
- if( isoutput( aov_env_specular ) )
- {
- aov_env_specular += __transparency * gi_env_color * trs * ray_coloration;
- }
- #endif
- uniform float add_to_final_mix = getGiAddToFinalMix();
- if( add_to_final_mix > 0 )
- {
- reflected += gi_env_color;
- }
- #if !defined(USE_DEPRECATED_SHADING) && defined(USE_AOV_aov_env_reflection)
- env_color += gi_env_color;
- #endif
- }
- #if !defined(USE_DEPRECATED_SHADING) && defined(USE_AOV_aov_env_reflection)
- env_color *= trs;
- #endif
- reflected *= trs;
- reflected += rc;
- }
- #ifdef USE_AOV_aov_env_reflection
- extern color aov_env_reflection;
- aov_env_reflection += __transparency * env_color * ray_coloration;
- #endif
- #ifdef USE_AOV_aov_reflection
- extern color aov_reflection;
- aov_reflection += __transparency * reflected * ray_coloration;
- #endif
- return reflected * ray_coloration;
- }
- float doRefraction(
- normal i_N;
- vector i_I;
- uniform float i_refractions;
- float i_refractiveIndex;
- uniform float i_refractionLimit;
- float i_lightAbsorbance;
- float i_shadowAttenuation;
- output color io_transparency;
- output color o_refraction; )
- {
- // Returns a non-zero value if there is a total internal reflection
- // (which should be computed elsewhere)
- //
- extern point P;
- uniform string rayType;
- uniform float isShadowMap;
- extern uniform float __refracts;
- float tir = 0;
- if( io_transparency != color(0) &&
- __refracts != 0)
- {
- /*
- Check for shadows (either raytraced or shadow maps), in which case
- we compute a straight opacity instead of tracing refraction rays.
- */
- if( (1 == rayinfo( "type", rayType ) && rayType == "transmission") ||
- (1 == attribute( "user:ShadowMapRendering", isShadowMap ) &&
- isShadowMap != 0) )
- {
- o_refraction = 0;
- io_transparency *=
- mix( 1, abs( normalize(i_I) . i_N ), i_shadowAttenuation );
- }
- else if( i_refractions != 0 )
- {
- color refractionColor = 0;
- if( raySpecularDepth() < i_refractionLimit )
- {
- float eta;
- normal Nf = i_N;
- if( i_I . i_N < 0 )
- {
- eta = 1.0 / i_refractiveIndex;
- Nf = i_N;
- }
- else
- {
- eta = i_refractiveIndex;
- Nf = -i_N;
- }
-
- vector refract = refract(normalize(i_I), Nf, eta);
- if( length( refract ) <= EPSILON )
- {
- o_refraction = 0;
- tir = 1.0;
- }
- else
- {
- color trs = 0;
- vector dir = normalize(refract);
-
- refractionColor = trace(
- P, dir,
- "subset", "-_3dfm_not_visible_in_refractions",
- "transmission", trs);
-
- uniform float add_to_final_mix = getGiAddToFinalMix();
- if( trs != 0 && add_to_final_mix > 0)
- {
- refractionColor += getGiEnvironmentSpecular(dir, 0, 0) * trs;
- }
- }
- }
- o_refraction = io_transparency * refractionColor;
- io_transparency = 0;
- }
- else
- {
- o_refraction = 0;
- }
- }
- else
- {
- o_refraction = 0;
- }
-
- return tir;
- }
- float computeShadowValue(normal i_N)
- {
- float shadowValue = 0;
- varying float totalLightIntensity = 0;
- extern varying point P;
- illuminance(P)
- {
- /* Do this manually instead of specifying i_N, PI/2 to illuminance so
- ambient lights are included. */
- if( L.i_N >= 0 )
- {
- float __3dfm_shadowing = 0;
- color __3dfm_unshadowed_cl = 0;
- lightsource("__3dfm_shadowing", __3dfm_shadowing);
- lightsource("__3dfm_unshadowed_cl", __3dfm_unshadowed_cl);
- float unshadowed_intensity = luminance(__3dfm_unshadowed_cl);
- shadowValue += __3dfm_shadowing * unshadowed_intensity;
- totalLightIntensity += unshadowed_intensity;
- }
- }
- // Environment contribution
- shader gi_shader = getshader( "maya_gi_shader" );
- if( gi_shader != null )
- {
- extern point P;
- color envDiffuse;
- color unshadowedEnvDiffuse;
-
- gi_shader->ComputeUseBackground(
- P, i_N, 1, envDiffuse, unshadowedEnvDiffuse );
- float unshadowedEnvDiffuseIntensity =
- CIEluminance(unshadowedEnvDiffuse);
- shadowValue += unshadowedEnvDiffuseIntensity - CIEluminance(envDiffuse);
- totalLightIntensity += unshadowedEnvDiffuseIntensity;
- }
- // Area lights contribution
- float samples = 16;
- option( "user:_3dfm_arealight_samples", samples );
- color areaLight;
- color unshadowedAreaLight;
- trace(
- P, i_N,
- "raytype", "transmission",
- "hitsides", "reversed",
- "samplearealights", 1,
- "samples", samples,
- "arealightcontribution", areaLight,
- "unshadowedarealight", unshadowedAreaLight,
- "bsdf", "uniform" );
- float unshadowedAreaLightIntensity = CIEluminance(unshadowedAreaLight);
- shadowValue += unshadowedAreaLightIntensity - CIEluminance(areaLight);
- totalLightIntensity += unshadowedAreaLightIntensity;
- shadowValue /= totalLightIntensity;
- return shadowValue;
- }
- void computeShadowPass(normal i_N)
- {
- #ifdef USE_AOV_aov_shadow
- extern float aov_shadow;
- aov_shadow = computeShadowValue(i_N);
- #endif
- }
- color computeLuminanceDepth()
- {
- uniform float near_far[2] = {0, 1e3};
- option( "Clipping", near_far );
- uniform float near = near_far[0];
- uniform float far = near_far[1];
-
- extern varying vector I;
- float depth = length(I) - near;
-
- far -= near;
- depth = (far - depth) / far;
- return color(depth, depth, depth);
- }
- color getPhong(
- normal i_N; vector i_V; float i_size;
- uniform float i_keyLightsOnly, unshadowed)
- {
- color C = 0;
- vector R = reflect( -normalize(i_V), normalize(i_N) );
- extern varying point P;
-
- illuminance( P, i_N, PI/2 )
- {
- float isKeyLight = 1;
-
- if( i_keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
-
- if( nonspecular < 1 )
- {
- vector Ln = normalize(L);
-
- varying color cur_cl;
- GET_CL(cur_cl);
- C += cur_cl * pow(max(0.0,R.Ln), i_size) * (1-nonspecular);
- }
- }
- }
- return C;
- }
- /* Implementation of specularstd function */
- color getPhongS(
- normal i_N; vector i_V; float i_size;
- uniform float i_keyLightsOnly, unshadowed)
- {
- color C = 0;
- extern varying point P;
-
- illuminance( P, i_N, PI/2 )
- {
- vector H = normalize(normalize(L)+i_V);
- float isKeyLight = 1;
-
- if( i_keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
-
- if( nonspecular < 1 )
- {
- vector Ln = normalize(L);
-
- varying color cur_cl;
- GET_CL(cur_cl);
- C += cur_cl * pow(max(0.0,i_N.H), i_size) * (1-nonspecular);
- }
- }
- }
- return C;
- }
- color getPhongE(vector i_R; float i_highlight_size, i_roughness;
- uniform float i_keyLightsOnly, unshadowed)
- {
- extern point P;
- varying color C = 0;
-
- illuminance( "specular", P, i_R, i_highlight_size * PI/2 )
- {
- float isKeyLight = 1;
-
- if( i_keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
-
- if( nonspecular < 1 )
- {
- float cos_angle = normalize(L) . i_R;
- float angle = acos(cos_angle);
- float spec = pow( cos(angle / i_highlight_size), pow(i_roughness, -2) );
- varying color cur_cl;
- GET_CL(cur_cl);
- C += spec * cur_cl * (1-nonspecular);
- }
- }
- }
- return C;
- }
- color getGaussian(vector i_I; vector i_N; float i_roughness;
- uniform float i_keyLightsOnly, unshadowed)
- {
- extern point P;
- color C = 0;
-
- illuminance( "specular", P )
- {
- float isKeyLight = 1;
-
- if( i_keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
-
- if( nonspecular < 1 )
- {
- vector Ln = normalize(L);
- vector Hn = normalize(-i_I + Ln);
-
- float spec = exp( -sq( acos(i_N.Hn) / i_roughness ) );
-
- varying color cur_cl;
- GET_CL(cur_cl);
-
- C += cur_cl * spec * (1-nonspecular);
- }
- }
- }
- return C;
- }
- color getGaussianG(vector i_I; vector i_N; float i_roughness;
- uniform float i_keyLightsOnly, unshadowed)
- {
- extern point P;
- color C = 0;
-
- illuminance( "specular", P )
- {
- float isKeyLight = 1;
-
- if( i_keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
-
- if( nonspecular < 1 )
- {
- vector Ln = normalize(L);
- vector Hn = normalize(-i_I + Ln);
-
- float spec = exp( -sq( acos(i_N.Hn) / i_roughness ) );
- spec = smoothstep(0, 1/3, spec);
-
- varying color cur_cl;
- GET_CL(cur_cl);
-
- C += cur_cl * spec * (1-nonspecular);
- }
- }
- }
- return C;
- }
- color getCookTorr(vector i_V; vector i_N; float i_roughness; color i_ior;
- uniform float i_keyLightsOnly, unshadowed)
- {
- extern point P;
-
- float etar = 1/i_ior[0];
- float etag = 1/i_ior[1];
- float etab = 1/i_ior[2];
- float Kt, Krr, Krg, Krb;
- fresnel(-i_V, i_N, etar, Krr, Kt);
- fresnel(-i_V, i_N, etag, Krg, Kt);
- fresnel(-i_V, i_N, etab, Krb, Kt);
-
- color F = color(Krr, Krg, Krb);
-
- color C = 0;
-
- illuminance( P, i_N, PI/2)
- {
- float isKeyLight = 1;
-
- if( i_keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
-
- if( nonspecular < 1 )
- {
- vector Ln = normalize(L);
- vector Hn = normalize(i_V + Ln);
- float NH = i_N.Hn;
- float alpha = acos(NH);
- float NV = i_N.i_V;
- float NL = i_N.Ln;
- float HV = Hn.i_V;
-
- // Geometric attenuation term:
- float G1 = (2 * NH * NV) / HV;
- float G2 = (2 * NH * NL) / HV;
- float G = min(1, min(G1, G2));
-
- // Beckmann distribution factor:
- float _D = tan(alpha) / i_roughness;
- float D = exp( - (_D*_D) ) /
- (4.0 * i_roughness * i_roughness * pow(cos(alpha), 4.0));
-
- color spec = D*G*F/NV;
-
- varying color cur_cl;
- GET_CL(cur_cl);
-
- C += cur_cl * spec * (1-nonspecular);
- }
- }
- }
-
- return C;
- }
- void do_bump_map(
- float i_bumpValue;
- float i_bumpDepth;
- normal i_normalCamera;
- output normal o_outNormal )
- {
- extern vector dPdu, dPdv;
- float depth = abs(i_bumpDepth);
- float offset = clamp(i_bumpValue * i_bumpDepth, -depth, depth);
- #ifndef NEW_BUMP /* old bump implementation */
- /*
- These scale factors are a bit experimental. The constant is to roughly
- match maya's bump mapping. The part about dPdu/dPdv ensures that the
- bump's scale does not depend on the underlying parametrization of the
- patch (the use of Du and Dv below introduce that) and that it happens
- in object space. Note that maya's handling of object space appears to
- be slightly broken since an enlarged sphere will have the same bump as
- a sphere with its control points moved outwards by a scale, somehow.
- */
- float uscale = 1.0 / (length(vtransform("object", dPdu)) * 6.0);
- float vscale = 1.0 / (length(vtransform("object", dPdv)) * 6.0);
- vector gu = vector(1, 0, Du(offset) * uscale);
- vector gv = vector(0, 1, Dv(offset) * vscale);
- normal n = normal(gu ^ gv);
-
- vector basisz = normalize(i_normalCamera);
- vector basisx = normalize((basisz ^ dPdu) ^ basisz);
- vector basisy = normalize((basisz ^ dPdv) ^ basisz);
- o_outNormal = normal(
- xcomp(n) * basisx + ycomp(n) * basisy + zcomp(n) * basisz);
- o_outNormal = normalize(o_outNormal);
- #else
- extern point P;
- extern normal Ng;
-
- normal Nn = normalize(i_normalCamera);
- normal Ngn = normalize(Ng);
- normal Noffset = Nn - Ngn;
-
- float scale = 0.25;
-
- point Pp =
- transform("world", P) +
- normalize(ntransform("world", Ngn)) * offset * scale;
- Nn = -ntransform("world", "current", calculatenormal(Pp));
- Nn = normalize(Nn);
- o_outNormal = normalize(Nn + Noffset);
- #endif
- }
- /* Macros to implement a special case for photons in the surface shaders. */
- #define BEGIN_PHOTON_CASE( diffuseColor, specularColor, transparency ) \
- string rayType; \
- if( 1 == rayinfo( "type", rayType ) && rayType == "light" ) \
- { \
- string shadingmodel; \
- if( 1 == attribute( "photon:shadingmodel", shadingmodel ) && \
- shadingmodel == "matte" ) \
- { \
- o_outColor = diffuseColor; \
- } \
- else \
- { \
- o_outColor = specularColor; \
- } \
- o_outTransparency = transparency; \
- } \
- else \
- { /* This encloses the shader body. */
- /* Macros to implement a special case for photons in the surface shaders
- without o_outTransparency parameter */
- #define BEGIN_PHOTON_CASE_OI( diffuseColor, specularColor, transparency ) \
- extern color Oi; \
- string rayType; \
- if( 1 == rayinfo( "type", rayType ) && rayType == "light" ) \
- { \
- string shadingmodel; \
- if( 1 == attribute( "photon:shadingmodel", shadingmodel ) && \
- shadingmodel == "matte" ) \
- { \
- o_outColor = diffuseColor * (1.0 - transparency); \
- } \
- else \
- { \
- o_outColor = specularColor; \
- } \
- Oi = 1.0 - transparency; \
- } \
- else \
- { /* This encloses the shader body. */
- #define END_PHOTON_CASE } /* This closes the brace above. */
- // Compute the roughness corresponding to a given glossiness value.
- float roughness(float gloss)
- {
- return pow(2.0, 8.0 * gloss);
- }
- /*
- * Oren and Nayar's generalization of Lambert's reflection model.
- * The roughness parameter gives the standard deviation of angle
- * orientations of the presumed surface grooves. When roughness=0,
- * the model is identical to Lambertian reflection.
- * Taken from Arman so credits go to Larry Gritz.
- */
- color
- LocIllumOrenNayar (
- normal N;
- vector V;
- float roughness;
- uniform float keyLightsOnly;
- uniform float unshadowed;)
- {
- /* Surface roughness coefficients for Oren/Nayar's formula */
- float sigma2 = roughness * roughness;
- float A = 1 - 0.5 * sigma2 / (sigma2 + 0.33);
- float B = 0.45 * sigma2 / (sigma2 + 0.09);
- /* Useful precomputed quantities */
- float theta_r = acos (V . N); /* Angle between V and N */
- vector V_perp_N = normalize(V-N*(V.N)); /* Part of V perpendicular to N */
- /* Accumulate incoming radiance from lights in C */
- color C = 0;
- extern point P;
- illuminance (P, N, PI/2)
- {
- float isKeyLight = 1;
-
- if( keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- /* Must declare extern L & Cl because we're in a function */
- extern vector L;
- uniform float nondiff = 0;
- lightsource ("__nondiffuse", nondiff);
- if (nondiff == 0)
- {
- vector LN = normalize(L);
- float cos_theta_i = LN . N;
- float cos_phi_diff = V_perp_N . normalize(LN - N*cos_theta_i);
- float theta_i = acos (cos_theta_i);
- float alpha = max (theta_i, theta_r);
- float beta = min (theta_i, theta_r);
- varying color cur_cl;
- GET_CL(cur_cl);
- C += cur_cl * cos_theta_i *
- (A + B * max(0,cos_phi_diff) * sin(alpha) * tan(beta));
- }
- }
- }
- return C;
- }
- // Compute sampling parameters.
- float compute_sampling_angle( float glossiness; )
- {
- if( glossiness >= 1.0 )
- return 0.0;
- else
- return (1.0 - pow(clamp(glossiness, 0.0, 1.0), 0.2)) * PI / 2.0;
- }
- color trace_reflection(
- vector In;
- normal Nf;
- vector V;
- float i_refl_gloss;
- float i_refl_gloss_samples;
- float i_use_max_dist;
- float i_max_dist;
- uniform float i_do_refl_falloff;
- varying color i_refl_falloff_color;
- varying color i_weight )
- {
- extern point P;
- extern uniform float __reflects;
-
- if( __reflects == 0 )
- {
- return color(0);
- }
- // Compute the sampling parameters.
- float sample_angle = compute_sampling_angle( i_refl_gloss );
- float sample_count = (i_refl_gloss == 0) ?
- min(4, i_refl_gloss_samples) : i_refl_gloss_samples;
- // Compute reflected direction.
- vector refl_dir = reflect(In, Nf);
- uniform float max_dist = i_use_max_dist > EPSILON ? i_max_dist : 1e38;
-
- color trs = 0;
- float dist = 0;
- float fade = 1.0;
- if( i_use_max_dist != 0 )
- {
- fade = pow( ( clamp( 1 - dist / max_dist, 0, 1 ) ), 2 );
- }
- color reflection = trace(
- P, refl_dir, dist,
- "samplecone", sample_angle,
- "samples", sample_count,
- "transmission", trs,
- "subset", "-_3dfm_not_visible_in_reflections",
- "maxdist", max_dist,
- "weight", i_weight*fade );
- reflection *= fade;
-
- extern color __transparency;
- #ifdef USE_AOV_aov_rt_reflection
- extern varying color aov_rt_reflection;
- if( isoutput( aov_rt_reflection ) )
- {
- aov_rt_reflection += __transparency * reflection;
- }
- #endif
- #ifdef USE_AOV_aov_rt_reflection_alpha
- extern varying float aov_rt_reflection_alpha;
- if( isoutput( aov_rt_reflection_alpha ) )
- {
- aov_rt_reflection_alpha += CIEluminance( __transparency * (1-trs) );
- }
- #endif
- if( trs != 0 )
- {
- color env_color = 0;
-
- if( i_do_refl_falloff != 0 )
- {
- env_color = i_refl_falloff_color;
- }
- else
- {
- env_color = getGiEnvironmentSpecular(refl_dir, sample_count, sample_angle);
- }
- if( i_use_max_dist != 0 )
- {
- env_color *= (1 - fade);
- }
-
- env_color *= trs;
- #ifdef USE_AOV_aov_env_specular
- extern varying color aov_env_specular;
- if( isoutput( aov_env_specular ) )
- {
- aov_env_specular += __transparency * env_color;
- }
- #endif
- #ifdef USE_AOV_aov_env_reflection
- extern color aov_env_reflection;
- aov_env_reflection += __transparency * env_color;
- #endif
- reflection += env_color;
- }
-
- return reflection;
- }
- color trace_refraction(
- normal Nn;
- vector In;
- normal Nf;
- vector V;
- float i_refr_ior;
- float i_refr_gloss;
- float i_refr_gloss_samples;
- output float o_total_internal_refl;
- varying color i_weight )
- {
- extern point P;
- extern uniform float __refracts;
-
- if( __refracts == 0 )
- {
- o_total_internal_refl = 0;
- return color(0);
- }
- // Compute the sampling parameters.
- float sample_angle = compute_sampling_angle( i_refr_gloss );
- float sample_count = (i_refr_gloss == 0) ?
- min(4, i_refr_gloss_samples) : i_refr_gloss_samples;
- // Compute refracted direction.
- float eta = (In . Nn < 0.0) ? 1.0 / i_refr_ior : i_refr_ior;
- vector refr_dir = refract(In, Nf, eta);
- color refraction = 0;
- if( length( refr_dir ) <= EPSILON )
- {
- o_total_internal_refl = 1;
- refraction = 0;
- }
- else
- {
- color trs = 0;
- refraction = trace(
- P, refr_dir,
- "samplecone", sample_angle,
- "samples", sample_count,
- "subset", "-_3dfm_not_visible_in_refractions",
- "transmission", trs,
- "weight", i_weight );
- if( trs != 0 )
- {
- color env_color = getGiEnvironmentSpecular(refr_dir, sample_count, sample_angle);
- refraction += env_color * trs;
- }
- o_total_internal_refl = 0;
- }
- return refraction;
- }
- /*
- Compute specular highlights.
- NOTES
- - We use the ward anisotropic model. But we sum 3 highlights with decreasing
- roughness and increasing contribution.
- */
- color specular_highlight(
- vector In;
- normal Nf;
- vector V;
- float refl_roughness_u, refl_roughness_v;
- uniform float keyLightsOnly;
- uniform float unshadowed;)
- {
- extern color Cl;
- extern vector dPdu, dPdv;
- extern point P;
- vector xdir = normalize( dPdu );
- vector ydir = normalize( dPdv );
-
- xdir = normalize(Nf^xdir^Nf);
- ydir = normalize(Nf^ydir^Nf);
- color highlights = 0;
- /* We have three specular higlihgts of diminushing roughness but increasing
- brightness */
- uniform float component_coefs[3] = {0.5, 1.0, 1.5};
- illuminance( P, Nf, PI * 0.5 )
- {
- float isKeyLight = 1;
-
- if( keyLightsOnly != 0 )
- {
- lightsource( "iskeylight", isKeyLight );
- }
-
- if( isKeyLight != 0 )
- {
- uniform float nonspecular = 0;
- lightsource( "__nonspecular", nonspecular );
- if( nonspecular == 0 )
- {
- vector Ln = normalize(L);
- float dot_ln = Ln . Nf;
- float dot_vn = V . Nf;
- if( dot_vn*dot_ln>0.0 )
- {
- vector Hn = normalize(V + Ln);
- float dot_hn2 = min(sq(Hn . Nf), 1.0);
- if( dot_hn2>0.0 )
- {
- /* precompute this to get it out of the loop below */
- float k1_devider = 1 / (sqrt(dot_vn * dot_ln) * 4.0 * PI);
- float smooth_step_ln = smoothstep( 0, 0.25, dot_ln );
- uniform float i=0;
- uniform float roughness_coef = 1;
- for( i=0; i<3; i+=1.0 )
- {
- // Compute the highlight due to this light source.
- float k1 =
- (refl_roughness_u * refl_roughness_v * roughness_coef * roughness_coef )
- * k1_devider;
- float k2 =
- sq(Hn . xdir * refl_roughness_u * roughness_coef)
- + sq(Hn . ydir * refl_roughness_v * roughness_coef);
- color c =
- k1 * exp(-k2 / dot_hn2)
- * dot_ln
- * smooth_step_ln;
-
- varying color cur_cl;
- GET_CL(cur_cl);
- // Accumulate highlights.
- highlights += cur_cl * c * component_coefs[i];
- roughness_coef *= 0.5;
- }
- }
- }
- }
- }
- }
- return highlights;
- }
- /*
- Compute motion vector.
- */
- vector motionVector()
- {
- extern point P;
- extern vector dPdtime;
- vector motion = dPdtime;
- point P0 = transform( "screen", P );
- point P1 = transform( "screen", P + motion );
- return P0 - P1;
- }
- #endif /* _shading_utils_h */
|