【问题标题】:OpenGL lighting changing based on look directionOpenGL光照根据观察方向变化
【发布时间】:2017-01-03 15:44:50
【问题描述】:

又是我做错了什么?

我一直在搞乱 OpenGL,现在我只是在尝试为立方体照明。我不确定我是否理解我应该正确执行的操作,因为当我四处移动相机时,立方体上的灯光会发生变化。

例如:

从上往下看立方体:

从侧面看立方体:

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

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

【问题讨论】:

  • 我了解您只是在使用 OpenGL 或在玩弄 OpenGL,但这是一些建议;我不会尝试学习 OpenGL 的旧版本,从外观上看,您使用的是 OpenGL 1.0。而且我会考虑学习从 3.3 版到当前 4.5 版的任何现代 OpenGL。这里有几个很棒的网站来学习 OpenGL learnopengl.comMarekKnows.com 第一个是 100% 现代化的,并且是基于文本的,第二个站点既有传统的也有现代的,但是是可下载的视频教程,会员价格低廉。
  • 有什么优势/值得整个项目升级吗?
  • 抱歉没有尽快回复。优点在于现代 OpenGL 着色器用于在 GPU 端而不是 CPU 端进行所有顶点处理。 GPU 在处理计算方面效率更高。此外,通过在 Legacy API 上使用现代 OpenGL,它正在远离“固定功能”管道,换句话说,使用 GLSL 着色器,顶点、几何、片段(像素)着色器和其他着色器允许程序员修改该函数管道使现代 OpenGL 成为可编程管道。
  • 那么你有两个选择,你可以尝试升级现有项目,或者只是创建一个新项目并从头开始。这将取决于您当前的项目有多远以及它有多大。如果您当前的项目非常大,那么这两种方法都有缺点:升级的缺点是重组过程并确保您不会通过大量的调试来破坏任何东西,重新开始的缺点是所涉及的时间和工作量被赶上。如果您的项目很小,那么它不会太麻烦。
  • 如果项目很大,我会开始一个新项目并复制无需更新即可工作的库和对象,并构建应用程序以使用现代 OpenGL。例如;您可能有一些独立于 OpenGL 本身的实用程序类,您恰好在其中加载图像文件以使用纹理,您可以将它们导入新引擎并稍作修改以使用新代码库。主要区别在于创建窗口和设置 OpenGL 上下文以开始渲染,以及设置使用着色器的能力。

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


【解决方案1】:

当您调用以下内容时:

glLightfv(GL_LIGHT0, GL_POSITION, lightPos);

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

【讨论】:

  • 哦,我明白了。我不知道它改变了它。看起来现在照明是静态的,但亮度有点不稳定。但我只需要使用参数来调整它。谢谢!
猜你喜欢
  • 2022-06-10
  • 2016-03-04
  • 2019-03-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-30
  • 1970-01-01
  • 2012-02-22
  • 1970-01-01
相关资源
最近更新 更多