2012-04-02 64 views
1

我遇到了麻煩Phong着色看的權利。我很確定我的OpenGL調用有問題,或者我正在加載我的法線,但我想這可能是其他問題,因爲3D圖形和Assimp對我來說仍然是非常新的。當試圖加載.obj/.mtl文件時,我看到的問題是:的OpenGL 3.x的Assimp麻煩實施Phong着色(法線?)

  1. 這些模型似乎被點亮得太激烈(少phong風格,更徹底洗掉,太亮)。
  2. 被點亮的面孔似乎全部點亮(只有當光源位置移動到實際上位於模型頂部時,纔會顯示鏡面高光)
  3. 由於問題1和2 ,球體看起來非常錯誤的:

picture of sphere

而且具有較大的臉的事情看(不太明顯)錯誤太:

picture of cube

我可能是錯的,但對我來說,這看起來不像正確的phong底紋。

這裏的,我認爲可能是相關的代碼(我可以發佈更多的如果需要的話):

文件:assimpRenderer.cpp

#include "assimpRenderer.hpp" 

namespace def 
{ 

assimpRenderer::assimpRenderer(std::string modelFilename, float modelScale) 
{ 
    initSFML(); 
    initOpenGL(); 

    if (assImport(modelFilename)) // if modelFile loaded successfully 
    { 
     initScene(); 
     mainLoop(modelScale); 
     shutdownScene(); 
    } 

    shutdownOpenGL(); 
    shutdownSFML(); 
} 

assimpRenderer::~assimpRenderer() 
{ 

} 

void assimpRenderer::initSFML() 
{ 
    windowWidth = 800; 
    windowHeight = 600; 
    settings.majorVersion = 3; 
    settings.minorVersion = 3; 
    app = NULL; 
    shader = NULL; 

    app = new sf::Window(sf::VideoMode(windowWidth,windowHeight,32), "OpenGL 3.x Window", sf::Style::Default, settings); 
    app->setFramerateLimit(240); 
    app->setActive(); 
    return; 
} 

void assimpRenderer::shutdownSFML() 
{ 
    delete app; 

    return; 
} 

void assimpRenderer::initOpenGL() 
{ 
    GLenum err = glewInit(); 
    if (GLEW_OK != err) 
    { 
     /* Problem: glewInit failed, something is seriously wrong. */ 
     std::cerr << "Error: " << glewGetErrorString(err) << std::endl; 
    } 

    // check the OpenGL context version that's currently in use 
    int glVersion[2] = {-1, -1}; 
    glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]); // get the OpenGL Major version 
    glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]); // get the OpenGL Minor version 
    std::cout << "Using OpenGL Version: " << glVersion[0] << "." << glVersion[1] << std::endl; 

    return; 
} 

void assimpRenderer::shutdownOpenGL() 
{ 

    return; 
} 

void assimpRenderer::initScene() 
{ 
    // allocate heap space for VAOs, VBOs, and IBOs 
    vaoID = new GLuint[scene->mNumMeshes]; 
    vboID = new GLuint[scene->mNumMeshes*2]; 
    iboID = new GLuint[scene->mNumMeshes]; 

    glClearColor(0.4f, 0.6f, 0.9f, 0.0f); 
    glEnable(GL_DEPTH_TEST); 
    glDepthFunc(GL_LEQUAL); 
    glEnable(GL_CULL_FACE); 


    shader = new Shader("shader.vert", "shader.frag"); 
    projectionMatrix = glm::perspective(60.0f, (float)windowWidth/(float)windowHeight, 0.1f, 100.0f); 

    rot = 0.0f; 
    rotSpeed = 50.0f; 

    faceIndex = 0; 


    colorArrayA = NULL; 
    colorArrayD = NULL; 
    colorArrayS = NULL; 

    normalArray = NULL; 


    genVAOs(); 

    return; 
} 

void assimpRenderer::shutdownScene() 
{ 
    delete [] iboID; 
    delete [] vboID; 
    delete [] vaoID; 

    delete shader; 
} 

void assimpRenderer::renderScene(float modelScale) 
{ 
    sf::Time elapsedTime = clock.getElapsedTime(); 
    clock.restart(); 

    if (rot > 360.0f) 
     rot = 0.0f; 
    rot += rotSpeed * elapsedTime.asSeconds(); 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 
    viewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -3.0f, -10.0f)); // move back a bit 
    modelMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(modelScale)); // scale model 
    modelMatrix = glm::rotate(modelMatrix, rot, glm::vec3(0, 1, 0)); 
    //modelMatrix = glm::rotate(modelMatrix, 25.0f, glm::vec3(0, 1, 0)); 


    glm::vec3 lightPosition(0.0f, -100.0f, 0.0f); 

    float lightPositionArray[3]; 
    lightPositionArray[0] = lightPosition[0]; 
    lightPositionArray[1] = lightPosition[1]; 
    lightPositionArray[2] = lightPosition[2]; 


    shader->bind(); 

    int projectionMatrixLocation = glGetUniformLocation(shader->id(), "projectionMatrix"); 
    int viewMatrixLocation = glGetUniformLocation(shader->id(), "viewMatrix"); 
    int modelMatrixLocation = glGetUniformLocation(shader->id(), "modelMatrix"); 
    int ambientLocation    = glGetUniformLocation(shader->id(), "ambientColor"); 
    int diffuseLocation    = glGetUniformLocation(shader->id(), "diffuseColor"); 
    int specularLocation   = glGetUniformLocation(shader->id(), "specularColor"); 
    int lightPositionLocation  = glGetUniformLocation(shader->id(), "lightPosition"); 
    int normalMatrixLocation  = glGetUniformLocation(shader->id(), "normalMatrix"); 

    glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]); 
    glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]); 
    glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]); 
    glUniform3fv(lightPositionLocation, 1, lightPositionArray); 

    for (unsigned int i = 0; i < scene->mNumMeshes; i++) 
    { 
     colorArrayA = new float[3]; 
     colorArrayD = new float[3]; 
     colorArrayS = new float[3]; 

     material = scene->mMaterials[scene->mNumMaterials-1]; 

     normalArray = new float[scene->mMeshes[i]->mNumVertices * 3]; 

     unsigned int normalIndex = 0; 
     for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++) 
     { 
      normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x 
      normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y 
      normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z 
     } 
     normalIndex = 0; 


     glUniformMatrix3fv(normalMatrixLocation, 1, GL_FALSE, normalArray); 

     aiColor3D ambient(0.0f, 0.0f, 0.0f); 
     material->Get(AI_MATKEY_COLOR_AMBIENT, ambient); 

     aiColor3D diffuse(0.0f, 0.0f, 0.0f); 
     material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); 

     aiColor3D specular(0.0f, 0.0f, 0.0f); 
     material->Get(AI_MATKEY_COLOR_SPECULAR, specular); 


     colorArrayA[0] = ambient.r; colorArrayA[1] = ambient.g; colorArrayA[2] = ambient.b; 
     colorArrayD[0] = diffuse.r; colorArrayD[1] = diffuse.g; colorArrayD[2] = diffuse.b; 
     colorArrayS[0] = specular.r; colorArrayS[1] = specular.g; colorArrayS[2] = specular.b; 

     // bind color for each mesh 
     glUniform3fv(ambientLocation, 1, colorArrayA); 
     glUniform3fv(diffuseLocation, 1, colorArrayD); 
     glUniform3fv(specularLocation, 1, colorArrayS); 

     // render all meshes 
     glBindVertexArray(vaoID[i]); // bind our VAO 
     glDrawElements(GL_TRIANGLES, scene->mMeshes[i]->mNumFaces*3, GL_UNSIGNED_INT, 0); 
     glBindVertexArray(0); // unbind our VAO 


     delete [] normalArray; 

     delete [] colorArrayA; 
     delete [] colorArrayD; 
     delete [] colorArrayS; 
    } 

    shader->unbind(); 

    app->display(); 

    return; 
} 

void assimpRenderer::handleEvents() 
{ 
    sf::Event event; 

    while (app->pollEvent(event)) 
    { 
     if (event.type == sf::Event::Closed) 
     { 
      app->close(); 
     } 

     if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) 
     { 
      app->close(); 
     } 

     if (event.type == sf::Event::Resized) 
     { 
      glViewport(0, 0, event.size.width, event.size.height); 
     } 
    } 

    return; 
} 

void assimpRenderer::mainLoop(float modelScale) 
{ 
    while (app->isOpen()) 
    { 
     renderScene(modelScale); 
     handleEvents(); 
    } 
} 

bool assimpRenderer::assImport(const std::string& pFile) 
{ 
    // read the file with some example postprocessing 
    scene = importer.ReadFile(pFile, 
      aiProcess_CalcTangentSpace  | 
      aiProcess_Triangulate   | 
      aiProcess_JoinIdenticalVertices | 
      aiProcess_SortByPType); 

    // if the import failed, report it 
    if (!scene) 
    { 
     std::cerr << "Error: " << importer.GetErrorString() << std::endl; 
     return false; 
    } 

    return true; 
} 

void assimpRenderer::genVAOs() 
{ 

    int vboIndex = 0; 
    for (unsigned int i = 0; i < scene->mNumMeshes; i++, vboIndex+=2) 
    { 
     mesh = scene->mMeshes[i]; 
     indexArray = new unsigned int[mesh->mNumFaces * sizeof(unsigned int) * 3]; 

     // convert assimp faces format to array 
     faceIndex = 0; 

     for (unsigned int t = 0; t < mesh->mNumFaces; ++t) 
     { 
      const struct aiFace* face = &mesh->mFaces[t]; 
      std::memcpy(&indexArray[faceIndex], face->mIndices, sizeof(float) * 3); 
      faceIndex += 3; 
     } 

     // generate VAO 
     glGenVertexArrays(1, &vaoID[i]); 
     glBindVertexArray(vaoID[i]); 

     // generate IBO for faces 
     glGenBuffers(1, &iboID[i]); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID[i]); 
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * mesh->mNumFaces * 3, indexArray, GL_STATIC_DRAW); 

     // generate VBO for vertices 
     if (mesh->HasPositions()) 
     { 
      glGenBuffers(1, &vboID[vboIndex]); 
      glBindBuffer(GL_ARRAY_BUFFER, vboID[vboIndex]); 
      glBufferData(GL_ARRAY_BUFFER, mesh->mNumVertices * sizeof(GLfloat) * 3, mesh->mVertices, GL_STATIC_DRAW); 
      glEnableVertexAttribArray((GLuint)0); 
      glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
     } 

     // generate VBO for normals 
     if (mesh->HasNormals()) 
     { 
      normalArray = new float[scene->mMeshes[i]->mNumVertices * 3]; 

      unsigned int normalIndex = 0; 
      for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++) 
      { 
       normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x 
       normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y 
       normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z 
      } 
      normalIndex = 0; 

      glGenBuffers(1, &vboID[vboIndex+1]); 
      glBindBuffer(GL_ARRAY_BUFFER, vboID[vboIndex+1]); 
      glBufferData(GL_ARRAY_BUFFER, mesh->mNumVertices * sizeof(GLfloat) * 3, normalArray, GL_STATIC_DRAW); 
      glEnableVertexAttribArray((GLuint)1); 
      glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); 

      delete [] normalArray; 
     } 

     // tex coord stuff goes here 

     // unbind buffers 
     glBindVertexArray(0); 
     glBindBuffer(GL_ARRAY_BUFFER, 0); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

     delete [] indexArray; 
    } 
    vboIndex = 0; 

    return; 
} 

} 

文件:shader.vert

#version 150 core 

in vec3 in_Position; 
in vec3 in_Normal; 

uniform mat4 projectionMatrix; 
uniform mat4 viewMatrix; 
uniform mat4 modelMatrix; 
uniform vec3 lightPosition; 
uniform mat3 normalMatrix; 

smooth out vec3 vVaryingNormal; 
smooth out vec3 vVaryingLightDir; 

void main() 
{  
    // derive MVP and MV matrices 
    mat4 modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix; 
    mat4 modelViewMatrix = viewMatrix * modelMatrix; 

    // get surface normal in eye coordinates 
    vVaryingNormal = normalMatrix * in_Normal; 

    // get vertex position in eye coordinates 
    vec4 vPosition4 = modelViewMatrix * vec4(in_Position, 1.0); 
    vec3 vPosition3 = vPosition4.xyz/vPosition4.w; 

    // get vector to light source 
    vVaryingLightDir = normalize(lightPosition - vPosition3); 

    // Set the position of the current vertex 
    gl_Position = modelViewProjectionMatrix * vec4(in_Position, 1.0); 

} 

文件:shader.frag

#version 150 core 

out vec4 out_Color; 

uniform vec3 ambientColor; 
uniform vec3 diffuseColor; 
uniform vec3 specularColor; 

smooth in vec3 vVaryingNormal; 
smooth in vec3 vVaryingLightDir; 

void main() 
{ 
    // dot product gives us diffuse intensity 
    float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir))); 

    // multiply intensity by diffuse color, force alpha to 1.0 
    out_Color = vec4(diff * diffuseColor, 1.0); 

    // add in ambient light 
    out_Color += vec4(ambientColor, 1.0); 

    // specular light 
    vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal))); 
    float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection)); 

    if (diff != 0) 
    { 
     float fSpec = pow(spec, 128.0); 
     // Set the output color of our current pixel 
     out_Color.rgb += vec3(fSpec, fSpec, fSpec); 
    } 
} 

我知道需要仔細查看,但我將大部分代碼放在了一起,以免假設問題出在哪裏。

回答

2

你在做正確的事情正常的矩陣?這對我來說很奇怪。

for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++) 
    { 
     normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x 
     normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y 
     normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z 
    } 
    glUniformMatrix3fv(normalMatrixLocation, 1, GL_FALSE, normalArray); 

爲什麼normalMatrix與mesh的頂點有什麼關係?它應該與您的modelMatrix相同(假設您沒有進行任何非均勻縮放)。

+0

我想我需要填充1正常的網格中的每個頂點一個VBO .. – Defcronyke 2012-04-02 23:53:33

+0

什麼,我認爲這些代碼是幹什麼的,加載所有從Assimp數據結構法線成normalArray,所以後來我就可以把正常陣列變成一個VBO。 – Defcronyke 2012-04-03 00:11:21

+0

哦,我在兩個地方的代碼,所以你引用的情況下,它是從Assimp結構給予normalArray着色器 – Defcronyke 2012-04-03 00:55:09