前言
上次规划了一下资源加载的方式,这次就要着手去加载资源,我们要准备好纹理,着色器代码,和顶点数据,开工。
正题
1.纹理
先来加载纹理,因为这个容易一些,我选择魔塔中的纹理,背景透明的,32X32的一个图像。有些模糊,是因为放大了的原因。
这支持其中的一张,我会准备很多张图片,将图片按照一定规则命名。现就这么多图片。
在全局类中添加三个加载资源的函数
资源的文件名我们专门放到一个文件中,然后函数读取指定文件中的资源路径就可以了,这样灵活一些。我们通过一条命令来获取所有文件名。例如这个。
然后保存到一个文件中,之后我们读取这个文件里的名字来获取相应资源文件。拓展名自己可以随便起。
void GLSTD_TOOLS::loadTexture(const char * path_file)
{
ifstream fin;
fin.open(path_file,ios::in);
char filename[64];
memset(filename,0,64);
while(!fin.eof())
{
fin>>filename;
//读取一张纹理
TEXTURE.push_back(GLSTD_TOOLS::createTexture(filename,GL_RGBA, SOIL_LOAD_RGBA));
memset(filename,0,64);
}
fin.close();
}
这样,我们读取到了纹理。
2.顶点
顶点文件有很多种,我们可以用软件生成的,也可以用自己输入的顶点,现在对于简单的形状,我们使用自己输入的。
4 5
-1.0 -1.0 0.0 0.0 0.0
1.0 -1.0 0.0 1.0 0.0
1.0 1.0 0.0 1.0 1.0
-1.0 1.0 0.0 0.0 1.0
6
0 1 2 2 3 0
4行5列的数据,6个顶点下标。这就是我们的顶点文件。通过读取这些来整理顶点数据。因为OpenGL顶点加载要符合一定的格式,所以还要一个格式解析函数来辅助。
int GLSTD_TOOLS::ReadFormat(const char * format, VertexFmt & res)
{
int length = strlen(format);
res.step = 0;
res.num = length / 2;
for (int i = 0; i < length; i++)
{
if (format[i] >= 48 && format[i] <= 57)
{
res.sizes.push_back(format[i] - '0');
res.step = res.step + format[i] - '0';
}
}
return res.step;
}
这个函数就解析顶点格式的,如果输入的格式是3f2f,就是3个GLfloat和2个GLfloat类型一组,通过结构体来存储格式控制数据。
void GLSTD_TOOLS::loadVertex(const char * path_file)
{
ifstream fin;
fin.open(path_file,ios::in);
char filename[64];
char format[16];
vec3 zoom;
int type;
memset(filename,0,64);
memset(format,0,16);
while(!fin.eof())
{
fin>>filename>>format>>zoom.x>>zoom.y>>zoom.z>>type;
//读取一张纹理
VERTEX.push_back(GLSTD_TOOLS::createMesh(filename,format,zoom,type));
memset(filename,0,64);
}
fin.close();
}
这样就完成了顶点文件的加载,文件路径格式要说明一下,分别是文件名,顶点格式,三个浮点是xyz缩放比例,随后一个整形是网格类型。最后可能有多种网格文件,目前使用的是其中的一种。
3.着色器
着色器加载过程中,需要对加载的着色器代码进行编译。所以要一些编译辅助函数来完成。着色器需要顶点着色器和片元着色器等多种组合,所以源代码也有多种组合,需要在加载文件中设计一种灵活的组合方案。
每一行是需要的着色器文件名字,最后面的%作为结束符,要有空格。着色器代码文件的格式作为区分标志。
void GLSTD_TOOLS::loadShader(const char * path_file)
{
ifstream fin;
fin.open(path_file,ios::in);
char filename[64];
memset(filename,0,64);
while(!fin.eof())
{
vector<char*>filenames;
while(true)
{
fin>>filename;
if(strcmp("%",filename) == 0)
break;
filenames.push_back(filename);
memset(filename,0,64);
}
//读取着色器
SHADER.push_back(GLSTD_TOOLS::createShader(filenames));
}
fin.close();
}
到这里我完成了有关于加载资源部分的代码。下面看看类的设计有什么变化。