0

似乎每次我尝试让纹理在我的 OpenGL 应用程序中工作时,我都会错过一些明显的东西,最终我会花费很多时间进行调试。好吧,它又发生了,尽管我已经尝试将我的代码与较旧的工作应用程序进行比较已有一段时间了,但我仍然缺少一些东西,因为纹理根本没有显示。网格显示为黑色。我没有收到任何 OpenGL 错误。

对于缩小问题范围的帮助,我将不胜感激。

这是我的代码的一部分,我很确定我的错误出在代码的这些区域:

OpenGL.cpp:

bool OpenGL::enable_attribs_and_uniforms(GLuint program_id)
{
    glGenVertexArrays(1, &this->vao_id);
    glBindVertexArray(this->vao_id);

    this->pos_a_loc = glGetAttribLocation(program_id, "pos_a");
    this->uv_a_loc = glGetAttribLocation(program_id, "uv_a");
    if (this->pos_a_loc == -1 || /*this->color_a_loc == -1 ||*/ this->uv_a_loc == -1)
    {
        std::cerr << "OpenGL Warning: Failed to get attribute locations, probably because at least one attribute isn't being used in the shader program. Attributes get optimized out if they don't affect the output of the shader program in any way.\n\n";
    }

    glEnableVertexAttribArray(this->pos_a_loc);
    glEnableVertexAttribArray(this->uv_a_loc);

    this->p_mat_u_loc = glGetUniformLocation(program_id, "p_mat_u");
    this->v_mat_u_loc = glGetUniformLocation(program_id, "v_mat_u");
    this->m_mat_u_loc = glGetUniformLocation(program_id, "m_mat_u");
    this->mvp_mat_u_loc = glGetUniformLocation(program_id, "mvp_mat_u");
    this->tex_samp_u_loc = glGetUniformLocation(program_id, "tex_samp_u");
    if (this->p_mat_u_loc == -1 || this->v_mat_u_loc == -1 ||
        this->m_mat_u_loc == -1 || this->mvp_mat_u_loc == -1 ||
        this->tex_samp_u_loc == -1)
    {
        std::cerr << "OpenGL Warning: Failed to get all uniform locations, probably because at least one uniform isn't being used in the shader program. Uniforms get optimized out if they don't affect the output of the shader program in any way.\n\n";
    }

    check_gl_error();

    return true;
}

void OpenGL::fill_buffers(std::vector<Object*>& objs)
{
    std::vector<Object*>::iterator it;
    for (it = objs.begin(); it != objs.end(); ++it)
    {
        GLuint vb_pos_id;
        glGenBuffers(1, &vb_pos_id);
        glBindBuffer(GL_ARRAY_BUFFER, vb_pos_id);
        glBufferData(GL_ARRAY_BUFFER, (*it)->v_pos.size() * sizeof(glm::vec3), &(*it)->v_pos[0], GL_STATIC_DRAW);
        this->vb_pos_ids.push_back(vb_pos_id);

        (*it)->tex_filenames[0] = "some_texture.png";

        SDL_Surface* tex_surface = IMG_Load((*it)->tex_filenames[0].c_str());
        if (!tex_surface)
        {
            std::cerr << "Texture Error: Couldn't open texture file: " << (*it)->tex_filenames[0] << "\n\n";
            return;
        }

        GLuint tex_samp_id;
        glGenTextures(1, &tex_samp_id);
        glBindTexture(GL_TEXTURE_2D, tex_samp_id);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_surface->w, tex_surface->h, 0,
            GL_RGBA, GL_UNSIGNED_BYTE, tex_surface->pixels);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        this->tex_samp_ids.push_back(tex_samp_id);

        GLuint vb_uv_id;
        glGenBuffers(1, &vb_uv_id);
        glBindBuffer(GL_ARRAY_BUFFER, vb_uv_id);
        glBufferData(GL_ARRAY_BUFFER, (*it)->v_uv.size() * sizeof(glm::vec2), &(*it)->v_uv[0], GL_STATIC_DRAW);
        this->vb_uv_ids.push_back(vb_uv_id);
    }

    check_gl_error();

    return;
}


void OpenGL::draw(std::vector<Object*>& objs)   // draws GL_TRIANGLES
{
    std::vector<Object*>::iterator objs_it;
    std::vector<GLuint>::iterator vb_pos_it;
    std::vector<GLuint>::iterator vb_col_it;
    std::vector<GLuint>::iterator vb_uv_it;
    unsigned int i = 0;
    for (objs_it = objs.begin(), vb_pos_it = this->vb_pos_ids.begin(),
         vb_col_it = this->vb_col_ids.begin(), vb_uv_it = this->vb_uv_ids.begin();
         objs_it != objs.end(); ++objs_it, ++vb_pos_it, ++vb_col_it, ++vb_uv_it, ++i)
    {
        (*objs_it)->m_mat = glm::rotate((*objs_it)->m_mat, 1.0f, glm::vec3(0.0f, 1.0f, 0.0f));

        this->mvp_mat = this->p_mat * this->v_mat * (*objs_it)->m_mat;

        // send attribs to vertex shader
        glBindBuffer(GL_ARRAY_BUFFER, (*vb_pos_it));
        glVertexAttribPointer(this->pos_a_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, this->tex_samp_ids[i]);

        glBindBuffer(GL_ARRAY_BUFFER, (*vb_uv_it));
        glVertexAttribPointer(this->uv_a_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);

        // send uniforms to vertex shader
        glUniformMatrix4fv(this->p_mat_u_loc, 1, GL_FALSE, &this->p_mat[0][0]);
        glUniformMatrix4fv(this->v_mat_u_loc, 1, GL_FALSE, &this->v_mat[0][0]);
        glUniformMatrix4fv(this->m_mat_u_loc, 1, GL_FALSE, &(*objs_it)->m_mat[0][0]);
        glUniformMatrix4fv(this->mvp_mat_u_loc, 1, GL_FALSE, &this->mvp_mat[0][0]);
        glUniform1i(this->tex_samp_u_loc, 0);

        // draw
        glDrawArrays(GL_TRIANGLES, 0, (*objs_it)->v_pos.size());

        check_gl_error();
        glGetError();   // clear GL error before next iteration
    }

    return;
}

简单的.vsh:

#version 330 core

in vec3 pos_a;
in vec2 uv_a;

uniform mat4 p_mat_u;
uniform mat4 v_mat_u;
uniform mat4 m_mat_u;
uniform mat4 mvp_mat_u;

out vec2 uv_v;

void main()
{
    gl_Position = mvp_mat_u * vec4(pos_a, 1.0);
    uv_v = uv_a;
}

简单的.fsh:

#version 330 core

smooth in vec2 uv_v;

uniform sampler2D tex_samp_u;

out vec4 color_o;

void main()
{
    color_o = texture2D(tex_samp_u, uv_v);
}
4

1 回答 1

1

好吧,事实证明代码不是问题,我从 Blender 导出错误。我想downvote是合适的。

这段代码可以显示纹理,但它显示的翻转方式错误,所以我必须在加载图像后翻转它,我仍然需要弄清楚如何让 Blender 的 collada 导出器使用 -Z forward 导出, Y向上方向......但这不是这个问题。

于 2013-06-14T17:00:32.207 回答