GLuint createTexture(const char* filename, int width = 128, int height = 128)
{
GLuint texture;
char bitmap[width][height][3];
FILE* fp = fopen(filename, "rb");
assert(fp);
assert(fread(bitmap, 3*sizeof(char), width*height, fp) == width*height);
fclose(fp);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmap);
glBindTexture( GL_TEXTURE_2D,0);
return texture;
}
大家好,我想知道上面的代码是如何工作的。据说它是一个可用于在OpenGL中构建实体对象的编码(例如:glutSolidSphere
)。有人可以向我解释上述编码是如何工作的吗?
答案 0 :(得分:4)
你有点问“OpenGL如何工作”,这取决于你使用的是哪个版本。我建议:http://www.opengl-tutorial.org/beginners-tutorials
或者更好的是,阅读“红皮书”(第8版涵盖OpenGL 4.3)
答案 1 :(得分:2)
GLuint createTexture(const char* filename, int width=128, int height=128)
{
GLuint texture;
使用C99可变参数数组在堆栈上分配宽度*高度* 3个字节的内存。如果没有足够的堆栈,程序会因堆栈溢出而崩溃。
char bitmap[width][height][3];
尝试打开文件以从中获取纹理。该文件必须是每通道8位RGB数据的无头,原始,紧密阵列。
FILE* fp=fopen(filename, "rb");
如果打开文件失败,则终止程序。从技术上讲,为此目的使用assert是一个编程错误,因为a)assert在发布版本中什么都不做,而b)这很容易从错误中恢复。如果文件无法打开,该函数应该返回0.
assert(fp);
读取宽度*高度为3个字节的块。 sizeof(char)
表示此作者对C没有任何线索,因为C标准定义sizeof(char) == 1
,因此进行乘法没有意义。
如果不能读取预期的数据量,则在调试模式下会使程序崩溃。如果出现错误,发布版本会做出奇怪的事情。
assert(fread(bitmap, 3*sizeof(char), width*height, fp) == width*height);
关闭文件。
fclose(fp);
分配OpenGL纹理对象句柄。
glGenTextures(1, &texture);
绑定纹理句柄,以便影响纹理的后续OpenGL操作在给定对象上运行。
glBindTexture(GL_TEXTURE_2D, texture);
设置纹理放大率和缩小滤镜。使用线性,因此不需要mipmap级别。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
将数据复制到OpenGL纹理中。由于这使用了新分配的纹理对象句柄,因此纹理也会被初始化。
这里缺少很多重要的步骤。即 glPixelStorei 必须用于准备OpenGL以从数组中读取数据。行对齐,跨步等。
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,bitmap);
取消绑定纹理对象。
glBindTexture( GL_TEXTURE_2D,0);
返回纹理对象句柄。
return texture;
}
此代码的主要问题:如果在调试版本中没有OpenGL错误检查并导致程序崩溃。在发布版本中,不会检测和处理文件操作错误。
不要使用此代码!