2013-04-27 2 views
1

Я использую VC++ 10 + OpenGL + библиотеку Assimp, чтобы потреблять, а затем визуализировать некоторые 3D-модели.OpenGL Texture Sampling не работает

Код правильно позиционирует позиции, но по какой-либо причине текстуры серьезно прослушиваются. Мои texcoords, похоже, загружаются правильно, как и сами файлы текстур, но я не могу не чувствовать, что проблема должна быть связана с загруженными текстурами.

www.flickr.com/photos/[email protected]/8685913640/in/photostream {я, кажется, есть недостаток репутации размещать встроенные изображения}

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

Итак, я использую удивительное приложение GDebugger для отладки и опроса конвейера OpenGL в реальном времени. 2 вещи выделяются на самом деле: 1. Бигги здесь является то, что загруженная текстура предназначена для выглядеть следующим образом -> 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 всегда является ЛОЖНЫ во всем игровом цикле.

Так что мне придется играть с кодом загрузки текстуры, чтобы посмотреть, смогу ли я получить какое-либо сцепление с ним и опубликовать другое обновление.

Несколько больших соответствующие куски кода {извините!}:

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

} 

* Фрагмент 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 и т.д. *

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 Загрузка *

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 Загрузка *

#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

+0

Прохладный - хотя я должен отметить, что это был другой пользовательxxxxxx (я только что подписался и еще не дал себе собственного имени), который посоветовал вам попробовать текстуру 2x2, поэтому я не могу взять на себя все заслуги. – GuyRT

0

Я думаю, что вам нужно включить текстуры с 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); 
} 

EDIT:

В случае, если ваша ссылка умирает, я должен добавить, что ваш скриншот показывает 3D-модель без каких-либо текстур или затенения, хотя она имеет цвет.

+0

Спасибо за ответ. Я думаю, однако, что для OpenGL 3.0+ «glEnable (GL_TEXTURE_2D)» устарел в пользу использования «glActiveTexture (GL_TEXTUREn)», а затем привязывает текстуру к n-му текстурному блоку и т. Д. В интересах отчаяния я пробовал это независимо - но до сих пор нет кубиков ха-ха! Я считаю, что проблема заключается в том, как файл текстур импортируется библиотекой glapsg GLSDK в отношении внутреннего цветового формата/или фактического процесса привязки шейдера между моим кодом и шейдерами. – DanoThom

+0

Я вижу. У вас есть пример с голой костью? Может быть, что-то, что просто рисует текстурированный треугольник? – dwMagician

+0

Нет, даже когда вы просто проверяете простой куб, используя 1 легкую текстуру типа травы - куб получает изображение с плоским/матовым зеленоватым цветом - однако это не фактическая текстура. Таким образом, кажется, что texcoords отображает правильные вершины в розыгрыше. – DanoThom