📄 tutorial_38.htm
字号:
<p>移动之后选“文件--〉全部保存”,然后文件部分就好了。好多的图阿:) </p>
<p>然
后我们开始code的部分。下面一段最重要的一行是#include
"resource.h".没有这行,编译的时候就会有无数未定义变量的错误。resource.h文件定义了资源文件里的对象。所以要从
IDB_BUTTERFLY1里面读取数据的话,最好include这个头文件 ! </p>
<font face="Tahoma,Verdana,sans-serif" size="-1"> </font></td>
<td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre>#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include "NeHeGL.h"
#include "resource.h" <font color="#ffffaa">// 资源文件的头文件</font>
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glu32.lib" )
#pragma comment( lib, "glaux.lib" )
GL_Window* g_window;
Keys* g_keys;
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_38_files/l.png"><img src="Tutorial_38_files/l.png"></td>
<td valign="top" width="100%">下面一段第一行分配三个纹理所需空间,接下来的结构体用于保存关于约50个在屏幕上运动的物体的信息。<br>
tex将跟踪每个物体所用纹理,x是物体的x坐标,y是y坐标,z,z坐标,yi是一个随机数用来控制物体下落速度,<br>
spinz用来控制沿z轴的旋转,spinzi是另一个随机树,记录旋转速度。flap用来控制物体的翅膀(一会在解释这个)随机数fi控制翅膀拍打的速度。
<br></td><td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre><font color="#ffffaa">// 定义三个保存纹理变量的ID</font>
GLuint texture[3]; <font color="#ffffaa">// 保存三个纹理</font>
struct object <font color="#ffffaa">// 定义一个物体</font>
{
int tex; <font color="#ffffaa">// 纹理值</font>
float x; <font color="#ffffaa"> // 位置</font>
float y;
float z;
float yi; <font color="#ffffaa">// 速度</font>
float spinz; <font color="#ffffaa">// 沿Z轴旋转的角度和速度</font>
float spinzi;
float flap; <font color="#ffffaa">// 是否翻转三角形</font>
float fi;
};
object obj[50]; <font color="#ffffaa">// 创建50个物体</font>
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_38_files/l.png"><img src="Tutorial_38_files/l.png"></td>
<td valign="top" width="100%">下面一段代码是物体obj[loop]的初始化,loop从0到49(表示50个物体中的一个)。首先是随机纹理从0到2表示<br>
一个随机着色的蝴蝶。x坐标随机的取-17.0f到+17.0f之间的值,y取18.0f,也就是从屏幕的上面一点点开始,<br>
这样一开始时看不到物体的。z也是-10.0f到-40.f之间的随机数,spinzi取-1.0f到1.0f之间。flap取翅膀中心<br>
位置,为0.0f。最后拍打速度fi和下落速度yi也是随机的。<br></td><td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre>void SetObject(int loop) <font color="#ffffaa">// 循环设置50个物体</font>
{
obj[loop].tex=rand()%3; <font color="#ffffaa">// 纹理</font>
obj[loop].x=rand()%34-17.0f; <font color="#ffffaa">// 位置</font>
obj[loop].y=18.0f;
obj[loop].z=-((rand()%30000/1000.0f)+10.0f);
obj[loop].spinzi=(rand()%10000)/5000.0f-1.0f; <font color="#ffffaa">// 旋转</font>
obj[loop].flap=0.0f;
obj[loop].fi=0.05f+(rand()%100)/1000.0f;
obj[loop].yi=0.001f+(rand()%1000)/10000.0f;
}
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_38_files/l.png"><img src="Tutorial_38_files/l.png"></td>
<td valign="top" width="100%">这回该到了最有意思的地方了。从资源文件中读入bitmap,转为纹理。hBMP是指向这个bitmap文件的指针,<br>
它将告诉我们的程序从哪里读取数据。BMP是一个bitmap结构体,我们把从资源文件中读取的数据保存在里面。<br>
第三行是告诉我们的程序我们将使用哪些ID:IDB_BUTTERFLY1,IDB_BUTTERFLY2,IDB_BUTTERFLY3。要用更多<br>
的图像的话,只需增加资源文件中的图像,并在Texture[]中增加新的ID。 <br></td><td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre>void LoadGLTextures() <font color="#ffffaa">// 资源文件中读入bitmap,转为纹理</font>
{
HBITMAP hBMP; <font color="#ffffaa">// 位图句柄</font>
BITMAP BMP; <font color="#ffffaa">// 位图结构</font>
<font color="#ffffaa">// 纹理句柄</font>
byte Texture[]={ IDB_BUTTERFLY1, IDB_BUTTERFLY2, IDB_BUTTERFLY3 };
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_38_files/l.png"><img src="Tutorial_38_files/l.png"></td>
<td valign="top" width="100%"><font color="#ffffff">下面一行使用sizeof(Texture)来计算要创建多少个纹理。我们有3个ID,也就是3个纹理。</font></td>
<td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre> glGenTextures(sizeof(Texture), &texture[0]); <font color="#ffffaa">// 创建三个纹理</font>
for (int loop=0; loop<sizeof(Texture); loop++) <font color="#ffffaa">// 循环载入所有的位图</font>
{
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_38_files/l.png"><img src="Tutorial_38_files/l.png"></td>
<td valign="top" width="100%">LoadImage需要如下参数:GetModuleHandle(NULL)-指向实例的句柄,MAKEINTRESOURCE(Texture[loop])-把Texture[loop]从整型转为一个资<br>
源值,也就是要读的图形文件。IMAGE_BITMAP-告诉我们要读的是一个bitmap文件。 <br>
接下来两个参数(0,0)是读入图像的高度和宽度像素数,使用默认大小就设为0。 <br>
最后一个参数(LR_CREATEDIBSECTION)返回DIB section bitmap??这是一个没有保存颜色信息的bitmap。也正是我们需要的。
<br>
hBMP 指向从LoadImage()读入的bitmap数据。 <br></td><td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3"><pre> hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(Texture[loop]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
</pre></font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_38_files/l.png"><img src="Tutorial_38_files/l.png"></td>
<td valign="top" width="100%">检查指针hBMP是否有效,即指向有用数据。如果没有指向任何数据,也可以弹出错误提示。 <br>
如果数据存在,用GetObject()从hBMP取得数据(sizeof(BMP))并存储在BMP中。 <br>
glPixelStorei告诉OpenGL这些数据是以word alignments存储的,也就是每像素4字节。 <br>
绑定纹理,设置滤波方式为GL_LINEAR_MIPMAP_LINEAR(又好又光滑),然后生成纹理。 <br>
注意到我们使用BMP.bmWidth和BMP.bmHeight获取图像的高度和宽度。并用GL_BGR_EXT交换红蓝,实际使用的资源数据是从BMP.bmBits中取得的<br>
。 <br>
最后删除bitmap对象,释放所有与之相联系的系统资源空间。 <br></td><td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre> if (hBMP) <font color="#ffffaa">// 位图是否存在</font>
{ <font color="#ffffaa">// 存在</font>
GetObject(hBMP,sizeof(BMP), &BMP); <font color="#ffffaa">// 获得位图</font>
glPixelStorei(GL_UNPACK_ALIGNMENT,4); <font color="#ffffaa">// 以四字节方式对其内存</font>
glBindTexture(GL_TEXTURE_2D, texture[loop]); <font color="#ffffaa">// 绑定位图</font>
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); <font color="#ffffaa">// 设置纹理过滤器</font>
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); <font color="#ffffaa">
// 创建纹理</font>
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
DeleteObject(hBMP); <font color="#ffffaa">// 删除位图对象</font>
}
}
}
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_38_files/l.png"><img src="Tutorial_38_files/l.png"></td>
<td valign="top" width="100%">init code没有什么新鲜的,只是增加了LoadGLTextures()调用上面的code。清屏的颜色是黑色,不进行深度检测,这样比较快。启用纹理映<br>
射和混色效果。 <br></td><td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre>BOOL Initialize (GL_Window* window, Keys* keys) <font color="#ffffaa">// 初始化</font>
{
g_window = window;
g_keys = keys;
LoadGLTextures(); <font color="#ffffaa">//载入纹理</font>
glClearColor (0.0f, 0.0f, 0.0f, 0.5f); <font color="#ffffaa">// 设置背景</font>
glClearDepth (1.0f);
glDepthFunc (GL_LEQUAL);
glDisable(GL_DEPTH_TEST); <font color="#ffffaa">// 启用深度测试</font>
glShadeModel (GL_SMOOTH);
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_TEXTURE_2D); <font color="#ffffaa">// 启用2D纹理</font>
glBlendFunc(GL_ONE,GL_SRC_ALPHA); <font color="#ffffaa">// 使用混合</font>
glEnable(GL_BLEND); </pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_38_files/l.png"><img src="Tutorial_38_files/l.png"></td>
<td valign="top" width="100%"><font color="#000066">初始化所有的物体</font></td>
<td background="Tutorial_38_files/r.png"><img src="Tutorial_38_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_38_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_38_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_38_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre> for (int loop=0; loop<50; loop++)
{
SetObject(loop);
}
return TRUE; <font color="#ffffaa">// 成功返回</font>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -