2

OpenGL ライティングに少し問題があります。

モデル (ユタ ティーポット) は問題なくレンダリングされていますが、奇妙な照明パターンがいくつかあります。モデルは、シーンを照らす 1 つのアンビエント ライトでフラット シェーディングする必要がありますが、ティーポット全体が斑点状のライトになってしまいます。

ティーポット イメージ

これは、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;
}

誰でも何か考えがありますか?

4

1 に答える 1

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 );照明の計算を行う前に、追加してみてください。

于 2013-03-08T17:49:00.087 に答える