home *** CD-ROM | disk | FTP | other *** search
-
- // Phong Shading Demo. By Keith Harrison (CIS:100431,1675). 15th Oct. 1995
- // Shades 20 spheres with differing values of Kd (diffuse)
- // and Ks (specular) properties.
- // Program uses single equation shading, evaluating only the red component.
- // Uses Watcom's graphics library (graph.h)
-
- // Phong's equation for Intensity:
- // I = IaKa + Ii[Kd(L.N) + Ks(N.H)ⁿ] / (r + K)
-
- // Developed with Watcom V10.0a from the MS Windows version
- // (the Windows version plotted 24bit colour values).
-
- // Based on information in 'Fundamentals of Three-Dimensional Computer
- // Graphics' by Alan Watt, ISBN 0 201 15442 0.
-
- #include <conio.h>
- #include <graph.h>
- #include <math.h>
-
- //Function prototypes.
- void setpalette(void);
- void plotpixel(short x, short y, short colour);
-
- void ShadeSphere(float Kd, float Ks,
- short SpecIndex, short Xcentre, short Ycentre, short radius);
-
- void CalculateLNandNnH( short x, short y, short z, short SpecIndex,
- float xn, float yn, float zn,
- float *LdotN, float *dist, float *NnH);
-
- //Ambient light intensity (0 to 1)
- const float IaKa = 0.2;
-
- //Vector H is the unit normal to the hypothetical surface oriented
- //halfway between the light direction vector (L) and the viewing vector (V).
- const float Hx = 0.326058, Hy = 0.325058, Hz = 0.888074;
-
- //Intensity of light source.
- const short Ilight = 140;
- //Light source distance factor.
- const float K = 70;
- //Light source position.
- const float dx = 110, dy = 110, dz = 110;
- //Light source normal.
- const float Lx = 0.57735, Ly = 0.57735, Lz = 0.57735;
-
- long palette[256];
-
- void setpalette(void)
- {
- short i;
-
- //The VGA can only handle 64 different shades of red.
- for (i=0; i<64; i++)
- palette[i] = (long)i;
-
- _remapallpalette( &palette);
- };
-
-
-
- void plotpixel(short x, short y, short colour)
- {
- _setcolor(colour);
- _setpixel(x, y);
- };
-
-
-
- void CalculateLNandNnH( short x, short y, short z, short SpecIndex,
- float xn, float yn, float zn,
- float *LdotN, float *dist, float *NnH)
- {
- float NH;
-
- *LdotN = xn*Lx + yn*Ly + zn*Lz;
-
- if (LdotN <= 0)
- LdotN = 0;
- else {
- *dist = sqrt((dx - x)*(dx - x) + (dy - y)*(dy - y) + (dz - z)*(dz - z));
- NH = Hx*xn + Hy*yn + Hz*zn;
- *NnH = exp(SpecIndex*log(NH));
- }
- };
-
-
-
- void ShadeSphere(float Kd, float Ks,
- short SpecIndex, short Xcentre, short Ycentre, short radius)
- {
- short Ir, Igb; // Ir = intensity of Red, Igb = intensity of green/blue.
- int x, y, z; // Coordinates of point on sphere surface.
- float rsquare, xsquare, ysquare, zsquare, denom, xn, yn, zn, LdotN, NnH,
- dist, distfactor, ambientterm, diffuseterm, specularterm;
-
- rsquare = radius * radius;
-
- for (y = -radius; y<radius; y++) {
- ysquare = y * y;
- for (x = -radius; x<radius; x++) {
- xsquare = x * x;
- if ( (xsquare + ysquare) <= rsquare) {
- z = sqrt(rsquare - xsquare - ysquare);
- zsquare = z * z;
- denom = sqrt(xsquare + ysquare + zsquare);
- // xn, yn, and zn are unit normals from the sphere surface.
- xn = x / denom;
- yn = y / denom;
- zn = z / denom;
- CalculateLNandNnH(x, y, z, SpecIndex, xn, yn, zn, &LdotN, &dist, &NnH);
- ambientterm = IaKa;
- if (LdotN <= 0) {
- //Point is not illuminated by light source.
- //Use only ambient component.
- Ir = 64 * ambientterm;
- Igb = 0;
- }
- else {
- distfactor = Ilight / (dist + K);
- diffuseterm = distfactor * Kd * LdotN;
- specularterm = distfactor * Ks * NnH;
- Ir = 64 * (ambientterm + diffuseterm + specularterm);
- Igb = 64 * specularterm;
- };
- plotpixel(Xcentre + x, Ycentre + y, Ir);
- }
- }
- }
-
- };
-
-
-
- int main(int argc, char *argv[])
- {
- short SpecIndex, i, j, Xpos, Ypos;
- float Kd, Ks;
-
- int videomode;
-
- if (argc != 2) {
- printf("\nPhong Shaded Spheres.\n");
- printf("By Keith Harrison.\n\n");
- printf("Usage: sphere <video_mode>\n");
- printf("Video modes: 320 = 320 x 200 x 256 colour (VGA)\n");
- printf(" 640 = 640 x 480 x 256 colour (SVGA)\n");
- printf(" 800 = 800 x 600 x 256 colour (SVGA)\n");
- printf(" 1024 = 1024 x 768 x 256 colour (SVGA)\n\n");
- return 1;
- };
-
- videomode = atoi(argv[1]);
-
- switch (videomode) {
- case 320: _setvideomode( _MRES256COLOR ); break;
- case 640: _setvideomode( _VRES256COLOR ); break;
- case 800: _setvideomode( _SVRES256COLOR ); break;
- case 1024: _setvideomode( _XRES256COLOR ); break;
- default:
- printf("\nIncorrect command line option.\n");
- printf("Defaulting to 640 x 480 x 256 colours\n");
- printf("Type 'sphere' to see options\n");
- printf("Press any key to continue.\n");
- getch();
- _setvideomode( _VRES256COLOR ); break;
- };
-
- setpalette();
-
- SpecIndex = 9;
- Ypos = 50;
-
- for (i=0; i<4; i++) {
- Xpos = 50;
- Kd = 0;
- Ks = 1;
- for(j=0; j<5; j++) {
- ShadeSphere(Kd, Ks, SpecIndex, Xpos, Ypos, 50);
- Kd += 0.25;
- Ks -= 0.25;
- Xpos += 110;
- };
- Ypos += 110;
- SpecIndex = SpecIndex * 2;
- };
-
- getch();
- _setvideomode( _DEFAULTMODE );
-
- return 0;
-
- }
-