c++ - OpenGL光照根据观察方向改变

标签 c++ c++11 opengl sfml

也就是我做错了什么?

我一直在摆弄 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 年代。我知道这些不合适,不应该那样做,但这不是这里的问题。

最佳答案

当您调用以下内容时:

glLightfv(GL_LIGHT0, GL_POSITION, lightPos);

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

关于c++ - OpenGL光照根据观察方向改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39175271/

相关文章:

c++ - 生成 std​​::thread 时的 shared_ptr 引用计数

c++ - std::move 和 static_cast<T&&> 不同的结果

c++ - 使用 OpenGL 3.3 和 Qt 5.6 创建相机

c++ - OpenGL使用统一缓冲区作为数组

c++ - Ortho 和 Persp 正在反转 Z 深度标志?

c++ - 为什么我的 C++ 程序不计算 'e' 的更多位数?

c++ - 从字符串中替换字符

c++ - OpenGL FBO 不渲染到纹理 (C++)

c++ - 难以对 2D vector 的元素求和

C++11 Lambda 表达式作为回调函数