// 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 ); } } } }
RGBA Plate::EvalColor(ShadeContext& sc) { BMM_Color_64 c; IPoint2 s; int id = sc.NodeID(); PlateMap *pmap = FindMap(id); if (gbufID) sc.SetGBufferID(gbufID); if (pmap) { s = sc.ScreenCoord(); int w = pmap->bm->Width(); int h = pmap->bm->Height(); Point3 view = sc.OrigView(); Point3 v2 = sc.V(); Point3 p = sc.P(); Point3 dV,dvf; Point3 N0 = sc.OrigNormal(); Point3 vf = RefractVector(sc, N0, view, sc.GetIOR()); RenderGlobalContext *gc = sc.globContext; if (gc==NULL) return blackrgba; // total deflection due to refraction dV = view-v2; // deflection due to flat refracton (no bumps) dvf = view-vf; dV = refrAmt*(dV-dvf) + thick*dvf; // compute screen deflection: This is really a cheat, and the // scale factor is arbitrary. Infact it depends on the distance // between to the point on the glass plate and to the point being // seen behind it, which we don't know. // these should be multiplied by the factor (Zbehind-Zcur)/Zcur // This assumes that the factor is .1 float dsx,dsy; if (gc->projType==0) { // perspective dsx = dV.x*0.1f*gc->xscale; dsy = dV.y*0.1f*gc->yscale; } else { // parallel projection dsx = -dV.x*gc->xscale*10.0f; dsy = -dV.y*gc->yscale*10.0f; } if (gc->fieldRender) dsy *= 2.0f; int x = s.x - (pmap->org.x+gc->devWidth/2); int y = s.y - (pmap->org.y+gc->devHeight/2); if (applyBlur) { float du = 1.0f/float(w); float dv = 1.0f/float(h); float u = (float(x)+dsx)*du; float v = (float(y)+dsy)*dv; if (u<0.0f||u>1.0f||v<0.0f||v>1.0f) { if (useEnvMap) { return sc.EvalGlobalEnvironMap(view-dvf); } else return blackrgba; } else pmap->bm->GetFiltered(u,v, du*blur, dv*blur,&c); } else { int ix = x + int(dsx); int iy = y + int(dsy); if (ix<0||ix>=w||iy<0||iy>=h) { if (useEnvMap) return sc.EvalGlobalEnvironMap(view-dvf); else return blackrgba; } else pmap->bm->GetLinearPixels(ix,iy,1,&c); } return c; } else return blackrgba; }
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 ); }
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 ); }
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 ); }