How to draw a texture as a 2D background in OpenGL ES 2.0?
Asked Answered
S

2

17

I'm just getting started with OpenGL ES 2.0, what I'd like to do is create some simple 2D output. Given a resolution of 480x800, how can I draw a background texture?

[My development environment is Java / Android, so examples directly relating to that would be best, but other languages would be fine.]

Shroyer answered 27/10, 2010 at 19:7 Comment(0)
U
32

Even though you're on Android, I created an iPhone sample application that does this for frames of video coming in. You can download the code for this sample from here. I have a writeup about this application, which does color-based object tracking using live video, that you can read here.

In this application, I draw two triangles to generate a rectangle, then texture that using the following coordinates:

   static const GLfloat squareVertices[] = {
        -1.0f, -1.0f,
        1.0f, -1.0f,
        -1.0f,  1.0f,
        1.0f,  1.0f,
    };

    static const GLfloat textureVertices[] = {
        1.0f, 1.0f,
        1.0f, 0.0f,
        0.0f,  1.0f,
        0.0f,  0.0f,
    };

To pass through the video frame as a texture, I use a simple program with the following vertex shader:

attribute vec4 position;
attribute vec4 inputTextureCoordinate;

varying vec2 textureCoordinate;

void main()
{
    gl_Position = position;
    textureCoordinate = inputTextureCoordinate.xy;
}

and the following fragment shader:

varying highp vec2 textureCoordinate;

uniform sampler2D videoFrame;

void main()
{
    gl_FragColor = texture2D(videoFrame, textureCoordinate);
}

Drawing is a simple matter of using the right program:

glUseProgram(directDisplayProgram);

setting the texture uniform:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, videoFrameTexture);

glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);   

setting the attributes:

glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);

and then drawing the triangles:

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Utile answered 19/11, 2010 at 17:49 Comment(5)
Remember that you need to change the attribute index - this is done in your sample program, but not in the post. // Attribute index. enum { ATTRIB_VERTEX, ATTRIB_COLOR, ATTRIB_TEXTUREPOSITON, NUM_ATTRIBUTES };Jasisa
What do you mean by that @dep?Cableway
your app needs some update. There are some deprecated functions and it crashed on ios 8. But I like it :-)Knoxville
@Knoxville - I don't maintain that sample application, it's just reference code. If you want to see a more modern version of this, I've replaced the above with the ColorObjectTracking sample application in my GPUImage framework: github.com/BradLarson/GPUImageUtile
Your textureVertices array gave me sideways output. I had to use: static const GLfloat textureVertices[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, };Globulin
P
15

You don't really draw a background, instead you draw a rectangle (or, even more correctly: two triangles forming a rectangle) and set a texture to that. This isn't different at all from drawing any other object on screen.

There are plenty of places showing how this is done, maybe there's even an android example project showing this.

The tricky part is getting something to display in front of or behind something else. For this to work, you need to set up a depth buffer and enable depth testing (glEnable(GL_DEPTH_TEST)). And your vertices need to have a Z coordinate (and tell glDrawElements that your vertices are made up of three values, not two).

If you don't do that, objects will be rendered in the order their glDrawElements() functions are called (meaning whichever you draw last will end up obscuring the rest).

My advice is to not have a background image or do anything fancy until you get the hang of it. OpenGL ES 2.0 has kind of a steep learning curve, and tutorials on ES 1.x don't really help with getting 3D to work because they can use helper functions like gluPerspective, which 2.0 just doesn't have. Start with creating a triangle on a background of nothing. Next, make it a square. Then, if you want to go fancy already, add a texture. Play with positions. See what happens when you change the Z value of your vertices. (Hint: Not a lot, if you don't have depth testing enabled. And even then, if you don't have perspective projection, objects won't get smaller the farther they are away, so it will still seem as if nothing happened)

After a few days, it stops being so damn frustrating, and you finally "get it", mostly.

Phia answered 10/12, 2010 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.