在OpenGL中处理纹理,直到最近,通常意味着要使用2的幂次方大小的图像,如1024、2048或4096。2005年4月26日,Mark J. Kilgard发布了NVIDIA的OpenGL 2.0支持说明,明确指出NVIDIA的GeForce 6系列和基于NV4xGL的Quadro FX GPU完全支持在片段级别使用非2的幂次方大小的纹理(当然,有一些限制)。对于程序员来说,有时使用任意大小的图像(指的是非常大的图像),并将其视为没有限制的非2的幂次方大纹理,比如8000 x 3000像素大小,而不必担心众所周知的纹理“厨房”问题,可能会很有吸引力。
anyTex是一个类,它允许从文件中加载具有给定颜色深度的位图,并将其视为没有限制的纹理(当然,受到计算机资源的限制,这是必须接受的)。
anyTex类包括两个文件:anytex.cpp和anytex.h,需要将它们添加到项目中。确保项目设置的链接选项卡中有OpenGL32.lib、GLu32.lib和GLaux.lib。然后在主对话框类的头文件中包含"anytex.h"。在主对话框类中添加一个公共成员,类型为AnyTex:
AnyTex m_atImage;
在应用程序中添加一个CStatic控件,它将负责渲染OpenGL场景(只是为了演示而做出这个选择)。然后,添加一个派生自CStatic的类,并映射一个该类型的变量到控件。假设m_oglDisplay是该变量的名称。在OnInitDialog()函数中,通过传递控件的地址给anyTex类提供的InitializeOpenGL()函数来创建OpenGL渲染上下文:
if (!m_atImage.InitializeOpenGL(&m_oglDisplay)) {
AfxMessageBox("Cannot initialize OpenGL");
PostMessage(WM_QUIT);
}
在继续之前,请记住,anyTex在幕后仍然使用2的幂次方的经典纹理作为基本的正方形单元。默认情况下,单元格大小是1024。如果想设置另一个单元格大小,可以通过调用anyTex提供的SetTexCellSize(int nSize)函数来自由设置nSize的值。
anyTex会自动将其调整为128、256、512或1024。加载选择的位图图像,并创建anyTex纹理,以后简称为anyTex。
if (m_atImage.LoadBmpImage("test.bmp")) m_atImage.CreateTex();
CreateTex()函数需要一个布尔参数,默认为false,这将创建2D图像纹理。通过将参数设置为true调用该函数,将生成mipmap。从现在起,只需要在CStatic派生类的OnPaint()函数中调用anyTex类的PreRender()函数(可以根据需求重写)和Render()函数。
anyTex背后是由一个CList<UINT, UINT> m_listTex支持的,它存储纹理单元的ID。位图被加载到内存中作为一个DIB。anytex“遍历”DIB,顺序提取与基本纹理单元大小相同的正方形。每个正方形被blitted到一个内存设备上下文中,结果是一个DDB。DDB被转换为一个32色深的DIB,然后用于生成基本纹理单元或其对应的mipmap,根据传递给AnyText::CreateTex()函数的布尔参数。纹理ID被添加到m_listTex中。
anyTex考虑一个大小为1的正方形纹理画布映射到anyTex对象上,如下所示:
anyTex与画布左上角对齐。AnyTex::Render()函数将anyText渲染为整体。如果现在对3D渲染感兴趣,并需要单独使用组件纹理单元,只需要调用:
UINT AnyTex::RetrieveTexCell(double atX, double atY, double &renLeft, double &renTop, double &renSize)