我正在开发一款适用于iPhone的简单小游戏,我想使用纹理,但我似乎无法让它正常工作......
经过一些研究后,我发现了this page和this site。两者都是很好的参考,并教我一些纹理,但是,在使用任一函数加载纹理后,我无法显示纹理,这里是我的代码:
非常简单的纹理显示功能(不工作)
void drawTexture(GLuint texture, float x, float y, float w, float h)
{
glBindTexture(GL_TEXTURE_2D,texture);
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0,box);
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
通常情况下,我不是每一帧都只创建一个数组来显示图像,但这只是一个例子。当我运行这个功能时,我什么都没得到。空白 - 没有图像,没有任何内容(除非我之前已经启用了彩色阵列并且之后没有禁用它)
第二个简单显示功能(这个使用快速的小班级)
void draw_rect(RectObject* robj){
glVertexPointer(2, GL_FLOAT, 0, [robj vertices]);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, [robj colors]);
glEnableClientState(GL_COLOR_ARRAY);
if ([robj texture] != -1){
glEnable(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glClientActiveTexture([robj texture]);
glTexCoordPointer(2, GL_FLOAT, 0, defaultTexCoord);
glBindTexture(GL_TEXTURE_2D, [robj texture]);
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_COORD_ARRAY);
}
另一方面,这个功能确实改变了显示,而不是输出纹理,但它输出一个黑色方块......
设置背景
在我的初始化函数中,我正在调用
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_SRC_COLOR);
两个长纹理加载函数
struct Texture2D LoadImage(NSString* path)
{
struct Texture2D tex;
tex.texture = -1;
// Id for texture
GLuint texture;
// Generate textures
glGenTextures(1, &texture);
// Bind it
glBindTexture(GL_TEXTURE_2D, texture);
// Set a few parameters to handle drawing the image
// at lower and higher sizes than original
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
//NSString *path = [[NSString alloc] initWithUTF8String:imagefile.c_str()];
path = [[NSBundle mainBundle] pathForResource:path ofType:@""];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil)
return tex;
// Get Image size
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Allocate memory for image
void *imageData = malloc( height * width * 4 );
CGContextRef imgcontext = CGBitmapContextCreate(
imageData, width, height, 8, 4 * width, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease( colorSpace );
CGContextClearRect( imgcontext,
CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( imgcontext, 0, height - height );
CGContextDrawImage( imgcontext,
CGRectMake( 0, 0, width, height ), image.CGImage );
// Generate texture in opengl
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
// Release context
CGContextRelease(imgcontext);
// Free Stuff
free(imageData);
[image release];
[texData release];
// Create and return texture
tex.texture=texture;
tex.width=width;
tex.height=height;
return tex;
}
GLuint makeTexture(NSString* path){
GLuint texture[1]={-1};
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
path = [[NSBundle mainBundle] pathForResource:path ofType:@"png"];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil)
NSLog(@"Do real error checking here");
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc( height * width * 4 );
CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease( colorSpace );
CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( context, 0, height - height );
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(context);
free(imageData);
[image release];
[texData release];
return texture[0];
}
如果你能指出我正确的方向,那将非常感激。
答案 0 :(得分:4)
首先,您的draw_rect
函数有错误。不要调用glClientActiveTexture
,它用于多纹理而你不需要它。使用纹理对象调用它将绑定一些非常奇怪的纹理单元,或者很可能导致错误。
在drawTexture
函数中,您实际上是按顺时针顺序绘制三角形。假设你没有在投影矩阵或类似的东西中翻转y方向,如果你启用了背面剔除,你的整个几何体将被剔除。尝试调用glDisable(GL_CULL_FACE)
,但默认情况下应禁用背面剔除。或者更好的是,将顶点更改为逆时针顺序:
box[] = { x,y+h, x,y, x+w,y+h, x+w,y };
你的drawTexture
函数中的纹理坐标与顶点不匹配,但这不应该导致纹理不被绘制,而是看起来有点奇怪。考虑到最后一段逆时针顺序的变化,纹理坐标应为:
tex[] = { 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f };
编辑:您的draw_rect
函数也会弄乱状态,因为您启用了顶点和颜色数组,但是在完成渲染后不再禁用它们。当你现在想要绘制不同颜色数组的东西时(比如在drawTexture
中),颜色数组仍然被启用并使用一些任意数据。所以你应该添加
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
之后
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
draw_rect
中的。
编辑:您还应该将drawTexture函数包装在一对glEnable(GL_TEXTURE_2D)
和glDisable(GL_TEXTURE_2D)
中。您在初始化代码中启用纹理,这是错误的。您应该在渲染之前设置所有必要的状态,尤其是像纹理这样高度依赖于对象的状态。例如,在draw_rect
之前调用drawTexture
之后,最终会禁用纹理,尽管您在初始化代码中启用了它,并认为它始终处于启用状态。你知道这不是个好主意吗?
编辑:我刚发现另一个错误。在draw_rect
中,您使用glEnable
拨打glDisable
和GL_TEXTURE_COORD_ARRAY
,这是错误的。您必须使用glEnableClientState
和glDisableClientState
来启用/禁用顶点数组,就像使用int drawTexture
一样。
因此,作为一个中途结论,您的功能应该看起来像:
void drawTexture(GLuint texture, float x, float y, float w, float h)
{
glBindTexture(GL_TEXTURE_2D,texture);
glEnable(GL_TEXTURE_2D);
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, box);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
void draw_rect(RectObject* robj)
{
if ([robj texture] != -1)
{
glBindTexture(GL_TEXTURE_2D, [robj texture]);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(2, GL_FLOAT, 0, defaultTexCoord);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glColorPointer(4, GL_UNSIGNED_BYTE, 0, [robj colors]);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, [robj vertices]);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
if ([robj texture] != -1)
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
}
答案 1 :(得分:1)
如果其中一个纹理起作用而另一个不起作用,那纹理文件是否有问题? 尺寸有时会欺骗你,尝试在两个纹理上使用相同的文件(工作一个),看看是否解决了。如果它确实是纹理文件的问题。
答案 2 :(得分:0)
乐趣确实有效。
void drawTexture(GLuint texture, float x, float y, float w, float h)
{
glBindTexture(GL_TEXTURE_2D,texture);
glEnable(GL_TEXTURE_2D);
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, box);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
但我们应该与纹理的右坐标相关联。我应该改变代码
形式
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
到
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = { 0.0f,1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f };
感谢stackoverflow。谢谢你的帮助。 祝你好运!