这是我第一次尝试理解opengl。我写了一个简单的opengles示例,用于绘制四边形的iphone。起初我忘记使用glBindTexture
,但它有效。后来我尝试添加另一个四边形并看到当我使用glBindTexture
时,没有一个四边形被纹理化,它们是白色的。然后我删除了新添加的四元组,当glBindTexture
存在时它仍然无效。如果我评论它一切都很好。当然,我需要不止一个四元组......纹理。
编辑:此方法在我的视图控制器中,从Apple OpenglES示例中窃取了EAGLView。它初始化opengl。每个四元组都有一个Place
类的实例。首先进行测试我只使用了一个四核;我只有一个Place
对象,正如我所说,我忘了使用glBindTexture
。但在那之后,当我开始使用它时,纹理不再有效,即使只有一个四边形。
EDIT2:以下是我想要的示例:http://www.youtube.com/watch?v=U2uH-jrsSxs
-(void) setupOpenGL
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Enable use of the texture
glEnable(GL_TEXTURE_2D);
// Enable blending
glEnable(GL_BLEND);
// Set a blending function to use
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
//!!!!!!!!!!!!
//EDIT: THIS IS WHERE I WAS WRONG: I NEED TO SET THESE FOR EVERY TEXTURE I USE
//THEY ARE NOT GLOBAL
//!!!!!!!!!!!!
// Set the texture parameters to use a minifying filter and a linear filer (weighted average)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//same for magnification
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//-----------------
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
for (Place *p in locations)
{
[p loadTexture];
[p reloadTitle];
/*
p.relativeHeading = 123.45;
p.absoluteHeading = 23.45;
p.distance = 1234.5;
[p reloadHeading];
[p reloadDistance];
*/
}
glError = glGetError(); //check if we f*cked up already or not;
NSLog(@"setupOpenGL result: %i", glError);
}
以下是我Place
班的代码:
- (void) loadTexture
{
Byte * textureData = [Place getTexture];
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, self.textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
TEXTURE_W, TEXTURE_H, 0,
GL_RGBA, GL_UNSIGNED_BYTE, textureData);
//copy the texture to video memory we can safely release our own copy of the texture after this
GLenum glError = 0;
glError = glGetError();
}
- (void) reloadTitle
{
CGSize actualSize = CGSizeZero; //not used now
CGRect cropRect = CGRectMake(TITLE_X, TITLE_Y, TITLE_W, TITLE_H);
Byte *imageData = [self writeTextOverTexture:
[Place getTextureCrop : cropRect] : cropRect.size :
CGRectMake(0, 0, TITLE_W, TITLE_H) :
self.title : [UIFont fontWithName: @"Arial" size: 14] :
[UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1] :
&actualSize];
glBindTexture(GL_TEXTURE_2D, self.textureID);
glTexSubImage2D(GL_TEXTURE_2D, 0,
TITLE_X, TITLE_Y, TITLE_W , TITLE_H, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
}
- (void) reloadDistance
{
//...very similar to reloadTitle
}
- (void) reloadHeading
{
// very similar to the other too
}
这是绘制四边形的方法。基本上在每个“地方”我都有纬度/经度,当我绘制时,我使用iPhone罗盘标题,位置和加速度计将其他地方绘制在正确的位置。
- (void) drawFrame
{
if (location == nil) return;
if (myHeading == -1) return;
[(EAGLView *)self.glView setFramebuffer];
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
perspective(LANDSCAPE_FOV, WIDTH/HEIGHT , 1.0f, 20.0f);
glRotatef((GLfloat)rollAngle, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
double tmpPitchAngle = pitchAngle;
tmpPitchAngle -= 20;
tmpPitchAngle = clampValue(tmpPitchAngle, -85, +85);
//glRotatef((GLfloat) tmpPitchAngle, 1, 0, 0);
glRotatef((GLfloat) myHeading, 0, 1, 0);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
for (Place *p in locations)
{
glPushMatrix();
glRotatef(-p.absoluteHeading, 0, 1, 0);
glTranslatef(0, 0, -5);
glScalef(0.4, 0.4, 1.0);
glBindTexture(GL_TEXTURE_2D, p.textureID);
glVertexPointer (3, GL_BYTE, 0, KVertices);
glTexCoordPointer(2, GL_BYTE, 0, texCoords);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glPopMatrix();
}
glError = glGetError();
NSLog(@"glError drawFrame = %i", glError);
[(EAGLView *)self.glView presentFramebuffer];
}
我该如何使这项工作?当我忘记绑定纹理时,我使用什么纹理。据我所知glBindTexture
用于选择或激活纹理,以便我可以绘制或更改它。
答案 0 :(得分:2)
你错过了一些东西,把它放在glTexImage2D之后:
glTexParameteri(GL_TEXTURE_2D, GL_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_MAG_FILTER, GL_NEAREST);
然后你的纹理会出现而不是白色。这是因为默认情况下,OpenGL使用mipmapped过滤器。由于没有mipmap,纹理不完整,看起来完全是白色。
答案 1 :(得分:2)
OpenGL是一个状态机。其中一个状态是目标GL_TEXTURE_2D的当前纹理。您可以随时上传纹理以替换当前纹理。
在OpenGL 1.0中,没有glGenTextures / glBindTexture,假设在第一次实现时你会在使用之前立即提交完整的每个纹理,并且作为第二个实现,你可以通过显示列表完成所有工作,驱动程序有机会在看到合适时缓存纹理。 OpenGL ES长期不推荐使用显示列表,这可能是一个坏主意。从OpenGL 1.1开始,在OpenGL ES的所有迭代中,都可以使用纹理名称和各种相关函数。
纹理名称只是保存GL_TEXTURE_2D状态的存储版本的一种方式。因此,如果您创建纹理名称并将其绑定,您将创建一个环境,您可以在其中更改纹理(和纹理参数),而不会影响任何其他命名纹理。并且驱动程序很容易将图像缓存在GPU可寻址内存中。
但是,如果您不想,实际上不需要使用纹理名称。它只是上传和使用纹理是有效的。这可能就是为什么你的应用程序在没有调用glBindTexture的情况下工作的原因。
鉴于您正在使用纹理名称,在提供新的子图像之前,您的reloadTitle不应该绑定相关纹理吗?你似乎没有绑定drawFrame中的任何特定纹理?