三维图形的这是opengl的强项,大型3D游戏都会把它作为首选。
图像处理,是opencv的锁定的目标,大多都是C的api,也有少部分是C++的,工业图像表现,图像识别,都会考虑opencv的。webgl,这是3维向web延伸的方案,它可以直接调用支持opengl的接口,硬件加速或者软件模拟,很强大,结和html5....blender,可以完成三维模型制作,3D动画制作了。
PC 游戏还是 DirectX 开发?事实上在早年OpenGL即使在游戏领域也是对DirectX压倒性的优势。John Carmack曾嘲讽DirectX是“horribly broken” 的API。直到DirectX6时代OpenGL都被认为是比DirectX更加优秀的API,即使那个时候DirectX已经有《CS》《极品飞车5》等大作的支持,却依然不受当时FPS游戏霸主id Software的待见。作为那个时代的显卡杀手,《Quake III》都仅仅只支持OpenGL。DirectX7发布之后DirectX和OpenGL开始逐渐平起平坐。直到2000年DirectX8的发布才使DirectX在游戏领域完全确立了自己的优势 —— 支持革命性的programmable GPU rendering pipeline来代替原有的fixed function pipeline,引入了Vertex Shader和Pixel Shader。而OpenGL的核心正式支持programmable rendering pipeline已经是四年之后OpenGL 2.0发布的时候了。想想这中间会有多少游戏公司/游戏引擎公司会倒向DirectX吧。说到OpenGL衰落的原因,不得不提到OpenGL开发的机制。OpenGL早期一直是由ARB (OpenGL Architecture Review Board,成员包括Nvidia, ATI, Intel, Apple, IBM, SGI等等)成员共同维护。每个成员可以为了支持自己硬件新的feature来开发OpenGL enxtension, 所有成员一致通过的extension才能加入到下个版本OpenGL核心中。这就造成了不同成员为了各自利益互相斗争,拖慢了开发进度。微软曾经也是ARB的成员之一,后来因为受不了这种机制退出专心搞自己的DirectX去了。如果一个API越流行,那么去学习这个API的人就会越多,游戏公司会越容易招到掌握这个API的图形程序员,也就会更多的基于这个API开发游戏。用这个API的游戏越来越多,就会更多的得到硬件厂商的支持,为面向这个API的驱动做更多的优化,然后这个API就会更加流行。如此进入一个良性循环,这就造成了DirectX现在称霸游戏领域,OpenGL几乎绝迹的局面。在06年从ARB交由Khronos Group掌管之后, OpenGL最近几年也迎头赶上,从性能,易用性来说其实和DirectX已经相差不大。但是在相比DirectX没有突出优点的情况下(除了跨平台),已经习惯使用DirectX的游戏厂商也不可能重新投出OpenGL的怀抱。最后一点,OpenGL只是一个单纯的图形库,而DirectX是包含图形(Direct3D), 声音(DirectSound), 输入(DirectInput), 网络(DirectPlay)的一整套游戏开发解决方案。对开发者来说使用DirectX显然要方便的多。/*******************************************************************************************************/下面是我之前一个同事看完我的回答的评论,也贴上来吧。“还有很重要的一点, GL从不淘汰任何老的API. DX10相对于DX9,是个全新的API,革命性的更新,彻底推倒重来. 但GL为了向后兼容,保留了很多对硬件和驱动都不友好的API.除了跨平台和早期对精度的要求比DX高,其他简直是一无是处”于是Game开发者就都去用DX了。如果Linux上有类似于DX的接口,只要它真正被广泛支持了,包括但不限于OpenGL DSA 扩展,相信我,没有哪个开发者会脑袋抽风继续跟随坑爹的状态机的。OpenGL的硬件兼容性不如DirectX。用OpenGL写一个程序,在nVidia上跑起来了,百分之八十是没法在intel上跑,百分之九十九没法在AMD上跑。OpenGL直到目前为止如果不用DSA的话,设置一个对象的属性还得先绑定,这样一来就使得code变得高度依赖于一个时刻在变的状态,而且很多驱动的实现某些特定的状态下有各种bug,极难调试。例如我之前在intel上跑一个程序,如果不每帧都重新设置一个framebuffer object的render target, 那个framebuffer到了下一帧就莫名其妙的失效了,而在NV和AMD上都没有此问题,但是AMD又出了另外一个问题。DirectX的好处有微软帮你测试兼容性。一个驱动想拿到WDDM认证,先得跑通积累了十几年的test set,这样一来在实际中遇到问题的可能性就大为减少了。另外DX有开发调试环境的优势,以及更合理的API设计。dx甩opengl几条街学图形学还是多看看理论书吧,看API没什么意思。你要知道,至少到vs2008,vs自带的opengl头文件都只是1.1版本的,你这叫人如何用? 微软为了发展DX抑制OpenGL几乎每一本OpenGL书籍都会提到。 -------分割更新-------- 再有就是DX的SDK属于虽然要自己下而且很大但是可以开箱即用,OpenGL就不一样了,glew,glext,glut等等一大堆各式版本的头文件,还要自己保证兼容等等问题……不说了,都是泪对于从游戏开发者角度而言,OpenGL 曾经是个没人用的东西,Windows / Xbox 上可以用 DirectX,PS3 和 Wii 则又是另外的图像API。直到iPhone的兴起,OpenGL 居然又活了过来,你看现在连 WebGL 都出现了,有一种统一天下的感觉。游戏开发者又开始重视 OpenGL 了,当然主要还是 OpenGL ES。对于显卡公司而言,Windows 上的 D3D 驱动特别重要,会针对各种流行游戏进行定制、优化、hack……至于 OpenGL 驱动,似乎只要满足 CAD 大厂的需求即可,毕竟几乎没有 Windows 上的 OpenGL 游戏啊……现阶段,从性能考虑(D3D 驱动会特别优化),大型的游戏还是以 D3D 的形式发布,不排除 OpenGL 的优化上去以后也会有大型的桌面 OpenGL 游戏。对于微软而言,他对于OpenGL的限制非常多,比如WindowsRT,Windows Phone是不支持OpenGL,Windows商店里的应用也必须是DirectX的。Dota2的OS X和Linux版就是OpenGL的Source引擎做的近10年来,opengl追赶dx就跟java追赶C#一样。opengl原本是一种设计来做CAD的api,后来被用来搞游戏,火了之后不思进取,造成了计算模型落后到爆炸,后面才慢慢改成了dx11现在的样子的。而且opengl煞笔还要怪那些A开头公司的编译器。众所周知,一个公司一旦以A开头,那他自主研发的编译器就跟垃圾一样。opengl(和opencl一样)标准要求驱动程序自己去写编译器,就别说linux了,在windows上不同的卡都有互相不兼容的bug。而directx的标准要求驱动程序解释一个指令集的中间语言,不兼容的情况就少了好多,虽然还有,但是已经没什么所谓了。不过由于底子不好,opengl的api用起来始终没有dx11那么舒服。P.S.,由于opencl也是一个德行,在windows上的A卡定义一个struct都会导致驱动程序崩溃什么的,让人怎么用啊,只能选cuda或directcompute了。llvm是apple买的?llvm的创造者在apple工作了快有十年了,而且他还是swift的创造者,他本人已经算apple的一份子了吧。llvm确实是2000年就诞生了,但是走向成熟且大展拳脚则是在加盟apple以后吧强烈建议初学计算机图形学的玩家不要跳OpenGL这个坑,可能在你编译第一个demo的时候,这辈子就和CG绝缘了。下面就是我的血泪史:首先,OpenGL自身功能集成度太低,你要么选择大量的附加依赖项,要么写大量的代码。于是各种附加依赖层出不穷,从创建Wnd的glut到windows扩展glew,你都需要了解学习。不过你学习的过程就会惊喜的发现,有一些竟然不更新了,XP available ONLY 哦!剩下那些有更新也是一个丑的不能看的网站(还不如GNU系列的网站,你懂得),只提供源码(由于服务器缘故,下载速度让我还以为被墙了),需要自己编译。很多还是有多层依赖的,这些都需要自己一层一层的下载编译。而且由于C++编译选项千奇百怪,你必须要注意每个库的编译,否则链接错误就是个灾难。而且由于都是自己编译的,拿到别人的电脑上也没法用,别人也需要重新编译,甚至还要修改一些头文件的引用!面对一堆不是你写的,一坨宏和依赖项的C++头文件,去修改,画面真美。而且每换一个地方就要编译20分钟,那酸爽也是绝了。而且你想写原生的windows窗口,使用Windows Message Loop,而不是用glut的玩具一样的功能,由于没有Help Templates,我当时为了写一个支持多重采样的窗体,看了十几个OpenGL的英文(中文几乎没有开发者!呵呵)wiki和网上教程,才理解了gl绘图上下文的“二次创建”还有颜色模式。最后写出了一个好几百行、N多函数满地宏的main.cpp。当我给别人讲这些的时候,别人都觉得是天书。而一年之后,我也忘了。而DX3D我下载了Sample之后,由于有Templates、Help Tools,我根本不操心窗体创建、Message Loop,可以直奔主题编辑图形,感觉直接到了天堂。此外,OpenGL里面各种绑定,API接口,让人头晕目眩,一个函数N个参数(而且参数名字长相还特别像,还都是宏,酸爽你懂得),还由于开发者少,生态差,没有一份清晰的文档,也没有特别好的教程。当时为了学习OpenGL,我买了一本红宝书,简直是API Reference + 计算机图形学导论啊,就觉得100块钱买了个砖,根本看不下去。顺带一提,这个绑定机制极其反人类,当时一不小心绑定错了一个ID,各种诡异的现象都出现了,因为模型库都来自于修改第三方,debug用了一天,顺便读了一次3000多行的3D图形导入库,对这一坨坨的递归找BUG,学到的知识简直丰富无比,DEBUG技能点不知道增长了多少。同样是由于生态差,目前本应该主流使用的GLSL也很难找到资料学习,所以只能用1.1版本的API。然而放弃GLSL就等于回到了那个固定流水的老GPU时代,现代GPU的高效运算、多线程根本用不到了,又回到那个CPU运算为主,命令列表渲染的低效率时代。老师讲解的模型视点变换、透视变换,本来都应该是自己用GLSL实现的,结果都变成了调用现成API,学的东西和练习的东西完全脱节,导致课程实验效果很差,学生们做起来都是十分痛苦。最后图形学的知识几乎成了死记硬背来考试的,学生也没有在实验中获得多少快乐(个别如我这种喜欢自虐的除外。当然,最大的问题是难以调试!纯C++的OpenGL出BUG时尽管看不到调试的图形反应,但是起码能看到数据反映。但是加入了着色器以后的,如果C++部分编译、运行全部正常,然而却没有任何图像或者不尽如人意的话,恭喜你,锅都在GLSL的部分,而这一部分根本你不能调试,只能对着黑屏发呆思考哪个公式不对,那个数据传递有问题,可能一折腾几个小时就过去了。后来尽管有nSight,但是笔记本双显卡还不能用(默哀~,不知道现在改进了吗?)。这样的调试支持,可以说是要把开发者逼上梁山,不能Debug还玩毛线啊。网上有人评论,OpenGL你看一本红宝书下去,写出的代码都未必能运行;但是你用DX3D,HelloWorld Sample能跑,基本就可以出程序了。看我想他们易用性差距也就这么大吧。最后,因为OpenGL的一坨坑,我差点放弃学习计算机图形学,幸好我凭借“毅力”挺了过来,还做出了一个有天空盒、地形、模型导入、粒子系统、反狗牙的小图形引擎,拿了很高的分数。尽管如此,这两天搞毕设,我宁愿用从来没有接触过的DX3D做,也不愿意再碰OpenGL了,毕竟少生点气,多活两年比啥也重要。我大学的图形学课程教了我OpenGL入门。如果改成DirectX入门我估计要挂到天荒地老...OpenGL上手容易:强大的glut封装了很多诸如创建窗口之类的繁琐工作,而且一开始你根本不需要接触复杂的顶点缓冲之类的复杂概念,挨着调用glVertex(),glColor()之类的函数就可以一个一个的将顶点画上去。反观DX,除了从一开始你就得掌握一些windows编程知识用于基本的创建窗口之外,你还必须掌握定点缓冲,一次性传输所有顶点进去才可以让DX进行绘制。作为新手,用OpenGL画一个正方体比DX容易太多... 也更容易建立初始的成就感和兴趣...事实上老师根本没有讲到顶点缓冲以后的知识。毕竟是计算机图形学,不是OpenGL课... 这些都是我后来自学的。不过还好我学了,DX才能入门..作为一个两边都接触过的码农来回这个帖子。因为太久没碰GL,可能有误,欢迎指出。代码我就不贴了。
Estereo是一个开源的双目或者三目立体视觉重建程序
编译需要安装vc.net和directx9.0 sdk,编译时可能需要修改几处地方1.很多显卡不支持硬件VB,所以修改这里可以自己加上一个按钮,将这些代码加入按钮的响应函数中
//#include <GL/gl.h>
#include <GL/glaux.h> #include <glut.h>//glaux.lib glut32.lib
namespace Test9
{ #include <windows.h> // Header File For Windows#include <math.h> // Math Library Header File#include <stdio.h> // Header File For Standard Input/Output#include <glgl.h> // Header File For The OpenGL32 Library#include <glglu.h> // Header File For The GLu32 Library#include <glglaux.h> // Header File For The Glaux LibraryHDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering ContextHWND hWnd=NULL; // Holds Our Window HandleHINSTANCE hInstance; // Holds The Instance Of The Applicationbool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Defaultbool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Defaultbool blend; // Blending ON/OFFbool bp; // B Pressed?bool fp; // F Pressed?const float piover180 = 0.0174532925f;
GLfloat walkbias = 0;
GLfloat walkbiasangle = 0;GLfloat rot_x = 0.0f;GLfloat rot_y=0; // Y RotationGLfloat rot_z=0; GLfloat g_z=-5.0f; // Depth Into The ScreenGLfloat x=0.0f; // Depth Into The ScreenGLfloat y=0.0f; // Depth Into The ScreenGLuint filter; // Which Filter To Use
GLuint texture[3]; // Storage For 3 Texturestypedef struct tagVERTEX
{ float x, y, z;//3D坐标float u, v;//纹理坐标} VERTEX;typedef struct tagTRIANGLE
{//Triangle三角形结构VERTEX vertex[3];} TRIANGLE;typedef struct tagSECTOR
{ int numtriangles;// Sector中的三角形个数TRIANGLE* triangle;// 指向三角数组的指针} SECTOR;SECTOR sector1; // Our Model Goes Here:
typedef struct{
int numPoints;VERTEX *vertex;}MYPOINTS;MYPOINTS g_pts;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
void readstr(FILE *f,char *string)
{// 读入一个字符串do{ fgets(string, 255, f);int i1=0,i2=strlen(string),i;
while (string[i1] && (string[i1]==' ' || string[i1]==' '))i1++;// printf("i1=%d ",i1);// printf(string);// while (string[i2]==' ' || string[i2]==' ')i1--;if(i1>=i2)continue;else if(i1>0){ for (i=i1;i<i2;i++){ string[i-i1]=string[i];}string[i2-i1]=0;// printf(string);}} while ((string[0] == '/') || (string[0] == ' '));return;}void SetupWorld()
{// 设置我们的世界float x, y, z, u, v;int numtriangles;FILE *filein;char oneline[255];filein = fopen("world.txt", "rt"); // File To Load World Data FromCHECK(filein);readstr(filein,oneline);
//printf(oneline);sscanf(oneline, "NUMPOLLIES %d ", &numtriangles);CHECK(numtriangles>0);sector1.triangle = new TRIANGLE[numtriangles];sector1.numtriangles = numtriangles;for (int loop = 0; loop < numtriangles; loop++){ for (int vert = 0; vert < 3; vert++){ readstr(filein,oneline);sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);sector1.triangle[loop].vertex[vert].x = x;sector1.triangle[loop].vertex[vert].y = y;sector1.triangle[loop].vertex[vert].z = z;sector1.triangle[loop].vertex[vert].u = u;sector1.triangle[loop].vertex[vert].v = v;}}fclose(filein);return;}//支持定义点和面(三角和四边形)
void SetupWorld2(){// 设置我们的世界float x, y, z, u, v;int numpoints;FILE *filein;char oneline[255];filein = fopen("world2.txt", "rt"); // File To Load World Data FromCHECK(filein);//读入点
readstr(filein,oneline);CHECK(1==sscanf(oneline, "NUMPOINTS %d ", &numpoints));CHECK(numpoints>0);g_pts.numPoints=numpoints;g_pts.vertex=new VERTEX[numpoints];for (int loop = 0; loop < numpoints; loop++){ readstr(filein,oneline);CHECK(5==sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v));g_pts.vertex[loop].x=x;g_pts.vertex[loop].y=y;g_pts.vertex[loop].z=z;g_pts.vertex[loop].u=u;g_pts.vertex[loop].v=v;}//读入面
int numtriangles=0;readstr(filein,oneline);CHECK(1==sscanf(oneline, "NUMPTRIANGLES %d ", &numtriangles));CHECK(numtriangles>0);sector1.triangle = new TRIANGLE[numtriangles];sector1.numtriangles = numtriangles;for ( loop = 0; loop < numtriangles; loop++){ int index[3];readstr(filein,oneline);CHECK(3==sscanf(oneline, "%d %d %d",index,index+1,index+2));CHECK(index[0]>=0 && index[0]<g_pts.numPoints);CHECK(index[1]>=0 && index[1]<g_pts.numPoints);CHECK(index[2]>=0 && index[2]<g_pts.numPoints);for (int vert = 0; vert < 3; vert++){ sector1.triangle[loop].vertex[vert]= g_pts.vertex[index[vert]];}}fclose(filein);return;}AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{ FILE *File=NULL; // File Handleif (!Filename) // Make Sure A Filename Was Given
{ return NULL; // If Not Return NULL}File=fopen(Filename,"r"); // Check To See If The File Exists
if (File) // Does The File Exist?
{ fclose(File); // Close The Handlereturn auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer}return NULL; // If Load Failed Return NULL}int LoadGLTextures() // Load Bitmaps And Convert To Textures
{ int Status=FALSE; // Status IndicatorAUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if (TextureImage[0]=LoadBMP("1.bmp")){ Status=TRUE; // Set The Status To TRUEglGenTextures(3, &texture[0]); // Create Three Textures
// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[0]);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[1]);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);// Create MipMapped Texture
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);gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);}if (TextureImage[0]) // If Texture Exists{ if (TextureImage[0]->data) // If Texture Image Exists{ free(TextureImage[0]->data); // Free The Texture Image Memory}free(TextureImage[0]); // Free The Image Structure
}return Status; // Return The Status
}GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{ if (height==0) // Prevent A Divide By Zero By{ height=1; // Making Height Equal One}glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix}int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{ if (!LoadGLTextures()) // Jump To Texture Loading Routine{ return FALSE; // If Texture Didn't Load Return FALSE}glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For TranslucencyglClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To BlackglClearDepth(1.0); // Enables Clearing Of The Depth BufferglDepthFunc(GL_LESS); // The Type Of Depth Test To DoglEnable(GL_DEPTH_TEST); // Enables Depth TestingglShadeModel(GL_SMOOTH); // Enables Smooth Color ShadingglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective CalculationsSetupWorld2();//建立世界
return TRUE; // Initialization Went OK
}int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth BufferglLoadIdentity(); // Reset The ViewGLfloat x_m, y_m, z_m, u_m, v_m;
static DWORD tickCnt=GetTickCount();int numtriangles;glTranslatef(x, y, g_z);
#if 1
glRotatef(rot_x,1.0f,0,0);glRotatef(rot_y,0,1.0f,0);glRotatef(rot_z,0,0,1.0f);#elseint norm=sqrt(rot_x*rot_x+rot_y*rot_y+rot_z*rot_z);int ang_x=0;int ang_y=0;int ang_z=0;if(norm>10)
{ ang_x=rot_x/norm;ang_y=rot_y/norm;ang_z=rot_z/norm;}elsenorm=0;glRotatef(norm,rot_x,rot_y,rot_z);#endifif(GetTickCount()-tickCnt>1000)
{ printf("Trans %8g %8g %8g ",x,y,g_z);printf("Rot %8g %8g %8g ",rot_x,rot_y,rot_z);tickCnt=GetTickCount();}glBindTexture(GL_TEXTURE_2D, texture[filter]);numtriangles = sector1.numtriangles;// Process Each Trianglefor (int loop_m = 0; loop_m < numtriangles; loop_m++){ glBegin(GL_TRIANGLES);glNormal3f( 0.0f, 0.0f, 1.0f);x_m = sector1.triangle[loop_m].vertex[0].x;y_m = sector1.triangle[loop_m].vertex[0].y;z_m = sector1.triangle[loop_m].vertex[0].z;u_m = sector1.triangle[loop_m].vertex[0].u;v_m = sector1.triangle[loop_m].vertex[0].v;glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);x_m = sector1.triangle[loop_m].vertex[1].x;y_m = sector1.triangle[loop_m].vertex[1].y;z_m = sector1.triangle[loop_m].vertex[1].z;u_m = sector1.triangle[loop_m].vertex[1].u;v_m = sector1.triangle[loop_m].vertex[1].v;glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);x_m = sector1.triangle[loop_m].vertex[2].x;y_m = sector1.triangle[loop_m].vertex[2].y;z_m = sector1.triangle[loop_m].vertex[2].z;u_m = sector1.triangle[loop_m].vertex[2].u;v_m = sector1.triangle[loop_m].vertex[2].v;glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);glEnd();}return TRUE; // Everything Went OK}GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
{ if (fullscreen) // Are We In Fullscreen Mode?{ ChangeDisplaySettings(NULL,0); // If So Switch Back To The DesktopShowCursor(TRUE); // Show Mouse Pointer}if (hRC) // Do We Have A Rendering Context?
{ if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?{ MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);}if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{ MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);}hRC=NULL; // Set RC To NULL}if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{ MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);hDC=NULL; // Set DC To NULL}if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{ MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);hWnd=NULL; // Set hWnd To NULL}if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class
{ MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);hInstance=NULL; // Set hInstance To NULL}}/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window ** width - Width Of The GL Window Or Fullscreen Mode ** height - Height Of The GL Window Or Fullscreen Mode ** bits - Number Of Bits To Use For Color (8/16/24/32) ** fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag){ GLuint PixelFormat; // Holds The Results After Searching For A MatchWNDCLASS wc; // Windows Class StructureDWORD dwExStyle; // Window Extended StyleDWORD dwStyle; // Window StyleRECT WindowRect; // Grabs Rectangle Upper Left / Lower Right ValuesWindowRect.left=(long)0; // Set Left Value To 0WindowRect.right=(long)width; // Set Right Value To Requested WidthWindowRect.top=(long)0; // Set Top Value To 0WindowRect.bottom=(long)height; // Set Bottom Value To Requested Heightfullscreen=fullscreenflag; // Set The Global Fullscreen Flag
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messageswc.cbClsExtra = 0; // No Extra Window Datawc.cbWndExtra = 0; // No Extra Window Datawc.hInstance = hInstance; // Set The Instancewc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Iconwc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointerwc.hbrBackground = NULL; // No Background Required For GLwc.lpszMenuName = NULL; // We Don't Want A Menuwc.lpszClassName = "OpenGL"; // Set The Class Nameif (!RegisterClass(&wc)) // Attempt To Register The Window Class
{ MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE}if (fullscreen) // Attempt Fullscreen Mode?{ DEVMODE dmScreenSettings; // Device Modememset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's CleareddmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode StructuredmScreenSettings.dmPelsWidth = width; // Selected Screen WidthdmScreenSettings.dmPelsHeight = height; // Selected Screen HeightdmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per PixeldmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL){ // If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By Your Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES){ fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE}else{ // Pop Up A Message Box Letting User Know The Program Is Closing.MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);return FALSE; // Return FALSE}}}if (fullscreen) // Are We Still In Fullscreen Mode?
{ dwExStyle=WS_EX_APPWINDOW; // Window Extended StyledwStyle=WS_POPUP; // Windows StyleShowCursor(FALSE); // Hide Mouse Pointer}else{ dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended StyledwStyle=WS_OVERLAPPEDWINDOW; // Windows Style}AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window"OpenGL", // Class Nametitle, // Window TitledwStyle | // Defined Window StyleWS_CLIPSIBLINGS | // Required Window StyleWS_CLIPCHILDREN, // Required Window Style0, 0, // Window PositionWindowRect.right-WindowRect.left, // Calculate Window WidthWindowRect.bottom-WindowRect.top, // Calculate Window HeightNULL, // No Parent WindowNULL, // No MenuhInstance, // InstanceNULL))) // Dont Pass Anything To WM_CREATE{ KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE}static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{ sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor1, // Version NumberPFD_DRAW_TO_WINDOW | // Format Must Support WindowPFD_SUPPORT_OPENGL | // Format Must Support OpenGLPFD_DOUBLEBUFFER, // Must Support Double BufferingPFD_TYPE_RGBA, // Request An RGBA Formatbits, // Select Our Color Depth0, 0, 0, 0, 0, 0, // Color Bits Ignored0, // No Alpha Buffer0, // Shift Bit Ignored0, // No Accumulation Buffer0, 0, 0, 0, // Accumulation Bits Ignored16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer0, // No Auxiliary BufferPFD_MAIN_PLANE, // Main Drawing Layer0, // Reserved0, 0, 0 // Layer Masks Ignored};if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?{ KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE}if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{ KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE}if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{ KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE}if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{ KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE}if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{ KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE}ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher PrioritySetFocus(hWnd); // Sets Keyboard Focus To The WindowReSizeGLScene(width, height); // Set Up Our Perspective GL Screenif (!InitGL()) // Initialize Our Newly Created GL Window
{ KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE}return TRUE; // Success
}LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This WindowWPARAM wParam, // Additional Message InformationLPARAM lParam) // Additional Message Information{ switch (uMsg) // Check For Windows Messages{ case WM_ACTIVATE: // Watch For Window Activate Message{ if (!HIWORD(wParam)) // Check Minimization State{ active=TRUE; // Program Is Active}else{ active=FALSE; // Program Is No Longer Active}return 0; // Return To The Message Loop
}case WM_SYSCOMMAND: // Intercept System Commands
{ switch (wParam) // Check System Calls{ case SC_SCREENSAVE: // Screensaver Trying To Start?case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?return 0; // Prevent From Happening}break; // Exit}case WM_CLOSE: // Did We Receive A Close Message?
{ PostQuitMessage(0); // Send A Quit Messagereturn 0; // Jump Back}case WM_KEYDOWN: // Is A Key Being Held Down?
{ keys[wParam] = TRUE; // If So, Mark It As TRUEreturn 0; // Jump Back}case WM_KEYUP: // Has A Key Been Released?
{ keys[wParam] = FALSE; // If So, Mark It As FALSEreturn 0; // Jump Back}case WM_SIZE: // Resize The OpenGL Window
{ ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Heightreturn 0; // Jump Back}}// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);}int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous InstanceLPSTR lpCmdLine, // Command Line Parametersint nCmdShow) // Window Show State{ MSG msg; // Windows Message StructureBOOL done=FALSE; // Bool Variable To Exit Loop// Ask The User Which Screen Mode They Prefer
if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO){ fullscreen=FALSE; // Windowed Mode}// Create Our OpenGL Window
if (!CreateGLWindow("Lionel Brits & NeHe's 3D World Tutorial",640,480,16,fullscreen)){ return 0; // Quit If Window Was Not Created}while(!done) // Loop That Runs While done=FALSE
{ if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?{ if (msg.message==WM_QUIT) // Have We Received A Quit Message?{ done=TRUE; // If So done=TRUE}else // If Not, Deal With Window Messages{ TranslateMessage(&msg); // Translate The MessageDispatchMessage(&msg); // Dispatch The Message}}else // If There Are No Messages{ // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?{ done=TRUE; // ESC or DrawGLScene Signalled A Quit}else // Not Time To Quit, Update Screen{ SwapBuffers(hDC); // Swap Buffers (Double Buffering)if (keys['B'] && !bp){ bp=TRUE;blend=!blend;if (!blend){ glDisable(GL_BLEND);glEnable(GL_DEPTH_TEST);}else{ glEnable(GL_BLEND);glDisable(GL_DEPTH_TEST);}}if (!keys['B']){ bp=FALSE;}if (keys['F'] && !fp)
{ fp=TRUE;filter+=1;if (filter>2){ filter=0;}}if (!keys['F']){ fp=FALSE;}if (keys['R'])//Reset totation matrix{ rot_x=rot_y=rot_z=0;}if (keys['T'])//Reset totation matrix{ x=y=0;g_z=-5;}if (keys[VK_F1])//pgup
{ x-=0.01f;}if (keys[VK_F2])
{ x+=0.01f;}if (keys[VK_F3])//pgup
{ y-=0.01f;}if (keys[VK_F4])
{ y+=0.01f;}if (keys[VK_F5])//pgup
{ g_z-=0.01f;}if (keys[VK_F6])
{ g_z+=0.01f;} if (keys[VK_PRIOR])//pgup{ rot_z-=1.0f;}if (keys[VK_NEXT])
{ rot_z+=1.0f;} if (keys[VK_RIGHT]){ rot_y -= 1.0f;}if (keys[VK_LEFT])
{ rot_y += 1.0f;}if (keys[VK_UP])
{ rot_x-= 1.0f;}if (keys[VK_DOWN])
{ rot_x+= 1.0f;}// if (keys[VK_ESCAPE]) // Is F1 Being Pressed?
// { // keys[VK_F1]=FALSE; // If So Make Key FALSE// KillGLWindow(); // Kill Our Current Window// fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode// // Recreate Our OpenGL Window// if (!CreateGLWindow("Lionel Brits & NeHe's 3D World Tutorial",640,480,16,fullscreen))// { // return 0; // Quit If Window Was Not Created// }// }}}}// Shutdown
KillGLWindow(); // Kill The Windowreturn (msg.wParam); // Exit The Program}}int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){ int nRetCode = 0;// initialize MFC and print and error on failureif (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){ // TODO: change error code to suit your needscerr << _T("Fatal Error: MFC initialization failed") << endl;nRetCode = 1;}else{ // TODO: code your application's behavior here.CString strHello;strHello.LoadString(IDS_HELLO);cout << (LPCTSTR)strHello << endl;}//Test1::main2();Test9::WinMain(0,0,0,SW_SHOWNORMAL);return nRetCode;}
附上测试使用的world2.txt
mud.bmp