首页 文章

OpenGL纹理采样不起作用

提问于
浏览
1

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

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

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

************** 编辑1: ***************

所以,我一直在使用非常棒的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 .

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

几个大的相关代码块{抱歉!}:

*** Vertex Shader ***

#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)));

}

*** Fragment Shader ***

#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 etc ***

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);
}

*** Texture Loading ***

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

*** Mesh Loading ***

#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

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

    out vec2 oTexCoord;
    

    但你的片段着色器声明:

    in vec2 TexCoord;
    

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

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

相关问题