| 订阅 | 在线投稿
分享
 
 
 

教你如何通过代码学习OpenGL

来源:互联网  宽屏版  评论
2008-05-19 00:44:11

创建了一个新的 Win32 程序(并非控制台程序) 之后, 链接 OpenGL 的库文件。

操作步骤是: Project- Settings, 点击 LINK 标签, 在 “Object/Library Modules” 下面那一行的开始处(在kernel32.lib之前) 增添 OpenGL32.lib, GLu32.lib 和 GLaux.lib, 完成之后点击 OK 按钮.

然后把下面的代码贴上去就可以编译了.

/////////////代码

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#include <windows.h // Header File For Windows

#include <stdio.h // Header File For Standard Input/Output

#include <stdlib.h

#include <gl\gl.h // Header File For The OpenGL32 Library

#include <gl\glu.h // Header File For The GLu32 Library

#include <gl\glaux.h // Header File For The GLaux Library

#include <stdio.h

#include <stdlib.h

////全局变量//////////////////////////////////////////////////////////////////////////////////

HGLRC

hRC=NULL; //设置一个渲染描述表,将OpenGL调用连接到设备描述表

HDC

hDC=NULL; //设置一个设备描述表,将窗口连接到 GDI(Graphics Device Interface, 图形设备接口)

HWND

hWnd=NULL; //保存 Windows 分配给程序的窗口句柄

HINSTANCE

hInstance; //保存应用程序实例句柄

bool keys[256]; //用于接收键盘输入的数组,支持同时按下多个键

bool active=TRUE; //程序是否被最小化,当最小化的时候挂起程序

bool fullscreen=TRUE; //是否运行于全屏幕模式,如果运行于窗口模式,它就为FALSE

bool blend=TRUE; //是否打开混合

//浮点数是OpenGL编程中最基本的东西

GLfloat rtri=0.0f; //保存四凌锥旋转角度

GLfloat rquad=0.0f; //保存立方体旋转角度

GLfloat xrot=0.0f; //控制立方体在x轴上的旋转角度

GLfloat yrot=0.0f; //控制立方体在y轴上的旋转角度

GLfloat zrot=0.0f; //控制立方体在z轴上的旋转角度

GLfloat

xspeed=0.2f; //控制立方体在x轴上的旋转速度

GLfloat

yspeed=0.3f; //控制立方体在x轴上的旋转速度

GLfloat

z=-5.0f; //控制立方体在屏幕中的深度

BOOL light=false; //记录光照是否打开

BOOL lp=false; //键盘上的L键是否被按下?

BOOL fp=false; //键盘上的F键是否被按下?

BOOL bp=false; //键盘上的B键是否被按下?

//设置光照的数组(光照参数)

GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; //创建半亮度白色环境光.因为参数都是0.5f,所以是一个介于无光(黑)和全亮(白)的灯光.

//没有环境光的话,漫射光照不到的地方将会非常黑暗

GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; //用于创建一个非常明亮,全亮度的漫射光.所有值都是1.0f,是可以达到的最亮的灯光

//设置光照位置

GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };//前三个参数当然是用于指定其坐标x,y和z,最后一个参数是1.0f告知OpenGL指定的坐标就是光源的位置

//你可以想象显示器的玻璃平面就是z轴上0.0f的平面,把光源放在2.0f的位置上,所以如果你真的能看到这个光源的话,它应该在你的显示器玻璃屏上飘浮着

//当你到达0.0f时,图像看起来会很大,充斥了整个屏幕;而如果你向里到达一个极限值的时候,图像就看不见了

GLuint filter; //用于指定显示哪一个纹理.第一个纹理(纹理0)使用GL_NEAREST过滤(无平滑),第二个纹理(纹理1)使用GL_LINEAR 过滤,得到平滑的图像.第三个纹理(纹理2)使用 mipmap 纹理,创建非常漂亮的纹理外观.默认值0

GLuint texture[3]; //用于给3个不同的纹理创建存储空间

//mipmap纹理按照观察距离选择不同尺寸的纹理,实现多层次的细节.mipmap 纹理显示更好的外观,但占用更多的内存

////函数声明//////////////////////////////////////////////////////////////////////////////////////

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //声明窗口回调函数 WndProc()

//////函数///////////////////////////////////////////////////////////////////////////////////////////

//纹理图像的宽度和高度必须是2的幂.宽度或高度最小应是64个像素,为了兼容性,最多应是256个像素

AUX_RGBImageRec *LoadBMP(char *Filename) //读入位图文件.果文件不存在将返回NULL值代表文件不能被读取

{

FILE *File=NULL; //创建一个文件句柄

if (!Filename) //检测文件名是否合法

{

return NULL; //If Not Return NULL

}

File=fopen(Filename,"r"); //检测文件是否存在

if (File) //文件是否存在?

{

fclose(File); //关闭文件

return auxDIBImageLoad(Filename); //返回auxDIBImageLoad(Filename)读入的图像数据。

} //使用aux库读入位图,所以要保证aux库被包含了.Delphi和Visual C++都有aux库

return NULL; //If Load Failed Return NULL

}

////////////////////////////////////////////////////////////////////////////////////////

int LoadGLTextures() //读取位图(通过调用上面的代码)并转换成纹理

{

int Status=FALSE; //记录是否成功地读取了位图并建造了纹理.初始化为FLASE(代表什么都没有读取和建造)

AUX_RGBImageRec *TextureImage[1]; //保存位图的图像记录,持有图像的宽度,高度和数据

memset(TextureImage,0,sizeof(void *)*1); //清空图像记录

//读入目录中的*.bmp Check For Errors, If Bitmap's Not Found Quit

if (TextureImage[0]=LoadBMP("Data/Data.bmp"))

{

Status=TRUE; //Set The Status To TRUE

//建造纹理

glGenTextures(3, &texture[0]); //获得3个未使用的纹理名称

//第一纹理使用GL_NEAREST过滤,它几乎不做过滤,低运算量,但效果很差

//如果某个游戏的纹理看起来都是锯齿,可能使用的就是这种过滤.不过通常它可以在慢速电脑上运行良好

glBindTexture(GL_TEXTURE_2D, texture[0]);//绑定一个纹理名称到一个纹理对象

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

//NEW

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);

//NEW

//定义一个2D纹理

//0代表图像的详细级别,这通常为0 (与多纹理贴图有关)

//3指定数据成分,因为这里的图像是红,绿,蓝组成的,所以为3

//TextureImage[0]-sizeX是纹理宽度,TextureImage[0]-sizeY是纹理高度

//0是纹理边界,通常为 0.GL_RGB告知OpenGL图像数据是红,绿,蓝顺序存储的

//GL_UNSIGNED_BYTE表示图像的数据类型是8位无符号整数.TextureImage[0]-data指定纹理数据

glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]-sizeX, TextureImage[0]-sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]-data);

//第二个纹理使用linear过滤建造纹理,不同的是这次储存在texture[1]

glBindTexture(GL_TEXTURE_2D, texture[1]);

//下面两行代码分别用于设置在放大(GL_TEXTURE_MAG_FILTER)和缩小(GL_TEXTURE_MIN_FILTER)纹理贴图的时候所使用的过滤

//通常将它们设置为GL_LINEAR,使纹理贴图在距离屏幕很远和很近的时候都能看起来很平滑

//使用GL_NEAREST可能会出现一些锯齿.也可以把它们结合起来使用,放大用一种,缩小用一种

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//线性过滤

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//线性过滤

//定义一个2D纹理

glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]-sizeX, TextureImage[0]-sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]-data);

//创建mipmap纹理

glBindTexture(GL_TEXTURE_2D, texture[2]);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); // New

//要创建一个 2D 纹理,使用3种颜色(RGB),TextureImage[0]-sizeX是图像宽度,TextureImage[0]-sizeY是图像高度

//GL_RGB表示使用红绿蓝顺序,GL_UNSIGNED_BYTE表示图像的数据类型是字节,TextureImage[0]-data指定纹理数据

gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]-sizeX, TextureImage[0]-sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]-data);

}

//释放掉存储位图数据的所有内存

if (TextureImage[0]) //检查是否有位图保存在

{

if (TextureImage[0]-data) //检查是否有数据

{

free(TextureImage[0]-data); //有即释放掉

}

free(TextureImage[0]); //释放掉图像结构

}

return Status; //如果一切顺利变量Status将为TRUE,否则为FALSE

}

///////////////////////

  创建了一个新的 Win32 程序(并非控制台程序) 之后, 链接 OpenGL 的库文件。   操作步骤是: Project- Settings, 点击 LINK 标签, 在 “Object/Library Modules” 下面那一行的开始处(在kernel32.lib之前) 增添 OpenGL32.lib, GLu32.lib 和 GLaux.lib, 完成之后点击 OK 按钮.   然后把下面的代码贴上去就可以编译了.   /////////////代码   #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers   #include <windows.h // Header File For Windows   #include <stdio.h // Header File For Standard Input/Output   #include <stdlib.h   #include <gl\gl.h // Header File For The OpenGL32 Library   #include <gl\glu.h // Header File For The GLu32 Library   #include <gl\glaux.h // Header File For The GLaux Library   #include <stdio.h   #include <stdlib.h   ////全局变量//////////////////////////////////////////////////////////////////////////////////   HGLRC   hRC=NULL; //设置一个渲染描述表,将OpenGL调用连接到设备描述表   HDC   hDC=NULL; //设置一个设备描述表,将窗口连接到 GDI(Graphics Device Interface, 图形设备接口)   HWND   hWnd=NULL; //保存 Windows 分配给程序的窗口句柄   HINSTANCE   hInstance; //保存应用程序实例句柄   bool keys[256]; //用于接收键盘输入的数组,支持同时按下多个键   bool active=TRUE; //程序是否被最小化,当最小化的时候挂起程序   bool fullscreen=TRUE; //是否运行于全屏幕模式,如果运行于窗口模式,它就为FALSE   bool blend=TRUE; //是否打开混合   //浮点数是OpenGL编程中最基本的东西   GLfloat rtri=0.0f; //保存四凌锥旋转角度   GLfloat rquad=0.0f; //保存立方体旋转角度   GLfloat xrot=0.0f; //控制立方体在x轴上的旋转角度   GLfloat yrot=0.0f; //控制立方体在y轴上的旋转角度   GLfloat zrot=0.0f; //控制立方体在z轴上的旋转角度   GLfloat   xspeed=0.2f; //控制立方体在x轴上的旋转速度   GLfloat   yspeed=0.3f; //控制立方体在x轴上的旋转速度   GLfloat   z=-5.0f; //控制立方体在屏幕中的深度   BOOL light=false; //记录光照是否打开   BOOL lp=false; //键盘上的L键是否被按下?   BOOL fp=false; //键盘上的F键是否被按下?   BOOL bp=false; //键盘上的B键是否被按下?   //设置光照的数组(光照参数)   GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; //创建半亮度白色环境光.因为参数都是0.5f,所以是一个介于无光(黑)和全亮(白)的灯光.   //没有环境光的话,漫射光照不到的地方将会非常黑暗   GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; //用于创建一个非常明亮,全亮度的漫射光.所有值都是1.0f,是可以达到的最亮的灯光   //设置光照位置   GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };//前三个参数当然是用于指定其坐标x,y和z,最后一个参数是1.0f告知OpenGL指定的坐标就是光源的位置   //你可以想象显示器的玻璃平面就是z轴上0.0f的平面,把光源放在2.0f的位置上,所以如果你真的能看到这个光源的话,它应该在你的显示器玻璃屏上飘浮着   //当你到达0.0f时,图像看起来会很大,充斥了整个屏幕;而如果你向里到达一个极限值的时候,图像就看不见了   GLuint filter; //用于指定显示哪一个纹理.第一个纹理(纹理0)使用GL_NEAREST过滤(无平滑),第二个纹理(纹理1)使用GL_LINEAR 过滤,得到平滑的图像.第三个纹理(纹理2)使用 mipmap 纹理,创建非常漂亮的纹理外观.默认值0   GLuint texture[3]; //用于给3个不同的纹理创建存储空间   //mipmap纹理按照观察距离选择不同尺寸的纹理,实现多层次的细节.mipmap 纹理显示更好的外观,但占用更多的内存   ////函数声明//////////////////////////////////////////////////////////////////////////////////////   LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //声明窗口回调函数 WndProc()   //////函数///////////////////////////////////////////////////////////////////////////////////////////   //纹理图像的宽度和高度必须是2的幂.宽度或高度最小应是64个像素,为了兼容性,最多应是256个像素   AUX_RGBImageRec *LoadBMP(char *Filename) //读入位图文件.果文件不存在将返回NULL值代表文件不能被读取   {   FILE *File=NULL; //创建一个文件句柄   if (!Filename) //检测文件名是否合法   {   return NULL; //If Not Return NULL   }   File=fopen(Filename,"r"); //检测文件是否存在   if (File) //文件是否存在?   {   fclose(File); //关闭文件   return auxDIBImageLoad(Filename); //返回auxDIBImageLoad(Filename)读入的图像数据。   } //使用aux库读入位图,所以要保证aux库被包含了.Delphi和Visual C++都有aux库   return NULL; //If Load Failed Return NULL   }   ////////////////////////////////////////////////////////////////////////////////////////   int LoadGLTextures() //读取位图(通过调用上面的代码)并转换成纹理   {   int Status=FALSE; //记录是否成功地读取了位图并建造了纹理.初始化为FLASE(代表什么都没有读取和建造)   AUX_RGBImageRec *TextureImage[1]; //保存位图的图像记录,持有图像的宽度,高度和数据   memset(TextureImage,0,sizeof(void *)*1); //清空图像记录   //读入目录中的*.bmp Check For Errors, If Bitmap's Not Found Quit   if (TextureImage[0]=LoadBMP("Data/Data.bmp"))   {   Status=TRUE; //Set The Status To TRUE   //建造纹理   glGenTextures(3, &texture[0]); //获得3个未使用的纹理名称   //第一纹理使用GL_NEAREST过滤,它几乎不做过滤,低运算量,但效果很差   //如果某个游戏的纹理看起来都是锯齿,可能使用的就是这种过滤.不过通常它可以在慢速电脑上运行良好   glBindTexture(GL_TEXTURE_2D, texture[0]);//绑定一个纹理名称到一个纹理对象   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);   //NEW   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);   //NEW   //定义一个2D纹理   //0代表图像的详细级别,这通常为0 (与多纹理贴图有关)   //3指定数据成分,因为这里的图像是红,绿,蓝组成的,所以为3   //TextureImage[0]-sizeX是纹理宽度,TextureImage[0]-sizeY是纹理高度   //0是纹理边界,通常为 0.GL_RGB告知OpenGL图像数据是红,绿,蓝顺序存储的   //GL_UNSIGNED_BYTE表示图像的数据类型是8位无符号整数.TextureImage[0]-data指定纹理数据   glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]-sizeX, TextureImage[0]-sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]-data);   //第二个纹理使用linear过滤建造纹理,不同的是这次储存在texture[1]   glBindTexture(GL_TEXTURE_2D, texture[1]);   //下面两行代码分别用于设置在放大(GL_TEXTURE_MAG_FILTER)和缩小(GL_TEXTURE_MIN_FILTER)纹理贴图的时候所使用的过滤   //通常将它们设置为GL_LINEAR,使纹理贴图在距离屏幕很远和很近的时候都能看起来很平滑   //使用GL_NEAREST可能会出现一些锯齿.也可以把它们结合起来使用,放大用一种,缩小用一种   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//线性过滤   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//线性过滤   //定义一个2D纹理   glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]-sizeX, TextureImage[0]-sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]-data);   //创建mipmap纹理   glBindTexture(GL_TEXTURE_2D, texture[2]);   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); // New   //要创建一个 2D 纹理,使用3种颜色(RGB),TextureImage[0]-sizeX是图像宽度,TextureImage[0]-sizeY是图像高度   //GL_RGB表示使用红绿蓝顺序,GL_UNSIGNED_BYTE表示图像的数据类型是字节,TextureImage[0]-data指定纹理数据   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]-sizeX, TextureImage[0]-sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]-data);   }   //释放掉存储位图数据的所有内存   if (TextureImage[0]) //检查是否有位图保存在   {   if (TextureImage[0]-data) //检查是否有数据   {   free(TextureImage[0]-data); //有即释放掉   }   free(TextureImage[0]); //释放掉图像结构   }   return Status; //如果一切顺利变量Status将为TRUE,否则为FALSE   }   ///////////////////////
󰈣󰈤
 
 
 
>>返回首页<<
 
 热帖排行
 
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
©2005- 王朝网络 版权所有