## Manuiplate Image with ES1.1 (Ripples/liquid)

I am able to get the screen to fill with little black and white triangles but guess I am missing how to map my image to this. I have searched long and far trying to find an example but I have had no luck so I am going to break down and ask

Is there an easier way to do this? Is there a tutorial or some documentation someone can point me to, I tried some of NeHe tutorials but they seem to be steering me even farther in the wrong direction.

TIA,

Mitch

arekkusu Wrote:You certainly don't need shaders to do this (obviously, since Koi Pond is doing it in ES1.1.)

As AnotherJake says, this is just a grid where you manipulate the vertex attributes.

See Drew's old distort sample for the general approach.

AnotherJake Wrote:Hey, I put together a Mac version of Drew's distort demo if you guys wanna play with it: http://www.anotherjake.com/AnotherJake/Distort.html

I just kind of whipped it together real quick, so I don't know if there are issues, but you can give it a try and see how it goes for you.

Mitch Wrote:I have been trying to get the source AnotherJake put together to work on the iphone, I have very little experience using opengl (so far is just 2D sprites) and I just cannot figure out what I am missing

I am able to get the screen to fill with little black and white triangles but guess I am missing how to map my image to this. I have searched long and far trying to find an example but I have had no luck so I am going to break down and ask

Is there an easier way to do this? Is there a tutorial or some documentation someone can point me to, I tried some of NeHe tutorials but they seem to be steering me even farther in the wrong direction.

TIA,

Mitch

Hi Mitch,

I'm not familiar with AnotherJake's code, but the task doesn't sound too bad to me (granted I've been using OpenGL for a long time).

I am going to assume your texture is loaded correctly, is currently bound using glBindTexture( ... ) and texturing is enabled.

I'm also going to assume that you've got an array where you are holding the texture coordinates for every vertex, that that array has been specified with glVertexPointer, and that texture coordinate arrays have been enabled with glEnableClientState(GL_TEXTURE_COORD_ARRAY) before you draw all the vertices.

So you've got triangles filling up the screen, that sounds like they just need the proper texture coordinates.

Rather than jump right in to trying to make ripple effects and the like, your first step should probably be to display the image non-distorted, but broken up into all those triangles you have.

Suppose your texture image is N pixels by M pixels. Since texture coordinates are specified in terms of fractions of the full texture, that means that a vertex at the location (x, y) needs to have the texture coordinate (x / N, y / M). This formula may be slightly off because odds are your NxM texture is not a power of two sized image and so it had to be loaded into a larger area in order to fit it. It may also be upside down depending on your coordinate system. But this basic idea will hopefully get you started.

Holmes Wrote:Hi Mitch,

I'm not familiar with AnotherJake's code...

That's not my code! That was done by Drew Olbrich many years ago. We were talking about it in another thread a couple weeks ago. I just put together a quick little port of it so others could fiddle with it on OS X right now. It'd be cool to see a little iPhone port of it, but I didn't volunteer for that yet (leetle bit too busy right now... although it shouldn't be hard to do)

Holmes Wrote:Hi Mitch,

I'm not familiar with AnotherJake's code, but the task doesn't sound too bad to me (granted I've been using OpenGL for a long time).

I am going to assume your texture is loaded correctly, is currently bound using glBindTexture( ... ) and texturing is enabled.

I'm also going to assume that you've got an array where you are holding the texture coordinates for every vertex, that that array has been specified with glVertexPointer, and that texture coordinate arrays have been enabled with glEnableClientState(GL_TEXTURE_COORD_ARRAY) before you draw all the vertices.

So you've got triangles filling up the screen, that sounds like they just need the proper texture coordinates.

Rather than jump right in to trying to make ripple effects and the like, your first step should probably be to display the image non-distorted, but broken up into all those triangles you have.

Suppose your texture image is N pixels by M pixels. Since texture coordinates are specified in terms of fractions of the full texture, that means that a vertex at the location (x, y) needs to have the texture coordinate (x / N, y / M). This formula may be slightly off because odds are your NxM texture is not a power of two sized image and so it had to be loaded into a larger area in order to fit it. It may also be upside down depending on your coordinate system. But this basic idea will hopefully get you started.

Ok I can draw the background image fine its when I try to adapt the code from the example that everything becomes crazy

Here is code snippets of what I am trying to translate from the example source:

Code:

`//// This is called when everything is setup`

for (i = 0; i < GRID_SIZE_X; i++)

for (j = 0; j < GRID_SIZE_Y; j++)

{

ripple_vertex[i][j].x[0] = i/(GRID_SIZE_X - 1.0)*WIN_SIZE_X;

ripple_vertex[i][j].x[1] = j/(GRID_SIZE_Y - 1.0)*WIN_SIZE_Y;

ripple_vertex[i][j].dt[0] = i/(GRID_SIZE_X - 1.0);

ripple_vertex[i][j].dt[1] = j/(GRID_SIZE_Y - 1.0);

}

Code:

`//// This is in the draw method after glBindTexture`

int i, j;

for (i = 0; i < GRID_SIZE_X - 1; i++)

{

for (j = 0; j < GRID_SIZE_Y - 1; j++)

{

GLfloat vertex_arr[] = {

ripple_vertex[i][j].x[0], ripple_vertex[i][j].x[1],

ripple_vertex[i][j + 1].x[0], ripple_vertex[i][j + 1].x[1],

ripple_vertex[i + 1][j + 1].x[0], ripple_vertex[i + 1][j + 1].x[1],

ripple_vertex[i + 1][j].x[0], ripple_vertex[i + 1][j].x[1],

};

GLfloat tex_arr[] = {

ripple_vertex[i][j].t[0], ripple_vertex[i][j].t[1],

ripple_vertex[i][j + 1].t[0], ripple_vertex[i][j + 1].t[1],

ripple_vertex[i + 1][j + 1].t[0], ripple_vertex[i + 1][j + 1].t[1],

ripple_vertex[i + 1][j].t[0], ripple_vertex[i + 1][j].t[1],

};

glVertexPointer(3, GL_FLOAT, 0, vertex_arr);

glTexCoordPointer(2, GL_FLOAT, 0, tex_arr);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

}

}

//////// I Think this is where everything is going screwy, here is how it was done in the original source.

// Did I convert this correctly?

int i, j;

glClear(GL_COLOR_BUFFER_BIT);

for (i = 0; i < GRID_SIZE_X - 1; i++)

{

for (j = 0; j < GRID_SIZE_Y - 1; j++)

{

glBegin(GL_POLYGON);

glTexCoord2fv(ripple_vertex[i][j].t);

glVertex2fv(ripple_vertex[i][j].x);

glTexCoord2fv(ripple_vertex[i][j + 1].t);

glVertex2fv(ripple_vertex[i][j + 1].x);

glTexCoord2fv(ripple_vertex[i + 1][j + 1].t);

glVertex2fv(ripple_vertex[i + 1][j + 1].x);

glTexCoord2fv(ripple_vertex[i + 1][j].t);

glVertex2fv(ripple_vertex[i + 1][j].x);

glEnd();

}

}

glutSwapBuffers();

Code:

`// defines etc...`

#define GRID_SIZE_X 32

#define GRID_SIZE_Y 32

#define WIN_SIZE_X 320

#define WIN_SIZE_Y 480

typedef struct {

float x[2]; /* initial vertex location */

float t[2]; /* texture coordinate */

float dt[2]; /* default texture coordinate */

} RIPPLE_VERTEX;

Any more tips you can provide?

Code:

` // I had a 3 instead of a 2 in the vertexPointer `

glVertexPointer(2, GL_FLOAT, 0, vertex_arr);

glTexCoordPointer(2, GL_FLOAT, 0, tex_arr);

So now I end up with this...

It's hard to tell since its a dark background but the background is contained in the triangles. Should it look like this, or is there a problem with the calculations? I am going to tinker with it some more and hopefully figure something out.

TIA,

Mitch

Mitch Wrote:Ok I was able to fix that last issue with the crazy lines

Code:

`// I had a 3 instead of a 2 in the vertexPointer`

glVertexPointer(2, GL_FLOAT, 0, vertex_arr);

glTexCoordPointer(2, GL_FLOAT, 0, tex_arr);

So now I end up with this...

It's hard to tell since its a dark background but the background is contained in the triangles. Should it look like this, or is there a problem with the calculations? I am going to tinker with it some more and hopefully figure something out.

TIA,

Mitch

I can't tell for certain, but from the looks of it and from personal experience my first guess is that your vertices are ordered incorrectly in the triangle strip. The reason I guess this is that the small black triangles could be formed when two white triangles which use the wrong vertices leave a gap.

Instead of proceeding in the order (i,j) (i,j+1), (i+1, j+1), (i+1, j), try the following order:

(i,j), (i, j+1), (i+1, j), (i+1, j+1)

Holmes Wrote:I can't tell for certain, but from the looks of it and from personal experience my first guess is that your vertices are ordered incorrectly in the triangle strip. The reason I guess this is that the small black triangles could be formed when two white triangles which use the wrong vertices leave a gap.

Instead of proceeding in the order (i,j) (i,j+1), (i+1, j+1), (i+1, j), try the following order:

(i,j), (i, j+1), (i+1, j), (i+1, j+1)

Excellent that seems to have solved the issue the vertices are correct! Now I am having an issue with my image being messed up. I am having problems with this power of 2 requirement. I have tried to re-size my texture to 512x512. Is there a specific way I should be creating and sizing this texture before applying it?

Thanks again for all the help!

Mitch

Mitch Wrote:Excellent that seems to have solved the issue the vertices are correct! Now I am having an issue with my image being messed up. I am having problems with this power of 2 requirement. I have tried to re-size my texture to 512x512. Is there a specific way I should be creating and sizing this texture before applying it?

Thanks again for all the help!

Mitch

Glad I could help

I'm assuming the image is just distorted now due to improper scaling?

Here's what I do when I load textures: I keep track of the original dimensions of the image, create an empty texture with power of two dimensions (which ends of being of equal or greater size than the original image), then load the image into the texture using glTexImage2D. So in other words the original image can be of any size, but it only ends up occupying one portion of the final texture.

Finally, when the image is drawn care must be taken with the texture coordinates, because, for example, instead of 1.0 corresponding to the right side of the image, now we have (width / power_of_two(width)) corresponding to the right side of the image.

Mitch

Mitch Wrote:Just wanted to let you know I got it working, I finally figured everything out. Thanks again for you advice!

Mitch

Cool! Any pictures of the final product?