Rebuild of Entagma's Thinfilm Shader for using with 3Delight
2567 3 0- Faitel
- Member
- 94 posts
- Joined: 7月 2019
- Offline
I've rebuilt mantra shader from Entagma Mantra Thin Film Shader [entagma.com] tutorial to use it with 3Delight [www.3delight.com] render engine.
Attached archive contains Thinfilm custom osl utility node (thinfilm.oso) and hip file from Entagma with additional shader.
How to use:
1. Download and extract files from the archive (Thinfilm_Shader_3Delight.zip)
2. Copy compiled shader file - thinfilm.oso to your _3DELIGHT_USER_OSO_PATH system variable folder. See the video [vimeo.com] to learn how to setup the system environment variable if don't have one.
3. Open Houdini to check that custom node is added to mat context - tab - 3Delight - Addons - Thinfilm
4. Open Soapfilm_bubble_FLIP_Render_3delight example file
5. Complete instructions at the file.
Render time comparison:
Mantra: 1 hour 17 min.
3Delight: 1 min 29 sec.
Additional links:
3Delight's osl support [documentation.3delightcloud.com]
3Delight's osl metadata [documentation.3delightcloud.com]
3Delight's standalone tools [documentation.3delightcloud.com]
OSL Specification [github.com]
Edited by Faitel - 2021年12月24日 15:52:15
- Faitel
- Member
- 94 posts
- Joined: 7月 2019
- Offline
OSL shader code for reference
//Thinfilm shader cobbled together from: //https://docs.chaosgroup.com/display/OSLShaders/Thin+Film+Shader //and: //https://www.shadertoy.com/view/ls2Bz1 //copied together by your's truly, Entagma - Dec. 2020 //https://entagma.com/holiday-giveaway-mantra-thinfilm-shader/ //sequentially copied and modified to use with 3delight by Faitel - Dec. 2022 #include "stdosl.h" surface thinfilm ( color col = color(0) [[ string help = "Constant color", string label = "Color", string widget = "number"]], float fintensity = 0 [[ string help = "Fresnel reduction multiplier", string label = "Intensity", string page = "Fresnel reduction", string widget = "number", float min = 0 ]], float fior = 1.4 [[ string help = "Index of reflection for fresnel reduction", string label = "Ior", string page = "Fresnel reduction", string widget = "number", float min = 0 ]], int sbiter = 8 [[ string help = "Number of spectral bands. 8 seems fine, 32 is excessive.", string label = "Iterations", string page = "Spectral Bands", string widget = "number", ]], int spfunc = 0 [[ string label = "Function", string page = "Spectral Bands", string widget = "mapper", string options = "Gems:0|" "Zucconi:1|" "Bruton:2|" ]], float thickness = 1 [[ string help = "Thin Film Thickness", string label = "Thickness", string page = "Thin Film", string widget = "number", float min = 0, float max = 1 ]], float thicknessMin = 100 [[ string help = "Minimal Thin Film Thickness", string label = "Thickness Min", string page = "Thin Film", string widget = "number", float min = 0, float max = 1000 ]], float thicknessMax = 900 [[ string help = "Maximal Thin Film Thickness", string label = "Thickness Max", string page = "Thin Film", string widget = "number", float min = 0, float max = 1000 ]], float nmedium = 1 [[ string help = "approximate refractive index of air", string label = "nmedium", string page = "Thin Film", string widget = "number", float min = 0, float max = 10 ]], float nfilm = 1.4 [[ string help = "approximate refractive index of water", string label = "nfilm", string page = "Thin Film", string widget = "number", float min = 0, float max = 10 ]], float ninternal = 1 [[ string help = "approximate refractive index of the lower material", string label = "ninternal", string page = "Thin Film", string widget = "number", float min = 0, float max = 10 ]], output color outColor = 0 ) { float saturate(float x) { return min(1.0, max(0.0,x)); } vector saturate (vector x) { return min(color(1.0,1.0,1.0), max(color(0.0,0.0,0.0),x)); } // --- Spectral Zucconi -------------------------------------------- // By Alan Zucconi // Based on GPU Gems: https://developer.nvidia.com/sites/all/modules/custom/gpugems/books/GPUGems/gpugems_ch08.html // But with values optimised to match as close as possible the visible spectrum // Fits this: https://commons.wikimedia.org/wiki/File:Linear_visible_spectrum.svg // With weighter MSE (RGB weights: 0.3, 0.59, 0.11) vector bump3y(vector x, vector yoffset) { vector y = color(1.0,1.0,1.0) - x * x; y = saturate(y-yoffset); return y; } vector spectral_zucconi(float w) { // w: [400, 700] // x: [0, 1] float x = saturate((w - 400.0)/ 300.0); vector cs = color(3.54541723, 2.86670055, 2.29421995); vector xs = color(0.69548916, 0.49416934, 0.28269708); vector ys = color(0.02320775, 0.15936245, 0.53520021); return bump3y ( cs * (x - xs), ys); } // --- GPU Gems ------------------------------------------------------- // https://developer.nvidia.com/sites/all/modules/custom/gpugems/books/GPUGems/gpugems_ch08.html vector bump3(vector x) { vector y = color(1.0,1.0,1.0) - x * x; y = max(y, {0.,0.,0.}); return y; } vector spectral_gems (float w) { // w: [400, 700] // x: [0, 1] float x = clamp((w - 400.0)/ 300.0, 0., 1.); float r = 4. * (x - 0.75); float g = 4. * (x - 0.5); float b = 4. * (x - 0.25); vector rgb = {r,g,b}; return bump3(rgb); } // --- Approximate RGB values for Visible Wavelengths ------------------ // by Dan Bruton // http://www.physics.sfasu.edu/astro/color/spectra.html // https://stackoverflow.com/questions/3407942/rgb-values-of-visible-spectrum vector spectral_bruton(float w) { vector c; if (w >= 380. && w < 440.) c = color ( -(w - 440.) / (440. - 380.), 0.0, 1.0 ); else if (w >= 440. && w < 490.) c = color ( 0.0, (w - 440.) / (490. - 440.), 1.0 ); else if (w >= 490. && w < 510.) c = color ( 0.0, 1.0, -(w - 510.) / (510. - 490.) ); else if (w >= 510. && w < 580.) c = color ( (w - 510.) / (580. - 510.), 1.0, 0.0 ); else if (w >= 580. && w < 645.) c = color ( 1.0, -(w - 645.) / (645. - 580.), 0.0 ); else if (w >= 645. && w <= 780.) c = color ( 1.0, 0.0, 0.0 ); else c = color ( 0.0, 0.0, 0.0 ); return saturate(c); } //--- OSL Thinfilm Shader --- /* Amplitude reflection coefficient (s-polarized) */ float rs(float n1, float n2, float cosI, float cosT) { return (n1 * cosI - n2 * cosT) / (n1 * cosI + n2 * cosT); } /* Amplitude reflection coefficient (p-polarized) */ float rp(float n1, float n2, float cosI, float cosT) { return (n2 * cosI - n1 * cosT) / (n1 * cosT + n2 * cosI); } /* Amplitude transmission coefficient (s-polarized) */ float ts(float n1, float n2, float cosI, float cosT) { return 2 * n1 * cosI / (n1 * cosI + n2 * cosT); } /* Amplitude transmission coefficient (p-polarized) */ float tp(float n1, float n2, float cosI, float cosT) { return 2 * n1 * cosI / (n1 * cosT + n2 * cosI); } // cosI is the cosine of the incident angle, that is, cos0 = dot(view angle, normal) // lambda is the wavelength of the incident light (e.g. lambda = 510 for green) // From http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/thin-film-interference-for-computer-graphics-r2962 float thinFilmReflectance(float cos0, float lambda, float thickness, float n0, float n1, float n2) { float PI=M_PI; //Pi osl constant // compute the phase change term (constant) float d10 = (n1 > n0) ? 0 : PI; float d12 = (n1 > n2) ? 0 : PI; float delta = d10 + d12; // now, compute cos1, the cosine of the reflected angle float sin1 = pow(n0 / n1, 2) * (1 - pow(cos0, 2)); if (sin1 > 1) return 1.0; // total internal reflection float cos1 = sqrt(1 - sin1); // compute cos2, the cosine of the final transmitted angle, i.e. cos(theta_2) // we need this angle for the Fresnel terms at the bottom interface float sin2 = pow(n0 / n2, 2) * (1 - pow(cos0, 2)); if (sin2 > 1) return 1.0; // total internal reflection float cos2 = sqrt(1 - sin2); // get the reflection transmission amplitude Fresnel coefficients float alpha_s = rs(n1, n0, cos1, cos0) * rs(n1, n2, cos1, cos2); // rho_10 * rho_12 (s-polarized) float alpha_p = rp(n1, n0, cos1, cos0) * rp(n1, n2, cos1, cos2); // rho_10 * rho_12 (p-polarized) float beta_s = ts(n0, n1, cos0, cos1) * ts(n1, n2, cos1, cos2); // tau_01 * tau_12 (s-polarized) float beta_p = tp(n0, n1, cos0, cos1) * tp(n1, n2, cos1, cos2); // tau_01 * tau_12 (p-polarized) // compute the phase term (phi) float phi = (2 * PI / lambda) * (2 * n1 * thickness * cos1) + delta; // finally, evaluate the transmitted intensity for the two possible polarizations float ts = pow(beta_s, 2) / (pow(alpha_s, 2) - 2 * alpha_s * cos(phi) + 1); float tp = pow(beta_p, 2) / (pow(alpha_p, 2) - 2 * alpha_p * cos(phi) + 1); // we need to take into account conservation of energy for transmission float beamRatio = (n2 * cos2) / (n0 * cos0); // calculate the average transmitted intensity (if you know the polarization distribution of your // light source, you should specify it here. if you don't, a 50%/50% average is generally used) float myt = beamRatio * (ts + tp) / 2; // and finally, derive the reflected intensity return 1 - myt; } float cos0 = abs(dot(I , N)); float myt = clamp(thickness, 0., 1.); float thick=thicknessMin*(1.0-myt)+thicknessMax*myt; color outcol = col; //get color; float fint = fintensity; //get fresnel multiplier float fnfilm = fior; //get fresnel ior int maxiter = sbiter; //number of spectral bands. 8 seems fine, 32 is excessive. for(int i = 0; i < maxiter; i++) { float lambda = 400. + (300. * (float(i)/float(maxiter))); //Spectral bands ranging from 400nm to 700nm float ref = thinFilmReflectance(cos0, lambda, thick, nmedium, nfilm, ninternal); //we don't need no fresnel, so we need to divide it out again //I know - being cheap, but atm just not in the mood for algebra float kr, kt; fresnel(-I, N, fnfilm, kr, kt); kr = kr; if (fint == 0 ) ref = ref; if (fint > 0 ) ref = ref / (kr * fint); vector rgb; if (spfunc == 0) rgb = spectral_gems(lambda); if (spfunc == 1) rgb = spectral_zucconi(lambda); if (spfunc == 2) rgb = spectral_bruton(lambda); rgb = rgb * ref; outcol = outcol + rgb; } outColor = outcol / float(maxiter); }
Edited by Faitel - 2021年12月24日 15:35:59
- lewis_T
- Member
- 234 posts
- Joined: 3月 2013
- Offline
- Midphase
- Member
- 833 posts
- Joined: 1月 2018
- Offline
"Render time comparison:
Mantra: 1 hour 17 min.
3Delight: 1 min 29 sec."
LOL!
Mantra: 1 hour 17 min.
3Delight: 1 min 29 sec."
LOL!
>>Kays
For my Houdini tutorials and more visit:
https://www.youtube.com/c/RightBrainedTutorials [www.youtube.com]
For my Houdini tutorials and more visit:
https://www.youtube.com/c/RightBrainedTutorials [www.youtube.com]
-
- Quick Links