OpenGl Es纹理颜色错误



我正在阅读《Beginning Android c++ Game Development》这本书。目前在第5章,本书的代码可以从他们的网站下载。

我已经跟随我的书到第4章没有问题,但来第5章渲染纹理时,我得到这个:

http://i193.photobucket.com/albums/z127/johto760/error - 1. - png

你可以看到颜色是不正确的,我希望是这样的:

http://i193.photobucket.com/albums/z127/johto760/somewhatexpected.png

甚至在第二个RGB是颠倒的,我使用TGA文件的图像。我从星期天开始就在谷歌上搜索解决方案,今天是星期二。

下面是我正在处理的相关代码:

     SampleTask.cpp
        namespace {
            float verts[] = {-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
                -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f};
            unsigned short indices[] = {0, 2, 1, 2, 3, 1};
        }
        SampleTask::SampleTask(Framework::Renderer* renderer,
                const unsigned int priority) :
                Framework::Task(priority), m_state(RUNNING), m_renderer(renderer), m_readBytes(
                        0), m_TGABuffer(NULL), m_file("test.tga"), m_fileLength(0) {
            m_renderable.SetGeometry(&m_geometry);
            m_renderable.SetShader(&m_textureShader);
        }
        SampleTask::~SampleTask() {
            m_renderer->RemoveRenderable(&m_renderable);
            m_renderer->RemoveTexture(&m_texture);
            m_renderer->RemoveShader(&m_textureShader);
            if (m_TGABuffer) {
                delete[] static_cast<char*>(m_TGABuffer);
                m_TGABuffer = 0;
            }
        }
        bool SampleTask::Start() {
            Framework::Geometry* pGeometry = m_renderable.GetGeometry();
            pGeometry->SetName("quad");
            pGeometry->SetVertexBuffer(verts);
            pGeometry->SetNumVertices(4);
            pGeometry->SetIndexBuffer(indices);
            pGeometry->SetNumIndices(6);
            pGeometry->SetNumVertexPositionElements(3);
            pGeometry->SetNumTexCoordsElements(2);
            pGeometry->SetVertexStride(sizeof(float) * 5);
            bool success = false;
            if (m_file.Open()) {
                m_fileLength = m_file.Length();
                m_TGABuffer = new char[m_fileLength];
                m_state = LOADING_FILE;
                success = true;
            }
            return success;
        }
        void SampleTask::Stop() {
            m_renderer->RemoveRenderable(&m_renderable);
        }
        void SampleTask::Update() {
            switch (m_state) {
            case (LOADING_FILE): {
                void* currentDataPos = static_cast<char*>(m_TGABuffer)
                        + (sizeof(char) * m_readBytes);
                size_t bytesRead = 0;
                m_file.Read(currentDataPos, 512 * 1024, bytesRead);
                m_readBytes += bytesRead;
                if (m_readBytes == m_fileLength) {
                    m_state = CREATE_TEXTURE;
                }
            }
                break;
            case (CREATE_TEXTURE): {
                Framework::TGAFile tgaFile(m_TGABuffer);
                Framework::Texture::Header textureHeader;
                textureHeader.m_width = tgaFile.GetWidth();
                textureHeader.m_height = tgaFile.GetHeight();
                textureHeader.m_bytesPerPixel = 4;
                textureHeader.m_dataSize = textureHeader.m_width
                        * textureHeader.m_height * textureHeader.m_bytesPerPixel;
                m_texture.SetData(textureHeader, tgaFile.GetImageData());
                m_textureShader.SetTexture(&m_texture);
                m_renderer->AddTexture(&m_texture);
                m_renderer->AddShader(&m_textureShader);
                m_renderer->AddRenderable(&m_renderable);
                m_state = RUNNING;
            }
                break;
            };
        }

   Renderer.cpp
    void Renderer::Update() {
        if (m_initialized) {
            glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            for (RenderableVectorIterator iter = m_renderables.begin();
                    iter != m_renderables.end(); iter++) {
                Renderable* pRenderable = *iter;
                if (pRenderable) {
                    Draw(pRenderable);
                }
            }
            eglSwapBuffers(m_display, m_surface);
        }
    }
    void Renderer::Init() {
        // initialize OpenGL ES and EGL
        /*
         * Here specify the attributes of the desired configuration.
         * Below, we select an EGLConfig with at least 8 bits per color
         * component compatible with on-screen windows
         */
        const EGLint attribs[] = {
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_BLUE_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_RED_SIZE, 8,
        EGL_NONE };
        EGLint format;
        EGLint numConfigs;
        EGLConfig config;
        m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        eglInitialize(m_display, NULL, NULL);
        /* Here, the application chooses the configuration it desires. In this
         * sample, we have a very simplified selection process, where we pick
         * the first EGLConfig that matches our criteria */
        eglChooseConfig(m_display, attribs, &config, 1, &numConfigs);
        /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
         * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
         * As soon as we picked a EGLConfig, we can safely reconfigure the
         * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
        eglGetConfigAttrib(m_display, config, EGL_NATIVE_VISUAL_ID, &format);
        ANativeWindow_setBuffersGeometry(m_state->window, 0, 0, format);
        m_surface = eglCreateWindowSurface(m_display, config, m_state->window,
        NULL);
        EGLint contextAttribs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE };
        m_context = eglCreateContext(m_display, config, NULL, contextAttribs);
        eglMakeCurrent(m_display, m_surface, m_surface, m_context);
        eglQuerySurface(m_display, m_surface, EGL_WIDTH, &m_width);
        eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &m_height);
        for (TextureVectorIterator iter = m_textures.begin();
                iter != m_textures.end(); ++iter) {
            Texture* pCurrent = *iter;
            pCurrent->Init();
        }
        for (ShaderVectorIterator iter = m_shaders.begin(); iter != m_shaders.end();
                ++iter) {
            Shader* pCurrent = *iter;
            pCurrent->Link();
        }
        m_initialized = true;
    }
    void Renderer::Draw(Renderable* renderable) {
        assert(renderable);
        if (renderable) {
            Geometry* geometry = renderable->GetGeometry();
            Shader* shader = renderable->GetShader();
            assert(geometry && shader);
            if (geometry && shader) {
                shader->Setup(*renderable);
                glDrawElements(GL_TRIANGLES, geometry->GetNumIndices(),
                GL_UNSIGNED_SHORT, geometry->GetIndexBuffer());
            }
        }
    }

Texture.cpp
    void Texture::Init() {
        GLint packBits = 4;
        GLint internalFormat = GL_RGBA;
        GLenum format = GL_RGBA;
        switch (m_header.m_bytesPerPixel) {
        case 1: {
            packBits = 1;
            internalFormat = GL_ALPHA;
            format = GL_ALPHA;
        }
            break;
        };
        glGenTextures(1, &m_id);
        glBindTexture(GL_TEXTURE_2D, m_id);
        glPixelStorei(GL_UNPACK_ALIGNMENT, packBits);
        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_header.m_width,
                m_header.m_height, 0, format, GL_UNSIGNED_BYTE, m_imageData);
    }

TextureShader.cpp
    m_vertexShaderCode =
    "attribute vec4 a_vPosition;        n"
    "attribute vec2 a_texCoord;         n"
    "varying   vec2 v_texCoord;         n"
    "void main(){                       n"
    "    gl_Position = a_vPosition;     n"
    "    v_texCoord = a_texCoord;       n"
    "}                                  n";
m_fragmentShaderCode =
    "precision highp float;                             n"
    "varying vec2 v_texCoord;                               n"
    "uniform sampler2D s_texture;                           n"
    "void main(){                                           n"
    "    gl_FragColor = texture2D(s_texture, v_texCoord);   n"
    "}                                                      n";

    void TextureShader::Link() {
        Shader::Link();
        m_positionAttribHandle = glGetAttribLocation(m_programId, "a_vPosition");
        m_texCoordAttribHandle = glGetAttribLocation(m_programId, "a_texCoord");
        m_samplerHandle = glGetUniformLocation(m_programId, "s_texture");
    }
    void TextureShader::Setup(Renderable& renderable){
        assert(m_texture);
        Geometry* pGeometry = renderable.GetGeometry();
        if (pGeometry && m_texture) {
            Shader::Setup(renderable);
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, m_texture->GetId());
            glUniform1i(m_samplerHandle, 0);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glVertexAttribPointer(m_positionAttribHandle,
                    pGeometry->GetNumVertexPositionElements(),
                    GL_FLOAT,
                    GL_FALSE, pGeometry->GetVertexStride(),
                    pGeometry->GetVertexBuffer());
            glEnableVertexAttribArray (m_positionAttribHandle);
            glVertexAttribPointer(m_texCoordAttribHandle,
                    pGeometry->GetNumTexCoordsElements(),
                    GL_FLOAT,
                    GL_FALSE, pGeometry->GetVertexStride(),
                    &static_cast<GLfloat*>(pGeometry->GetVertexBuffer())[pGeometry->GetNumVertexPositionElements()]);
            glEnableVertexAttribArray (m_texCoordAttribHandle);
        }
    }

找到问题所在了。

我决定使用本书网站上的头文件和cpp文件,然后我从自己的代码版本中逐一复制粘贴每个cpp文件,结果是TGA文件的图像数据大小"计算错误"。

我的错误在代码中:

m_imageData = static_cast<void*>(static_cast<char*>(data) + sizeof(m_header));

我正在计算"m_header"变量的大小,相反,我应该计算TGAHeader类的大小,我认为这是18个字节或什么的,所以我把m_header改成了TGAHeader,像这样:

m_imageData = static_cast<void*>(static_cast<char*>(data) + sizeof(TGAHeader));

现在颜色是正确的,我还将格式从GL_RGB更改为GL_BGR_EXT,并保持内部格式为GL_RGB,以便在进入gl的缓冲区时反转颜色

最新更新