Animating a texture across a surface in OpenGL - iphone

I'm working with the iPhone OpenGLES implementation and I wish to endlessly scroll a texture across a simple surface (two triangles making up a rectangle). This should be straightforward, but it's not something I've done before and I must be missing something. I can rotate the texture fine, but translate does not work at all. Do I have a minor implementation issue or am I doing something fundamentally wrong?
// move texture
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
// increment offset - no reset for demo purposes
wallOffset += 1.0;
// move the texture - this does not work
glTranslatef(wallOffset,wallOffset,0.0);
// rotate the texture - this does work
//glRotatef(wallOffset, 1.0, 0.0, 0.0);
glMatrixMode(GL_MODELVIEW);
glBindTexture(GL_TEXTURE_2D, WallTexture.name);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
// simple drawing code
glNormalPointer(GL_FLOAT, 0, normals);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// push matrix back
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);

You're incrementing your texture offset by 1.0f; but textures coordinates are considered in the range [0, 1], so you're not actually changing the texture coordinates (assuming you've enabled some sort of wrapping).
Try changing that increment (try .01f, or maybe something depending on the framerate) and see if it works. If not, then it may have something to do with the texture parameters you've got enabled.

Related

GL_POINT not rendering when center is off screen

I'm making an iPhone game that involves the use of GL_POINT to render a point. However, when the center of the point is off screen, I still want to draw whatever portion of the point that is still onscreen. Here is my code that I'm using to render the point.
-(void)render {
if (!fill || !outline || !active || dead)
return;
NSLog(#"rendering");
glPushMatrix();
glLoadIdentity();
glMultMatrixf(matrix);
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glPointSize(scale.x*2);
[outline render];
glPointSize(2*(scale.x-kLineWidth));
[fill render];
glPopMatrix();
}
note that it logs "rendering" when it should be rendering, so this method is getting called properly.
and the [outline render] and [fill render] methods look like this
-(void)render {
// load arrays into the engine
glVertexPointer(vertexSize, GL_FLOAT, 0, vertexes);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(colorSize, GL_FLOAT, 0, colors);
glEnableClientState(GL_COLOR_ARRAY);
//render
glDrawArrays(renderStyle, 0, vertexCount);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
and I'm using a "panning" effect using this code
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-kScreenWidth/2.0 + xPan, kScreenWidth/2.0 + xPan, -kScreenHeight/2.0 + yPan, kScreenHeight/2.0 + yPan, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
but when the point's center is not on the screen (after panning with glOrthof), the whole point is not drawn. How can I have the point still render even when the center is not on the screen?
I don't believe there is anything you can do for an easy fix. Primitives are clipped before rasterization, so if that point lies outside the view frustum, it's not going to be rasterized, even if the rasterization would create fragments that do lie inside the view frustum.
Either switch to real quads with GL_TRIANGLES/GL_QUADS, or if you really don't want to do that, you can render your points to an offscreen buffer with size slightly larger than the viewport, and then blit the center of that image back onto the main frame.

Changing Alpha Value of OpenGL ES Object - GL_BLEND - iPhone

I have a textured object in my OpenGL ES scene (version 1.1) for which I want to change the alpha to 0.5.
I am trying the following code :
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1.0, 1.0, 1.0, 0.5);
glVertexPointer(3, GL_FLOAT, 0, vertexes);
glNormalPointer(GL_FLOAT, 0, normals);
glTexCoordPointer(2, GL_FLOAT, 0, textures);
GLfloat ambientAndDiffuse[] = kAmbience;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, ambientAndDiffuse);
GLfloat specular[] = kSpecular;
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, kShininess);
GLfloat emission[] = kEmission;
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission);
glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_SHORT, indices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_BLEND);
The problem is that the transparency of the model is not changing. The model is displayed on the screen correctly, however the alpha is still 1.
EDIT
My textures are jpgs. Do I need to save these as PNGs ?
Can anyone spot how I can correct this ?
Thank you.
Ah think I've solved it - you need to turn off the lighting and then it seems to work.
glDisable(GL_LIGHTING);
Have you set the texture environment variable to modulate? Like this:
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
That tells OpenGL to multiply the object's color by the texture's color. Also, I don't remember if you need to use a GL_COLOR_ARRY with glDrawElements() instead of just setting the current color.

Separately rotating 2 texture coordinates sets for the same object

I've given this a go for a while, but I haven't been able to get favorable results. Basically, I have a sphere with 2 textures. One is blended on top with other and the idea is to have it be a face environment mapping. I want one texture to rotate with the sphere and the other to stay fixed to the initial texture coordinates.
I have tried rotating the GL_TEXTURE matrix of one texture and resetting the other, but this doesn't really do the trick because the texture mapping isn't right when it's rotated certain ways.
Anyone know how i can rotate only one set of texture coordinates and keep the other fixed?
Here's my render code at the moment:
glColor4f(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glClientActiveTexture( GL_TEXTURE0);
glActiveTexture( GL_TEXTURE0);
glBindTexture( GL_TEXTURE_2D, tex[0]);
glEnableClientState( GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(TexturedVertexData3D), &SphereVertexData[0].texCoord);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glTranslatef(0, 0, -4.5f);
glRotatef(.00001, .00001, .0, .0);
glClientActiveTexture( GL_TEXTURE1);
glActiveTexture( GL_TEXTURE1);
glEnable( GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, tex[1]);
glEnableClientState( GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(TexturedVertexData3D), &SphereVertexData[0].texCoord);
glPopMatrix();
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(0, 0, -4.5f);
glVertexPointer(3, GL_FLOAT, sizeof(TexturedVertexData3D), &SphereVertexData[0].vertex);
glNormalPointer(GL_FLOAT, sizeof(TexturedVertexData3D), &SphereVertexData[0].normal);
glDrawArrays(GL_TRIANGLES, 0, kSphereNumberOfVertices);
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
rotation += .0001;
If anyone needs to see more of what is going on just let me know.
You could use two spheres and only issue the glRotatef() to the sphere with the texture that you want rotating. The other sphere would just receive the corresponding glTranslatef() commands. If you are using the alpha channel to blend the textures it should work the same.

glBindTexture Problem with OpenGL ES on iPhone

I'm new to OpenGL, and am having a curious problem with my textures - looking for a nudge in the right direction.
I have an app which uses a Render to texture technique for accomplishing a certain effect - it's working marvelously. I draw to an offscreen buffer every time I need to, and am able to use this as a texture in my render loop.
This texture is only updated when necessary - it's drawn to the screen as is most frames.
I have some toolbars which are also drawn using OpenGL, on top of this surface using a texture atlas, and using blending.
I have recently begun trying to incorporate a particle system into the app, but whenever I try to render my particle system graphics, I "lose" my texture that I've rendered in the first step - ie it's contents disappear.
I have traced this to the call to glBindTexture that binds the texture of the particles.
EDIT: I can reproduce this in my simple toolbar drawing routine, code below. This is a crude routine that animates toolbar graphics on and off screen.
When I uncomment the first two lines in drawToolBar(), my rendered in memory texture disappears, ie the drawarrays call in my render loop renders nothing to the screen. Through testing, I have determined that the glBidTexture call is what triggers this. (For example, I can render colored quads over my texture, just not textured ones)
However, everything is fine if I allow drawToolbar() to run as below - the only difference is that the eventual call to drawTools() is wrapped in glPush/Pop, and is translated.
Note that the toolbar rendering always works - there is some unintended side effect, consequence, or bug issue going on here, which causes my background texture to disappear.
Any ideas are welcome - this is driving me nuts.
The code:
void drawTools()
{
//*Texture Coordinate Stuff Snipped*//
glBindTexture(GL_TEXTURE_2D, _buttontexture);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer (2, GL_FLOAT, 0,bottomToolQuads);
glTexCoordPointer(2, GL_FLOAT, 0,texc);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
glDisable(GL_TEXTURE_2D);
}
void drawToolBar()
{
//drawTools();
//return;
if(_toolbarState ==0)
{
drawTools();
}
else if(_toolbarState == 2)//hiding
{
_toolbarVisiblePct -= TOOLINC;
if(_toolbarVisiblePct <= 0.0)
{
_toolbarState = 1;
_toolbarVisiblePct = 0.0;
}
else
{
glPushMatrix();
glTranslatef(0.0, -(1-_toolbarVisiblePct) * 50, 0);
drawTools();
glPopMatrix();
}
}
else if(_toolbarState == 3) //showing
{
_toolbarVisiblePct += TOOLINC;
if(_toolbarVisiblePct >= 1.0)
{
_toolbarState = 0;
_toolbarVisiblePct = 1.0;
drawTools();
}
else
{
glPushMatrix();
glTranslatef(0.0, -(1-_toolbarVisiblePct) * 50, 0);
drawTools();
glPopMatrix();
}
}
}
Looks like you're disabling texture rendering at the end of the drawTools method. OpenGL is a state machine, if you disable a state it will stay disabled until you enable it again.

OpenGL-ES variable texture alpha (2D)?

I have a texture with transparency (the white triangle with that lighting information), and just can't make it's alpha variable.
alt text http://gotoandplay.freeblog.hu/files/alpha_help.png
The drawing code, with the missing piece:
//Place polygon vertices to the bottom left within the view.
glLoadIdentity();
glTranslatef(centerX, centerY, 0);
//Draw "diffuse" layer.
glBindTexture(GL_TEXTURE_2D, spriteTexture[0]); //Bind.
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//Offset during development only.
glLoadIdentity();
glTranslatef(centerX-10, centerY+10, 0);
//Draw "specular" layer.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, spriteTexture[1]); //Bind.
//Some smart alpha scaling code needs here...
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Could somebody please help me out with the appropriate lines of code?
Some glBlendFunc, or maybe glTextEnvi stuff I suppose.
Ok, I got it even if I don't understand what I did exactly.
//Place polygon vertices to the bottom left within the view.
glLoadIdentity();
glTranslatef(centerX, centerY, 0);
//--1
//Draw "diffuse" layer.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, spriteTexture[0]); //Bind.
//Blending.
glBlendFunc(GL_ONE, GL_ONE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//--2
//Draw "specular" layer.
glBindTexture(GL_TEXTURE_2D, spriteTexture[1]); //Bind.
//Blending.
glColor4f(opacity, opacity, opacity, opacity);
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
I tried another way before...
glColor4f(1.0f, 1.0f, 1.0f, opacity);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
...but the second map was somehow "weaker".