OPENGL初学

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OPENGL初学相关的知识,希望对你有一定的参考价值。

一。部分常用的实体绘制函数部分常用的实体绘制函数:

//以下所有函数中,radius表示球体的半径,slices表示球体纵向分割的数目(经线),主要是设置绘制的细密度,stacks表示球体横向分割的数目(纬线),创建了绘制中心在模型坐标原点,半径为radius的球体

void glutWireSphere(GLdouble radius, GLint slices, GLint stacks); //网状球

void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); //实心球

void glutWireCube(GLdouble size); //网状立方体

void glutSolidCube(GLdouble size); //实心立方体

void glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings); //网状圆环

void glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings); //实心圆环

void glutWireCone(GLdouble radius, GLdouble height, GLint slices, GLint stacks); //网状圆锥体

void glutSolidCone(GLdouble radius, GLdouble height, GLint slices, GLint stacks); //实心圆锥体

void glutWireTeapot(GLdouble size); //网状茶壶

void glutSolidTeapot(GLdouble size); //实心茶壶

 

 

使用代码实例:

void display(void)
{
    glColor3f(0.0f, 1.0f, 0.0f);//绿色
    glutSolidSphere(0.5,10,10);//半径r=0.5,细密程度横纵10份,会发现,细密程度越高越精准,这是微积分的体现。但是高精度对性能的要求高,过高则渲染效率会降低,俗话会卡
 
    glFlush();
}

 

 

二。视点变换(右为x,上为y,前为z)

OpenGL实用库提供了gluLookAt()函数,该函数有三个变量,分别定义了视点的位置、相机瞄准方向的参考点以及相机的向上方向。

void gluLookAt(
    GLdouble eyex,GLdouble eyey,GLdouble eyez,//(eyex,eyey,eyez)视点的位置;
    GLdouble centerx,GLdouble centery,GLdouble centerz,//(centerx,centery,centerz)注视的点,和视点之间连线形成注视方向;
    GLdouble upx,GLdouble upy,GLdouble upz //(upx,upy,upz)向上的方向,即头顶的方向
);

          

视点比做人的眼睛,当眼睛看物体时,头朝天时(站立时)看到的物体和头朝地时(倒立时)看到的物体是不一样的.你还可以将头部左右倾斜从不同的角度来看物体.那么,gluLookAt的朝上向量就是用来确定这个方向的.不过在默认情况下,头是朝天的,即朝上向量为(0, 1, 0)。      

 向上的方向(即头顶方向)一旦确定后,视线的范围就确定了,和人站住不动后,所能看到的角度是有限的一样。还是用代码实例测试来看效果,我们以茶壶为三维实体。屏幕朝外的方向是Z轴正向。

1>默认状态下,头顶方向:(0,1,0)

void display(void)

{

    glColor3f(0.0f, 1.0f, 0.0f);//画笔颜色

    {

        glMatrixMode(GL_MODELVIEW); //gluLookAt函数的作用范围就是模型视图下,这里设置是必要的

        glLoadIdentity();//初始化当前矩阵为单位矩阵,不设置默认单位矩阵

        gluLookAt(0,0,1,  0,0,0,  0,1,0);//头顶方向:Y轴正向,视点位置是Z轴正向1个单位(屏幕外),沿着Z轴看向原点

        glutWireTeapot(0.5);//绘制茶壶

    }

    glFlush();

}

 

 

2>超出视野范围时,看不到物体了

/* 视点在Y轴正向1单位处,而头顶的方向是Y轴正向,这时,视线看不到脚下的原点,除非低头,而低头的话就改变了头顶的方向,所以如下的设置是看不到物体的! */

gluLookAt(0,1,0,  0,0,0,  0,1,0);

 

1.gluLookAt(0.0,0.0,5.0, 0.0,0.0,0.0, 0.0,1.0,0.0); 相当于我们的脑袋位置在(0.0,0.0,5.0)处,眼睛望向(0.0,0.0,0.0),即原点。后面的三个参数(0.0,1.0,0.0),y轴为1,其余为0,表示脑袋朝上,就是正常的情况。看到的情况如下图:

 

 

 2.若将gluLookAt的后三个参数设置为(0.0,-1.0,0.0),即y轴为-1,其余为0。这样表示脑袋向下,即人眼倒着看,看到的效果如下图:

 

3.再次修改gluLookAt的后三个参数为(1.0,0.0,0.0);x轴为1,其余为0.即人的脑袋像右歪90度来看,即顺时针转90度(换个角度思考就是壶逆时针转90度),猜想看到的结果应该是壶嘴在上,壶盖在右,壶底在左,壶柄在下。如下图:

 

4.其余情况依次类推。再次重述gluLookAt的参数,前三个参数表示的是脑袋的位置,中间三个参数是人眼的朝向,后三个位置表示的是脑袋朝向的方向。

三。模型变换

1.模型平移

void myDisplay(void)
{
    glColor3f(0.0f, 1.0f, 0.0f);
    {
        glMatrixMode(GL_MODELVIEW); 
        //这是没有平移的时候默认设置,(x,y,z)平移量为0
        glTranslatef(0,0,0);
        //画一个茶壶:一定要先做变换在绘制,先变换是改变了矩阵栈中的当前矩阵,然后用当前矩阵对要绘制的图形做变换
        glutWireTeapot(0.5);//画一个茶壶
    }
    glFlush();
}

需要注意的是,默认情况下,我们的视点位置在(0,0,1)处(float参数下),所以如果平移的超出视点所能看到的位置,则看不到物体。如glTranslatef(0,0,2):到了视点的后脑勺处,自然看不到物体。

glTranslatef(0.5,0.5,0);//向右上方偏移

 

2.模型旋转

void myDisplay(void)
{
    glColor3f(0.0f, 1.0f, 0.0f);
    {
        glMatrixMode(GL_MODELVIEW); 
        glRotatef(45, 0,0,1);//后三个参数确定了一个方向点,和原点连线构成旋转的轴线,这里是Z轴,即绕Z轴旋转45度
        glutWireTeapot(0.5);
    }
    glFlush();
}

 

3.模型缩放

void myDisplay(void)
{
    glColor3f(0.0f, 1.0f, 0.0f);
    {
        glMatrixMode(GL_MODELVIEW); 
        glScalef(1,3,0.5);//分别表示x,y,z轴的缩放比例
        glutWireTeapot(0.5);
    }
    glFlush();
}
 

四。正射投影 glOrtho

void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);
//left和right:矩形视景体的左右平面,之间的距离为“宽”
//bottom和top:矩形视景体的上下平面,之间的距离为“高”
//near和far:矩形视景体的前后平面,之间的距离为“深度
 
void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top);//同glOrtho一样,只不过物体的Z轴坐标为0,缺省的近远平面距离为-1和1
 
void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0,1,0);
 
    //glMatrixMode(GL_PROJECTION);下面的函数自动做了矩阵变换,这里可以不写
    glOrtho(-1,1,-1,1,-1,15);//视点在原点,而物体位移到-10处,为了能够看到物体,视景体就必须包含住物体,所以设置15
 
    //glMatrixMode(GL_MODELVIEW);下面的函数自动做了矩阵变换,这里可以不写
    glTranslatef(0,0,-10);
 
    glutWireTeapot(1);
 
    glFlush();
}

 

五。透视投影 glFrustum

void glFrustum(GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top, GLdouble near,GLdouble far);

eft, right:裁剪窗口左右边界的平面距离,距离(视点与物体连线:中心线)的两侧距离。左右边界决定了视口的宽。

bottom, top:裁剪窗口下上边界的平面距离,距离(视点与物体连线:中心线)的上下距离。上下边界决定了视口的高。

znear, zfar:视点到近、远平面的距离,必须是正的。

void myDisplay(void)
{
    glColor3f(0.0f, 1.0f, 0.0f);
    {
        //透视投影,通过参数GL_PROJECTION,将矩阵转为投影矩阵,然后设置系数,调节投影
        glMatrixMode(GL_PROJECTION);
        glFrustum(-1,1, -1,1, 0,2);//前四个变量控制棱台的宽高,宽:2,高:2 ,后两个调节远近。
 
        //模型变换,由于默认视点和模型都在原点,所以如果不设置模型移动,则视点在模型内部中心处,投影不能看到模型的整体
        glMatrixMode(GL_MODELVIEW);//可以不写,转换函数内部已转换矩阵模式
        glTranslatef(0,0,-1);
        glutWireSphere(0.5,20,20);
    }
    glFlush();
}

 

 

六。透视投影。gluPerspective

void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar);
//fovy:  指定视景体的视野的角度,以度数为单位,x、z平面张开的角度,比喻人眼的余光的范围。角度变小好比“眯眼”时,视野收缩到正前方,此时看到的物体会变小,距离会拉远。
//aspect:指定你的视景体的宽高比,影响投影图像的宽高比例
//zNear: 指定观察者到视景体的最近的裁剪面的距离(必须为正数)
//zFar:  指定观察者到视景体的最远的裁剪面的距离(必须为正数)
void myDisplay(void)
{
    glColor3f(0.0f, 1.0f, 0.0f);
    {
        //透视投影,通过参数GL_PROJECTION,将矩阵转为投影矩阵,然后设置系数,调节投影
        glMatrixMode(GL_PROJECTION);
        gluPerspective(150,1,0,100);
 
        //模型变换,由于默认视点和模型都在原点,所以如果不设置模型移动,则视点在模型内部中心处,投影不能看到模型的整体
        glMatrixMode(GL_MODELVIEW);
        glTranslatef(0,0,-1);
        glutWireSphere(0.5,20,20);
    }
    glFlush();
}

 

 

第一个小程序:茶壶

// openglTest.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include <gl/glut.h>

#include <stdio.h>

#include <stdlib.h>

#include <iostream>

 

using namespace std;

 

void display(void)

{

  //清除掉所有像素

  glClear(GL_COLOR_BUFFER_BIT);

  glColor3f(0.0f, 1.0f, 0.0f);

  {

     glMatrixMode(GL_MODELVIEW);

     //这是没有平移的时候默认设置,(x,y,z)平移量为0

     glTranslatef(0, 0, 0);

     glRotated(45, 0, 0, 1);

     //画一个茶壶:一定要先做变换在绘制,先变换是改变了矩阵栈中的当前矩阵,然后用当前矩阵对要绘制的图形做变换

     glutWireTeapot(0.5);//画一个茶壶

  }

  glFlush();

}

 

void displayMotion(int x, int y)

{

  //这里的x,y都是相对于绘制的窗口而言的,窗口的左上角为(0,0),右下角为(250,250)

  cout << x << "" << y << endl;

}

 

void displayMouse(int button, int state, int x, int y)

{

  /*

  * 这里的x,y都是相对于绘制的窗口而言的,窗口的左上角为(0,0),右下角为(250,250)

  * button==0 左键 button==2 右键 state==0 按下 state==1 抬起

  */

  cout << "button=" << button << "  state=" << state << "  x=" << x << "  y=" << y << endl;

}

 

void displayKeyboard(unsigned char key, int x, int y)

{

  /*

  * 这里的x,y都是相对于绘制的窗口而言的,窗口的左上角为(0,0),右下角为(250,250),是鼠标所在的位置

  * key 是按下去的键

  */

  cout << "key=" << key << "  x=" << x << "  y=" << y << endl;

}

 

void init(void)

{

  //设置清除背景的颜色

  glClearColor(0.0, 0.0, 0.0, 0.0);

  //初始化

  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();

  //    glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);//设置坐标系 左、右、下、上、近、远

  glOrtho(0.5, 0.5, 0.5, 0.5, -1.0, 1.0);

 

  //这个程序画出来的图形,比例会随着窗口大小的变化而自动调整

}

 

int main(int argc, char** argv)

{

  glutInit(&argc, argv);

  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//初始化显示模式:单缓冲区,RGB模式

  glutInitWindowSize(250, 250);

  glutInitWindowPosition(100, 100);

  glutCreateWindow("Hello,OpenGL");

  init();

 

  /*

  * 显示回调函数,当GLUT确定一个窗口的内容重新显示时,通过这个函数注册的回调函数就会执行

  * 所以应该把重绘场景所需要的所有代码都放在这个显示回调函数里

  */

  glutDisplayFunc(display);

 

 

  /*

  * 当按下鼠标并移动鼠标时调用注册函数 glutMotionFunc(void(*func)(int x, int y))

  */

  glutMotionFunc(displayMotion);

 

 

  /*

  * 当按下鼠标时调用注册函数

  */

  glutMouseFunc(displayMouse);

 

  /*

  * 当按下键盘上的某个键时

  */

  glutKeyboardFunc(displayKeyboard);

 

 

  /*

  * 如果程序修改了窗口的内容,有时候可能需要调用 glutPostRedisplay(),则它将会指示下面这个

  * 函数调用已注册的显示回调函数。

  * 必须调用这个函数来启动程序。已注册的显示回调函数,一旦进入循环永远不会退出

  */

 

  glutMainLoop();

 

  return 0;

}

七。绘制一个点

void display()

{

  glClear(GL_COLOR_BUFFER_BIT);

  glBegin(GL_POINTS);

glVertex2f(0.0f,0.0f);

glEnd();

glFinish();

}

使用glVertex2f()的时候, 在他的前后使用了glBegin()和glEnd()包围了他。看看有哪些常用的类型:

GL_POINTS:把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制N个点
GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n条线段,总共绘制N/2条线段
GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制n-1条线段
GL_LINE_LOOP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,第n和n+1个顶点定义了线段n,总共绘制n条线段
GL_TRIANGLES:把每个顶点作为一个独立的三角形,顶点3n-2、3n-1和3n定义了第n个三角形,总共绘制N/3个三角形
 GL_TRIANGLE_STRIP:绘制一组相连的三角形,对于奇数n,顶点n、n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1、n和n+2定义了第n个三角形,总共绘制N-2个三角形
GL_TRIANGLE_FAN:绘制一组相连的三角形,三角形是由第一个顶点及其后给定的顶点确定,顶点1、n+1和n+2定义了第n个三角形,总共绘制N-2个三角形
GL_QUADS:绘制由四个顶点组成的一组单独的四边形。顶点4n-3、4n-2、4n-1和4n定义了第n个四边形。总共绘制N/4个四边形
GL_QUAD_STRIP:绘制一组相连的四边形。每个四边形是由一对顶点及其后给定的一对顶点共同确定的。顶点2n-1、2n、2n+2和2n+1定义了第n个四边形,总共绘制N/2-1个四边形
GL_POLYGON:绘制一个凸多边形。顶点1到n定义了这个多边形。

 

例如:

直线:

void display()
{
      glClear( GL_COLOR_BUFFER_BIT);
      glBegin( GL_LINES);
              glVertex2f( 0.0f, 0.0f);
              glVertex2f( -0.3f, 0.1f);
              glVertex2f( 0.1f, 0.3f);
              glVertex2f( 0.4f, 0.6f);
      glEnd();
      glFinish();
}

在openGL里面有这样一系列的函数, 他们以glVertex开头, 没错, 这就是我们需要的绘制点的函数, 来看看有哪些:

WINGDIAPI void APIENTRY glVertex2d (GLdouble x, GLdouble y);
WINGDIAPI void APIENTRY glVertex2dv (const GLdouble *v);
WINGDIAPI void APIENTRY glVertex2f (GLfloat x, GLfloat y);
WINGDIAPI void APIENTRY glVertex2fv (const GLfloat *v);
WINGDIAPI void APIENTRY glVertex2i (GLint x, GLint y);
WINGDIAPI void APIENTRY glVertex2iv (const GLint *v);
WINGDIAPI void APIENTRY glVertex2s (GLshort x, GLshort y);
WINGDIAPI void APIENTRY glVertex2sv (const GLshort *v);
WINGDIAPI void APIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z);
WINGDIAPI void APIENTRY glVertex3dv (const GLdouble *v);
WINGDIAPI void APIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z);
WINGDIAPI void APIENTRY glVertex3fv (const GLfloat *v);
WINGDIAPI void APIENTRY glVertex3i (GLint x, GLint y, GLint z);
WINGDIAPI void APIENTRY glVertex3iv (const GLint *v);
WINGDIAPI void APIENTRY glVertex3s (GLshort x, GLshort y, GLshort z);
WINGDIAPI void APIENTRY glVertex3sv (const GLshort *v);
WINGDIAPI void APIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
WINGDIAPI void APIENTRY glVertex4dv (const GLdouble *v);
WINGDIAPI void APIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
WINGDIAPI void APIENTRY glVertex4fv (const GLfloat *v);
WINGDIAPI void APIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w);
WINGDIAPI void APIENTRY glVertex4iv (const GLint *v);
WINGDIAPI void APIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w);
WINGDIAPI void APIENTRY glVertex4sv (const GLshort *v);
WINGDIAPI void APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
WINGDIAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);

不看不知道,一看吓一跳, 光是绘制点就有这么多函数。 安啦, 我们仔细看一下就会明白: 后面跟的数字表示参数的个数, 字母表示参数的类型

s表示16位整数(GLshort)
i表示32位整数(GLint和GLsizei)
f表示32位浮点数(GLfloat和GLclampf)
d表示64位浮点数(GLdouble和GLclampd)
v表示传递的几个参数将使用指针的方式

虽然他们表现方式不同, 但是功能都是一样的, 就像下面几个, 效果都没差, 小伙伴们可以自己看看:

glVertex2i( 1, 1);
glVertex2f( 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 0.0f);
GLfloat posArr[] = { 1.0f, 1.0f, 0.0f};
glVertex3fv( posArr);

说了这么多, 我们来看看该如何绘制一个点, 直接上代码:

void display()
{
    glClear( GL_COLOR_BUFFER_BIT);
    glBegin(GL_POINTS);
        glVertex2f( 0.0f, 0.0f);
    glEnd();
    glFinish();
}

将我们原来的display函数替换成现在这样, 运行, 是不是在屏幕的中间出现了一个白色的小亮点啊

 

在使用glVertex2f()的时候, 在他的前后使用了glBegin()和glEnd()包围了他

我们再来看看有哪些常用的类型:

    GL_POINTS:把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制N个点
    GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n条线段,总共绘制N/2条线段
    GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制n-1条线段
    GL_LINE_LOOP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,第n和n+1个顶点定义了线段n,总共绘制n条线段
    GL_TRIANGLES:把每个顶点作为一个独立的三角形,顶点3n-2、3n-1和3n定义了第n个三角形,总共绘制N/3个三角形
    GL_TRIANGLE_STRIP:绘制一组相连的三角形,对于奇数n,顶点n、n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1、n和n+2定义了第n个三角形,总共绘制N-2个三角形
    GL_TRIANGLE_FAN:绘制一组相连的三角形,三角形是由第一个顶点及其后给定的顶点确定,顶点1、n+1和n+2定义了第n个三角形,总共绘制N-2个三角形
    GL_QUADS:绘制由四个顶点组成的一组单独的四边形。顶点4n-3、4n-2、4n-1和4n定义了第n个四边形。总共绘制N/4个四边形
    GL_QUAD_STRIP:绘制一组相连的四边形。每个四边形是由一对顶点及其后给定的一对顶点共同确定的。顶点2n-1、2n、2n+2和2n+1定义了第n个四边形,总共绘制N/2-1个四边形
    GL_POLYGON:绘制一个凸多边形。顶点1到n定义了这个多边形。

直线:

void display()
{
      glClear( GL_COLOR_BUFFER_BIT);
      glBegin( GL_LINES);
              glVertex2f( 0.0f, 0.0f);
              glVertex2f( -0.3f, 0.1f);
              glVertex2f( 0.1f, 0.3f);
              glVertex2f( 0.4f, 0.6f);
      glEnd();
      glFinish();
}

 

多边形:

void display()
{
      glClear( GL_COLOR_BUFFER_BIT);
      glBegin( GL_LINE_LOOP);
      glVertex2f( 0.0f, 0.0f);
      glVertex2f( -0.3f, 0.1f);
      glVertex2f( 0.1f, 0.3f);
      glVertex2f( 0.4f, 0.6f);
      glEnd();
      glFinish();
}

 
1.创立opengl窗口
#include <windows.h>  // Windows的头文件
#include <gl/glew.h>  // 包含最新的gl.h,glu.h库
#include <gl/glut.h>  // 包含OpenGL实用库
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)    // 重置OpenGL窗口大小
{
 if (height==0)        // 防止被零除
 {
  height=1;       // 将Height设为1
 }

glViewport(0, 0, width, height);     // 重置当前的视口
 glMatrixMode(GL_PROJECTION);      // 选择投影矩阵
 glLoadIdentity();       // 重置投影矩阵

 // 设置视口的大小
 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

 glMatrixMode(GL_MODELVIEW);      // 选择模型观察矩阵
 glLoadIdentity();       // 重置模型观察矩阵
}
void InitGL(GLvoid)        // 此处开始对OpenGL进行所有设置
{
 glShadeModel(GL_SMOOTH);      // 启用阴影平滑
 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);     // 黑色背景
 glClearDepth(1.0f);       // 设置深度缓存
 glEnable(GL_DEPTH_TEST);      // 启用深度测试
 glDepthFunc(GL_LEQUAL);       // 所作深度测试的类型
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   // 告诉系统对透视进行修正 

 

}
void DrawGLScene(GLvoid)        // 从这里开始进行所有的绘制
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   // 清除屏幕和深度缓存
 glLoadIdentity();       // 重置当前的模型观察矩阵
       
}
int main(int argc, char *argv[])
{
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
 glutInitWindowPosition(100, 100);
 glutInitWindowSize(400, 400);
 glutCreateWindow("第一个OpenGL程序");
 InitGL();
 glutDisplayFunc(DrawGLScene);
 glutReshapeFunc(ReSizeGLScene);
 glutMainLoop();
 return 0;
}

2.绘制图形

///***********改动部分:


void DrawGLScene(GLvoid)        // 从这里开始进行所有的绘制
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   // 清除屏幕及深度缓存
 glLoadIdentity();       // 重置当前的模型观察矩阵
 glTranslatef(-1.5f,0.0f,-6.0f);      // 左移 1.5 单位,并移入屏幕 6.0

 glBegin(GL_TRIANGLES);       // 绘制三角形
  glVertex3f( 0.0f, 1.0f, 0.0f);     // 上顶点
  glVertex3f(-1.0f,-1.0f, 0.0f);     // 左下
  glVertex3f( 1.0f,-1.0f, 0.0f);     // 右下
 glEnd();        // 三角形绘制结束

 glTranslatef(3.0f,0.0f,0.0f);      // 右移3单位

 glBegin(GL_QUADS);       //  绘制正方形
  glVertex3f(-1.0f, 1.0f, 0.0f);     // 左上
  glVertex3f( 1.0f, 1.0f, 0.0f);     // 右上
  glVertex3f( 1.0f,-1.0f, 0.0f);     // 左下
  glVertex3f(-1.0f,-1.0f, 0.0f);     // 右下
 glEnd();        // 正方形绘制结束

}

颜色//改动部分:
void DrawGLScene(GLvoid)        // 从这里开始进行所有的绘制
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // 清除屏幕及深度缓存
 glLoadIdentity();      // 重置模型观察矩阵
 glTranslatef(-1.5f,0.0f,-6.0f);     // 左移 1.5 单位,并移入屏幕 6.0

 glBegin(GL_TRIANGLES);      // 绘制三角形
  glColor3f(1.0f,0.0f,0.0f);    // 设置当前色为红色
  glVertex3f( 0.0f, 1.0f, 0.0f);    // 上顶点
  glColor3f(0.0f,1.0f,0.0f);    // 设置当前色为绿色
  glVertex3f(-1.0f,-1.0f, 0.0f);    // 左下

  glColor3f(0.0f,0.0f,1.0f);    // 设置当前色为蓝色
  glVertex3f( 1.0f,-1.0f, 0.0f);    // 右下
 glEnd();       // 三角形绘制结束

 glTranslatef(3.0f,0.0f,0.0f);     // 右移3单位
 glColor3f(0.5f,0.5f,1.0f);     // 一次性将当前色设置为蓝色
 glBegin(GL_QUADS);      // 绘制正方形
  glVertex3f(-1.0f, 1.0f, 0.0f);    // 左上
  glVertex3f( 1.0f, 1.0f, 0.0f);    // 右上
  glVertex3f( 1.0f,-1.0f, 0.0f);    // 左下
  glVertex3f(-1.0f,-1.0f, 0.0f);    // 右下
 glEnd();       // 正方形绘制结束

}

旋转

 

第二个小程序:

// openglTest.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include <windows.h>  // Windows的头文件

#include <gl/glew.h>  // 包含最新的gl.h,glu.h库

#include <gl/glut.h>  // 包含OpenGL实用库

 

static GLfloat   rtri = 0;;      // 用于三角形的角度

static GLfloat   rquad = 0;      // 用于四边形的角度

 

 

 

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)    // 重置OpenGL窗口大小

{

  if (height == 0)        // 防止被零除

  {

     height = 1;       // 将Height设为1

  }

 

  glViewport(0, 0, width, height);     // 重置当前的视口

  glMatrixMode(GL_PROJECTION);      // 选择投影矩阵

  glLoadIdentity();       // 重置投影矩阵

 

                       // 设置视口的大小

  gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);

 

  glMatrixMode(GL_MODELVIEW);      // 选择模型观察矩阵

  glLoadIdentity();       // 重置模型观察矩阵

}

 

 

void InitGL(GLvoid)        // 此处开始对OpenGL进行所有设置

{

  glShadeModel(GL_SMOOTH);      // 启用阴影平滑

  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);     // 黑色背景

  glClearDepth(1.0f);       // 设置深度缓存

  glEnable(GL_DEPTH_TEST);      // 启用深度测试

  glDepthFunc(GL_LEQUAL);       // 所作深度测试的类型

  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   // 告诉系统对透视进行修正 return TRUE;        // 初始化 OK

}

void DrawGLScene(GLvoid)        // 从这里开始进行所有的绘制

{

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕及深度缓存

  glLoadIdentity();     // 重置模型观察矩阵

  glTranslatef(-1.5f, 0.0f, -6.0f);    // 左移 1.5 单位,并移入屏幕 6.0

 

  glRotatef(rtri, 0.0f, 1.0f, 0.0f);    // 绕Y轴旋转金字塔

 

  glBegin(GL_TRIANGLES);     // 开始绘制金字塔的各个面

 

  glColor3f(1.0f, 0.0f, 0.0f);   // 红色

  glVertex3f(0.0f, 1.0f, 0.0f);   // 三角形的上顶点 (前侧面)

  glColor3f(0.0f, 1.0f, 0.0f);   // 绿色

  glVertex3f(-1.0f, -1.0f, 1.0f);   // 三角形的左下顶点 (前侧面)

 

  glColor3f(0.0f, 0.0f, 1.0f);   // 蓝色

  glVertex3f(1.0f, -1.0f, 1.0f);   // 三角形的右下顶点 (前侧面)

  glColor3f(1.0f, 0.0f, 0.0f);   // 红色

  glVertex3f(0.0f, 1.0f, 0.0f);   // 三角形的上顶点 (右侧面)

 

  glColor3f(0.0f, 0.0f, 1.0f);   // 蓝色

  glVertex3f(1.0f, -1.0f, 1.0f);   // 三角形的左下顶点 (右侧面)

  glColor3f(0.0f, 1.0f, 0.0f);   // 绿色

  glVertex3f(1.0f, -1.0f, -1.0f);   // 三角形的右下顶点 (右侧面)

 

  glColor3f(1.0f, 0.0f, 0.0f);   // 红色

  glVertex3f(0.0f, 1.0f, 0.0f);   // 三角形的上顶点 (后侧面)

  glColor3f(0.0f, 1.0f, 0.0f);   // 绿色

  glVertex3f(1.0f, -1.0f, -1.0f);   // 三角形的左下顶点 (后侧面)

  glColor3f(0.0f, 0.0f, 1.0f);   // 蓝色

  glVertex3f(-1.0f, -1.0f, -1.0f);   // 三角形的右下顶点 (后侧面)

 

  glColor3f(1.0f, 0.0f, 0.0f);   // 红色

  glVertex3f(0.0f, 1.0f, 0.0f);   // 三角形的上顶点 (左侧面)

  glColor3f(0.0f, 0.0f, 1.0f);   // 蓝色

  glVertex3f(-1.0f, -1.0f, -1.0f);   // 三角形的左下顶点 (左侧面)

  glColor3f(0.0f, 1.0f, 0.0f);   // 绿色

  glVertex3f(-1.0f, -1.0f, 1.0f);   // 三角形的右下顶点 (左侧面)

  glEnd();      // 金字塔绘制结束

 

  glLoadIdentity();

  glTranslatef(1.5f, 0.0f, -7.0f);    // 先右移再移入屏幕

 

  glRotatef(rquad, 1.0f, 1.0f, 1.0f);   // 在XYZ轴上旋转立方体

 

  glBegin(GL_QUADS);     // 开始绘制立方体

 

  glColor3f(0.0f, 1.0f, 0.0f);   // 颜色改为蓝色

  glVertex3f(1.0f, 1.0f, -1.0f);   // 四边形的右上顶点 (顶面)

  glVertex3f(-1.0f, 1.0f, -1.0f);   // 四边形的左上顶点 (顶面)

  glVertex3f(-1.0f, 1.0f, 1.0f);   // 四边形的左下顶点 (顶面)

  glVertex3f(1.0f, 1.0f, 1.0f);   // 四边形的右下顶点 (顶面)

 

  glColor3f(1.0f, 0.5f, 0.0f);   // 颜色改成橙色

  glVertex3f(1.0f, -1.0f, 1.0f);   // 四边形的右上顶点(底面)

  glVertex3f(-1.0f, -1.0f, 1.0f);   // 四边形的左上顶点(底面)

  glVertex3f(-1.0f, -1.0f, -1.0f);   // 四边形的左下顶点(底面)

  glVertex3f(1.0f, -1.0f, -1.0f);   // 四边形的右下顶点(底面)

 

  glColor3f(1.0f, 0.0f, 0.0f);   // 颜色改成红色

  glVertex3f(1.0f, 1.0f, 1.0f);   // 四边形的右上顶点(前面)

  glVertex3f(-1.0f, 1.0f, 1.0f);   // 四边形的左上顶点(前面)

  glVertex3f(-1.0f, -1.0f, 1.0f);   // 四边形的左下顶点(前面)

  glVertex3f(1.0f, -1.0f, 1.0f);   // 四边形的右下顶点(前面)

 

 

  glColor3f(0.0f, 0.0f, 1.0f);   // 颜色改成蓝色

  glVertex3f(-1.0f, 1.0f, 1.0f);   // 四边形的右上顶点(左面)

  glVertex3f(-1.0f, 1.0f, -1.0f);   // 四边形的左上顶点(左面)

  glVertex3f(-1.0f, -1.0f, -1.0f);   // 四边形的左下顶点(左面)

  glVertex3f(-1.0f, -1.0f, 1.0f);   // 四边形的右下顶点(左面)

 

  glColor3f(1.0f, 0.0f, 1.0f);   // 颜色改成紫罗兰色

  glVertex3f(1.0f, 1.0f, -1.0f);   // 四边形的右上顶点(右面)

  glVertex3f(1.0f, 1.0f, 1.0f);   // 四边形的左上顶点(右面)

  glVertex3f(1.0f, -1.0f, 1.0f);   // 四边形的左下顶点(右面)

  glVertex3f(1.0f, -1.0f, -1.0f);   // 四边形的右下顶点(右面)

  glEnd();      // 立方体绘制结束

 

 

 

  glutSwapBuffers();

 

}

void MyIdle()

{

  rtri += 0.2f;      // 增加三角形的旋转变量

  rquad -= 0.15f;      // 减少四边形的旋转变量

  if (rtri>100)

     rtri = 0;

  if (rquad<-100)

     rquad = 0;

  DrawGLScene();

 

}

int main(int argc, char *argv[])

{

  glutInit(&argc, argv);

  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);

  glutInitWindowPosition(100, 100);

  glutInitWindowSize(400, 400);

  glutCreateWindow(" OpenGL程序:3D旋转");

  InitGL();

  glutDisplayFunc(DrawGLScene);

  glutReshapeFunc(ReSizeGLScene);

  glutIdleFunc(MyIdle);

  glutMainLoop();

  return 0;

}

 

 

                                                                                                                                                                    

 

以上是关于OPENGL初学的主要内容,如果未能解决你的问题,请参考以下文章

带有顶点/片段着色器的光。使用不同的变量。 (openGL)

OpenGL、GLSL 片段着色器无法读取 Sampler2D 纹理

初学者 openGL 项目渲染三角形的问题

损坏的顶点和片段着色器

片段着色器中的OpenGL点精灵旋转

正在渲染opengl的随机屏幕片段-这表明啥错误?