How do i use glBindTexture in opengles for iphone?
this is my first try at understanding opengl. I wrote a simple opengles example for the iphone that draws a quad. At first I forgot to use glBindTexture
, BUT it worked. Later I tried to add another quad and saw that when i use glBindTexture
none of the quads gets textured, they are white. Then I removed the newly added quad, and it still didn't work when glBindTexture
was there. If I commented it out everything was fine. Of course I will need more than one quad...with texture.
EDIT: This method is in my view controller that has an EAGLView stolen from an Apple OpenglES example. It initializes opengl. I have an instance of Place
class for every quad. At first for testing I only used ONE quad; I had only one Place
object and as I said I forgot to use glBindTexture
. But after that when I started using it, textures no longer worked, even with just one quad.
EDIT2: Here is an example of what I wanted: 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);
}
Here is code from my Place
class:
- (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
}
Here is the method that draws the quads. Basically in every `Place' I have latitude/longitude and when I draw I use the iPhone compass heading, location and accelerometer to draw the other places in the correct location.
- (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];
}
How can I make this work? What texture am I using when I forget to bind the texture. As far as I understand glBindTexture
is used to select, or activate a texture so i can draw it, or change it.
You're missing some stuff, put this after glTexImage2D:
glTexParameteri(GL_TEXTURE_2D, GL_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_MAG_FILTER, GL_NEAREST);
Then your textures will appear and not look white. This is because by default, OpenGL uses the mipmapped filters. Since you have no mipmaps, the texture is incomplete and appears completely white.
OpenGL is a state machine. One of those states is the current texture for target GL_TEXTURE_2D. You can upload a texture any time you want to replace the current texture.
In OpenGL 1.0, there was no glGenTextures/glBindTexture, it being assumed that at a first implementation you'd submit every texture in full immediately before using it and that as a second you'd do everything via a display list, giving the driver an opportunity to cache the texture as it saw fit. Display lists are long deprecated and absent from OpenGL ES, and were probably a bad idea. As of OpenGL 1.1, and in all iterations of OpenGL ES, texture names and the various related functions are available.
A texture name is just a way of keeping a stored version of the GL_TEXTURE_2D state. So if you create a texture name and bind it, you're creating an environment in which you can change the texture (and the texture parameters) without affecting any of the other named textures. And it becomes really easy for the driver to cache the images in GPU addressable memory.
However, you don't actually need to use texture names if you don't want to. It's valid just to upload and use a texture. That's probably why your application worked without any calls to glBindTexture.
Given that you're using texture names, shouldn't your reloadTitle bind the relevant texture before providing a new subimage? And you don't seem to be binding any particular texture in drawFrame?
精彩评论