OpenGL照明根据外观方向变化

时间:2016-08-26 22:08:33

标签: c++ c++11 opengl sfml

AKA我做错了什么?

我一直在搞乱OpenGL,而我现在只是想尝试点亮一个立方体。我不确定我是否理解我应该做的正确,因为当我移动相机时,立方体上的灯光会发生变化。

例如:

从上到下看立方体:

top down

从侧面看立方体:

enter image description here

通过搜索我见过的所有答案,说当正常设置不正确时会发生这种情况,但我认为它们设置正确,因为当我打印出所有顶点及其法线时,这是结果(按面部分组,按照它们绘制的顺序):

Position:  0  0  0       Normal:   -1  0  0
Position:  0 30  0       Normal:   -1  0  0
Position:  0 30 30       Normal:   -1  0  0
Position:  0  0 30       Normal:   -1  0  0

Position:  0  0  0       Normal:    0  1  0
Position:  0  0 30       Normal:    0  1  0
Position: 30  0 30       Normal:    0  1  0
Position: 30  0  0       Normal:    0  1  0

Position:  0  0  0       Normal:    0  0 -1
Position: 30  0  0       Normal:    0  0 -1
Position: 30 30  0       Normal:    0  0 -1
Position:  0 30  0       Normal:    0  0 -1

Position:  0  0 30       Normal:    0  0  1
Position:  0 30 30       Normal:    0  0  1
Position: 30 30 30       Normal:    0  0  1
Position: 30  0 30       Normal:    0  0  1

Position:  0 30  0       Normal:    0 -1  0
Position: 30 30  0       Normal:    0 -1  0
Position: 30 30 30       Normal:    0 -1  0
Position:  0 30 30       Normal:    0 -1  0

Position: 30  0  0       Normal:    1  0  0
Position: 30  0 30       Normal:    1  0  0
Position: 30 30 30       Normal:    1  0  0
Position: 30 30  0       Normal:    1  0  0

这里还有一些用于渲染的代码,以防出现错误:

RenderEngine::RenderEngine(int width, int height) {
    //initializing the window...

    glClearDepth(1.f);
    glClearColor(217.f / 256.f, 233.f / 256.f, 255.f / 256.f, 1.f);

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    glFrontFace(GL_CW);
    glEnable(GL_CULL_FACE);

    glEnable(GL_LIGHTING);

    //glEnable(GL_COLOR_MATERIAL);

    GLfloat lightPos[] = { 0.f, -1.0f, 0.0f, 0.f  };
    GLfloat ambient[] = {0.3f,0.3f,0.3f,1.0f};
    GLfloat diffuse[] = {0.7f,0.7f,0.7f,1.0f};
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glEnable(GL_LIGHT0);

    //more window related things
}

void RenderEngine::beginRender() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void RenderEngine::endRender() {
    //window stuff
}

void RenderEngine::translatePlayer(const sf::Vector3f& position) {
    glTranslatef(-(position.x + 0.5) * 30, -(position.y + 1.75)  * 30, -(position.z + 0.5) * 30);
}

void RenderEngine::rotatePlayer(const sf::Vector3f& rotation) {
    glRotatef(rotation.x, 1.f, 0.f, 0.f);
    glRotatef(rotation.y, 0.f, 1.f, 0.f);
    glRotatef(rotation.z, 0.f, 0.f, 1.f);
}

void RenderEngine::renderVertexArray(const std::vector<Vertex>& vertices) {
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &vertices[0].pos[0]);
    glColorPointer(3, GL_FLOAT, sizeof(Vertex), &vertices[0].color[0]);
    glNormalPointer(GL_FLOAT, sizeof(Vertex), &vertices[0].normal[0]);

    glDrawArrays(GL_QUADS, 0, vertices.size());

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
}

顶点对象:

struct Vertex {
    float pos[3];
    float color[3];
    float normal[3];

    Vertex(float _pos[3], float _color[3], float _normal[3]) :
        pos   {_pos[0],    _pos[1],    _pos[2]},
        color {_color[0],  _color[1],  _color[2]},
        normal{_normal[0], _normal[1], _normal[2]} {}

    Vertex() : pos{0,0,0}, color{0,0,0}, normal{0,0,0} {}
};

请忽略所有随机30。我知道那些不合适,不应该这样做,但这不是问题。

1 个答案:

答案 0 :(得分:3)

当您拨打以下电话时:

glLightfv(GL_LIGHT0, GL_POSITION, lightPos);

...然后使用当前模型视图矩阵转换传递的lightPos,然后将其存储在相机坐标中。因此,您的灯光将与相机一起移动。如果您希望它是静态的,则必须在设置模型视图矩阵后再次执行上面的行。