简体   繁体   English

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

[英]OpenGL flat shading - Strange lighting behaviour

I have a slight issue with my OpenGL lighting. 我的OpenGL照明有点问题。

It's rendering the model (Utah Teapot) just fine, but I have some weird lighting patterns. 它可以很好地渲染模型(犹他茶壶),但是我有一些奇怪的照明图案。 The model should be flat shaded with a single ambient light illuminating the scene, but I end up with splotchy light all over the teapot: 该模型应该使用单一的环境光来平淡地阴影,以照亮场景,但最终我在整个茶壶上都出现了斑点光:

茶壶图片

This is just a simple exercise to build a model loader in C++ with SFML. 这只是使用SFML在C ++中构建模型加载器的简单练习。

Code is as follows: 代码如下:

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

Main loop: 主循环:

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

Anyone got any thoughts? 有人有什么想法吗?

OpenGL lights have default values for all properties (eg, GL_AMBIENT , GL_DIFFUSE , etc.). OpenGL的灯都为所有属性(例如默认值GL_AMBIENTGL_DIFFUSE等)。 In the case of GL_LIGHT0 , the diffuse property is not set to zero (which is what you'd need to get only ambient lighting). GL_LIGHT0的情况下,漫反射属性未设置为零(这是仅需要获得环境照明的条件)。 To remedy that, you'd need to do 为了解决这个问题,您需要做

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

Since, IIRC, the rest of the light properties are zero already, that should give you ambient-only lighting, which removes the directional component of your lighting. 由于IIRC,其余的灯光属性已经为零,因此应该为您提供仅用于环境的照明,从而消除了照明的方向性分量。 Also, the default mode for glColorMaterial is GL_AMBIENT_AND_DIFFUSE , which sets both the ambient and diffuse material properties to the incoming vertex color. 此外,用于默认模式glColorMaterialGL_AMBIENT_AND_DIFFUSE ,其同时设置环境和漫射材料属性将输入顶点颜色。 You might consider switching that to ambient only ( glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT ); ) as well. 您可能还考虑将其仅切换到环境( glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT ); )。

However, the root cause of the oddity of your shading, I think is likely due to non-unit-length normals. 但是,我认为阴影的根本原因是非单位长度的法线。 You might try adding glEnable( GL_NORMALIZE ); 您可以尝试添加glEnable( GL_NORMALIZE ); before doing lighting computations. 在进行照明计算之前。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM