RGB Ray::getColor(const Scene &scene, const Fragment &intersection)const { color3 color; if (intersection.id) { for (int i = 0; i < scene.lights.size(); i++) { color += PhongColor(scene.lights[i], (*intersection.id).material, intersection); } } color = clamp(color, 0.0 ,1.0); RGB pixel = RGB(color[0] * 255, color[1] * 255, color[2] * 255); return pixel; }
void Scene::GouraudFacet (Facet& f) // // Draws a facet using Gourauds's color interpolation model. // A scan line approach is taken for drawing this facet. // // Uses the global intermediate storage array pix. // // If outline == True then the facet ist outlined using the // current line drawing color. // { float rstep,gstep,bstep,rr,gg,bb; long /*previous_color,*/ color; int maxy,miny,maxx,minx,k,mono; Pixel2D p; // number of vertices int n = f.GetNumVertices(); // facet is degenerate or has too many facets if (n < 3 || n > MaxVertices) return; Material *Mp; static Material M; if (coloring == PerVertex) { if (f.material) { M.ambient = f.material->ambient; M.specular = f.material->specular; M.exponent = f.material->exponent; } else { M.ambient = mat.ambient; M.specular = mat.specular; M.exponent = mat.exponent; } Mp = &M; } else if (coloring == Global) { Mp = f.GetMaterial(); } else /* (coloring == PerFacet) */ { M.color = f.front; if (f.material) { M.ambient = f.material->ambient; M.specular = f.material->specular; M.exponent = f.material->exponent; } else { M.ambient = mat.ambient; M.specular = mat.specular; M.exponent = mat.exponent; } Mp = &M; } // remember previous line color //previous_color = linecolor; ColorF previous_color = foreground_color; maxy = miny = f[0].p.py; for (int i = 0; i < n; i++) { const Vertex& Vi = f[i]; // copy projected vertex coordinates to polygon array pix[i] = Vi.p; // find minimum and maximum y-value if (pix[i].py > maxy) maxy = pix[i].py; else if (pix[i].py < miny) miny = pix[i].py; // get color at each vertex (vertex color + illumination effect) if (coloring == PerVertex) { M.color.red = float(Vi.red) / 255; M.color.green = float(Vi.green) / 255; M.color.blue = float(Vi.blue) / 255; } PhongColor(Vi.x,Vi.y,Vi.z, Vi.nx,Vi.ny,Vi.nz, Mp,r[i],g[i],b[i]); } // special case of a black/and white display if (displaymono) { Polygon(n,pix,White,Fill); // draw a white background polyogon SetColor(Black); // set foreground color to black for the dots } // fill facet using a scan line approach // loop through the scanlines // -------------------------- for ( p.py = miny; p.py <= maxy; (p.py)++ ) { // polygon is wider than 30000 pixel minx = 30000; maxx = -30000; int imin = 0, imax = 0; for (int i = 0, j = n-1; i < n; j = i++) { int pjy = pix[j].py, piy = pix[i].py; if ((pjy != piy) && (pjy >= p.py || piy >= p.py) && (pjy <= p.py || piy <= p.py)) { float mu = float(p.py-pjy)/float(piy-pjy), mu1 = 1.0-mu; k = int(mu1*pix[j].px+mu*pix[i].px+0.5); if (k < minx) { minx = k; // minimum x imin = i; } if (k > maxx) { maxx = k; // maximum x imax = i; } } } { int i = imin, j = i ? i-1 : n-1, dpy = pix[i].py-pix[j].py; float mu = dpy ? float(p.py-pix[j].py)/float(dpy) : 0, mu1 = 1.0-mu; // minimum values rr = mu1 * r[j] + mu * r[i]; gg = mu1 * g[j] + mu * g[i]; bb = mu1 * b[j] + mu * b[i]; } if (minx < maxx) { int i = imax, j = i ? i-1 : n-1, dpy = pix[i].py-pix[j].py; float mu = dpy ? float(p.py-pix[j].py)/float(dpy) : 0, mu1 = 1.0-mu; // steps float dx = float(maxx-minx); rstep = (mu1 * r[j] + mu * r[i] - rr)/dx; gstep = (mu1 * g[j] + mu * g[i] - gg)/dx; bstep = (mu1 * b[j] + mu * b[i] - bb)/dx; } else rstep = gstep = bstep = 0; if (displaymono) { // for a monochrome display - ditherized for (p.px = minx; p.px <= maxx; ++(p.px)) { // compute the monochrome intensity - scale from 0..255 to 0..63 // and diherize using Bayer's algorithm mono = (int)(0.30*rr+0.59*gg+0.11*bb) >> 2; if (mono < Bayer_Dithering_8x8 [p.px & 7][p.py & 7]) Dot(p); rr += rstep; gg += gstep; bb += bstep; } } else if (colordither) { // for a color display - ditherized for (p.px = minx; p.px <= maxx; ++(p.px)) { // scale from 0..255 to 0..15 // and ditherize using Bayer's algorithm int red,green,blue; red = (int)rr >> 4; green = (int)gg >> 4; blue = (int)bb >> 4; // map to color table (fixed entries 0..8) color = ((blue > Bayer_Dithering_4x4 [p.px & 3][p.py & 3])?1:0) | ((green > Bayer_Dithering_4x4 [p.px & 3][p.py & 3]?1:0)<<1) | ((red > Bayer_Dithering_4x4 [p.px & 3][p.py & 3]?1:0)<<2); Dot(p,color); // color is a color table index rr += rstep; gg += gstep; bb += bstep; } } else { // for a color display - non-ditherized for (p.px = minx; p.px <= maxx; ++(p.px)) {
void Scene::FlatFacet (Facet& f) // // If shading is 'Flat' the facet is drawn using flat shading, otherwise // if shading is 'false' it will be filled with the background color. // // Uses the global intermediate storage array pix. // { int i,j; float cx,cy,cz,nx,ny,nz,nk; short r,g,b; long color; // number of vertices int n = f.GetNumVertices(); // facet is degenerate (a line) ----- CURRENTLY DEGENERATE NOT ALLOWED if (n == 2) { Line(f[0].p,f[1].p); return; } // can't happen ! if (n < 2 || n > MaxVertices) { Warn("Scene::FlatFacet: number of vertices out of range"); return; } static Material M; Material *Mp; if (coloring == Global) { Mp = f.GetMaterial(); } else { M.color = f.front; if (f.material) { M.ambient = f.material->ambient; M.specular = f.material->specular; M.exponent = f.material->exponent; } else { M.ambient = mat.ambient; M.specular = mat.specular; M.exponent = mat.exponent; } Mp = &M; } // copy projected vertex coordinates to polygon array for (i = 0; i < n; i++) pix[i] = f[i].p; // compute color of facet from reflection properties if (shading == Facet::Flat) { f.Normal(nx,ny,nz,nk); f.Center(cx,cy,cz); PhongColor(cx,cy,cz,nx,ny,nz,Mp,r,g,b); // find color in colormap //color = LookupColor(r,g,b,f.GetMaterial()); color = LookupColor(r,g,b,&mat); // else if (shading == false) then use the background color } else color = backcolor; // ======================================================= // testing: fog for edgelines to get a depth cueing effect // ======================================================= ColorF previous_color; if (fog_opacity) { previous_color = foreground_color; SetColor( ColorF_Weighted(0.5*(1-tanh((6/fog_opacity) *(hypot(cx,cy,cz)-fog_distance-1))), previous_color,fog_color) ); } // draw outlines if requested if (edgelines == 1) Polygon(n,pix,color,Outline|Fill); else if (edgelines == 0) Polygon(n,pix,color,Fill); else if (edgelines == Facet::Individual ) { if (f.edgelines == 1) Polygon(n,pix,color,Outline|Fill); else if (f.edgelines == 0) Polygon(n,pix,color,Fill); else if (f.edgelines == Facet::Individual) { Polygon(n,pix,color,Fill); for (i = 0, j = n-1; i < n; j = i++) if ( f.GetEdgeLine(j) ) Line(pix[j],pix[i]); } } if (fog_opacity) SetColor(previous_color); }