OpenGL纹理采样不起作用

时间:2013-04-27 10:35:25

标签: c++ opengl textures texture-mapping assimp

我正在使用VC ++ 10 + OpenGL + Assimp Library来使用,然后渲染一些3D模型。

代码正确地渲染位置,但由于某种原因,纹理严重错误。我的texcoords似乎正在加载正确的纹理文件本身 - 但我不禁觉得问题必须与加载的纹理本身一起定位。

www.flickr.com/photos/95269725@N02/8685913640/in/photostream   {我似乎缺乏发布内联图片的代表}

* ** * ** * ** * EDIT1:的 * ** * ** * ****

所以,我一直在使用非常棒的GDebugger应用程序来实时调试和查询OpenGL管道。事情突出2件事:  这里的重点是加载的纹理看起来像这样 - >    http://www.flickr.com/photos/95269725@N02/8688860034/in/photostream     但加载到OpenGL内存时实际上看起来像这样:    http://www.flickr.com/photos/95269725@N02/8688860042/in/photostream/  2.不确定这是否仍然适用(如评论中所述),但GL_TEXTURE_2D状态变量在整个游戏循环中始终为FALSE。

所以我将不得不使用纹理加载代码来查看我是否可以获得任何牵引力并发布另一个更新。

一些重要的相关代码块{抱歉!}:

*顶点着色器*

    #version 420

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoord;

uniform mat4 cameraToClipMatrix;
uniform mat4 modelToCameraMatrix;

out vec2 oTexCoord;
out vec4 oNormal;

void main()
{
    oTexCoord = texCoord;
    vec4 cameraPos = modelToCameraMatrix * vec4(position,1.0);
    gl_Position = cameraToClipMatrix * cameraPos;

    oNormal = normalize(vec4(modelToCameraMatrix * vec4(normal,0.0)));

}

*片段着色器*

    #version 420

in vec4 Normal;
in vec2 TexCoord;

layout (location = 0) out vec4  FragColor;

uniform sampler2D gSampler;   

void main()
{
    FragColor = texture(gSampler, TexCoord);
    //FragColor = vec4(1.1, 0.0, 1.1, 1.0);
}

* GL Init等*

    void GLSystem::init() {

    InitializeProgram();

    glClearColor(0.75f, 0.75f, 1.0f, 1.0f);
    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glDepthFunc(GL_LEQUAL);
    glDepthRange(0.0f, 1.0f);
}

void GLSystem::InitializeProgram()
{
    std::vector<GLuint> shaderList;

    shaderList.push_back(LoadShader(GL_VERTEX_SHADER, "VertShader1.vert"));
    shaderList.push_back(LoadShader(GL_FRAGMENT_SHADER, "FragShader1.frag"));

    theProgram = CreateProgram(shaderList);

    modelToCameraMatrixUnif =       glGetUniformLocation(theProgram, "modelToCameraMatrix"); // view matrix
    cameraToClipMatrixUnif =        glGetUniformLocation(theProgram, "cameraToClipMatrix"); // projection matrix
    m_samplerUnif =                 glGetUniformLocation(theProgram, "gSampler"); // grab the gSampler uniform location reference in the fragment shader

    float fzNear = 1.0f; float fzFar = 45.0f;

    cameraToClipMatrix[0].x = fFrustumScale;
    cameraToClipMatrix[1].y = fFrustumScale;
    cameraToClipMatrix[2].z = (fzFar + fzNear) / (fzNear - fzFar);
    cameraToClipMatrix[2].w = -1.0f;
    cameraToClipMatrix[3].z = (2 * fzFar * fzNear) / (fzNear - fzFar);

    glUseProgram(theProgram);
    glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
    glUseProgram(0);
}

*纹理加载*

    bool CTexture::Load()  {
    m_texObj = 0;  // init to zero
    std::auto_ptr<glimg::ImageSet> pImgSet;
    try {
        pImgSet.reset( glimg::loaders::stb::LoadFromFile(m_filename) );
        m_texObj = glimg::CreateTexture( &(*pImgSet), 0);               // generates a texture and returns the related texture id

        //glimg::SingleImage image = pImgSet->GetImage(0, 0, 0);
        //glimg::Dimensions dims = image.GetDimensions();
        //GLuint targetTexType = glimg::GetTextureType( &(*pImgSet), 0); // not using this yet - but potentially might need to base this objects targetType on this interpreted value.
        //glimg::OpenGLPixelTransferParams params = GetUploadFormatType(image.GetFormat(), 0);
        //glPixelStorei(GL_UNPACK_ALIGNMENT, image.GetFormat().LineAlign());

        //glGenTextures(1, &m_texObj);
        //glActiveTexture(GL_TEXTURE0);
        //glBindTexture(GL_TEXTURE_2D, m_texObj);
        //glTexImage2D(m_targetType, 0, glimg::GetInternalFormat(image.GetFormat(), 0), dims.width, dims.height, 0, params.format, params.type, image.GetImageData());
        //glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, dims.width, dims.height, 0, GL_RGB, GL_UNSIGNED_BYTE, image.GetImageData() );

        /*glTexParameterf(m_targetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(m_targetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(m_targetType, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameterf(m_targetType, GL_TEXTURE_WRAP_T, GL_REPEAT);*/
    }
    catch(glimg::loaders::stb::StbLoaderException &e) {
        std::cout << "Warning : " << e.what() << " || .Image file loading failed for file : '" << m_filename << std::endl;
        return false;
    }

    glBindTexture(m_targetType, 0);  // Bind to default texture

    return true;
}

*网格加载*

    #include "MeshModel.h"
// ----------------------------------------------------------------------------------------
#include "Texture.h"
#include "GLSystem.h"
#include "Game.h"
// ----------------------------------------------------------------------------------------
#include <assert.h>
// ----------------------------------------------------------------------------------------

MeshItem::MeshItem() {
}

MeshItem::MeshItem(MeshModel& p_meshModel) {
    m_pmeshModel = &p_meshModel;
    p_delete_object_data = true;
    VBO = INVALID_OGL_VALUE;
    IBO = INVALID_OGL_VALUE;
    NBO = INVALID_OGL_VALUE;
    TBO = INVALID_OGL_VALUE;
    NumVertices = 0;
    NumFaces = 0;
    NumIndices  = 0;
    MaterialIndex = INVALID_MATERIAL;
};

MeshItem::~MeshItem() {
    if (VBO != INVALID_OGL_VALUE) {
        glDeleteBuffers(1, &VBO);
    }
    if (IBO != INVALID_OGL_VALUE) {
        glDeleteBuffers(1, &IBO);
    }
    if (NBO != INVALID_OGL_VALUE) {
        glDeleteBuffers(1, &NBO);
    }
    if (TBO != INVALID_OGL_VALUE) {
        glDeleteBuffers(1, &TBO);
    }
}

void MeshItem::BuildVBO() {
    glGenVertexArrays(1, &VAO); /* Generate a vertex array object - container for all vertex attribute arrays */
    glBindVertexArray(VAO); /* Bind this VAO as the current Vertex Attribute Array container [ Holds the state for all attributes i.e. not the Vertex and Index data ] */

    // Positions
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * NumVertices * 3, &Positions[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Positions

    // Indices
    glGenBuffers(1, &IBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * NumFaces * 3, &Indices[0], GL_STATIC_DRAW);

    // Normals
    glGenBuffers(1, &NBO);
    glBindBuffer(GL_ARRAY_BUFFER, NBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * NumVertices * 3, &Normals[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0); // Normals

    // TexCoords
    glGenBuffers(1, &TBO);
    glBindBuffer(GL_ARRAY_BUFFER, TBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * NumVertices * 2, &TexCoords[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0); // TexCoords

    glBindVertexArray(0);                           // Unbind the VAO
    glBindBuffer(GL_ARRAY_BUFFER,0);                // Unbind the vertices array buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);       // Unbind the indices array buffer


    // Our copy of the data is no longer necessary, it is safe in the graphics card memory
    if(p_delete_object_data) {
        Positions.erase( Positions.begin(), Positions.end() );
        Indices.erase( Indices.begin(), Indices.end() );
        Normals.erase( Normals.begin(), Normals.end() );
        TexCoords.erase( TexCoords.begin(), TexCoords.end() );
    }
}

// ********************* MESHMODEL *********************

MeshModel::MeshModel(GLSystem& p_gls) 
    : m_pgls(&p_gls)
{
    m_texUnit = 0;
    m_samplerObj = 0;
}

MeshModel::~MeshModel() {
    Clear();
}

GLSystem& MeshModel::getGLSystem() {
    return *m_pgls;
}

void MeshModel::Clear() {
    //for (unsigned int i = 0 ; i < m_textures.size() ; i++) {
    //    m_textures[i]);
    //}
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
}

bool MeshModel::LoadMesh(const std::string& p_filename) {
    Clear(); // Release the previously loaded mesh (if it exists)

    bool Ret = false;
    Assimp::Importer Importer;
    const aiScene* pScene = Importer.ReadFile(p_filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals /* | aiProcess_FlipWindingOrder*/ /* | aiProcess_FlipUVs*/ | aiProcess_ValidateDataStructure);
    //const aiScene* pScene = aiImportFile(p_filename.c_str(), aiProcessPreset_TargetRealtime_MaxQuality);

    if (pScene) {
        printf("3D Object File '%s' loaded successfully.\n", p_filename.c_str() );
        Ret = InitFromScene(pScene, p_filename);
    }
    else {
        printf("Error parsing '%s': '%s'.\n", p_filename.c_str(), Importer.GetErrorString());
    }

    return Ret;
}

bool MeshModel::InitFromScene(const aiScene* pScene, const std::string& p_filename) {  
    //m_meshItems.resize(pScene->mNumMeshes);
    m_textures.resize(pScene->mNumMaterials);

    InitMaterials(pScene, p_filename); // load materials/textures etc

    // Initialize the meshes in the scene one by one
    for (unsigned int i = 0 ; i < pScene->mNumMeshes ; i++) {
        const aiMesh* paiMesh = pScene->mMeshes[i];
        MeshItem mItem(*this);
        InitMesh(mItem, paiMesh);
        mItem.BuildVBO();
        m_meshItems.push_back(mItem);
    }

    return true;
}

void MeshModel::InitMesh(MeshItem& p_meshItem, const aiMesh* p_paiMesh) {
    p_meshItem.MaterialIndex = p_paiMesh->mMaterialIndex;

    // Indices
    p_meshItem.NumFaces = p_paiMesh->mNumFaces;
    p_meshItem.NumIndices = p_meshItem.NumFaces * 3;
    p_meshItem.Indices.resize(p_meshItem.NumIndices);

    for (unsigned int i = 0 ; i < p_paiMesh->mNumFaces ; ++i) {
        const aiFace& face = p_paiMesh->mFaces[i];
        assert(face.mNumIndices == 3);
        p_meshItem.Indices[i*3+0] = face.mIndices[0];
        p_meshItem.Indices[i*3+1] = face.mIndices[1];
        p_meshItem.Indices[i*3+2] = face.mIndices[2];
    }

    p_meshItem.NumVertices = p_paiMesh->mNumVertices;
    p_meshItem.Positions.resize(p_meshItem.NumVertices * 3);
    p_meshItem.Normals.resize(p_meshItem.NumVertices * 3);
    p_meshItem.TexCoords.resize(p_meshItem.NumVertices * 2);

    for (unsigned int i = 0 ; i < p_paiMesh->mNumVertices ; ++i) {
        // Positions
        if( p_paiMesh->HasPositions() ) {
            p_meshItem.Positions[i*3+0] = p_paiMesh->mVertices[i].x;
            p_meshItem.Positions[i*3+1] = p_paiMesh->mVertices[i].y;
            p_meshItem.Positions[i*3+2] = p_paiMesh->mVertices[i].z;
        }
        // Normals
        if( p_paiMesh->HasNormals() ) {
            p_meshItem.Normals[i*3+0] = p_paiMesh->mNormals[i].x;
            p_meshItem.Normals[i*3+1] = p_paiMesh->mNormals[i].y;
            p_meshItem.Normals[i*3+2] = p_paiMesh->mNormals[i].z;
        }
        // TexCoords
        if( p_paiMesh->HasTextureCoords(0) ) {
            p_meshItem.TexCoords[i*2+0] = p_paiMesh->mTextureCoords[0][i].x;
            p_meshItem.TexCoords[i*2+1] = p_paiMesh->mTextureCoords[0][i].y;
        }

    }
}

bool MeshModel::InitMaterials(const aiScene* pScene, const std::string& p_filename) {
    // Extract the directory part from the file name
    std::string::size_type SlashIndex = p_filename.find_last_of("/");
    std::string Dir;

    if (SlashIndex == std::string::npos) {
        Dir = ".";
    }
    else if (SlashIndex == 0) {
        Dir = "/";
    }
    else {
        Dir = p_filename.substr(0, SlashIndex);
    }

    bool Ret = true;

    // Initialize the materials
    for (unsigned int i = 0 ; i < pScene->mNumMaterials ; i++) {
        const aiMaterial* pMaterial = pScene->mMaterials[i];

        m_textures[i] = NULL;
        std::string FullPath = "";

        if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
            aiString Path;

            if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
                FullPath = Dir + "/" + Path.data;
                m_textures[i] = std::make_shared<CTexture>( GL_TEXTURE_2D, FullPath.c_str() );
                if ( !m_textures[i]->Load() ) {
                    printf("Error loading texture '%s'.\n", FullPath.c_str());
                    m_textures[i].reset();
                    m_textures[i] = NULL;
                    Ret = false;
                }
                else {
                    printf("Texture File '%s' loaded successfully\n", FullPath.c_str());
                }
            }
        }

        // Load a white texture in case the model does not include its own texture
        if (!m_textures[i]) {
            m_textures[i] = std::make_shared<CTexture>( GL_TEXTURE_2D, "..//Data/Textures/white.png");
            printf("A default Texture File was loaded for '%s'.\n", FullPath.c_str());

            Ret = m_textures[i]->Load();
        }
    }

    // Genertate a Sampler object
    glGenSamplers(1, &m_samplerObj);
    glSamplerParameteri(m_samplerObj, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glSamplerParameteri(m_samplerObj, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glSamplerParameteri(m_samplerObj, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glSamplerParameteri(m_samplerObj, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    return Ret;
}

void MeshModel::DrawMesh() {

    for (unsigned int i = 0 ; i < m_meshItems.size() ; i++) {
        glUseProgram( getGLSystem().getProgram() ); // Bind to our selected shader program
        glBindVertexArray(m_meshItems[i].VAO);

        const unsigned int MaterialIndex = m_meshItems[i].MaterialIndex;
        // If textures exist then bind them to samplers etc
        if (MaterialIndex < m_textures.size() && m_textures[MaterialIndex]) {
            glUniform1i(m_pgls->m_samplerUnif, 0);
            glActiveTexture(GL_TEXTURE0 + 0);
            glBindTexture(GL_TEXTURE_2D, m_textures[MaterialIndex]->m_texObj);
            glBindSampler(0, m_samplerObj);
        } else {
            printf("MeshItem has no material!");
        }

        // RTS
        glutil::MatrixStack currMatrix;
        currMatrix.Translate(glm::vec3(0.0f, -3.0f, -10.0f));
        currMatrix.Scale(0.1f, 0.1f, 0.1f);
        currMatrix.RotateX(-90);
        float a = Game::m_tick.asSeconds() /10;
        float fAngRad = m_pgls->ComputeAngleRad(a, 2.0);
        float fCos = cosf(fAngRad);
        float fSin = sinf(fAngRad);

        glm::mat3 theMat(1.0f);
        theMat[0].x = fCos; theMat[1].x = -fSin;
        theMat[0].y = fSin; theMat[1].y = fCos;
        currMatrix.ApplyMatrix(glm::mat4(theMat));
        glUniformMatrix4fv(m_pgls->modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(currMatrix.Top()));

        glDrawElements(GL_TRIANGLES, m_meshItems[i].NumIndices, GL_UNSIGNED_INT, 0);

        glBindVertexArray(0); // Unbind the VAO
        glUseProgram(0); // Close the link to the bound shader programs
    }
}

2 个答案:

答案 0 :(得分:0)

我认为您需要在init部分中使用glEnable(GL_TEXTURES_2D)启用纹理。我通过从我的项目中注释掉那一行来获得相同的外观。这是代码,如果有帮助:

EnableGraphics::EnableGraphics()
{
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1.0);        
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // typical alpha transparency
    glEnable(GL_TEXTURE_2D);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

编辑:

如果您的链接死亡,我应该补充一点,您的屏幕截图显示的是没有纹理或阴影的3D模型,尽管它有颜色。

答案 1 :(得分:0)

我注意到你的顶点着色器声明:

out vec2 oTexCoord;

但你的片段着色器声明:

in vec2 TexCoord;

这可能会使纹理坐标未定义。