1

我正在使用 VC++10 + OpenGL + Assimp 库来使用并渲染一些 3D 模型。

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

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

* ** * ** * ** * EDIT1: * ** * ** * ****

所以,我一直在使用很棒的 GDebugger 应用程序来实时调试和询问 OpenGL 管道。有两件事真的很突出:1.这里最重要的是加载的纹理看起来像这样-> 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 初始化等 *

    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
    }
}
4

2 回答 2

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 模型,尽管它有颜色。

于 2013-04-27T11:35:48.473 回答
0

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

out vec2 oTexCoord;

但是您的片段着色器声明:

in vec2 TexCoord;

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

于 2013-04-28T14:37:11.990 回答