📄 chapter08.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-2">
<META NAME="GENERATOR" CONTENT="Mozilla/4.07 [en] (Win98; I) [Netscape]">
<META NAME="Author" CONTENT="Goran UnreaL Krajnovic">
<TITLE>Chapter 8 - OpenGL Programming Guide (Addison-Wesley Publishing Company)</TITLE>
</HEAD>
<BODY BGCOLOR="#EFEFEF" LINK="#0000FF" VLINK="#551A8B" ALINK="#FF0000">
<DIV ALIGN=right><IMG SRC="figures/SGI_ID.gif" ALT="Silicon Graphics" NOSAVE HEIGHT=43 WIDTH=151 ALIGN=TEXTTOP></DIV>
<PRE>
</PRE>
<HR>
<H1>
Chapter 8<BR>
Drawing Pixels, Bitmaps, Fonts, and Images</H1>
<B>Chapter Objectives</B>
<P>After reading this chapter, you'll be able to do the following:
<UL>Position and draw bitmapped data
<BR>
<P>Read pixel data (bitmaps and images) from the framebuffer into processor
memory and from memory into the framebuffer
<BR>
<P>Copy pixel data from one buffer to another, or to another location in
the same buffer
<BR>
<P>Magnify or reduce an image as it's written to the framebuffer
<BR>
<P>Control pixel-data formatting and perform other transformations as the
data is moved to and from the framebuffer</UL>
So far, most of the discussion in this guide has concerned the rendering
of geometric data - points, lines, and polygons. Two other important classes
of data that can be rendered by OpenGL are the following:
<UL>Bitmaps, typically used for characters in fonts
<BR>
<P>Image data, which might have been scanned in or calculated</UL>
Both bitmaps and image data take the form of rectangular arrays of pixels.
One difference between them is that a bitmap consists of a single bit of
information about each pixel, and image data typically includes several
pieces of data per pixel (the complete red, green, blue, and alpha color
components, for example). Also, bitmaps are like masks in that they're
used to overlay another image, but image data simply overwrites or is blended
with whatever data might have existed previously.
<P>This chapter describes how to read pixel data (bitmaps and images) from
the framebuffer into processor memory (and vice versa), and how to copy
pixel data from one buffer to another, or within a single buffer to another
position. This chapter contains the following major sections:
<UL>"Bitmaps and Fonts" describes the commands for positioning and drawing
bitmapped data. Such data may describe a font.
<BR>
<P>"Images" presents the basic information about reading and copying pixel
data. It also explains how to magnify or reduce an image as it's written
to the framebuffer.
<BR>
<P>"Storing, Transforming, and Mapping Pixels" covers all the details of
how pixel data is stored in memory and how to transform it as it's moved
into or out of memory.</UL>
In most cases, the necessary pixel operations are simple, so the first
two sections might be all you need to read for your application. However,
pixel manipulation can be complex - there are many ways to store pixel
data in memory, and you can apply any of several transformations to pixels
as they're moved to and from the framebuffer. These details are the subject
of the third section of this chapter; most likely, you'll want to read
this section only when you actually need to make use of the information.
<P>
<HR>
<H2>
Bitmaps and Fonts</H2>
A bitmap is a rectangular array of 0s and 1s that serves as a drawing mask
for a corresponding rectangular portion of the window. Suppose you're drawing
a bitmap and that the current color is red. Everywhere there's a 1 in the
bitmap, the corresponding pixel is replaced by a red pixel (or combined
with the red pixel, depending on which per-fragment operations are in effect;
see "Testing and Operating on Fragments" ). If there's a 0 in the bitmap,
the contents of the pixel are unaffected. The most common use for bitmaps
is for drawing characters on the screen.
<P>OpenGL provides only the lowest level of support for drawing strings
of characters and manipulating fonts. The commands <B>glRasterPos*()</B>
and <B>glBitmap()</B> position and draw a single bitmap on the screen.
In addition, through the display-list mechanism, you can use a sequence
of character codes to index into a corresponding series of bitmaps representing
those characters. See Chapter 4 for more information about display lists.
You'll have to write your own routines to provide any other support you
need for manipulating bitmaps, fonts, and strings of characters.
<P>As an example, consider Example 8-1 , which draws the character F three
times on the screen. Figure 8-1 shows the F as a bitmap and its corresponding
bitmap data.
<P><IMG SRC="figures/Fdata.gif" ALT="[IMAGE]" NOSAVE >
<P><B>Figure 8-1 : </B>A Bitmapped F and Its Data
<BR>
<BR>
<P><B>Example 8-1 : </B>Drawing a Bitmapped Character: drawf.c
<PRE>#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"
GLubyte rasters[24] = {
0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00,
0xc0, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc0, 0x00,
0xc0, 0x00, 0xc0, 0x00, 0xff, 0xc0, 0xff, 0xc0};
void myinit(void)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor(0.0, 0.0, 0.0, 0.0);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glRasterPos2i (20.5, 20.5);
glBitmap(10, 12, 0.0, 0.0, 12.0, 0.0, rasters);
glBitmap(10, 12, 0.0, 0.0, 12.0, 0.0, rasters);
glBitmap(10, 12, 0.0, 0.0, 12.0, 0.0, rasters);
glFlush();
}
void myReshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
auxInitDisplayMode(AUX_SINGLE | AUX_RGBA);
auxInitPosition(0, 0, 500, 500);
auxInitWindow(argv[0]);
myinit();
auxReshapeFunc(myReshape);
auxMainLoop(display);
}</PRE>
In Figure 8-1 , note that the visible part of the F character is at most
10 bits wide. Bitmap data is always stored in chunks that are multiples
of 8 bits, but the width of the actual bitmap doesn't have to be a multiple
of 8. The bits making up a bitmap are drawn starting from the lower left
corner: First, the bottom row is drawn, then the next row above it, and
so on. As you can tell from the code, the bitmap is stored in memory in
this order - the array of rasters begins with 0xc0, 0x00, 0xc0, 0x00 for
the bottom two rows of the F and continues to 0xff, 0xc0, 0xff, 0xc0 for
the top two rows.
<P>The commands of interest in this example are <B>glRasterPos2i()</B>
and <B>glBitmap()</B>; they're discussed in detail in the next section.
For now, ignore the call to <B>glPixelStorei()</B>; it describes how the
bitmap data is stored in computer memory. This topic is discussed in "Controlling
Pixel-Storage Modes."
<H3>
The Current Raster Position</H3>
The current raster position is the origin where the next bitmap (or image)
is to be drawn. In the F example, the raster position was set using <B>glRasterPos*()</B>
to (20, 20), which is where the lower left corner of the F was drawn:
<PRE>glRasterPos2i(20, 20);</PRE>
void <B>glRasterPos</B>{234}{sifd}{v}(<B>TYPE x, TYPE y, TYPE z, TYPE w</B>);
<P>Sets the current raster position. The <B>x, y, z</B>, and <B>w</B> arguments
specify the coordinates of the raster position. If <B>glRasterPos2*()</B>
is used, <B>z</B> is implicitly set to zero and <B>w</B> is implicitly
set to one; similarly, with <B>glRasterPos3*()</B>, <B>w</B> is set to
one.
<P>The coordinates of the raster position are transformed to screen coordinates
in exactly the same way as coordinates supplied with a <B>glVertex*()</B>
command (that is, with the modelview and perspective matrices). After transformation,
they either define a valid spot in the window on the screen, or they're
clipped out because the transformed coordinates lie outside the viewport.
If the transformed point is clipped out, the current raster position is
invalid.
<P>To obtain the current raster position, you can use the query command
<B>glGetFloatv()</B> with GL_CURRENT_RASTER_POSITION as the first argument.
The second argument should be a pointer to an allocated array that can
hold the (<B>x, y, z, w</B>) values as floating-point numbers. Call<B>
glGetBooleanv()</B> with GL_CURRENT_RASTER_POSITION_VALID as the first
argument to determine whether the current raster position is valid.
<H3>
Drawing the Bitmap</H3>
Once you've set the desired raster position, you probably want to use the
<B>glBitmap()</B> command to draw the data. void <B>glBitmap</B>(GLsizei
<B>width</B>, GLsizei <B>height</B>, GLfloat <B>x</B>bo, GLfloat <B>y</B>bo,
GLfloat <B>x</B>bi, GLfloat <B>y</B>bi, const GLubyte <B>*bitmap</B>);
<P>Draws the bitmap specified by <B>bitmap</B>, which is a pointer to the
bitmap image. The origin of the bitmap is placed at the most recently defined
current raster position. If the current raster position is invalid, nothing
is drawn, and the raster position remains invalid. The <B>width</B> and
<B>height</B> arguments indicate the width and height, in pixels, of the
bitmap. The width need not be a multiple of 8, although the data is stored
in unsigned characters of 8 bits each. (In the F example, it wouldn't matter
if there were garbage bits in the data beyond the tenth bit; since <B>glBitmap()</B>
was called with a width of 10, only 10 bits of the row are rendered.) Use
<B>x</B>bo and <B>y</B>bo to define the origin of the bitmap (positive
values move the origin up and to the right; negative values move it down
and to the left); <B>x</B>bi and <B>y</B>bi indicate the <B>x</B> and <B>y</B>
increments that are added to the raster position after the bitmap is rasterized
(see Figure 8-2 ).
<P><IMG SRC="figures/Fparams.gif" ALT="[IMAGE]" NOSAVE >
<P><B>Figure 8-2 : </B>A Bitmap and Its Associated Parameters
<BR>
<BR>
<P>Allowing the origin of the bitmap to be placed arbitrarily makes it
easy for characters to extend below the origin (typically used for characters
with descenders, such as g, j, and y), or to extend beyond the left of
the origin (used for various swash characters, which have extended flourishes,
or for characters in fonts that lean to the left).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -