home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 10 / graphprg.asc < prev    next >
Text File  |  1991-09-10  |  15KB  |  393 lines

  1. _GRAPHICS PROGRAMMING COLUMN_
  2. by Michael Abrash
  3.  
  4. [LISTING ONE]
  5.  
  6. /* Demonstrates non-antialiased drawing in 256 color mode. Tested with
  7.    Borland C++ 2.0 in C mode in the small model. */
  8.  
  9. #include <conio.h>
  10. #include <dos.h>
  11. #include "polygon.h"
  12.  
  13. /* Draws the polygon described by the point list PointList in color
  14.    Color with all vertices offset by (X,Y) */
  15. #define DRAW_POLYGON(PointList,Color,X,Y)                   \
  16.    Polygon.Length = sizeof(PointList)/sizeof(struct Point); \
  17.    Polygon.PointPtr = PointList;                            \
  18.    FillConvexPolygon(&Polygon, Color, X, Y);
  19.    
  20. void main(void);
  21. extern int FillConvexPolygon(struct PointListHeader *, int, int, int);
  22.  
  23. /* Palette RGB settings to load the first four palette locations with
  24.    black, pure blue, pure green, and pure red */
  25. static char Palette[4*3] = {0, 0, 0,  0, 0, 63,  0, 63, 0,  63, 0, 0};
  26.  
  27. void main()
  28. {
  29.    struct PointListHeader Polygon;
  30.    static struct Point Face0[] =
  31.          {{198,138},{211,89},{169,44},{144,89}};
  32.    static struct Point Face1[] =
  33.          {{153,150},{198,138},{144,89},{105,113}};
  34.    static struct Point Face2[] =
  35.          {{169,44},{133,73},{105,113},{144,89}};
  36.    union REGS regset;
  37.    struct SREGS sregs;
  38.  
  39.    /* Set the display to VGA mode 13h, 320x200 256-color mode */
  40.    regset.x.ax = 0x0013; int86(0x10, ®set, ®set);
  41.  
  42.    /* Set color 0 to black, color 1 to pure blue, color 2 to pure
  43.       green, and color 3 to pure red */
  44.    regset.x.ax = 0x1012;   /* load palette block BIOS function */
  45.    regset.x.bx = 0;        /* start with palette register 0 */
  46.    regset.x.cx = 4;        /* set four palette registers */
  47.    regset.x.dx = (unsigned int) Palette;
  48.    segread(&sregs);
  49.    sregs.es = sregs.ds;       /* point ES:DX to Palette */
  50.    int86x(0x10, ®set, ®set, &sregs);
  51.  
  52.    /* Draw the cube */
  53.    DRAW_POLYGON(Face0, 3, 0, 0);
  54.    DRAW_POLYGON(Face1, 2, 0, 0);
  55.    DRAW_POLYGON(Face2, 1, 0, 0);
  56.    getch();    /* wait for a keypress */
  57.  
  58.    /* Return to text mode and exit */
  59.    regset.x.ax = 0x0003;   /* AL = 3 selects 80x25 text mode */
  60.    int86(0x10, ®set, ®set);
  61. }
  62.  
  63.  
  64.  
  65.  
  66. [LISTING TWO]
  67.  
  68. /* Demonstrates unweighted antialiased drawing in 256 color mode.
  69.    Tested with Borland C++ 2.0 in C mode in the small model. */
  70.  
  71. #include <conio.h>
  72. #include <dos.h>
  73. #include <stdlib.h>
  74. #include <string.h>
  75. #include "polygon.h"
  76.  
  77. /* Draws the polygon described by the point list PointList in color
  78.    Color, with all vertices offset by (X,Y), to ScanLineBuffer, at
  79.    double horizontal and vertical resolution */
  80. #define DRAW_POLYGON_DOUBLE_RES(PointList,Color,x,y)        \
  81.    Polygon.Length = sizeof(PointList)/sizeof(struct Point); \
  82.    Polygon.PointPtr = PointTemp;                            \
  83.    /* Double all vertical & horizontal coordinates */       \
  84.    for (k=0; k<sizeof(PointList)/sizeof(struct Point); k++) { \
  85.       PointTemp[k].X = PointList[k].X * 2;                  \
  86.       PointTemp[k].Y = PointList[k].Y * 2;                  \
  87.    }                                                        \
  88.    FillCnvxPolyDrvr(&Polygon, Color, x, y, DrawBandedList);
  89.  
  90. #define SCREEN_WIDTH 320
  91. #define SCREEN_HEIGHT 200
  92. #define SCREEN_SEGMENT 0xA000
  93. #define SCAN_BAND_WIDTH (SCREEN_WIDTH*2)  /* # of double-res pixels
  94.                                              across scan band */
  95. #define BUFFER_SIZE  (SCREEN_WIDTH*2*2)   /* enough space for one scan
  96.                                            line scanned out at double
  97.                                            resolution horz and vert */
  98. void main(void);
  99. void DrawPixel(int, int, char);
  100. int ColorComponent(int, int);
  101. extern int FillCnvxPolyDrvr(struct PointListHeader *, int, int, int,
  102.    void (*)());
  103. extern void DrawBandedList(struct HLineList *, int);
  104.  
  105. /* Pointer to buffer in which double-res scanned data will reside */
  106. unsigned char *ScanLineBuffer;
  107. int ScanBandStart, ScanBandEnd;  /* top & bottom of each double-res
  108.                                   band we'll draw to ScanLineBuffer */
  109. int ScanBandWidth = SCAN_BAND_WIDTH;  /* # pixels across scan band */
  110. static char Palette[256*3];
  111.  
  112. void main()
  113. {
  114.    int i, j, k;
  115.    struct PointListHeader Polygon;
  116.    struct Point PointTemp[4];
  117.    static struct Point Face0[] =
  118.          {{198,138},{211,89},{169,44},{144,89}};
  119.    static struct Point Face1[] =
  120.          {{153,150},{198,138},{144,89},{105,113}};
  121.    static struct Point Face2[] =
  122.          {{169,44},{133,73},{105,113},{144,89}};
  123.    unsigned char Megapixel;
  124.    union REGS regset;
  125.    struct SREGS sregs;
  126.  
  127.    if ((ScanLineBuffer = malloc(BUFFER_SIZE)) == NULL) {
  128.       printf("Couldn't get memory\n");
  129.       exit(0);
  130.    }
  131.  
  132.    /* Set the display to VGA mode 13h, 320x200 256-color mode */
  133.    regset.x.ax = 0x0013; int86(0x10, ®set, ®set);
  134.  
  135.    /* Stack the palette for the desired megapixel effect, with each
  136.       2-bit field representing 1 of 4 double-res pixels in one of four
  137.       colors */
  138.    for (i=0; i<256; i++) {
  139.       Palette[i*3] = ColorComponent(i, 3);   /* red component */
  140.       Palette[i*3+1] = ColorComponent(i, 2); /* green component */
  141.       Palette[i*3+2] = ColorComponent(i, 1); /* blue component */
  142.    }
  143.    regset.x.ax = 0x1012;   /* load palette block BIOS function */
  144.    regset.x.bx = 0;        /* start with palette register 0 */
  145.    regset.x.cx = 256;      /* set all 256 palette registers */
  146.    regset.x.dx = (unsigned int) Palette;
  147.    segread(&sregs);
  148.    sregs.es = sregs.ds;       /* point ES:DX to Palette */
  149.    int86x(0x10, ®set, ®set, &sregs);
  150.  
  151.    /* Scan out the polygons at double resolution one screen scan line
  152.       at a time (two double-res scan lines at a time) */
  153.    for (i=0; i<SCREEN_HEIGHT; i++) {
  154.       /* Set the band dimensions for this pass */
  155.       ScanBandEnd = (ScanBandStart = i*2) + 1;
  156.       /* Clear the drawing buffer */
  157.       memset(ScanLineBuffer, 0, BUFFER_SIZE);
  158.       /* Draw the current band of the cube to the scan line buffer */
  159.       DRAW_POLYGON_DOUBLE_RES(Face0, 3, 0, 0);
  160.       DRAW_POLYGON_DOUBLE_RES(Face1, 2, 0, 0);
  161.       DRAW_POLYGON_DOUBLE_RES(Face2, 1, 0, 0);
  162.  
  163.       /* Coalesce the double-res pixels into normal screen pixels
  164.          and draw them */
  165.       for (j=0; j<SCREEN_WIDTH; j++) {
  166.          Megapixel = (ScanLineBuffer[j*2] << 6) +
  167.                      (ScanLineBuffer[j*2+1] << 4) +
  168.                      (ScanLineBuffer[j*2+SCAN_BAND_WIDTH] << 2) +
  169.                      (ScanLineBuffer[j*2+SCAN_BAND_WIDTH+1]);
  170.          DrawPixel(j, i, Megapixel);
  171.       }
  172.    }
  173.  
  174.    getch();    /* wait for a keypress */
  175.  
  176.    /* Return to text mode and exit */
  177.    regset.x.ax = 0x0003;   /* AL = 3 selects 80x25 text mode */
  178.    int86(0x10, ®set, ®set);
  179. }
  180.  
  181. /* Draws a pixel of color Color at (X,Y) in mode 13h */
  182. void DrawPixel(int X, int Y, char Color)
  183. {
  184.    char far *ScreenPtr;
  185.  
  186.    ScreenPtr = (char far *)MK_FP(SCREEN_SEGMENT, Y*SCREEN_WIDTH+X);
  187.    *ScreenPtr = Color;
  188. }
  189.  
  190. /* Returns the gamma-corrected value representing the number of
  191.    double-res pixels containing the specified color component in a
  192.    megapixel with the specified value */
  193. int ColorComponent(int Value, int Component)
  194. {
  195.    /* Palette settings for 0%, 25%, 50%, 75%, and 100% brightness,
  196.       assuming a gamma value of 2.3 */
  197.    static int GammaTable[] = {0, 34, 47, 56, 63};
  198.    int i;
  199.  
  200.    /* Add up the number of double-res pixels of the specified color
  201.       in a megapixel of this value */
  202.    i = (((Value & 0x03) == Component) ? 1 : 0) +
  203.        ((((Value >> 2) & 0x03) == Component) ? 1 : 0) +
  204.        ((((Value >> 4) & 0x03) == Component) ? 1 : 0) +
  205.        ((((Value >> 6) & 0x03) == Component) ? 1 : 0);
  206.    /* Look up brightness of the specified color component in a
  207.       megapixel of this value */
  208.    return GammaTable[i];
  209. }
  210.  
  211.  
  212.  
  213. [LISTING THREE]
  214.  
  215. /* Draws pixels from the list of horizontal lines passed in; drawing
  216.    takes place only for scan lines between ScanBandStart and
  217.    ScanBandEnd, inclusive; drawing goes to ScanLineBuffer, with
  218.    the scan line at ScanBandStart mapping to the first scan line in
  219.    ScanLineBuffer. Intended for use in unweighted antialiasing,
  220.    whereby a polygon is scanned out into a buffer at a multiple of the
  221.    screen's resolution, and then the scanned-out info in the buffer is
  222.    grouped into megapixels that are mapped to the closest
  223.    approximation the screen supports and drawn. Tested with Borland
  224.    C++ 2.0 in C mode in the small model */
  225.  
  226. #include <string.h>
  227. #include <dos.h>
  228. #include "polygon.h"
  229.  
  230. extern unsigned char *ScanLineBuffer;  /* drawing goes here */
  231. extern int ScanBandStart, ScanBandEnd; /* limits of band to draw */
  232. extern int ScanBandWidth;  /* # of pixels across scan band */
  233.    
  234. void DrawBandedList(struct HLineList * HLineListPtr, int Color)
  235. {
  236.    struct HLine *HLinePtr;
  237.    int Length, Width, YStart = HLineListPtr->YStart;
  238.    unsigned char *BufferPtr;
  239.  
  240.    /* Done if fully off the bottom or top of the band */
  241.    if (YStart > ScanBandEnd) return;
  242.    Length = HLineListPtr->Length;
  243.    if ((YStart + Length) <= ScanBandStart) return;
  244.  
  245.    /* Point to the XStart/XEnd descriptor for the first (top)
  246.       horizontal line */
  247.    HLinePtr = HLineListPtr->HLinePtr;
  248.  
  249.    /* Confine drawing to the specified band */
  250.    if (YStart < ScanBandStart) {
  251.       /* Skip ahead to the start of the band */
  252.       Length -= ScanBandStart - YStart;
  253.       HLinePtr += ScanBandStart - YStart;
  254.       YStart = ScanBandStart;
  255.    }
  256.    if (Length > (ScanBandEnd - YStart + 1))
  257.       Length = ScanBandEnd - YStart + 1;
  258.  
  259.    /* Point to the start of the first scan line on which to draw */
  260.    BufferPtr = ScanLineBuffer + (YStart - ScanBandStart) *
  261.          ScanBandWidth;
  262.  
  263.    /* Draw each horizontal line within the band in turn, starting with
  264.       the top one and advancing one line each time */
  265.    while (Length-- > 0) {
  266.       /* Draw the whole horizontal line if it has a positive width */
  267.       if ((Width = HLinePtr->XEnd - HLinePtr->XStart + 1) > 0)
  268.          memset(BufferPtr + HLinePtr->XStart, Color, Width);
  269.       HLinePtr++;                /* point to next scan line X info */
  270.       BufferPtr += ScanBandWidth; /* point to next scan line start */
  271.    }
  272. }
  273.  
  274.  
  275.  
  276.  
  277. [LISTING FOUR]
  278.  
  279. /* The changes required to convert the function FillConvexPolygon,
  280.    from Listing 1 in the Feb, 1991, column, into FillCnvxPolyDrvr.
  281.    FillConvexPolygon was hardwired to call DrawHorizontalLineList to
  282.    draw to the display; FillCnvxPolyDrvr is more flexible because it
  283.    draws via the driver passed in as the DrawListFunc parameter */
  284.  
  285. /****** Delete this line ******/
  286. extern void DrawHorizontalLineList(struct HLineList *, int);
  287.  
  288. /****** Change this... ******/
  289. int FillConvexPolygon(struct PointListHeader * VertexList, int Color,
  290.       int XOffset, int YOffset)
  291. /****** ...to this ******/
  292. int FillCnvxPolyDrvr(struct PointListHeader * VertexList, int Color,
  293.       int XOffset, int YOffset, void (*DrawListFunc)())
  294.  
  295. /****** Change this... ******/
  296.    DrawHorizontalLineList(&WorkingHLineList, Color);
  297. /****** ...to this ******/
  298.    (*DrawListFunc)(&WorkingHLineList, Color);
  299.  
  300.  
  301.  
  302.  
  303. [LISTING FIVE]
  304.  
  305.  
  306. ; Mode X (320x240, 256 colors) mode set routine. Works on all VGAs.
  307. ; ****************************************************************
  308. ; * Revised 6/19/91 to select correct clock; fixes vertical roll *
  309. ; * problems on fixed-frequency (IBM 851X-type) monitors.        *
  310. ; ****************************************************************
  311. ; C near-callable as:    void Set320x240Mode(void);
  312. ; Tested with TASM 2.0.
  313. ; Modified from public-domain mode set code by John Bridges.
  314.  
  315. SC_INDEX equ    03c4h   ;Sequence Controller Index
  316. CRTC_INDEX equ  03d4h   ;CRT Controller Index
  317. MISC_OUTPUT equ 03c2h   ;Miscellaneous Output register
  318. SCREEN_SEG equ  0a000h  ;segment of display memory in mode X
  319.  
  320.         .model  small
  321.         .data
  322. ; Index/data pairs for CRT Controller registers that differ between
  323. ; mode 13h and mode X.
  324. CRTParms label  word
  325.         dw      00d06h  ;vertical total
  326.         dw      03e07h  ;overflow (bit 8 of vertical counts)
  327.         dw      04109h  ;cell height (2 to double-scan)
  328.         dw      0ea10h  ;v sync start
  329.         dw      0ac11h  ;v sync end and protect cr0-cr7
  330.         dw      0df12h  ;vertical displayed
  331.         dw      00014h  ;turn off dword mode
  332.         dw      0e715h  ;v blank start
  333.         dw      00616h  ;v blank end
  334.         dw      0e317h  ;turn on byte mode
  335. CRT_PARM_LENGTH equ     (($-CRTParms)/2)
  336.  
  337.         .code
  338.         public  _Set320x240Mode
  339. _Set320x240Mode proc    near
  340.         push    bp      ;preserve caller's stack frame
  341.         push    si      ;preserve C register vars
  342.         push    di      ; (don't count on BIOS preserving anything)
  343.  
  344.         mov     ax,13h  ;let the BIOS set standard 256-color
  345.         int     10h     ; mode (320x200 linear)
  346.  
  347.         mov     dx,SC_INDEX
  348.         mov     ax,0604h
  349.         out     dx,ax   ;disable chain4 mode
  350.         mov     ax,0100h
  351.         out     dx,ax   ;synchronous reset while setting Misc Output
  352.                         ; for safety, even though clock unchanged
  353.         mov     dx,MISC_OUTPUT
  354.         mov     al,0e3h
  355.         out     dx,al   ;select 25 MHz dot clock & 60 Hz scanning rate
  356.  
  357.         mov     dx,SC_INDEX
  358.         mov     ax,0300h
  359.         out     dx,ax   ;undo reset (restart sequencer)
  360.  
  361.         mov     dx,CRTC_INDEX ;reprogram the CRT Controller
  362.         mov     al,11h  ;VSync End reg contains register write
  363.         out     dx,al   ; protect bit
  364.         inc     dx      ;CRT Controller Data register
  365.         in      al,dx   ;get current VSync End register setting
  366.         and     al,7fh  ;remove write protect on various
  367.         out     dx,al   ; CRTC registers
  368.         dec     dx      ;CRT Controller Index
  369.         cld
  370.         mov     si,offset CRTParms ;point to CRT parameter table
  371.         mov     cx,CRT_PARM_LENGTH ;# of table entries
  372. SetCRTParmsLoop:
  373.         lodsw           ;get the next CRT Index/Data pair
  374.         out     dx,ax   ;set the next CRT Index/Data pair
  375.         loop    SetCRTParmsLoop
  376.  
  377.         mov     dx,SC_INDEX
  378.         mov     ax,0f02h
  379.         out     dx,ax   ;enable writes to all four planes
  380.         mov     ax,SCREEN_SEG ;now clear all display memory, 8 pixels
  381.         mov     es,ax         ; at a time
  382.         sub     di,di   ;point ES:DI to display memory
  383.         sub     ax,ax   ;clear to zero-value pixels
  384.         mov     cx,8000h ;# of words in display memory
  385.         rep     stosw   ;clear all of display memory
  386.  
  387.         pop     di      ;restore C register vars
  388.         pop     si
  389.         pop     bp      ;restore caller's stack frame
  390.         ret
  391. _Set320x240Mode endp
  392.         end
  393.