Hi Joe,
The BRTDfunc type is probably the most confusing material primitive in the Radiance collection, which is really saying something…
Whereas the specular reflection and transmission coefficients are purely functions of the standard Radiance ray variables (e.g., Nx, Ny, Nz, Dx, Dy, Dz, etc.), the directional-diffuse component is computed from those variables and the direction and size of each light source they are applied to. Therefore, you only give the function names, which can be the same name repeated 3 times for RGB, and define it/tem in your file like so:
directional_diffuse(idx,idy,idz,iom) = {some function of incident direction (idx,idy,idz) and subtended solid angle iom};
Unfortunately, the resulting material calculation will not be complete in the sense that only light sources are considered for the directional-diffuse portion. If you only care about the light scattered by the sun or other known sources and can safely neglect the sky, ground, and any indirect contributions to the directional-diffuse portion, then you are OK. Otherwise, you might want to consider the more complete solution offered by the aBSDF material type, as shown below.
To use a BSDF or aBSDF primitive from a function, you create an appropriate .cal file and call either bsdf2klems or bsdf2ttree. A complete example using a modified Kotey model for roller shades with a Gaussian lobe is given below. Here is the “gaussKoteyBSDF.cal” file:
{
Modified Kotey shade model with Gaussian lobe
converted to BSDF that obeys reciprocity
Need to specify:
AccDeg - peak full width angle for half maximum in degrees (constant)
T0s - transmittance at normal incidence (direct-direct)
T0d - transmittance at normal incidence (direct-diffuse)
R0df - front reflection at normal incidence (direct-diffuse)
R0db - back reflection at normal incidence (direct-diffuse)
}
bound(a,x,b) : if(a-x, a, if(x-b, b, x));
Exp(x) : if(-x-100, 0, exp(x));
Acos(x) : acos(bound(-1,x,1));
GaussFact : sqrt(-.5/log(.5)); { ratio of Gaussian radius over half-max radius }
Gaussian(r) : .5/PI * Exp(-.5*r*r);
abs(x) : if(x, x, -x);
xor(a,b) : if(a, -b, b);
b(T0) : max(-.35*log(max(T0,.01)),.35);
{ functions take argument of ct=cos(theta) }
Ts(ct) : T0s*ct^(b(T0s)-1);
Tdh(ct) : T0d*ct^b(T0d);
Ry(R0) : R0/(1-T0s);
R90d(R0) : R0 + (1-R0)*(.7*Ry(R0)^.7);
Rdfh(ct) : (R0df + (R90d(R0df) - R0df)*(1-ct^.6));
Rdbh(ct) : (R0db + (R90d(R0db) - R0db)*(1-ct^.6));
{ make hemispherical diffuse into BSDFs }
Td(cti,cto) : T0d*(b(T0d)+2)/(2*PI) * cti^b(T0d) * cto^b(T0d);
Rdf(cti,cto) : Rdfh(cti) * Rdfh(cto) / (PI*R0df + 3*PI/13*(R90d(R0df)-R0df));
Rdb(cti,cto) : Rdbh(cti) * Rdbh(cto) / (PI*R0db + 3*PI/13*(R90d(R0db)-R0db));
{ compute Gaussian function }
lobe2(a,k) : k*k * Gaussian(k*a);
lobe(ct) : lobe2(Acos(ct), 1/(GaussFact*PI/360* AccDeg ));
{ complete model }
gaussKotey(ix,iy,iz,sx,sy,sz) : if(xor(iz,sz),
max(Ts(abs(iz))*lobe(-ix*sx-iy*sy-iz*sz), Td(abs(iz),abs(sz))),
if(iz, Rdf(iz,sz), Rdb(-iz,-sz)));
To use this definition to create an isotropic tensor tree, you can run something like:
bsdf2ttree +forward +backward -t3 -g 6 -f aerc6220.cal -e “AccDeg:2.5” -f gaussKoteyBSDF.cal gaussKotey > aerc6220_tt6.xml
Where the file “aerc6220.cal” contains reflectance/transmittance measurements required by “gaussKoteyBSDF.cal”:
{ Reflectance and Transmittance measured using AERC recommendation }
T0s : 0.0608;
T0d : 0.0926 - T0s;
R0df : 0.3862;
R0db : R0df; { not measured? }
The “AccDeg” constant set on the command-line is the acceptance angle in degrees for the specular portion, which gets represented in this case as a Gaussian lobe. The bottom line is that the.cal file defines a complete BSDF, which bsdf2ttree samples according to some maximum resolution, then adaptively reduces into an isotropic tensor tree that can be used in a BSDF or aBSDF type like so:
void aBSDF aerc6220
5 aerc6220_tt6.xml 0 0 1 .
0
0
(If your material is on a horizontal surface, you’ll need a different “up” vector, which doesn’t really matter in the case of an isotropic material.)
If you still want to use the BRTDfunc type and need a more complete example, I have one for the He-Torrance model that is even more complicated than what’s above.
Cheers,
-Greg