POV-Ray : Newsgroups : povray.beta-test : SSLT macros Server Time
31 Oct 2024 10:22:21 EDT (-0400)
  SSLT macros (Message 1 to 1 of 1)  
From: clipka
Subject: SSLT macros
Date: 6 Apr 2009 08:20:01
Message: <web.49d9f2debb38f2752983f9e20@news.povray.org>
For all who want to toy around with beta.32's Subsurface Light Transport, here's
a macro suite that might make life easier if you don't happen to know the
scattering and absorption coefficents of a material you try to model.

To use it, just replace the "subsurface { COLOR, COLOR }" statement with
"Subsurface(COLOR,COLOR,FLOAT)", the first parameter being the desired apparent
color of the material, the second one controlling the translucency, and the
third being the material's IOR.

For convenience, the generated material coefficients will be written to debug
output.

(Anyone happen to know a more efficient algorithm to compute the albedo from a
given reflectance?)


#local fnReflectanceSub = function(albedo,root,A) { (albedo/2) * (1 +
exp(-(4/3)*A*root)) * exp(-root) }
#local fnReflectance = function(albedo,A) { fnReflectanceSub(albedo,
sqrt(3*(1-albedo)), A) }

#local fnFdr = function(eta) { -1.440/(eta*eta) + 0.710/eta + 0.668 + 0.0636*eta
}
#local fnASub = function(Fdr) { (1+Fdr)/(1-Fdr) }
#local fnA = function(eta) { fnASub(fnFdr(eta)) }

// Precomputed albedo values for a refractive index of 1.0
#declare AlbedoGuessN = 10;
#declare AlbedoGuess  = array[AlbedoGuessN+1] { 0.0000, 0.5379, 0.7401, 0.8454,
0.9073, 0.9457, 0.9700, 0.9852, 0.9941, 0.9987, 1.0000, };


#macro Albedo(reflectance,eta)
  #local A = fnA(eta);
  #local guessA = 0.0;
  #local guessB = 1.0;
  #local fA = fnReflectance(guessA,A) - reflectance;
  #local fB = fnReflectance(guessB,A) - reflectance;
  #local guessC =
AlbedoGuess[clip(int(reflectance*AlbedoGuessN+0.5),0,AlbedoGuessN)];
  #local fC = fnReflectance(guessC,A) - reflectance;
  #local i = 0;
  #while ((i < 100) & (abs(fC) > reflectance * 0.001))
    #switch(sgn(fA)*sgn(fC))
    #case(1)
      #local guessA = guessC;
      #local fA = fC;
    #break
    #case(-1)
      #local guessB = guessC;
      #local fB = fC;
    #break
    #else
      #local i = 100;
    #end
    #if (mod(i,2)=0)
      #local guessC = (guessA*fB-guessB*fA)/(fB-fA);
    #else
      #local guessC = (guessA+guessB)/2;
    #end
    #local fC = fnReflectance(guessC,A) - reflectance;
    #local i = i + 1;
  #end
  guessC
#end

#macro Subsurface(clrReflectance, clrTranslucency, eta)
  #local Component = array[3] { x,y,z };
  #local vSigmaPrimeS   = <0,0,0>;
  #local vSigmaA        = <0,0,0>;
  #local i = 0;
  #while (i < 3)
    #local reflectance  = vdot(Component[i],clrReflectance);
    #local translucency = vdot(Component[i],clrTranslucency);
    #local alphaPrime   = Albedo(reflectance, eta);
    #local sigmaTr      = 1.0 / translucency;
    #local sigmaPrimeT  = sigmaTr / sqrt(3*(1-alphaPrime));
    #local sigmaPrimeS  = alphaPrime * sigmaPrimeT;
    #local sigmaA       = sigmaPrimeT - sigmaPrimeS;
    #local vSigmaPrimeS = vSigmaPrimeS + Component[i] * sigmaPrimeS;
    #local vSigmaA      = vSigmaA      + Component[i] * sigmaA;
    #local i = i + 1;
  #end
  #debug concat( "subsurface { <", vstr(3,vSigmaPrimeS,",",7,4), ">,<",
vstr(3,vSigmaA,",",7,4), "> }\n")
  subsurface { vSigmaPrimeS, vSigmaA }
#end


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.