2013-04-27 147 views
1

我使用VC++ 10 + OpenGL + Assimp库来消耗并渲染一些3D模型。OpenGL纹理采样不起作用

代码正确渲染位置,但由于某些原因,纹理严重杂物。我的texcoords好像是正确加载的,就像纹理文件本身一样 - 但我不禁感到这个问题必须与加载的纹理本身一起定位。

www.flickr.com/photos/[email protected]/8685913640/in/photostream {我似乎有缺乏代表的张贴内嵌图像}

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

所以,我一直在使用令人敬畏的GDebugger应用程序来实时调试和询问OpenGL管道。 2个东西脱颖而出真的: 1.这里的biggy的是,加载的纹理意味着这个样子 - > http://www.flickr.com/photos/[email protected]/8688860034/in/photostream 但实际上,当加载到内存的OpenGL看起来是这样的: http://www.flickr.com/photos/[email protected]/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 
    } 
} 

回答

0

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

out vec2 oTexCoord; 

,但你的片段着色器声明:

in vec2 TexCoord; 

这可能会离开你的纹理坐标定义。

+0

哈哈,你提到它很有趣。今天早上我已经明白了。这样一个简单的小问题导致了所有这些问题。 我只注意到它,这要感谢您指出我应该使用小的2x2像素颜色图集进行测试。您可以在之前上传的剪辑中看到结果。 http://www.youtube.com/watch?v=g5sOgFlSkRY 感谢您的帮助兄弟! – DanoThom 2013-04-28 14:58:05

+0

酷 - 尽管我应该指出这是一个不同的用户xxxxxxx(我只是注册了,并没有给自己一个正式的名字),他建议你尝试2x2纹理,所以我不能完全承担所有功劳。 – GuyRT 2013-04-28 15:31:47

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

+0

感谢您的回应。然而,我认为对于OpenGL 3.0+“glEnable(GL_TEXTURE_2D)”已被弃用,倾向于使用“glActiveTexture(GL_TEXTUREn)”,然后将纹理绑定到第n个纹理单元等。 为了绝望的利益,我尝试了它 - 但仍然没有骰子哈哈!我认为这个问题或者是由GLSDK glimg库导入的纹理文件关于内部颜色格式/或者我的代码和着色器之间的实际着色器绑定过程。 – DanoThom 2013-04-27 14:14:54

+0

我明白了。你有没有一个简单的骨头例子工作?也许只是绘制了一个纹理三角形? – dwMagician 2013-04-27 17:00:16

+0

不用,即使只是使用简单的立方体使用1个简单的草地类型纹理进行测试 - 立方体会以平坦/暗淡的绿色进行映射 - 但它不是实际的纹理。所以看起来texcoords正在绘制到正确的顶点。 – DanoThom 2013-04-27 18:05:00