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
)。有人能向我解释一下上面的编码是如何工作的吗?
你在问" OpenGL是如何工作的"那取决于你使用的是哪个版本。我建议:http://www.opengl-tutorial.org/beginners-tutorials
或者更好,阅读"红皮书"(第8版涵盖OpenGL 4.3)
http://www.opengl-redbook.com/GLuint createTexture(const char* filename, int width=128, int height=128)
{
GLuint texture;
使用C99可变数组在堆栈上分配宽度*高度*3字节的内存。如果没有足够的堆栈剩余,程序将崩溃并导致堆栈溢出。
char bitmap[width][height][3];
尝试打开文件获取纹理。文件必须是一个无头的、原始的、紧凑的数组,每通道RGB数据8位。
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纹理中。由于这使用了一个新分配的纹理对象句柄,因此纹理也由this初始化。
这里遗漏了很多重要的步骤。即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错误检查,如果在调试构建中会导致程序崩溃。在发布版本中,没有文件操作错误被检测和处理。
不要使用这个代码!