// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 /********************************************************************** *< FILE: shaveVrayBaseBSDF.h ( was HairVrBaseBSDF.h ) DESCRIPTION: Generic class for BSDFs CREATED BY: Vladimir Dubovoy HISTORY: created 09-09-2008 ( as part of 3ds Max + VRay hair shaders) merged 31-03-2010 *> **********************************************************************/ #include "shaveVrayBaseBSDF.h" void shaveVrayBaseBSDF::init(const VR::VRayContext &rc, const VR::Color &reflectionColor, const VR::Color &diffuseColor, const VR::Color &ambientColor, const VR::Color &specularTint, const VR::Color &specularTint2, float ambDiff, float specularLevel, float reflectionGlossiness, int ns, const VR::Color &transp, const VR::ShadeVec &hairDir, float requiredTransparency, bool cameraVisibility, bool reflVisibility, bool refrVisibility, bool lightVisibility, bool giVisibility, float selfshadow, bool recvshadow) { this->hairDir=hairDir; // Russian roulette for the transparency for camera rays; this drastically // improves render times for soft transprent hair by reducing the number of // lighting calculations, for roughly the same visual result. It could be // slightly noisier, but the speed gain is worth it. if (rc.rayresult.transpLevel>0 && 0==(rc.rayparams.rayType & (VR::RT_SHADOW | VR::RT_INDIRECT | VR::RT_LIGHT | VR::RT_LIGHTMAP))) { float t=const_cast(rc).getDMCValue(); if (trayresult.sd==rc.rayresult.sd) { //requiredTransparency=1.0f; requiredTransparency = (1.0f - selfshadow); } } } //else if (requiredTransparency!=1.0f && (rc.rayparams.rayType & VR::RT_SHADOW)!=0 // && rc.parent!=NULL && rc.parent->rayresult.sd!=rc.rayresult.sd) //{ // requiredTransparency=1.0f; //} this->requiredTransparency=requiredTransparency; this->isGatherPoint = rc.vray->getSequenceData().globalLightManager->isGatheringPoint(rc) != 0; float contrib=(1.0f-requiredTransparency); // *0.5f; _reflect_filter() = VR::toShadeCol(reflectionColor)*contrib*0.5f; _transparency() = VR::toShadeCol(transp); _diffuse() = VR::toShadeCol(diffuseColor)*contrib; _ambient() = VR::toShadeCol(ambientColor); _spec_tint() = VR::toShadeCol(specularTint); _spec_tint2() = VR::toShadeCol(specularTint2); _ambdiff() = ambDiff; _speclvl() = specularLevel; _cameraVisibility() = cameraVisibility; _lightVisibility() = lightVisibility; _giVisibility() = giVisibility; _combineSampling()= rc.vray->getSequenceData().globalLightManager->isGatheringPoint(rc) != 0; float divd=(reflectionGlossiness*70.0f); divd*=divd; if (divd<1e-6f) { _glossiness()=0.0f; } else { _glossiness() = divd; } _normal() = rc.rayresult.normal; _gnormal()= rc.rayresult.gnormal; } /* | from BRDFSampler */ VR::ShadeCol shaveVrayBaseBSDF::getDiffuseColor(VR::ShadeCol &lightColor) { VR::ShadeCol res=lightColor*diffuse(); lightColor*=currentTransp; //performance test //lightColor.makeZero(); return res; } /* | from BRDFSampler */ VR::ShadeCol shaveVrayBaseBSDF::getLightMult(VR::ShadeCol &lightColor) { VR::ShadeCol res = lightColor*diffuse(); lightColor*=currentTransp; //performance test //lightColor.makeZero(); return res; } /* | from BRDFSampler */ VR::ShadeCol getColorFromDir(const VR::Vector &a) { return VR::ShadeCol(a.x, a.y, a.z)*0.5f+VR::ShadeCol(0.5f, 0.5f, 0.5f); } // This is based on Kajiya, J. T. and Kay, T. L., "Rendering Fur with Three Dimensional Texures", // in SIGGRAPH '89: Proceedings of the 16th annual conference on Computer graphics and interactive techniques inline VR::real getGlossyProbability(const VR::ShadeVec &direction, const VR::ShadeVec &viewDir, const VR::ShadeVec &hairDir, float p) { float cs1=(float) (direction*hairDir); float sn1=sqrtf(VR::Max(0.0f, 1.0f-cs1*cs1)); float cs=(float) (viewDir*hairDir); float sn=sqrtf(VR::Max(0.0f, 1.0f-cs*cs)); float k = VR::Max(0.0f, cs1*cs+sn1*sn); k=powf(k, p); return k; } VR::ShadeCol shaveVrayBaseBSDF::eval(const VR::VRayContext &rc, const VR::ShadeVec &direction, VR::ShadeCol &lightColor, VR::ShadeCol &origLightColor, float probLight, int flags) { //if(((rc.rayparams.rayType & (VR::RT_SHADOW | VR::RT_LIGHT | VR::RT_LIGHTMAP)) != 0) && !lightVisibility()) //{ // return VR::ShadeCol(0.0f, 0.0f, 0.0f); //} //else if(((rc.rayparams.rayType & VR::RT_INDIRECT) != 0) && !giVisibility()) //{ // return VR::ShadeCol(0.0f, 0.0f, 0.0f); //} //else if(rc.rayparams.totalLevel == 0 && !cameraVisibility()) //{ // return origLightColor;//VR::ShadeCol(0.0f, 0.0f, 0.0f); //} float cs0=(float) (direction*rc.rayresult.normal); VR::ShadeVec d2; if (cs0<0.0f) return VR::ShadeCol(0.0f, 0.0f, 0.0f); float cs=(float) (direction*hairDir); ///////////// performance test ////////////// ///////////// white-like BSDF ///////////// //VR::ShadeCol res; //if ((flags & FBRDF_DIFFUSE)==0) res.makeZero(); //else { // float k=cs; // // Apply combined sampling ONLY if GI is on which will pick up the rest of the result // if (isGatherPoint) { // float probReflection=k*2.0f; // probReflection*=probReflection; // probLight*=probLight; // k*=probLight/(probLight+probReflection); // } // res=lightColor*k; //} //lightColor.makeZero(); //origLightColor.makeZero(); //return res; //////////////////////////////////////////// VR::ShadeCol res; VR::ShadeCol diff; VR::ShadeCol spec; VR::ShadeCol spec2; res.makeZero(); diff.makeZero(); spec.makeZero(); spec2.makeZero(); //use spec_tint() and spec_tint2() - to get speclar colors //test //printf("spec_tint %f %f %f \n",spec_tint().r, spec_tint().g, spec_tint().b); //printf("spec_tint2 %f %f %f \n",spec_tint2().r, spec_tint2().g, spec_tint2().b); //if(isGatherPoint)//does not make a difference for perfromance -- 01-11-2010 { if (flags & FBRDF_DIFFUSE) { float sn=sqrtf(VR::Max(0.0f, 1.0f-cs*cs)); float K = sn*ambdiff() + (1.0f - ambdiff()); diff = (lightColor*diffuse())*K; } if (glossiness() > 0.0f && (flags & FBRDF_SPECULAR) && ((rc.rayparams.rayType & VR::RT_NOSPECULAR)==0)) { VUtils::real k = getGlossyProbability(direction, rc.rayparams.viewDir, hairDir, glossiness()); if (k>1.0f) k=1.0f; spec = (speclvl()*k)*(reflect_filter()*lightColor); spec *= spec_tint(); d2=direction*.7+rc.rayparams.viewDir*.3; d2.makeNormalized0(); VUtils::real k2 = getGlossyProbability(d2, rc.rayparams.viewDir, hairDir, glossiness()*.55f); if (k2>1.0f) k2=1.0f; spec2 = (speclvl()*k2)*(reflect_filter()*lightColor); spec2 *= spec_tint2(); } lightColor*=currentTransp; origLightColor*=currentTransp; res = diff + spec+spec2; } return res; } /* | from BRDFSampler */ VR::ShadeCol shaveVrayBaseBSDF::getTransparency(const VR::VRayContext &rc) { return VR::ShadeCol(currentTransp, currentTransp, currentTransp); } void shaveVrayBaseBSDF::traceForward(VR::VRayContext &rc, int doDiffuse) { if (!doDiffuse) rc.mtlresult.color.makeZero(); else rc.mtlresult.color=diffuse()*rc.evalDiffuse(); // joe dec23 if(requiredTransparency < 0.0001f) if ((requiredTransparency < 0.15f)||( (rc.rayparams.rayType & VR::RT_CAMERA)==0 ) ) { rc.mtlresult.transp.set(0.0f, 0.0f, 0.0f); rc.mtlresult.alpha.set(1.0f, 1.0f, 1.0f); // rc.mtlresult.alphaTransp=rc.mtlresult.transp; rc.mtlresult.alphaTransp.set(0.0f, 0.0f, 0.0f); } else { rc.mtlresult.transp.set(requiredTransparency, requiredTransparency, requiredTransparency); rc.mtlresult.alpha=rc.mtlresult.transp.whiteComplement(); rc.mtlresult.alphaTransp=rc.mtlresult.transp; } VR::Fragment *f=rc.mtlresult.fragment; if (f) { const VR::ShadeCol diffColor=diffuse(); const VR::ShadeCol rawGI(rc.evalDiffuse()); const VR::ShadeCol finalGI = rawGI * diffColor; f->setChannelDataByAlias(REG_CHAN_VFB_DIFFUSE, &diffColor); // raw GI shows the light contribution from the GI f->setChannelDataByAlias(REG_CHAN_VFB_RAWGI, &rawGI); f->setChannelDataByAlias(REG_CHAN_VFB_GI, &finalGI); } } /* | from BRDFSampler */ VR::RenderChannelsInfo* shaveVrayBaseBSDF::getRenderChannels() { return &VR::RenderChannelsInfo::reflectChannels; } /* | from BSDFSampler */ VR::BRDFSampler* shaveVrayBaseBSDF::getBRDF(VR::BSDFSide side) { if (side == VR::bsdfSide_front) currentTransp=(1.0f+requiredTransparency)*0.5f; else currentTransp=2.0f*requiredTransparency/(1.0f+requiredTransparency); return static_cast(this); }