int m_brdf2( /* color a ray that hit a BRDF material */ OBJREC *m, RAY *r ) { BRDFDAT nd; COLOR ctmp; FVECT vtmp; double dtmp; /* always a shadow */ if (r->crtype & SHADOW) return(1); /* check arguments */ if ((m->oargs.nsargs < (hasdata(m->otype)?4:2)) | (m->oargs.nfargs < ((m->otype==MAT_TFUNC)|(m->otype==MAT_TDATA)?6:4))) objerror(m, USER, "bad # arguments"); /* check for back side */ if (r->rod < 0.0) { if (!backvis) { raytrans(r); return(1); } raytexture(r, m->omod); flipsurface(r); /* reorient if backvis */ } else raytexture(r, m->omod); nd.mp = m; nd.pr = r; /* get material color */ setcolor(nd.mcolor, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); /* get specular component */ nd.rspec = m->oargs.farg[3]; /* compute transmittance */ if ((m->otype == MAT_TFUNC) | (m->otype == MAT_TDATA)) { nd.trans = m->oargs.farg[4]*(1.0 - nd.rspec); nd.tspec = nd.trans * m->oargs.farg[5]; dtmp = nd.trans - nd.tspec; setcolor(nd.tdiff, dtmp, dtmp, dtmp); } else { nd.tspec = nd.trans = 0.0; setcolor(nd.tdiff, 0.0, 0.0, 0.0); } /* compute reflectance */ dtmp = 1.0 - nd.trans - nd.rspec; setcolor(nd.rdiff, dtmp, dtmp, dtmp); nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */ multcolor(nd.mcolor, r->pcol); /* modify material color */ multcolor(nd.rdiff, nd.mcolor); multcolor(nd.tdiff, nd.mcolor); /* load auxiliary files */ if (hasdata(m->otype)) { nd.dp = getdata(m->oargs.sarg[1]); getfunc(m, 2, 0, 0); } else { nd.dp = NULL; getfunc(m, 1, 0, 0); } /* compute ambient */ if (nd.trans < 1.0-FTINY) { copycolor(ctmp, nd.mcolor); /* modified by material color */ scalecolor(ctmp, 1.0-nd.trans); multambient(ctmp, r, nd.pnorm); addcolor(r->rcol, ctmp); /* add to returned color */ } if (nd.trans > FTINY) { /* from other side */ flipsurface(r); vtmp[0] = -nd.pnorm[0]; vtmp[1] = -nd.pnorm[1]; vtmp[2] = -nd.pnorm[2]; copycolor(ctmp, nd.mcolor); scalecolor(ctmp, nd.trans); multambient(ctmp, r, vtmp); addcolor(r->rcol, ctmp); flipsurface(r); } /* add direct component */ direct(r, dirbrdf, &nd); return(1); }
int m_ashikhmin( /* shade ray that hit something anisotropic */ OBJREC *m, RAY *r ) { ASHIKDAT nd; COLOR ctmp; double fres; int i; /* easy shadow test */ if (r->crtype & SHADOW) return(1); if (m->oargs.nfargs != 8) objerror(m, USER, "bad number of real arguments"); /* check for back side */ if (r->rod < 0.0) { if (!backvis) { raytrans(r); return(1); } raytexture(r, m->omod); flipsurface(r); /* reorient if backvis */ } else raytexture(r, m->omod); /* get material color */ nd.mp = m; nd.rp = r; setcolor(nd.mcolor, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); setcolor(nd.scolor, m->oargs.farg[3], m->oargs.farg[4], m->oargs.farg[5]); /* get specular power */ nd.specfl = 0; nd.u_power = m->oargs.farg[6]; nd.v_power = m->oargs.farg[7]; nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */ if (nd.pdot < .001) nd.pdot = .001; /* non-zero for dirashik() */ multcolor(nd.mcolor, r->pcol); /* modify diffuse color */ if (bright(nd.scolor) > FTINY) { /* adjust specular color */ nd.specfl |= SPA_REFL; /* check threshold */ if (specthresh >= bright(nd.scolor)-FTINY) nd.specfl |= SPA_RBLT; fres = schlick_fres(nd.pdot); /* Schick's Fresnel approx */ for (i = 0; i < 3; i++) colval(nd.scolor,i) += (1.-colval(nd.scolor,i))*fres; } if (r->ro != NULL && isflat(r->ro->otype)) nd.specfl |= SPA_FLAT; /* set up coordinates */ getacoords_as(&nd); /* specular sampling? */ if ((nd.specfl & (SPA_REFL|SPA_RBLT)) == SPA_REFL) ashiksamp(&nd); /* diffuse interreflection */ if (bright(nd.mcolor) > FTINY) { copycolor(ctmp, nd.mcolor); /* modified by material color */ if (nd.specfl & SPA_RBLT) /* add in specular as well? */ addcolor(ctmp, nd.scolor); multambient(ctmp, r, nd.pnorm); addcolor(r->rcol, ctmp); /* add to returned color */ } direct(r, dirashik, &nd); /* add direct component */ return(1); }
int m_brdf( /* color a ray that hit a BRDTfunc material */ OBJREC *m, RAY *r ) { int hitfront = 1; BRDFDAT nd; RAY sr; double mirtest=0, mirdist=0; double transtest=0, transdist=0; int hasrefl, hastrans; int hastexture; COLOR ctmp; FVECT vtmp; double d; MFUNC *mf; int i; /* check arguments */ if ((m->oargs.nsargs < 10) | (m->oargs.nfargs < 9)) objerror(m, USER, "bad # arguments"); nd.mp = m; nd.pr = r; /* dummy values */ nd.rspec = nd.tspec = 1.0; nd.trans = 0.5; /* diffuse reflectance */ if (r->rod > 0.0) setcolor(nd.rdiff, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); else setcolor(nd.rdiff, m->oargs.farg[3], m->oargs.farg[4], m->oargs.farg[5]); /* diffuse transmittance */ setcolor(nd.tdiff, m->oargs.farg[6], m->oargs.farg[7], m->oargs.farg[8]); /* get modifiers */ raytexture(r, m->omod); hastexture = DOT(r->pert,r->pert) > FTINY*FTINY; if (hastexture) { /* perturb normal */ nd.pdot = raynormal(nd.pnorm, r); } else { VCOPY(nd.pnorm, r->ron); nd.pdot = r->rod; } if (r->rod < 0.0) { /* orient perturbed values */ nd.pdot = -nd.pdot; for (i = 0; i < 3; i++) { nd.pnorm[i] = -nd.pnorm[i]; r->pert[i] = -r->pert[i]; } hitfront = 0; } copycolor(nd.mcolor, r->pcol); /* get pattern color */ multcolor(nd.rdiff, nd.mcolor); /* modify diffuse values */ multcolor(nd.tdiff, nd.mcolor); hasrefl = bright(nd.rdiff) > FTINY; hastrans = bright(nd.tdiff) > FTINY; /* load cal file */ nd.dp = NULL; mf = getfunc(m, 9, 0x3f, 0); /* compute transmitted ray */ setbrdfunc(&nd); errno = 0; setcolor(ctmp, evalue(mf->ep[3]), evalue(mf->ep[4]), evalue(mf->ep[5])); if ((errno == EDOM) | (errno == ERANGE)) objerror(m, WARNING, "compute error"); else if (rayorigin(&sr, TRANS, r, ctmp) == 0) { if (!(r->crtype & SHADOW) && hastexture) { /* perturb direction */ VSUM(sr.rdir, r->rdir, r->pert, -.75); if (normalize(sr.rdir) == 0.0) { objerror(m, WARNING, "illegal perturbation"); VCOPY(sr.rdir, r->rdir); } } else { VCOPY(sr.rdir, r->rdir); } rayvalue(&sr); multcolor(sr.rcol, sr.rcoef); addcolor(r->rcol, sr.rcol); if (!hastexture) { transtest = 2.0*bright(sr.rcol); transdist = r->rot + sr.rt; } } if (r->crtype & SHADOW) /* the rest is shadow */ return(1); /* compute reflected ray */ setbrdfunc(&nd); errno = 0; setcolor(ctmp, evalue(mf->ep[0]), evalue(mf->ep[1]), evalue(mf->ep[2])); if ((errno == EDOM) | (errno == ERANGE)) objerror(m, WARNING, "compute error"); else if (rayorigin(&sr, REFLECTED, r, ctmp) == 0) { VSUM(sr.rdir, r->rdir, nd.pnorm, 2.*nd.pdot); checknorm(sr.rdir); rayvalue(&sr); multcolor(sr.rcol, sr.rcoef); addcolor(r->rcol, sr.rcol); if (!hastexture && r->ro != NULL && isflat(r->ro->otype)) { mirtest = 2.0*bright(sr.rcol); mirdist = r->rot + sr.rt; } } /* compute ambient */ if (hasrefl) { if (!hitfront) flipsurface(r); copycolor(ctmp, nd.rdiff); multambient(ctmp, r, nd.pnorm); addcolor(r->rcol, ctmp); /* add to returned color */ if (!hitfront) flipsurface(r); } if (hastrans) { /* from other side */ if (hitfront) flipsurface(r); vtmp[0] = -nd.pnorm[0]; vtmp[1] = -nd.pnorm[1]; vtmp[2] = -nd.pnorm[2]; copycolor(ctmp, nd.tdiff); multambient(ctmp, r, vtmp); addcolor(r->rcol, ctmp); if (hitfront) flipsurface(r); } if (hasrefl | hastrans || m->oargs.sarg[6][0] != '0') direct(r, dirbrdf, &nd); /* add direct component */ d = bright(r->rcol); /* set effective distance */ if (transtest > d) r->rt = transdist; else if (mirtest > d) r->rt = mirdist; return(1); }
int m_aniso( /* shade ray that hit something anisotropic */ OBJREC *m, RAY *r ) { ANISODAT nd; COLOR ctmp; int i; /* easy shadow test */ if (r->crtype & SHADOW) return(1); if (m->oargs.nfargs != (m->otype == MAT_TRANS2 ? 8 : 6)) objerror(m, USER, "bad number of real arguments"); /* check for back side */ if (r->rod < 0.0) { if (!backvis) { raytrans(r); return(1); } raytexture(r, m->omod); flipsurface(r); /* reorient if backvis */ } else raytexture(r, m->omod); /* get material color */ nd.mp = m; nd.rp = r; setcolor(nd.mcolor, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); /* get roughness */ nd.specfl = 0; nd.u_alpha = m->oargs.farg[4]; nd.v_alpha = m->oargs.farg[5]; if ((nd.u_alpha <= FTINY) | (nd.v_alpha <= FTINY)) objerror(m, USER, "roughness too small"); nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */ if (nd.pdot < .001) nd.pdot = .001; /* non-zero for diraniso() */ multcolor(nd.mcolor, r->pcol); /* modify material color */ /* get specular component */ if ((nd.rspec = m->oargs.farg[3]) > FTINY) { nd.specfl |= SP_REFL; /* compute specular color */ if (m->otype == MAT_METAL2) copycolor(nd.scolor, nd.mcolor); else setcolor(nd.scolor, 1.0, 1.0, 1.0); scalecolor(nd.scolor, nd.rspec); /* check threshold */ if (specthresh >= nd.rspec-FTINY) nd.specfl |= SP_RBLT; /* compute refl. direction */ VSUM(nd.vrefl, r->rdir, nd.pnorm, 2.0*nd.pdot); if (DOT(nd.vrefl, r->ron) <= FTINY) /* penetration? */ VSUM(nd.vrefl, r->rdir, r->ron, 2.0*r->rod); } /* compute transmission */ if (m->otype == MAT_TRANS2) { nd.trans = m->oargs.farg[6]*(1.0 - nd.rspec); nd.tspec = nd.trans * m->oargs.farg[7]; nd.tdiff = nd.trans - nd.tspec; if (nd.tspec > FTINY) { nd.specfl |= SP_TRAN; /* check threshold */ if (specthresh >= nd.tspec-FTINY) nd.specfl |= SP_TBLT; if (DOT(r->pert,r->pert) <= FTINY*FTINY) { VCOPY(nd.prdir, r->rdir); } else { for (i = 0; i < 3; i++) /* perturb */ nd.prdir[i] = r->rdir[i] - r->pert[i]; if (DOT(nd.prdir, r->ron) < -FTINY) normalize(nd.prdir); /* OK */ else VCOPY(nd.prdir, r->rdir); } } } else nd.tdiff = nd.tspec = nd.trans = 0.0; /* diffuse reflection */ nd.rdiff = 1.0 - nd.trans - nd.rspec; if (r->ro != NULL && isflat(r->ro->otype)) nd.specfl |= SP_FLAT; getacoords(&nd); /* set up coordinates */ if (nd.specfl & (SP_REFL|SP_TRAN)) agaussamp(&nd); if (nd.rdiff > FTINY) { /* ambient from this side */ copycolor(ctmp, nd.mcolor); /* modified by material color */ scalecolor(ctmp, nd.rdiff); if (nd.specfl & SP_RBLT) /* add in specular as well? */ addcolor(ctmp, nd.scolor); multambient(ctmp, r, nd.pnorm); addcolor(r->rcol, ctmp); /* add to returned color */ } if (nd.tdiff > FTINY) { /* ambient from other side */ FVECT bnorm; flipsurface(r); bnorm[0] = -nd.pnorm[0]; bnorm[1] = -nd.pnorm[1]; bnorm[2] = -nd.pnorm[2]; copycolor(ctmp, nd.mcolor); /* modified by color */ if (nd.specfl & SP_TBLT) scalecolor(ctmp, nd.trans); else scalecolor(ctmp, nd.tdiff); multambient(ctmp, r, bnorm); addcolor(r->rcol, ctmp); flipsurface(r); } /* add direct component */ direct(r, diraniso, &nd); return(1); }