代码之家  ›  专栏  ›  技术社区  ›  Mark Ingram

如何在OpenGLES2.0中将纹理绘制为二维背景?

  •  17
  • Mark Ingram  · 技术社区  · 15 年前

    我刚开始使用OpenGLES2.0,我想做的是创建一些简单的二维输出。如果分辨率为480x800,如何绘制背景纹理?

    [我的开发环境是Java/Android,所以直接与此相关的例子是最好的,但其他语言也可以。

    2 回复  |  直到 15 年前
        1
  •  30
  •   Brad Larson    15 年前

    即使你在安卓系统上,我还是创建了一个iPhone示例应用程序,它可以为即将到来的视频帧做这个。您可以从下载此示例的代码 here . 我有一篇关于这个应用程序的文章,它使用实时视频进行基于颜色的对象跟踪,您可以阅读 here .

    在此应用程序中,我绘制两个三角形以生成一个矩形,然后使用以下坐标对其进行纹理处理:

       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,
        };
    

    要将视频帧作为纹理进行传递,我使用一个简单的程序,其中包含以下顶点明暗器:

    attribute vec4 position;
    attribute vec4 inputTextureCoordinate;
    
    varying vec2 textureCoordinate;
    
    void main()
    {
        gl_Position = position;
        textureCoordinate = inputTextureCoordinate.xy;
    }
    

    以及以下片段明暗器:

    varying highp vec2 textureCoordinate;
    
    uniform sampler2D videoFrame;
    
    void main()
    {
        gl_FragColor = texture2D(videoFrame, textureCoordinate);
    }
    

    绘图是使用正确程序的简单问题:

    glUseProgram(directDisplayProgram);
    

    设置纹理均匀:

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, videoFrameTexture);
    
    glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);   
    

    设置属性:

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

    然后画三角形:

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
        2
  •  14
  •   fzwo    15 年前

    你不需要绘制背景,而是绘制一个矩形(或者更准确地说,两个三角形组成一个矩形),然后设置纹理。这与在屏幕上绘制任何其他对象完全不同。

    有很多地方显示了这是如何做到的,也许甚至有一个Android示例项目显示了这一点。

    棘手的部分是让一些东西显示在其他东西的前面或后面。为此,您需要设置深度缓冲区并启用深度测试(Glenable(GL U深度测试))。顶点需要有一个z坐标(并告诉gldrawElements顶点由三个值组成,而不是两个值)。

    如果不这样做,对象将按照调用它们的gldrawElements()函数的顺序进行渲染(也就是说,无论最后绘制的是哪个,最终都会掩盖其余的函数)。

    我的建议是,在你掌握了背景图片的窍门之前,不要做任何花哨的事情。OpenGLES2.0有一条陡峭的学习曲线,而ES1.x上的教程并不能真正帮助3D工作,因为它们可以使用像GluPerspective这样的辅助功能,而2.0没有。从创建一个没有背景的三角形开始。接下来,把它变成一个正方形。然后,如果你想变得花哨,添加一个纹理。玩弄姿势。查看更改顶点的Z值时会发生什么。(提示:如果没有启用深度测试,则不会太多。即使这样,如果你没有透视投影,物体离得越远,就不会变小,所以看起来好像什么都没有发生一样)

    几天后,它就不再那么令人沮丧了,你终于“明白了”,主要是。