void StraussShader::AffectReflection(ShadeContext &sc, IllumParams &ip, Color &rClr ) { 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 ]; float rn = opac - (1.0f - g * g * g) * opac; // the reflection of the reflection vector is just the view vector // so dot(v, r) is 1, to any power is still 1 float a, b; // NB: this has been transformed for existing in-pointing v float NV = Dot( sc.V(), sc.Normal() ); Point3 R = sc.V() - 2.0f * NV * sc.Normal(); float NR = Dot( sc.Normal(), R ); a = (float)acos( NR ) * OneOverHalfPi; b = (float)acos( NV ) * OneOverHalfPi; float fa = F( a ); float j = fa * G( a ) * G( b ); float rj = Bound( rn + (rn+kj)*j ); Color white( 1.0f, 1.0f, 1.0f ); Color Cs = white + m * (1.0f - fa) * (Cd - white); rClr *= Cs * rj * REFL_BRIGHTNESS_ADJUST; }
void DumMtl::Shade(ShadeContext& sc) { Color lightCol; Color diffwk(0.0f,0.0f,0.0f); Color specwk(0.0f,0.0f,0.0f); Point3 N = sc.Normal(); Point3 R = sc.ReflectVector(); LightDesc *l; for (int i = 0; i<sc.nLights; i++) { l = sc.Light(i); register float NL, diffCoef; Point3 L; if (!l->Illuminate(sc, N, lightCol, L, NL, diffCoef)) continue; // diffuse if (l->affectDiffuse) diffwk += diffCoef*lightCol; // specular if (l->affectSpecular) { float c = DotProd(L,R); if (c>0.0f) { c = (float)pow((double)c, (double)phongexp); specwk += c*lightCol*NL; // multiply by NL to SOFTEN } } } sc.out.t = Color(0.0f,0.0f,0.0f); sc.out.c = (.3f*sc.ambientLight + diffwk)*diff + specwk*spec; }
Point3 Gradient::EvalNormalPerturb(ShadeContext& sc) { Point3 dPdu, dPdv; if (!sc.doMaps) return Point3(0,0,0); if (gbufID) sc.SetGBufferID(gbufID); Point2 dM = uvGen->EvalDeriv(sc,&mysamp); uvGen->GetBumpDP(sc,dPdu,dPdv); #if 0 // Blinn's algorithm Point3 N = sc.Normal(); Point3 uVec = CrossProd(N,dPdv); Point3 vVec = CrossProd(N,dPdu); Point3 np = -dM.x*uVec+dM.y*vVec; #else // Lazy algorithm Point3 np = dM.x*dPdu+dM.y*dPdv; // return texout->Filter(dM.x*dPdu+dM.y*dPdv); #endif Texmap* sub[3]; for (int i=0; i<3; i++) sub[i] = mapOn[i]?subTex[i]:NULL; if (sub[0]||sub[1]||sub[2]) { // d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da) + da float a,b,k; Point3 da,db; Point2 UV, dUV; uvGen->GetUV(sc, UV,dUV); k = gradFunc(UV.x,UV.y); if (k<=center) { k = k/center; EVALSUBPERTURB(a,da,2); EVALSUBPERTURB(b,db,1); } else { k = (k-center)/(1.0f-center); EVALSUBPERTURB(a,da,1); EVALSUBPERTURB(b,db,0); } np = (b-a)*np + k*(db-da) + da; } return texout->Filter(np); }
// perpendicular to N, in the U (reference) direction Point3 GetTangent( ShadeContext &sc, int uvChan ) { // Point3 basisVecs[ 3 ]; // sc.DPdUVW( basisVecs, uvChan ); // 0 is vtxclr, 1..n is uv channels, max_meshmaps in mesh.h // Point3 U = Normalize( basisVecs[0] ); Point3 U = sc.VectorFrom( Point3( 0.01f, 0.0f, 1.0f ), REF_OBJECT ); //Retry: U = Normalize( U ); Point3 N = sc.Normal(); //assumed normalized // the line between the tip of vec[0] and its projection on N is tangent float UN = Dot( U, N ); // if ( Abs(UN) > 0.9999999f ){ // U = sc.VectorFrom( Point3( 0.01f, 1.0f, 0.0f ), REF_OBJECT ); // goto Retry; // } Point3 T = U - N * UN; T = Normalize( T ); return T; }
void plPassMtl::ShadeWithBackground(ShadeContext &sc, Color background, bool useVtxAlpha /* = true */) { #if 1 // old #if 0 Color lightCol,rescol, diffIllum0; RGBA mval; Point3 N0,P; BOOL bumped = FALSE; int i; if (gbufID) sc.SetGBufferID(gbufID); if (sc.mode == SCMODE_SHADOW) { float opac = 0.0; for (i=0; i < NumSubTexmaps(); i++) { if (SubTexmapOn(i)) { hsMaxLayerBase *hsmLay = (hsMaxLayerBase *)GetSubTexmap(i); opac += hsmLay->GetOpacity(t); } } float f = 1.0f - opac; sc.out.t = Color(f,f,f); return; } N0 = sc.Normal(); P = sc.P(); #endif TimeValue t = sc.CurTime(); Color color(0, 0, 0); float alpha = 0.0; // Evaluate Base layer Texmap *map = fLayersPB->GetTexmap(kPassLayBase); if (map && ( map->ClassID() == LAYER_TEX_CLASS_ID || map->ClassID() == STATIC_ENV_LAYER_CLASS_ID ) ) { plLayerTex *layer = (plLayerTex*)map; AColor evalColor = layer->EvalColor(sc); color = evalColor; alpha = evalColor.a; } // Evaluate Top layer, if it's on if (fLayersPB->GetInt(kPassLayTopOn)) { Texmap *map = fLayersPB->GetTexmap(kPassLayTop); if (map && ( map->ClassID() == LAYER_TEX_CLASS_ID || map->ClassID() == STATIC_ENV_LAYER_CLASS_ID || map->ClassID() == ANGLE_ATTEN_LAYER_CLASS_ID) ) { plPlasmaMAXLayer *layer = (plPlasmaMAXLayer*)map; AColor evalColor = layer->EvalColor(sc); // Blend layers if( !layer->DiscardColor() ) { int blendType = fLayersPB->GetInt(kPassLayBlend); switch (blendType) { case kBlendAdd: color += evalColor * evalColor.a; break; case kBlendAlpha: color = (1.0f - evalColor.a) * color + evalColor.a * evalColor; break; case kBlendMult: color *= evalColor; break; default: // No blend... color = evalColor; break; } } if( !layer->DiscardAlpha() ) { int alphaType = fLayersPB->GetInt(kPassLayOutputBlend); switch( alphaType ) { case kAlphaMultiply: alpha *= evalColor.a; break; case kAlphaAdd: alpha += evalColor.a; break; case kAlphaDiscard: default: break; } } } } #if 1 AColor black; black.Black(); AColor white; white.White(); SIllumParams ip; if (fBasicPB->GetInt(kPassBasEmissive)) { // Emissive objects don't get shaded ip.diffIllum = fBasicPB->GetColor(kPassBasColorAmb, t) * color; ip.diffIllum.ClampMinMax(); ip.specIllum = black; } else { // // Shading setup // // Setup the parameters for the shader ip.amb = fBasicPB->GetColor(kPassBasColorAmb, t); ip.diff = fBasicPB->GetColor(kPassBasColor, t) * color; ip.diffIllum = black; ip.specIllum = black; ip.N = sc.Normal(); ip.V = sc.V(); // // Specularity // if (fBasicPB->GetInt(kPassBasUseSpec, t)) { ip.sh_str = 1.f; ip.spec = fBasicPB->GetColor( kPassBasSpecColor, t ); ip.ph_exp = (float)pow(2.0f,float(fBasicPB->GetInt(kPassBasShine, t)) / 10.0f); ip.shine = float(fBasicPB->GetInt(kPassBasShine, t)) / 100.0f; } else { ip.spec = black; ip.sh_str = 0; ip.ph_exp = 0; ip.shine = 0; } ip.softThresh = 0; // // Do the shading Shader *myShader = GetShader(SHADER_BLINN); myShader->Illum(sc, ip); // Override shader parameters if (fAdvPB->GetInt(kPBAdvNoShade)) { ip.diffIllum = black; ip.specIllum = black; } if (fAdvPB->GetInt(kPBAdvWhite)) { ip.diffIllum = white; ip.specIllum = black; } ip.specIllum.ClampMinMax(); ip.diffIllum = ip.amb * sc.ambientLight + ip.diff * ip.diffIllum; ip.diffIllum.ClampMinMax(); } // AColor returnColor = AColor(opac * ip.diffIllum + ip.specIllum, opac) #endif // Get opacity and combine with alpha float opac = float(fBasicPB->GetInt(kPassBasOpacity, t)) / 100.0f; alpha *= opac; float vtxAlpha = 1.0f; if (useVtxAlpha && GetOutputBlend() == plPassMtlBase::kBlendAlpha) { Point3 p; GetInterpVtxValue(MAP_ALPHA, sc, p); vtxAlpha = p.x; } alpha *= vtxAlpha; // MAX will do the additive/alpha/no blending for us based on what Requirements() // we tell it. However, since MAX's formula is bgnd*sc.out.t + sc.out.c, // we have to multiply our output color by the alpha. // If we ever need a more complicated blending function, you can request the // background color via Requirements() (otherwise it's just black) and then do // the blending yourself; however, if the transparency isn't set, the shadows // will be opaque, so be careful. Color outC = ip.diffIllum + ip.specIllum; sc.out.c = ( outC * alpha ); sc.out.t = Color( 1.f - alpha, 1.f - alpha, 1.f - alpha ); #endif }
// 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 ); } } } }
// 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; }
AColor plStaticEnvLayer::EvalColor(ShadeContext& sc) { if (!sc.doMaps) return AColor(0.0f, 0.0f, 0.0f, 1.0f); AColor color; if (sc.GetCache(this, color)) return color; if (gbufID) sc.SetGBufferID(gbufID); // Evaluate the Bitmap // Point3 v = sc.VectorTo( sc.V(), REF_OBJECT );//WORLD ); Point3 v = sc.VectorTo( sc.Normal(), REF_OBJECT ); float wx,wy,wz; Color rcol; Bitmap *refmap = NULL; Point3 rv; Point2 uv; int size; wx = (float)fabs( v.x ); wy = (float)fabs( v.y ); wz = (float)fabs( v.z ); if( wx >= wy && wx >= wz ) { if( v.x < 0 ) { refmap = fBitmaps[ kLeftFace ]; uv = CompUV( -v.y, -v.z, v.x ); } else { refmap = fBitmaps[ kRightFace ]; uv = CompUV( v.y, -v.z, -v.x ); } } else if( wy >= wx && wy >= wz ) { if( v.y > 0 ) { refmap = fBitmaps[ kBackFace ]; uv = CompUV( -v.x, -v.z, -v.y ); } else { refmap = fBitmaps[ kFrontFace ]; uv = CompUV( v.x, -v.z, v.y ); } } else if( wz >= wx && wz >= wy ) { if( v.z < 0 ) { refmap = fBitmaps[ kBottomFace ]; uv = CompUV( -v.x, -v.y, v.z ); } else { refmap = fBitmaps[ kTopFace ]; uv = CompUV( -v.x, v.y, -v.z ); } } if( refmap == NULL ) color.White(); else { if( uv.x < 0.0f ) uv.x = 0.0f; else if( uv.x > 1.0f ) uv.x = 1.0f; if( uv.y < 0.0f ) uv.y = 0.0f; else if( uv.y > 1.0f ) uv.y = 1.0f; size = refmap->Width(); int x = (int)( uv.x * (float)( size - 1 ) ); int y = (int)( ( 1.0f - uv.y ) * (float)( size - 1 ) ); BMM_Color_64 c; refmap->GetLinearPixels( x, y, 1, &c ); color = AColor( c.r / 65535.f, c.g / 65535.f, c.b / 65535.f, c.a / 65535.f ); } // Invert color if specified if( fBitmapPB->GetInt( kBmpInvertColor ) ) { color.r = 1.0f - color.r; color.g = 1.0f - color.g; color.b = 1.0f - color.b; } // Discard color if specified if( fBitmapPB->GetInt( kBmpDiscardColor ) ) color.r = color.g = color.b = 1.0f; // Invert alpha if specified if( fBitmapPB->GetInt( kBmpInvertAlpha ) ) color.a = 1.0f - color.a; // Discard alpha if specified if( fBitmapPB->GetInt( kBmpDiscardAlpha ) ) color.a = 1.0f; // If RGB output is set to alpha, show RGB as grayscale of the alpha if( fBitmapPB->GetInt( kBmpRGBOutput ) == 1 ) color = AColor( color.a, color.a, color.a, 1.0f ); sc.PutCache(this, color); return color; }
float BerconGradient::getGradientValueNormal(ShadeContext& sc) { switch (p_normalType) { case 0: { // View return -DotProd(sc.Normal(), sc.V()); } case 1: { // Local X return (sc.VectorTo(sc.Normal(), REF_OBJECT)).x; } case 2: { // Local Y return (sc.VectorTo(sc.Normal(), REF_OBJECT)).y; } case 3: { // Local Z return (sc.VectorTo(sc.Normal(), REF_OBJECT)).z; } case 4: { // World X return (sc.VectorTo(sc.Normal(), REF_WORLD)).x; } case 5: { // World Y return (sc.VectorTo(sc.Normal(), REF_WORLD)).y; } case 6: { // World Z return (sc.VectorTo(sc.Normal(), REF_WORLD)).z; } case 7: { // Camera X return sc.Normal().x; //(sc.VectorTo(sc.Normal(), REF_CAMERA)).x; } case 8: { // Camera Y return sc.Normal().y; //(sc.VectorTo(sc.Normal(), REF_CAMERA)).y; } case 9: { // Camera Z return sc.Normal().z; //(sc.VectorTo(sc.Normal(), REF_CAMERA)).z; } case 10: { // To Object if (sc.InMtlEditor() || !p_node) return -DotProd(sc.Normal(), sc.V()); return DotProd(sc.Normal(), FNormalize(sc.PointFrom((p_node->GetNodeTM(sc.CurTime())).GetTrans(),REF_WORLD) - sc.P())); } case 11: { // Object Z if (sc.InMtlEditor() || !p_node) return -DotProd(sc.Normal(), sc.V()); return DotProd(sc.Normal(), FNormalize(sc.VectorFrom(p_node->GetNodeTM(sc.CurTime()).GetRow(2),REF_WORLD))); } } return 0.f; }
void plParticleMtl::ShadeWithBackground(ShadeContext &sc, Color background) { #if 1 TimeValue t = sc.CurTime(); Color color(0, 0, 0); float alpha = 0.0; // Evaluate Base layer Texmap *map = fBasicPB->GetTexmap(kTexmap); if (map && map->ClassID() == LAYER_TEX_CLASS_ID) { plLayerTex *layer = (plLayerTex*)map; AColor evalColor = layer->EvalColor(sc); color = evalColor; alpha = evalColor.a; } #if 1 AColor black; black.Black(); AColor white; white.White(); SIllumParams ip; if( fBasicPB->GetInt( kNormal ) == kEmissive ) { // Emissive objects don't get shaded ip.diffIllum = fBasicPB->GetColor(kColorAmb, t) * color; ip.diffIllum.ClampMinMax(); ip.specIllum = black; } else { // // Shading setup // // Setup the parameters for the shader ip.amb = black; ip.diff = fBasicPB->GetColor(kColor, t) * color; ip.spec = white; ip.diffIllum = black; ip.specIllum = black; ip.N = sc.Normal(); ip.V = sc.V(); // // Specularity // ip.sh_str = 0; ip.ph_exp = 0; ip.shine = 0; ip.softThresh = 0; // Do the shading Shader *myShader = GetShader(SHADER_BLINN); myShader->Illum(sc, ip); ip.diffIllum.ClampMinMax(); ip.specIllum.ClampMinMax(); ip.diffIllum = ip.amb * sc.ambientLight + ip.diff * ip.diffIllum; } // AColor returnColor = AColor(opac * ip.diffIllum + ip.specIllum, opac) #endif // Get opacity and combine with alpha float opac = float(fBasicPB->GetInt(kOpacity, t)) / 100.0f; //float opac = 1.0f; alpha *= opac; // MAX will do the additive/alpha/no blending for us based on what Requirements() // we tell it. However, since MAX's formula is bgnd*sc.out.t + sc.out.c, // we have to multiply our output color by the alpha. // If we ever need a more complicated blending function, you can request the // background color via Requirements() (otherwise it's just black) and then do // the blending yourself; however, if the transparency isn't set, the shadows // will be opaque, so be careful. Color outC = ip.diffIllum + ip.specIllum; sc.out.c = ( outC * alpha ); sc.out.t = Color( 1.f - alpha, 1.f - alpha, 1.f - alpha ); #endif }
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 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 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 ); }