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; }