基础概念
1,图元:组成3D物体最小的单位,包括:点,直线,多边形。就和化学里所有物体都是由原子组成的一样。
2,点:数学上的点,只有位置,没有大小。但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点。另一方面,无论图形输出设备(例如,显示器)如何精确,始终不能输出一个无穷小的点。默认情况下,OpenGL中的点将被画成单个的像素,虽然它可能足够小,但并不会是无穷小。同一像素上,OpenGL可以绘制许多坐标只有稍微不同的点,但该像素的具体颜色将取决于OpenGL的实现。当然,过度的注意细节就是钻牛角尖,我们大可不必花费过多的精力去研究“多个点如何画到同一像素上”。
3,直线:数学上的直线没有宽度,但OpenGL的直线则是有宽度的。同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。
4,多边形:是由多条线段首尾相连而形成的闭合区域。OpenGL规定,一个多边形必须是一个“凸多边形”(其定义为:多边形内任意两点所确定的线段都在多边形内,由此也可以推导出,凸多边形不能是空心的)。多边形可以由其边的端点(这里可称为顶点)来确定。(注意:如果使用的多边形不是凸多边形,则最后输出的效果是未定义的——OpenGL为了效率,放宽了检查,这可能导致显示错误。要避免这个错误,尽量使用三角形,因为三角形都是凸多边形)
5,多边形细节:一,多边形可以通过glPolygonMode来指定绘制的模式,包括填充,线框,点三种模式。二,相邻的填充多边形如果共享一条边或一个顶点,共享部分像素只绘制一次,它们只包含在其中一个多边形中。三,多边形具有正面与背面之分,默认逆时针连接的顶点所围成的面是正面,可以通过glFrontFace改变。四,可以通过glCullFace剔除不需要绘制的面,提高效率。五,opengl只能渲染凸多边形,而为了绘制非凸多边形,一般把他们分解为几个凸多边形,然后再分别绘制。然而这种做法我们就不能使用glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)来绘制它的真正轮廓了(即内部的边也会绘制),这时我们可以通过glEdgeFlag来标志顶点是否是边界边,默认顶点都是边界边。(默认逆时针连接时,对于非边界边就不会绘制)
6,可以想象,通过点、直线和多边形,就可以组合成各种几何图形。甚至于,你可以把一段弧看成是很多短的直线段相连,这些直线段足够短,以至于其长度小于一个像素的宽度。这样一来弧和圆也可以表示出来了。通过位于不同平面的相连的小多边形,我们还可以组成一个“曲面”。
注:它们的实际渲染其实还受是否开启了抗锯齿处理和多重采样功能的影响,如果没有开启,像一些尺寸大小会进行四舍五入取邻近的整数值,而开启了就允许使用非整数的宽度,这样位于边界处的像素一般会画得淡一些。
7,OpenGL的图元总共有10种:如下图,
实例程序
示例1:画出正玄函数的图形
#include "GLTools.h"
#include "GLShaderManager.h"
#ifdef __APPLE__
#include
#else
#define FREEGLUT_STATIC
#endif
#include
const GLfloat factor = 0.3f;
void display(void)
{
GLfloat x;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES); //线段
glVertex2f(-1.0f, 0.0f);
glVertex2f(1.0f, 0.0f); // 画x轴
glVertex2f(0.0f, -1.0f);
glVertex2f(0.0f, 1.0f); // 画y轴
glEnd();
glBegin(GL_LINE_STRIP);//线带
for(x=-1.0f/factor; x<1.0f/factor; x+=0.01f)
{
glVertex2f(x*factor, sin(x)*factor);
}
glEnd();
glFlush(); //用于单缓冲中
}
int main(int argc,char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(250, 250);
glutInitWindowPosition(100, 100);
glutCreateWindow("sinFunc");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
示例2:直线点画模式(其实就是画虚线)
#include "GLTools.h"
#include "GLShaderManager.h"
#ifdef __APPLE__
#include
#else
#define FREEGLUT_STATIC
#endif
//带参宏定义画线
#define drawOneLine(x1, y1, x2, y2) glBegin(GL_LINES); \
glVertex2f(x1, y1); glVertex2f(x2, y2); glEnd();
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glEnable(GL_LINE_STIPPLE); //激活点画线功能
/*注:glLineStipple设置当前点画模式,参数1表重复因子(即本来连续像素 * 参数1
= 现在连续个数),参数2是一个由1或0组成的16位序列,从低位开始,如果为1则绘制这
个像素,否则就不绘制。*/
glLineStipple(1, 0x0101);
drawOneLine(50.0, 125.0, 150.0, 125.0);
glLineStipple(1, 0x00ff);
drawOneLine(150.0, 125.0, 250.0, 125.0);
glLineStipple(1, 0x1c47);
drawOneLine(250.0, 125.0, 350.0, 125.0);
glLineWidth(5.0); //设置线宽度
glLineStipple(1, 0x0101);
drawOneLine(50.0, 100.0, 150.0, 100.0);
glLineStipple(1, 0x00ff);
drawOneLine(150.0, 100.0, 250.0, 100.0);
glLineStipple(1, 0x1c47);
drawOneLine(250.0, 100.0, 350.0, 100.0);
/*重复因子设置为5(即:如果有2个连续为1的位,则后面2 * 5 = 10个连续绘制,反
之,如果3个连续为0的位,则这里3 * 5 = 15个像素连续不绘制)*/
glLineStipple(5, 0x1c47);
drawOneLine(50, 50, 350, 50);
glDisable(GL_LINE_STIPPLE); //关闭点画线功能
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);
}
int main(int argc,char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(400, 150);
glutInitWindowPosition(100, 100);
glutCreateWindow("line");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
示例3:多边形的点画模式
#include "GLTools.h"
#include "GLShaderManager.h"
#ifdef __APPLE__
#include
#else
#define FREEGLUT_STATIC
#endif
void display(void)
{
//位图数据(32 * 32位的)
GLubyte fly[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x80, 0x01, 0xC0, 0x06, 0xC0, 0x03, 0x60,
0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20,
0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20,
0x04, 0x06, 0x60, 0x20, 0x44, 0x03, 0xC0, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x66, 0x01, 0x80, 0x66, 0x33, 0x01, 0x80, 0xCC,
0x19, 0x81, 0x81, 0x98, 0x0C, 0xC1, 0x83, 0x30,
0x07, 0xe1, 0x87, 0xe0, 0x03, 0x3f, 0xfc, 0xc0,
0x03, 0x31, 0x8c, 0xc0, 0x03, 0x33, 0xcc, 0xc0,
0x06, 0x64, 0x26, 0x60, 0x0c, 0xcc, 0x33, 0x30,
0x18, 0xcc, 0x33, 0x18, 0x10, 0xc4, 0x23, 0x08,
0x10, 0x63, 0xC6, 0x08, 0x10, 0x30, 0x0c, 0x08,
0x10, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x08};
GLubyte halftone[] = {
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glRectf (25.0, 25.0, 125.0, 125.0); //绘制矩形
/*glPolygonStipple:多边形点画模式,参数是一个指向32 * 32位图的指针,
如果出现1对应的像素就被绘制,如果是0则不绘制*/
glEnable (GL_POLYGON_STIPPLE); //激活多边形点画模式
glPolygonStipple (fly);
glRectf (125.0, 25.0, 225.0, 125.0);
glPolygonStipple (halftone);
glRectf (225.0, 25.0, 325.0, 125.0);
glDisable (GL_POLYGON_STIPPLE); //关闭多边形点画模式
glFlush ();
}
void init (void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (0.0, (GLdouble) w, 0.0, (GLdouble) h);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27: //esc键
exit(0);
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (350, 150);
glutCreateWindow ("polys");
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc (keyboard); //键盘按键回调
glutMainLoop();
return 0;
}