加载多纹理opengl es 2.0

时间:2014-03-25 07:41:25

标签: c++ opengl-es

我在互联网上找到了关于如何在opengl es 2.0中加载多个纹理的这段代码:

//
// Book:      OpenGL(R) ES 2.0 Programming Guide
// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10:   0321502795
// ISBN-13:   9780321502797
// Publisher: Addison-Wesley Professional
// URLs:      http://safari.informit.com/9780321563835
//            http://www.opengles-book.com
//

// MultiTexture.c
//
//    This is an example that draws a quad with a basemap and
//    lightmap to demonstrate multitexturing.
//
#include"pch.h"
#include <stdlib.h>

typedef struct
{
    // Handle to a program object
    GLuint programObject;

    // Attribute locations
    GLint  positionLoc;
    GLint  texCoordLoc;

    // Sampler locations
    GLint baseMapLoc;
    GLint lightMapLoc;

    // Texture handle
    GLuint baseMapTexId;
    GLuint lightMapTexId;

} UserData;


///
// Load texture from disk
//
GLuint LoadTexture(char *fileName)
{
    int width,
        height;
    char *buffer = esLoadTGA(fileName, &width, &height);
    GLuint texId;

    if (buffer == NULL)
    {
        esLogMessage("Error loading (%s) image.\n", fileName);
        return 0;
    }

    glGenTextures(1, &texId);
    glBindTexture(GL_TEXTURE_2D, texId);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    free(buffer);

    return texId;
}



///
// Initialize the shader and program object
//
int Init(ESContext *esContext)
{
    UserData *userData = (UserData*) esContext->userData;
    const char vShaderStr[] =
        "attribute vec4 a_position;   \n"
        "attribute vec2 a_texCoord;   \n"
        "varying vec2 v_texCoord;     \n"
        "void main()                  \n"
        "{                            \n"
        "   gl_Position = a_position; \n"
        "   v_texCoord = a_texCoord;  \n"
        "}                            \n";

    const char fShaderStr[] =
        "precision mediump float;                            \n"
        "varying vec2 v_texCoord;                            \n"
        "uniform sampler2D s_baseMap;                        \n"
        "uniform sampler2D s_lightMap;                       \n"
        "void main()                                         \n"
        "{                                                   \n"
        "  vec4 baseColor;                                   \n"
        "  vec4 lightColor;                                  \n"
        "                                                    \n"
        "  baseColor = texture2D( s_baseMap, v_texCoord );   \n"
        "  lightColor = texture2D( s_lightMap, v_texCoord ); \n"
        "  gl_FragColor = baseColor * (lightColor + 0.25);   \n"
        "}                                                   \n";

    // Load the shaders and get a linked program object
    userData->programObject = esLoadProgram(vShaderStr, fShaderStr);


    // Get the attribute locations
    userData->positionLoc = glGetAttribLocation(userData->programObject, "a_position");
    userData->texCoordLoc = glGetAttribLocation(userData->programObject, "a_texCoord");

    // Get the sampler location
    userData->baseMapLoc = glGetUniformLocation(userData->programObject, "s_baseMap");
    userData->lightMapLoc = glGetUniformLocation(userData->programObject, "s_lightMap");

    // Load the textures
    userData->baseMapTexId = LoadTexture("basemap.tga");
    userData->lightMapTexId = LoadTexture("lightmap.tga");

    if (userData->baseMapTexId == 0 || userData->lightMapTexId == 0)
        return FALSE;

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    return TRUE;
}

///
// Draw a triangle using the shader pair created in Init()
//
void Draw(ESContext *esContext)
{
    UserData *userData = (UserData*)esContext->userData;
    GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f,  // Position 0
        0.0f, 0.0f,        // TexCoord 0 
        -0.5f, -0.5f, 0.0f,  // Position 1
        0.0f, 1.0f,        // TexCoord 1
        0.5f, -0.5f, 0.0f,  // Position 2
        1.0f, 1.0f,        // TexCoord 2
        0.5f, 0.5f, 0.0f,  // Position 3
        1.0f, 0.0f         // TexCoord 3
    };
    GLushort indices[] = { 0, 1, 2, 0, 2, 3 };

    // Set the viewport
    glViewport(0, 0, esContext->width, esContext->height);

    // Clear the color buffer
    glClear(GL_COLOR_BUFFER_BIT);

    // Use the program object
    glUseProgram(userData->programObject);

    // Load the vertex position
    glVertexAttribPointer(userData->positionLoc, 3, GL_FLOAT,
        GL_FALSE, 5 * sizeof(GLfloat), vVertices);
    // Load the texture coordinate
    glVertexAttribPointer(userData->texCoordLoc, 2, GL_FLOAT,
        GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]);

    glEnableVertexAttribArray(userData->positionLoc);
    glEnableVertexAttribArray(userData->texCoordLoc);

    // Bind the base map
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, userData->baseMapTexId);

    // Set the base map sampler to texture unit to 0
    glUniform1i(userData->baseMapLoc, 0);

    // Bind the light map
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, userData->lightMapTexId);

    // Set the light map sampler to texture unit 1
    glUniform1i(userData->lightMapLoc, 1);

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

    eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}

///
// Cleanup
//
void ShutDown(ESContext *esContext)
{
    UserData *userData = (UserData*)esContext->userData;

    // Delete texture object
    glDeleteTextures(1, &userData->baseMapTexId);
    glDeleteTextures(1, &userData->lightMapTexId);

    // Delete program object
    glDeleteProgram(userData->programObject);
}


int main(int argc, char *argv[])
{
    ESContext esContext;
    UserData  userData;

    esInitContext(&esContext);
    esContext.userData = &userData;

    esCreateWindow(&esContext, L"MultiTexture", 320, 240, ES_WINDOW_RGB);

    if (!Init(&esContext))
        return 0;

    esRegisterDrawFunc(&esContext, Draw);

    esMainLoop(&esContext);

    ShutDown(&esContext);
}

但是当我运行它时它只显示黑暗!调试代码表明什么都不是null或者什么,那么它有什么问题呢? 我添加两个名称与代码相同的文件,但我仍然看到一个黑暗的空间! 有什么建议吗? 另一个问题是这是加载任何数量纹理的常用方法吗?

1 个答案:

答案 0 :(得分:0)

首先尝试绘制一个红色正方形(使用gl_FragColor = vec4(1.0,0.0,0.0,1.0))。如果没有绘制,则更改索引​​的顺序(您可能正常向后)。

第二,你需要在绘制之前将纹理提交给GPU。

在GPU有机会接管内存之前释放缓冲区(在使用该纹理绘制任何内容之前调用free(缓冲区),缓冲区还没有在GPU内存上)。

要提交纹理,请使用该纹理绘制内容。

以下是强制提交的示例代码(随意根据您的需求进行调整):

void cColorTest::ForceCommitTexture(unsigned int texId)
{
glUseProgram(m_nProgram);
glBindTexture(GL_TEXTURE_2D,texId);
GLfloat triangle[]= {   0.0f,  0.5f, 0.5f,  1.0f,   1.0f, 0.0f,
                        -0.5f, -0.5f, 0.5f, 1.0f,   0.0f, 1.0f,
                        0.5f, -0.5f, 0.5f,  1.0f,   0.0f, 0.0f};

glVertexAttribPointer ( m_nPosLoc, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(float), triangle );
glEnableVertexAttribArray ( m_nPosLoc );
glVertexAttribPointer ( m_nUVLoc, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(float), triangle + 4 );
glEnableVertexAttribArray ( m_nUVLoc );

glDrawArrays(GL_TRIANGLES,0,1);

}