簡體   English   中英

OpenGL平面着色-奇怪的照明行為

[英]OpenGL flat shading - Strange lighting behaviour

我的OpenGL照明有點問題。

它可以很好地渲染模型(猶他茶壺),但是我有一些奇怪的照明圖案。 該模型應該使用單一的環境光來平淡地陰影,以照亮場景,但最終我在整個茶壺上都出現了斑點光:

茶壺圖片

這只是使用SFML在C ++中構建模型加載器的簡單練習。

代碼如下:

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

有人有什么想法嗎?

OpenGL的燈都為所有屬性(例如默認值GL_AMBIENTGL_DIFFUSE等)。 GL_LIGHT0的情況下,漫反射屬性未設置為零(這是僅需要獲得環境照明的條件)。 為了解決這個問題,您需要做

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

由於IIRC,其余的燈光屬性已經為零,因此應該為您提供僅用於環境的照明,從而消除了照明的方向性分量。 此外,用於默認模式glColorMaterialGL_AMBIENT_AND_DIFFUSE ,其同時設置環境和漫射材料屬性將輸入頂點顏色。 您可能還考慮將其僅切換到環境( glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT ); )。

但是,我認為陰影的根本原因是非單位長度的法線。 您可以嘗試添加glEnable( GL_NORMALIZE ); 在進行照明計算之前。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM