Point3 Splat::EvalNormalPerturb(ShadeContext& sc) { float del, d, f; Point3 p, dp, np; if (gbufID) sc.SetGBufferID(gbufID); xyzGen->GetXYZ(sc, p, dp); d = splatter(p); del = 0.1f; // float strength = (abs((int)col[1].r-(int)col[0].r)+ // abs((int)col[1].g-(int)col[0].g)+ // abs((int)col[1].b-(int)col[0].b)); ///100.0f; // 756.0f // f = strength/del; f = 1.0f/del; Point3 M[3]; xyzGen->GetBumpDP(sc,M); np.x = f*(splatter(p+del*M[0]) - d); np.y = f*(splatter(p+del*M[1]) - d); np.z = f*(splatter(p+del*M[2]) - d); np = sc.VectorFromNoScale(np,REF_OBJECT); Texmap *sub0 = mapOn[0]?subTex[0]:NULL; Texmap *sub1 = mapOn[1]?subTex[1]:NULL; if (sub0||sub1) { // d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da) + da float a,b; Point3 da,db; if (sub0) { a = sub0->EvalMono(sc); da = sub0->EvalNormalPerturb(sc); } else { a = Intens(col[0]); da = Point3(0.0f,0.0f,0.0f); } if (sub1) { b = sub1->EvalMono(sc); db = sub1->EvalNormalPerturb(sc); } else { b = Intens(col[1]); db= Point3(0.0f,0.0f,0.0f); } np = (b-a)*np + d*(db-da) + da; } else np *= Intens(col[1])-Intens(col[0]); return np; }
Point3 Speckle::EvalNormalPerturb(ShadeContext& sc) { float del, d; Point3 p, dp; Point3 np; if (gbufID) sc.SetGBufferID(gbufID); xyzGen->GetXYZ(sc, p, dp); if (size == 0.0f) size = 0.0001f; p *= SCALE_FACTOR/size; del = 0.1f; d = SpeckleFunc(p); Point3 M[3]; xyzGen->GetBumpDP(sc,M); np.x = (SpeckleFunc(p+del*M[0]) - d)/del; np.y = (SpeckleFunc(p+del*M[1]) - d)/del; np.z = (SpeckleFunc(p+del*M[2]) - d)/del; np = sc.VectorFromNoScale(np,REF_OBJECT); Texmap *sub0 = mapOn[0]?subTex[0]:NULL; Texmap *sub1 = mapOn[1]?subTex[1]:NULL; if (sub0||sub1) { // d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da) + da float a,b; Point3 da,db; if (sub0) { a = sub0->EvalMono(sc); da = sub0->EvalNormalPerturb(sc); } else { a = Intens(col[0]); da = Point3(0.0f,0.0f,0.0f); } if (sub1) { b = sub1->EvalMono(sc); db = sub1->EvalNormalPerturb(sc); } else { b = Intens(col[1]); db= Point3(0.0f,0.0f,0.0f); } np = (b-a)*np + d*(db-da) + da; } else np *= Intens(col[1])-Intens(col[0]); return np; }
Point3 Stucco::EvalNormalPerturb(ShadeContext& sc) { float d,k; Point3 p, dp, np; if (gbufID) sc.SetGBufferID(gbufID); xyzGen->GetXYZ(sc, p, dp); float scl = compscl(dp, size); p /= size; d = Func(p, scl); k = 0.25f/del; Point3 M[3]; xyzGen->GetBumpDP(sc,M); np.x = (Func(p + del*M[0], scl) - d)*k; np.y = (Func(p + del*M[1], scl) - d)*k; np.z = (Func(p + del*M[2], scl) - d)*k; np = sc.VectorFromNoScale(np,REF_OBJECT); Texmap *sub0 = mapOn[0]?subTex[0]:NULL; Texmap *sub1 = mapOn[1]?subTex[1]:NULL; if (sub0||sub1) { // d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da) + da float a,b; Point3 da,db; if (sub0) { a = sub0->EvalMono(sc); da = sub0->EvalNormalPerturb(sc); } else { a = Intens(col[0]); da = Point3(0.0f,0.0f,0.0f); } if (sub1) { b = sub1->EvalMono(sc); db = sub1->EvalNormalPerturb(sc); } else { b = Intens(col[1]); db= Point3(0.0f,0.0f,0.0f); } np = (b-a)*np + d*(db-da) + da; } else np *= Intens(col[1])-Intens(col[0]); return np; }
float plStaticEnvLayer::EvalMono(ShadeContext& sc) { if (fBitmapPB->GetInt(kBmpMonoOutput) == 1) return EvalColor(sc).a; return Intens(EvalColor(sc)); }
Point3 Noise::EvalNormalPerturb(ShadeContext& sc) { Point3 p,dp; if (!sc.doMaps) return Point3(0,0,0); if (gbufID) sc.SetGBufferID(gbufID); UpdateCache(sc.CurTime()); // DS 10/3/00 xyzGen->GetXYZ(sc,p,dp); p /= size; filter = sc.filterMaps; float smw; float limlev = LimitLevel(dp,smw); float del,d; d = NoiseFunction(p,limlev,smw); //del = (dp.x+dp.y+dp.z)/(size*3.0f); del = .1f; Point3 np; Point3 M[3]; xyzGen->GetBumpDP(sc,M); np.x = (NoiseFunction(p+del*M[0],limlev,smw) - d)/del; np.y = (NoiseFunction(p+del*M[1],limlev,smw) - d)/del; np.z = (NoiseFunction(p+del*M[2],limlev,smw) - d)/del; np = sc.VectorFromNoScale(np, REF_OBJECT); Texmap *sub0 = mapOn[0]?subTex[0]:NULL; Texmap *sub1 = mapOn[1]?subTex[1]:NULL; if (sub0||sub1) { // d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da) + da float a,b; Point3 da,db; if (sub0) { a = sub0->EvalMono(sc); da = sub0->EvalNormalPerturb(sc); } else { a = Intens(col[0]); da = Point3(0.0f,0.0f,0.0f); } if (sub1) { b = sub1->EvalMono(sc); db = sub1->EvalNormalPerturb(sc); } else { b = Intens(col[1]); db= Point3(0.0f,0.0f,0.0f); } np = (b-a)*np + d*(db-da) + da; } else np *= Intens(col[1])-Intens(col[0]); return texout->Filter(np); }
float Noise::EvalMono(ShadeContext& sc) { Point3 p,dp; if (!sc.doMaps) return 0.0f; float f; if (sc.GetCache(this,f)) return f; if (gbufID) sc.SetGBufferID(gbufID); UpdateCache(sc.CurTime()); // DS 10/3/00 xyzGen->GetXYZ(sc,p,dp); p /= size; filter = sc.filterMaps; float smw; float limlev = LimitLevel(dp, smw); float d = NoiseFunction(p,limlev,smw); float c0 = mapOn[0]&&subTex[0] ? subTex[0]->EvalMono(sc): Intens(col[0]); float c1 = mapOn[1]&&subTex[1] ? subTex[1]->EvalMono(sc): Intens(col[1]); f = texout->Filter((1.0f-d)*c0 + d*c1); sc.PutCache(this,f); return f; }
float Plate::EvalMono(ShadeContext& sc) { return Intens(EvalColor(sc)); }
Point3 BerconNoise::EvalNormalPerturb(ShadeContext& sc) { if (!sc.doMaps) return Point3(0,0,0); if (gbufID) sc.SetGBufferID(gbufID); // UVW and Distortion Point3 p, dpdx, dpdy; Point3 M[3]; if (!berconXYZ.get(sc, p, dpdx, dpdy, M)) return Point3(0,0,0); if (useDistortion) applyDistortion(sc,p); float nSize = (mapOn[4] && subtex[4]) ? subtex[4]->EvalMono(sc)*size : size; p /= nSize; Noise::alterUVW(p, uvwDist); NoiseParams np = EvalParameters(&sc); // Vector Point3 normal; float d = Noise::limitedNoise(p, np); if (useCurve) { d = curve->GetControlCurve(0)->GetValue(sc.CurTime(), d); normal.x = (curve->GetControlCurve(0)->GetValue(sc.CurTime(), Noise::limitedNoise(p+DELTA*M[0], np)) - d) / DELTA; normal.y = (curve->GetControlCurve(0)->GetValue(sc.CurTime(), Noise::limitedNoise(p+DELTA*M[1], np)) - d) / DELTA; normal.z = (curve->GetControlCurve(0)->GetValue(sc.CurTime(), Noise::limitedNoise(p+DELTA*M[2], np)) - d) / DELTA; } else { normal.x = (Noise::limitedNoise(p+DELTA*M[0], np) - d) / DELTA; normal.y = (Noise::limitedNoise(p+DELTA*M[1], np) - d) / DELTA; normal.z = (Noise::limitedNoise(p+DELTA*M[2], np) - d) / DELTA; } normal = -sc.VectorFromNoScale(normal, REF_OBJECT); // Eval sub maps float f1, f2; Point3 v1, v2; bool maps = false; if (subtex[0]) { f1 = subtex[0]->EvalMono(sc); v1 = subtex[0]->EvalNormalPerturb(sc); maps = true; } else { f1 = Intens(col[0]); v1 = Point3(0.f, 0.f, 0.f); } if (subtex[1]) { f2 = subtex[1]->EvalMono(sc); v2 = subtex[1]->EvalNormalPerturb(sc); maps = true; } else { f2 = Intens(col[1]); v2 = Point3(0.f, 0.f, 0.f); } // Calculate vector if (maps) normal = (f2-f1)*normal + d*v2 + (1.f-d)*v1; else normal *= f2 - f1; return texout->Filter(normal); // Does this filter actually do something? }
float BerconNoise::EvalMono(ShadeContext& sc) { // TODO: Evaluate two maps with mono instead of color, slightly faster... return Intens(EvalColor(sc)); }
float BerconTile::EvalMono(ShadeContext& sc) { return Intens(EvalColor(sc)); }
void WardShader::Illum(ShadeContext &sc, IllumParams &ip) { LightDesc *l; Color lightCol; #ifdef _DEBUG IPoint2 sp = sc.ScreenCoord(); if ( sp.x == stopX && sp.y == stopY ) sp.x = stopX; #endif BOOL isShiny= (ip.channels[W_SL].r > 0.0f) ? 1 : 0; for (int i=0; i<sc.nLights; i++) { l = sc.Light(i); float NL, Kl; Point3 L; if (l->Illuminate( sc, sc.Normal(), lightCol, L, NL, Kl)) { if (l->ambientOnly) { ip.ambIllumOut += lightCol; continue; } if (NL<=0.0f) continue; // diffuse if (l->affectDiffuse){ ip.diffIllumOut += Kl / Pi * ip.channels[W_DL].r * lightCol; } // specular if (isShiny && l->affectSpecular) { float gx = ip.channels[W_GX].r; float gy = ip.channels[W_GY].r; assert( gx >= 0.0f && gy >= 0.0f ); Point3 H = Normalize(L - sc.V() ); // (L + -V)/2 float NH = DotProd(sc.Normal(), H); if (NH > 0.0f) { float g2 = normalizeOn ? gx * gy : DEFAULT_GLOSS2; float norm = 1.0f / (4.0f * PI * g2); float NV = -DotProd(sc.Normal(), sc.V() ); if ( NV <= 0.001f) NV = 0.001f; float g = 1.0f / (float)sqrt( NL * NV ); if ( g > 6.0f ) g = 6.0f; //Point3 basisVecs[ 3 ]; //sc.DPdUVW( basisVecs, uvChan ); // 0 is vtxclr, 1..n is uv channels, max_meshmaps in mesh.h //basisVecs[0] = Normalize( basisVecs[0] ); // This is the new preferred method for getting bump basis vectors -- DS 5/22/00 Point3 basisVecs[2]; sc.BumpBasisVectors(basisVecs, 0, uvChan); // the line between the tip of vec[0] and its projection on N is tangent Point3 T = basisVecs[0] - sc.Normal() * Dot( basisVecs[0], sc.Normal() ); Point3 B = CrossProd( sc.Normal(), T ); float x = DotProd( H, T ) / gx; float y = DotProd( H, B ) / gy; float e = (float)exp( -2.0 * (x*x + y*y) / (1.0+NH) ); ip.specIllumOut += Kl * ip.channels[W_SL].r * norm * g * e * lightCol; } } } } // for each light // now we can multiply by the clrs, ip.ambIllumOut *= ip.channels[W_AM]; ip.diffIllumIntens = Intens(ip.diffIllumOut); ip.diffIllumOut *= ip.channels[W_DI]; ip.specIllumOut *= ip.channels[W_SP]; int chan = ip.stdIDToChannel[ ID_RR ]; ShadeTransmission(sc, ip, ip.channels[chan], ip.refractAmt); chan = ip.stdIDToChannel[ ID_RL ]; ShadeReflection( sc, ip, ip.channels[chan] ); if (sc.globContext != NULL && sc.globContext->pToneOp != NULL) { if (isInvertSelfIllum()) sc.globContext->pToneOp->RGBToScaled(ip.selfIllumOut); if (isInvertReflect() && (ip.hasComponents & HAS_REFLECT)) sc.globContext->pToneOp->RGBToScaled(ip.reflIllumOut); if (isInvertRefract() && (ip.hasComponents & HAS_REFRACT)) sc.globContext->pToneOp->RGBToScaled(ip.transIllumOut); } CombineComponents( sc, ip ); }
float CrackVisualizer::EvalMono(ShadeContext& sc) { //TODO: Evaluate the map for a "mono" channel return Intens(EvalColor(sc)); }
float CellTex::EvalMono(ShadeContext& sc) { return Intens(EvalColor(sc)); }
float SampleShaderPlugin::EvalMono(ShadeContext& sc) { //TODO: Evaluate the map for a "mono" channel return Intens(EvalColor(sc)); }
// if this function changes, please also check SupportsReShading, PreShade and PostShade // end - ke/mjm - 03.16.00 - merge reshading code // [attilas|29.5.2000] if this function changes, please also check EvalColorStdChannel void Matte::Shade(ShadeContext& sc) { Color c,t, shadowClr; float atten; float reflA; // > 6/15/02 - 11:12am --MQM-- // for renderer prepass, we need to at least call // illuminate so that Light Tracer can cache shading if ( SHADECONTEXT_IS_PREPASS( sc ) ) { Color lightCol; Point3 L; float NL = 0.0f, diffCoef = 0.0f; LightDesc *l = NULL; for ( int i = 0; i < sc.nLights; i++ ) { l = sc.Light( i ); if ( NULL != l ) l->Illuminate( sc, sc.Normal(), lightCol, L, NL, diffCoef ); } return; } #ifdef _DEBUG IPoint2 sp = sc.ScreenCoord(); if ( sp.x == stopX && sp.y == stopY ) sp.x = stopX; #endif if (gbufID) sc.SetGBufferID(gbufID); IllumParams ip( 1, &shadowIllumOutStr); IllumParams ipNS(0, NULL); ip.ClearInputs(); ip.ClearOutputs(); ipNS.ClearInputs(); ipNS.ClearOutputs(); ip.hasComponents = ipNS.hasComponents = HAS_MATTE_MTL; // get background color & transparency if (!opaque) sc.Execute(0x1000); // DS: 6/24/99:use black bg when AA filtering (#192348) sc.GetBGColor(c, t, fogBG&&(!fogObjDepth) ); if (!opaque) sc.Execute(0x1001); // DS: 6/24/99:use black bg when AA filtering (#192348) if (shadowBG && sc.shadow) { /******** sc.shadow = 0; Color col0 = sc.DiffuseIllum(); sc.shadow = 1; Color scol = sc.DiffuseIllum(); float f = Intens(col0); atten = (f>0.0f)?Intens(scol)/f:1.0f; if (atten>1.0f) atten = 1.0f/atten; ********/ atten = IllumShadow( sc, shadowClr ); atten = amblev + (1.0f-amblev) * atten; // key on black user-set shadow clr if( gUseLocalShadowClr || col.r != 0.0f || col.g != 0.0f || col.b != 0.0f ) shadowClr = col; ipNS.finalC = ipNS.diffIllumOut = c; c *= atten; ip.diffIllumOut = c; shadowClr *= 1.0f - atten; ip.finalC = sc.out.c = c + shadowClr; ip.SetUserIllumOutput( 0, shadowClr ); if (shadowAlpha) t *= atten; } else { sc.out.c = ipNS.finalC = ipNS.diffIllumOut = ip.finalC = ip.diffIllumOut = c; } // add the reflections if (reflmap && useReflMap) { AColor rcol; if (reflmap->HandleOwnViewPerturb()) { sc.TossCache(reflmap); rcol = reflmap->EvalColor(sc); } else rcol = sc.EvalEnvironMap(reflmap, sc.ReflectVector()); Color rc; rc = Color(rcol.r,rcol.g,rcol.b)*reflAmt; ip.reflIllumOut = ipNS.reflIllumOut = rc; if( additiveReflection ) { // additive compositing of reflections sc.out.c += rc; ip.finalC += rc; ipNS.finalC += rc; } else { reflA = Intens( rc ); // over compositing of reflections sc.out.c = (1.0f - reflA) * sc.out.c + rc; ip.finalC = (1.0f - reflA) * ip.finalC + rc; ipNS.finalC = (1.0f - reflA) * ipNS.finalC + rc; } } // render elements Clamp( t ); Clamp( reflA ); ip.finalT = ipNS.finalT = sc.out.t = opaque ? black: additiveReflection? t : Color(reflA,reflA,reflA) ; int nEles = sc.NRenderElements(); if( nEles != 0 ){ ip.pShader = ipNS.pShader = NULL; // no shader on matte mtl ip.stdIDToChannel = ipNS.stdIDToChannel = NULL; ip.pMtl = ipNS.pMtl = this; ip.finalAttenuation = ipNS.finalAttenuation = 1.0f; for( int i=0; i < nEles; ++i ){ IRenderElement* pEle = sc.GetRenderElement(i); if( pEle->IsEnabled() ){ MaxRenderElement* pMaxEle = (MaxRenderElement*)pEle->GetInterface( MaxRenderElement::IID ); if( pEle->ShadowsApplied() ) pMaxEle->PostIllum( sc, ip ); else pMaxEle->PostIllum( sc, ipNS ); } } } }
//???????????????????????????????????????????????????????????????????????? // The stdID parameter doesn't really have a meaning in this case. // bool Matte::EvalMonoStdChannel ( ShadeContext& sc, // describes context of evaluation int stdID, // must be ID_AM, ect float& outVal // output var ) { switch ( stdID ) { case ID_BU: // Bump (value 8) case ID_RR: // Refraction (value 10) case ID_DP: // Displacement (value 11) case ID_SI: // Self-illumination (value 5) case ID_FI: // Filter color (value 7) return false; break; case ID_RL: // Reflection (value 9) if ( sc.doMaps && reflmap && useReflMap && reflmap->IsOutputMeaningful(sc) ) { if ( reflmap->HandleOwnViewPerturb() ) { sc.TossCache(reflmap); outVal = reflmap->EvalMono(sc); } else { AColor rcol; rcol = sc.EvalEnvironMap( reflmap, sc.ReflectVector() ); Color rc; rc = Color(rcol.r,rcol.g,rcol.b)*reflAmt; outVal = Intens(rc); } } else return false; break; case ID_AM: // Ambient (value 0) outVal = Intens( GetAmbient() ); break; case ID_DI: // Diffuse (value 1) outVal = Intens( GetDiffuse() ); break; case ID_SP: // Specular (value 2) outVal = Intens( GetSpecular() ); break; case ID_SH: // Shininess (value 3). In R3 and later this is called Glossiness. outVal = GetShininess(); break; case ID_SS: // Shininess strength (value 4). In R3 and later this is called Specular Level. outVal = GetShinStr(); break; case ID_OP: // Opacity (value 6) outVal = GetXParency(); break; default: // Should never happen //DbgAssert( false ); return false; break; } return true; }
void OrenNayarBlinnShader::Illum(ShadeContext &sc, IllumParams &ip) { LightDesc *l; Color lightCol; #ifdef _DEBUG IPoint2 sp = sc.ScreenCoord(); if ( sp.x == stopX && sp.y == stopY ) sp.x = stopX; #endif // Blinn style phong BOOL isShiny= (ip.channels[ID_SS].r > 0.0f) ? 1 : 0; double phExp = 0.0; if (isShiny) phExp = pow(2.0, ip.channels[ID_SH].r * 10.0) * 4.0; for (int i=0; i<sc.nLights; i++) { l = sc.Light(i); float NL, kL; Point3 L; if (l->Illuminate( sc, sc.Normal(), lightCol, L, NL, kL)) { if (l->ambientOnly) { ip.ambIllumOut += lightCol; continue; } if (NL<=0.0f) continue; // specular Color spec( 0.0f, 0.0f, 0.0f ); if (isShiny && l->affectSpecular) { Point3 H = Normalize(L-sc.V() ); // (L + -V)/2 float c = DotProd(sc.Normal(), H); if (c>0.0f) { if (softThresh != 0.0 && kL < softThresh) { c *= Soften(kL/softThresh); } c = (float)pow((double)c, phExp); // could use table lookup for speed spec = c * ip.channels[ID_SS].r * lightCol; ip.specIllumOut += spec; } } // diffuse if (l->affectDiffuse){ float diffIntens; Color d = OrenNayarIllum( sc.Normal(), L, sc.V(), ip.channels[ID_DIFF_ROUGH].r * Pi*0.5f, ip.channels[ID_DI], &diffIntens, NL ); d = d * ip.channels[ID_DIFF_LEV].r; ip.diffIllumOut += kL * d * lightCol; ip.diffIllumIntens += kL * diffIntens * Intens(lightCol); } } } // for each light // Apply mono self illumination if ( ! selfIllumClrOn ){ float si = 0.3333333f * (ip.channels[ID_SI].r + ip.channels[ID_SI].g + ip.channels[ID_SI].b); // float si = ip.channels[ID_SI].r; //DS: 4/23/99 if ( si > 0.0f ) { si = Bound( si ); ip.selfIllumOut = si * ip.channels[ID_DI]; ip.diffIllumOut *= (1.0f - si); // fade the ambient down on si: 5/27/99 ke ip.ambIllumOut *= 1.0f-si; } } else { // colored self illum, ip.selfIllumOut += ip.channels[ID_SI]; } // get the diffuse intensity...unscramble the wavelength dependence // float rho, diffIntens; // rho = ip.channels[ID_DI].r == 0.0f ? 1.0f : 1.0f / ip.channels[ID_DI].r; // diffIntens = ip.diffIllumOut.r * rho; // rho = ip.channels[ID_DI].g == 0.0f ? 1.0f : 1.0f / ip.channels[ID_DI].g; // diffIntens += ip.diffIllumOut.g * rho; // rho = ip.channels[ID_DI].b == 0.0f ? 1.0f : 1.0f / ip.channels[ID_DI].b; // diffIntens += ip.diffIllumOut.b * rho; // ip.diffIllumIntens = diffIntens * 0.5f; // now we can multiply by the clrs ip.specIllumOut *= ip.channels[ID_SP]; ip.ambIllumOut *= ip.channels[ID_AM]; int chan = ip.stdIDToChannel[ ID_RR ]; ShadeTransmission(sc, ip, ip.channels[chan], ip.refractAmt); chan = ip.stdIDToChannel[ ID_RL ]; ShadeReflection( sc, ip, ip.channels[chan] ); if (sc.globContext != NULL && sc.globContext->pToneOp != NULL) { if (isInvertSelfIllum()) sc.globContext->pToneOp->RGBToScaled(ip.selfIllumOut); if (isInvertReflect() && (ip.hasComponents & HAS_REFLECT)) sc.globContext->pToneOp->RGBToScaled(ip.reflIllumOut); if (isInvertRefract() && (ip.hasComponents & HAS_REFRACT)) sc.globContext->pToneOp->RGBToScaled(ip.transIllumOut); } CombineComponents( sc, ip ); }
float PainterTextureSample::EvalMono(ShadeContext& sc) { //TODO: Evaluate the map for a "mono" channel return Intens(EvalColor(sc)); }
void StraussShader::Illum(ShadeContext &sc, IllumParams &ip) { LightDesc *l; Color lightClr; #ifdef _DEBUG IPoint2 sp = sc.ScreenCoord(); if ( sp.x == stopX && sp.y == stopY ) sp.x = stopX; #endif float opac = ip.channels[ S_TR ].r; float g = ip.channels[ S_GL ].r; float m = ip.channels[ S_MT ].r; Color Cd = ip.channels[ S_DI ]; // BOOL dimDiffuse = ip.hasComponents & HAS_REFLECT; BOOL dimDiffuse = ip.hasComponents & HAS_REFLECT_MAP; float rd; float g3 = Cube( g ); if ( dimDiffuse ) rd = (1.0f - g3) * opac; else rd = (1.0f - m * g3) * opac; //ke 10/28/98 float rn = opac - (1.0f - g3) * opac; float h = (g == 1.0f ) ? 600.0f : 3.0f / (1.0f - g ); float d = 1.0f - m * g; for (int i=0; i<sc.nLights; i++) { l = sc.Light(i); float NL, Kl; Point3 L; if (l->Illuminate( sc, sc.Normal(), lightClr, L, NL, Kl)) { if (l->ambientOnly) { ip.ambIllumOut += lightClr; continue; } if (NL<=0.0f) continue; // diffuse if (l->affectDiffuse){ ip.diffIllumOut += Kl * d * rd * lightClr; } // specular if (l->affectSpecular) { // strauss uses the reflected LIGHT vector Point3 R = L - 2.0f * NL * sc.Normal(); R = Normalize( R ); float RV = -Dot(R, sc.V() ); float s; if (RV < 0.0f) { // soften if ( NL < softThresh ) RV *= SoftSpline2( NL / softThresh ); // specular function s = SpecBoost * (float)pow( -RV, h); } else continue; float a, b; a = (float)acos( NL ) * OneOverHalfPi; b = (float)acos( -Dot(sc.Normal(), sc.V()) ) * OneOverHalfPi; float fa = F( a ); float j = fa * G( a ) * G( b ); float rj = rn > 0.0f ? Bound( rn + (rn+kj)*j ) : rn; Color Cl = lightClr; // normalize the light color in case it's really bright float I = NormClr( Cl ); Color Cs = Cl + m * (1.0f - fa) * (Cd - Cl); ip.specIllumOut += s * rj * I * Cs; } // end, if specular } // end, illuminate } // for each light // now we can multiply by the clrs, except specular, which is already done ip.ambIllumOut *= 0.5f * rd * Cd; ip.diffIllumIntens = Intens(ip.diffIllumOut); ip.diffIllumOut *= Cd; // next due reflection if ( ip.hasComponents & HAS_REFLECT ){ Color rc = ip.channels[ ip.stdIDToChannel[ ID_RL ] ]; AffectReflection(sc, ip, rc); ip.reflIllumOut = rc * ip.reflectAmt; } // last do refraction/ opacity if ( (ip.hasComponents & HAS_REFRACT) ){ // Set up attenuation opacity for Refraction map. dim diffuse & spec by this ip.finalAttenuation = ip.finalOpac * (1.0f - ip.refractAmt); // Make more opaque where specular hilite occurs: float max = Max(ip.specIllumOut); if (max > 1.0f) max = 1.0f; float newOpac = ip.finalAttenuation + max - ip.finalAttenuation * max; // Evaluate refraction map, filtered by filter color. // Color tClr = ((StdMat2*)(ip.pMtl))->TranspColor( newOpac, ip.channels[filtChan], ip.channels[diffChan]); Color tClr = transpColor( TRANSP_FILTER, newOpac, Cd, Cd ); ip.transIllumOut = ip.channels[ ip.stdIDToChannel[ ID_RR ] ] * tClr; // no transparency when doing refraction ip.finalT.Black(); } else { // no refraction, transparent? ip.finalAttenuation = opac; if (ip.hasComponents & HAS_OPACITY) { // ip.finalT = Cd * (1.0f-opac); Cd = greyVal * Color( 1.0f, 1.0f, 1.0f ) + clrVal * Cd; ip.finalT = transpColor( TRANSP_FILTER, opac, Cd, Cd ); } } if (sc.globContext != NULL && sc.globContext->pToneOp != NULL) { if (isInvertSelfIllum()) sc.globContext->pToneOp->RGBToScaled(ip.selfIllumOut); if (isInvertReflect() && (ip.hasComponents & HAS_REFLECT)) sc.globContext->pToneOp->RGBToScaled(ip.reflIllumOut); if (isInvertRefract() && (ip.hasComponents & HAS_REFRACT)) sc.globContext->pToneOp->RGBToScaled(ip.transIllumOut); } CombineComponents( sc, ip ); }
// returns shadow fraction & shadowClr // move this util to shade context at first opportunity float IllumShadow( ShadeContext& sc, Color& shadowClr ) { IlluminateComponents illumComp; IIlluminationComponents* pIComponents = NULL; Color illumClr(0,0,0); Color illumClrNS(0,0,0); shadowClr.Black(); Point3 N = sc.Normal(); // scale the sums so we don't overflow // float scaleFactor = 1.0; // if( sc.nLights ) // scaleFactor = 1.0f / float( sc.nLights ); // > 9/24/02 - 2:30pm --MQM-- // poke flag to let Light Tracer/Radiosity so they will // separate out the shadow value. int oldXID = sc.xshadeID; sc.xshadeID |= SHADECONTEXT_GUESS_SHADOWS_FLAG; for (int i = 0; i < sc.nLights; i++) { LightDesc* l = sc.Light( i ); pIComponents = (IIlluminationComponents*)l->GetInterface( IID_IIlluminationComponents ); if( pIComponents ){ // use component wise illuminate routines if (!pIComponents->Illuminate( sc, N, illumComp )) continue; // illumClr += (illumComp.finalColor - illumComp.shadowColor ) * illumComp.geometricAtten * scaleFactor; LBound( illumComp.shadowColor ); illumClr += (illumComp.finalColor - illumComp.shadowColor ) * illumComp.geometricAtten; // illumClrNS += illumComp.finalColorNS * illumComp.geometricAtten * scaleFactor; illumClrNS += illumComp.finalColorNS * illumComp.geometricAtten; if( illumComp.rawColor != illumComp.filteredColor ){ // light is filtered by a transparent object, sum both filter & user shadow color shadowClr += illumComp.finalColor * illumComp.geometricAtten; //attenuated filterColor } else { // no transparency, sum in just the shadow color shadowClr += illumComp.shadowColor * illumComp.geometricAtten; } } else { // no component interface, shadow clr is black Color lightCol; Point3 L; register float NL, diffCoef; if (!l->Illuminate(sc, N, lightCol, L, NL, diffCoef)) continue; if (diffCoef <= 0.0f) continue; // illumClr += diffCoef * lightCol * scaleFactor; illumClr += diffCoef * lightCol; if( sc.shadow ){ sc.shadow = FALSE; l->Illuminate(sc, N, lightCol, L, NL, diffCoef); // illumClrNS += diffCoef * lightCol * scaleFactor; illumClrNS += diffCoef * lightCol; sc.shadow = TRUE; } else { illumClrNS = illumClr; } } }// end, for each light // > 9/24/02 - 2:31pm --MQM-- // restore xshadeID sc.xshadeID = oldXID; float intensNS = Intens(illumClrNS); // Clamp( intensNS ); float intens = Intens(illumClr); // Clamp( intens ); float atten = (intensNS > 0.01f)? intens/intensNS : 1.0f; if (atten > 1.0f) atten = 1.0f/atten; return atten; }
// Calculates 0..1 value which is given to the gradient float BerconGradient::getGradientValue(ShadeContext& sc) { switch (p_type) { case 0: { // UVW break; // Handled in main evaluation } case 1: { // Normal switch (p_normalFunction) { case 0: { // Perpendicular / Parallel return fabs(getGradientValueNormal(sc)); } case 1: { // Towards / Away return (getGradientValueNormal(sc) + 1.f) / 2.f; } case 2: { // Fresnel // NOTE: Should this get IOR from sc.GetIOR()? // I think not since its just a map, not material. // You get more predictable behaviour with constant 1.f. static float n1 = 1.0f; float cti = fabs(getGradientValueNormal(sc)); float stt = (n1 / p_ior) * sqrt(1 - cti * cti); float ctt = sqrt(1 - stt * stt); float rs = (p_ior * ctt - n1 * cti ) / (p_ior * ctt + n1 * cti); rs = rs * rs; float rp = (n1 * ctt - p_ior * cti ) / (n1 * ctt + p_ior * cti); rp = rp * rp; return 1.f - 0.5f * (rs + rp); } } } case 2: { // Distance return getGradientValueDist(sc); } case 3: { // Light return Intens(sc.DiffuseIllum()); } case 4: { // Map return p_maptex?p_maptex->EvalMono(sc):0.f; // TODO: Evaluate submaps color, bump is tougher DELTA shift with BerconSC? } case 5: { // Random seedRandomGen(sc); return (float)sfrand(); break; } case 6: { // Particle age Object *ob = sc.GetEvalObject(); if (ob && ob->IsParticleSystem()) { ParticleObject *obj = (ParticleObject*)ob; TimeValue t = sc.CurTime(); TimeValue age = obj->ParticleAge(t,sc.mtlNum); TimeValue life = obj->ParticleLife(t,sc.mtlNum); if (age>=0 && life>=0) return float(age)/float(life); } break; } case 7: { // Particle speed Object *ob = sc.GetEvalObject(); if (ob && ob->IsParticleSystem()) { ParticleObject *obj = (ParticleObject*)ob; /*IChkMtlAPI* chkMtlAPI = static_cast<IChkMtlAPI*>(obj->GetInterface(I_NEWMTLINTERFACE)); if ((chkMtlAPI&&chkMtlAPI->SupportsParticleIDbyFace())) return (Length(obj->ParticleVelocity(sc.CurTime(),chkMtlAPI->GetParticleFromFace(sc.FaceNumber()))) - p_rangeMin) / (p_rangeMax - p_rangeMin); else*/ return Length(obj->ParticleVelocity(sc.CurTime(),sc.mtlNum)); } break; } case 8: { // Particle size Object *ob = sc.GetEvalObject(); if (ob && ob->IsParticleSystem()) { ParticleObject *obj = (ParticleObject*)ob; return obj->ParticleSize(sc.CurTime(),sc.mtlNum); } break; } default: break; } return 0.f; }
float plMAXCameraLayer::EvalMono(ShadeContext& sc) { return Intens(EvalColor(sc)); }
float BerconGradient::EvalMono(ShadeContext& sc) { return Intens(EvalColor(sc)); }
Point3 BerconGradient::EvalNormalPerturb(ShadeContext& sc) { // Returned vector Point3 res(0.0f,0.0f,0.0f); if (p_type != 0) return res; // Bump only works for UVW, otherwise we don't really know the derivative of the gradient // Use cache if (sc.GetCache(this,res)) return res; if (gbufID) sc.SetGBufferID(gbufID); // UVW Point3 p; Point3 M[3]; if (!berconXYZ.get(sc, p, M)) return res; // Distortion float dist = 0.f; if (p_disOn && p_distex) dist = (1.f - p_distex->EvalMono(sc) * 2.f) * p_disStr; // Origin float d = getGradientValueUVW(p) + dist; if (!limitRange(d)) return res; if (p_curveOn) d = curve->GetControlCurve(0)->GetValue(sc.CurTime(), d); d = Intens(gradient->getColor(d, sc)); // Deltas Point3 normal; /*if (berconXYZ.req()) { Point3 MP[3]; MP[0] = Point3(DELTA,0.f,0.f); MP[1] = Point3(0.f,DELTA,0.f); MP[2] = Point3(0.f,DELTA,0.f); for (int i=0; i<3; i++) { normal[i] = getGradientValueUVW(p+DELTA*M[i]) + dist; if (!limitRange(normal[i])) return res; if (p_curveOn) normal[i] = curve->GetControlCurve(0)->GetValue(sc.CurTime(), normal[i]); normal[i] = (normal[i] - d) / DELTA; } normal = M[0]*normal.x + M[1]*normal.y + M[2]*normal.z; } else {*/ Point3 MP[3]; MP[0] = Point3(DELTA,0.f,0.f); MP[1] = Point3(0.f,DELTA,0.f); MP[2] = Point3(0.f,DELTA,0.f); for (int i=0; i<3; i++) { normal[i] = getGradientValueUVW(p+MP[i]) + dist; if (!limitRange(normal[i])) return res; if (p_curveOn) normal[i] = curve->GetControlCurve(0)->GetValue(sc.CurTime(), normal[i]); normal[i] = Intens(gradient->getColor(normal[i], sc)); normal[i] = (normal[i] - d) / DELTA; } normal = M[0]*normal.x + M[1]*normal.y + M[2]*normal.z; //normal = sc.VectorFromNoScale(normal, REF_OBJECT); //} // Compute maps and proper bump vector res = gradient->getBump(p_reverse?1.f-d:d, p_reverse?normal:-normal, sc); // Output res = texout->Filter(res); // Shading ready, return results sc.PutCache(this,res); return res; }
Point3 BerconWood::EvalNormalPerturb(ShadeContext& sc) { Point3 p,dpdx,dpdy; if (!sc.doMaps) return Point3(0,0,0); if (gbufID) sc.SetGBufferID(gbufID); // Evaluate parameters WoodParam wp = EvalParameters(sc); float grainA = mapOn[19]&&subtex[19]?subtex[19]->EvalMono(sc)*grainAmount:grainAmount; float grainF = mapOn[20]&&subtex[20]?subtex[20]->EvalMono(sc)*grainFreq:grainFreq; // UVW, Distortion and size Point3 M[3]; berconXYZ.get(sc, p, dpdx, dpdy, M); if (useDistortion) applyDistortion(sc,p); float wSize = mapOn[5]&&subtex[5]?subtex[5]->EvalMono(sc)*woodSize:woodSize; p /= wSize; dpdx /= (wSize / 2.f); dpdy /= (wSize / 2.f); // Vectors bool grainON = (grainAmount > .001f); Point3 np, nG, gP; float d = sc.filterMaps? Noise::wood(p, dpdx, dpdy, gP, wp) : Noise::wood(p, gP, wp); if (useCurve) d = curve->GetControlCurve(0)->GetValue(sc.CurTime(), d); float g = grainON ? Fractal::grain(gP, grainA, grainF): 0.f; for (int i=0; i<3; i++) { np[i] = sc.filterMaps? Noise::wood(p + DELTA * M[i], dpdx, dpdy, gP, wp) : Noise::wood(p + DELTA * M[i], gP, wp); if (useCurve) np[i] = curve->GetControlCurve(0)->GetValue(sc.CurTime(), np[i]); np[i] = (np[i] - d) / DELTA; if (grainON) nG[i] = Fractal::grain(gP, grainA, grainF); // gP is updated by wood() } np = -sc.VectorFromNoScale(np, REF_OBJECT); nG = -sc.VectorFromNoScale(nG, REF_OBJECT); // Eval sub maps float f1, f2, f3; Point3 v1, v2, v3; bool maps = false; if (subtex[0]) { f1 = subtex[0]->EvalMono(sc); v1 = subtex[0]->EvalNormalPerturb(sc); maps = true; } else { f1 = Intens(col[0]); v1 = Point3(0.f, 0.f, 0.f); } if (subtex[1]) { f2 = subtex[1]->EvalMono(sc); v2 = subtex[1]->EvalNormalPerturb(sc); maps = true; } else { f2 = Intens(col[1]); v2 = Point3(0.f, 0.f, 0.f); } if (subtex[2]) { f3 = subtex[2]->EvalMono(sc); v3 = subtex[2]->EvalNormalPerturb(sc); maps = true; } else { f3 = Intens(col[2]); v3 = Point3(0.f, 0.f, 0.f); } // Calculate vector if (maps) { np = (f2-f1)*np + d*v2 + (1.f-d)*v1; if (grainON) { float val = d*f1 + (1.f-d)*f2; np = (f3-val)*nG + g*v3 + (1.f-g)*np; } } else { np *= f2 - f1; if (grainON) { float val = d*f1 + (1.f-d)*f2; np = (f3-val)*nG + (1.f-g)*np; } } return texout->Filter(np); // Does this filter actually do something? }