2013-03-08 52 views
2

我的OpenGL照明有一个小问题。OpenGL平面着色 - 奇怪的照明行为

它渲染模型(犹他州茶壶)很好,但我有一些奇怪的照明模式。该模型应该有一个单一的环境光照明的场景中平面着色,但我最终有污点的光明遍照在茶壶:

Teapot image

这仅仅是一个简单的练习,以建立在C模型装载机++与SFML。

代码如下:

bool modelLoader(string fileName, vector<GLfloat>& vertices, vector<GLushort>& indices, vector<GLfloat>& normals) 
{ 
    fstream object; 
    string face; 
    string dataLine; 
    string lineChar; 
    GLfloat point; 
    GLfloat uvs; 
    GLfloat storedNorm; 
    GLushort ind; 
    vector<GLfloat> storedNormals; 
    vector<GLfloat> storedUVs; 
    vector<GLfloat> localNormals , localVertices; 
    vertices.clear(); 
    indices.clear(); 

    object.open(fileName); 
    if(!object.is_open()) 
    { 
     printf("Cannot open file: %f \n", fileName); 
     return false; 
    } 
    while(object>>lineChar) 
    { 
      if(lineChar == "v" /*|| dataLine.find("vt ") == 0*/ || lineChar == "f" || lineChar == "vn") 
      { 
       if(lineChar == "v") 
       { 
        //cout<<"v "; 
        for(int i=0;i<3;++i) 
        { 
         object >> point; 
         //cout << point << " "; 
         localVertices.push_back(point); 
        } 
        //cout<<endl; 
       } 
       else if(lineChar == "vn") 
       { 
        //cout<<"vn"; 
        for(int j=0;j<3;++j) 
        { 
         object >> point; 
         //cout<<point<<" "; 
         localNormals.push_back(point); 
        } 
        //cout<<endl; 
       } 
       else if(lineChar == "f") 
       { 
        for(int k=0;k<3;++k) 
        { 
         getline(object, face, '/'); 
         ind = atoi(face.c_str()); 
         indices.push_back(ind-1); 
         object.ignore(2); 
         //getline(object, face, '/'); 
         //uvs = atoi(face.c_str()); 
         //storedUVs.push_back(uvs); 
         getline(object, face, ' '); 
         storedNorm = atoi(face.c_str()); 
         storedNormals.push_back(storedNorm); 
        } 
       } 

      } 
    } 
    for (unsigned int i=0; i<indices.size(); ++i) 
    { 
     vertices.push_back(localVertices[indices[i]*3]); 
     vertices.push_back(localVertices[indices[i]*3 + 1]); 
     vertices.push_back(localVertices[indices[i]*3 + 2]); 

     normals.push_back(localNormals[(unsigned int) storedNormals[i]*3]); 
     normals.push_back(localNormals[(unsigned int) storedNormals[i]*3 + 1]); 
     normals.push_back(localNormals[(unsigned int) storedNormals[i]*3 + 2]); 
    } 

    return true; 
} 

主回路:

int main() 
{ 
    // Create the main window 
    sf::Window App(sf::VideoMode(SC_WIDTH, SC_HEIGHT, 32), "SFML OpenGL"); 

    // Create a clock for measuring time elapsed 
    sf::Clock Clock; 

    //output version of OpenGL to the console 
    cout<<"OpenGL version: "<<glGetString(GL_VERSION)<<endl; 

    // Create the vectors to hold the object data 
    vector<GLfloat> vertices; 
    vector<GLushort> indices; 
    vector<GLfloat> normals; 

    //Load model 
    if(!modelLoader("teapot2.obj", vertices, indices, normals)) 
    { 
     printf("Failed to load model. Make sure the .obj file has no errors."); 
     system("pause"); 
     return 0; 
    } 

    //enable the use of vertex arrays 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_NORMAL_ARRAY); 

    // tell OpenGL where the vertices are with glVertexPointer() 
    glVertexPointer(3, GL_FLOAT, 0, &vertices[0]); 
    glNormalPointer(GL_FLOAT, 0, &normals[0]); 


    //************************************************************* 
    // Set color and depth clear value 
    glClearDepth(1.f); 
    glClearColor(0.f, 0.f, 0.f, 0.f); 

    // Enable Z-buffer read and write 

    glDepthMask(GL_TRUE); 

    // Set up lighting for the scene 
    GLfloat ambient[4] = {0.f,0.5f,0.5f, 1.f}; 
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); 

    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_LIGHT0); 
    glEnable(GL_LIGHTING); 
    glEnable(GL_COLOR_MATERIAL); 

    // Setup a perspective projection 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(90.f, 1.f, 1.f, 500.f); 

    // Start game loop 
    while (App.IsOpened()) 
    { 
     // Process events 
     sf::Event Event; 
     while (App.GetEvent(Event)) 
     { 
      // Close window : exit 
      if (Event.Type == sf::Event::Closed) 
       App.Close(); 

      // Escape key : exit 
      if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape)) 
       App.Close(); 

      // Resize event : adjust viewport 
      if (Event.Type == sf::Event::Resized) 
       glViewport(0, 0, Event.Size.Width, Event.Size.Height); 
     } 

     // Set the active window before using OpenGL commands 
     // It's useless here because active window is always the same, 
     // but don't forget it if you use multiple windows or controls 
     App.SetActive(); 


     if((float)Clock.GetElapsedTime()>REFRESH_RATE){ 
      // Clear colour and depth buffer 
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

      // Apply some transformations 
      glMatrixMode(GL_MODELVIEW); 
      glLoadIdentity(); 



      glTranslatef(0.f, 0.f, -5.f); 
      glRotatef(45.f, 1.f, 1.f, 1.f); 

      glPushMatrix(); 
      //draw the triangles with glDrawArrays() and then with glDrawElements() 
      glDrawArrays(GL_TRIANGLES, 0, vertices.size()/3); 
      //glDrawElements(GL_TRIANGLES, vertices.size(), GL_UNSIGNED_SHORT, &indices[0]); 
      //glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, &indices[0]); 
      glPopMatrix(); 


      Clock.Reset(); 
     } 


     // Finally, display rendered frame on screen 
     App.Display(); 
    } 
    //delete the vertex arrays using glDisableClientState() 
    glDisableClientState(GL_VERTEX_ARRAY); 
    glDisableClientState(GL_NORMAL_ARRAY); 


    return EXIT_SUCCESS; 
} 

任何人有什么想法?

+0

[此OBJ loader](http://stackoverflow.com/a/14887071/44729)是否适合您? – genpfault 2013-03-08 17:38:48

+0

看起来我需要做一些适当的调整才能使这个工作与SFML,但我会给它一个镜头。 – MrGroggle 2013-03-08 17:49:17

+0

修正了它。使用你的代码的一部分和一些想法,我终于得到它正确绘制。非常感谢! – MrGroggle 2013-03-08 21:01:59

回答

1

OpenGL灯具有所有属性的默认值(例如,GL_AMBIENT,GL_DIFFUSE等)。在GL_LIGHT0的情况下,diffuse属性未设置为零(这是您只需获取环境光照所需的值)。为了弥补这一点,你就需要做

GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f }; 
glLightfv(GL_LIGHT0, GL_DIFFUSE, black); 

因为,IIRC,光属性的其余均为零已经,应该给你的环境,只有照明,从而消除您的灯光的方向分量。此外,glColorMaterial的默认模式为GL_AMBIENT_AND_DIFFUSE,它将环境和漫反射材质属性设置为入射顶点颜色。您也可以考虑将其切换到仅环境(glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);)。

然而,你的阴影怪异的根本原因,我认为可能是由于非单位长度的法线。在进行照明计算之前,您可以尝试添加glEnable(GL_NORMALIZE);