c++ - 如何跟踪光位的变化?

标签 c++ opengl light

我正在尝试制作一个非常简单的 MFC OpenGL 教程。
有一个球体。球体是光源(如太阳)。并且有两个三角形。根据球体的运动,我想让三角形变亮。
但是当我移动球体时,三角形的表面第一次发生了变化。
球体的下一次运动不会改变三角形的表面。

如何保持光位的踪迹?
这是键盘处理函数。

void CView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if (nChar == VK_UP)
    {
        m.x += 0.1f;
    }
    else if (nChar == VK_DOWN)
    {
        m.y -= 0.1f;
    }
    else if (nChar == VK_LEFT)
    {
        m.x -= 0.1f;
    }
    else if (nChar == VK_RIGHT)
    {
        m.x += 0.1f;
    }
    setGL();
    DrawGL();
    CView::OnKeyDown(nChar, nRepCnt, nFlags);
}  

这些是键盘函数调用的函数。

void CView::setGL(GLvoid)           
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);       
    glClearDepth(1.0f); 
    glEnable(GL_DEPTH_TEST);    
    glDepthFunc(GL_LEQUAL);             
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    // light source configuration ##################
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0.f,0.f,1.f, 0.f,0.f,0.f, 0.f,1.f,0.f);

    GLfloat light0_diffuse[] = {0.5, 0.5, 1.0};
    GLfloat light0_specular[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat light0_spot_direction[] = {1,1,1,0};

    GLfloat light1_diffuse[] = {1.0f, 0.3f, 0.3f};
    GLfloat light1_specular[] = {1.0f, 0.8f, 0.8f, 1.0f};
    GLfloat light1_shiniess[] = {50.0};
    GLfloat light1_pos[] = {m.x, m.y, m.z};

    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0_spot_direction);

    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
    glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
    glLightfv(GL_LIGHT1, GL_SHININESS, light1_shiniess);
    glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
}

void CView::DrawGL(void)                
{
    // clear screen and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity();
    // camera view configuration 
    gluLookAt(0.0f,0.0f,1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);

    // draw 
    //glColor3f(1.f, 1.f, 1.f);
    glPushMatrix();
    glTranslatef(m.x, m.y, m.z);
    glutSolidSphere(0.25f, 120, 120);

    glPopMatrix();
    glBegin(GL_TRIANGLES);
    glVertex3f(-0.5f, 0.5f, -0.5f);
    glVertex3f(0.0f, 0.0f, -0.5f);
    glVertex3f(-1.0f, 0.0f, -0.5f);

    m.calculateNormal(-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -1.0f, 0.0f, -0.5f);
    glNormal3f(m.normalX, m.normalY, m.normalZ);

    glBegin(GL_TRIANGLES);
    glVertex3f(0.5f, 0.5f, -1.0f);
    glVertex3f(0.0f, 0.0f, -1.0f);
    glVertex3f(1.0f, 0.0f, -1.0f);

    m.calculateNormal(0.5f, 0.5f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f);
    glNormal3f(m.normalX, m.normalY, m.normalZ);

    glEnd();

    // swap buffer
    SwapBuffers(m_hDC);
}

最佳答案

您永远不应该在输入事件处理程序中放置绘图调用。那是你的主要问题。另一个问题是 - 看起来 - 您将 OpenGL 与场景​​图混淆了。

OpenGL 是一种绘图 API,无论如何都不会记忆场景。在您的输入处理程序中,您设置了一些变量,发出重绘事件,然后在绘图事件处理程序中从这些变量中渲染。 OpenGL 作为状态机绘图 API 也意味着没有明确的初始化阶段。类似 setGL 的函数没有任何意义。你在 setGL 做什么实际上属于绘图功能。这包括设置视口(viewport)和投影矩阵!

void CView::drawGL(GLvoid)           
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);       
    glClearDepth(1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glViewport(…);
    glMatrixMode(GL_PROJECTION);
        set_projection_matrix(…);    

    // light source configuration ##################
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); // gluLookAt expects to work from a identity matrix.
    gluLookAt(0.f,0.f,1.f, 0.f,0.f,0.f, 0.f,1.f,0.f);

    GLfloat light0_diffuse[] = {0.5, 0.5, 1.0};
    GLfloat light0_specular[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat light0_spot_direction[] = {1,1,1,0};

    GLfloat light1_diffuse[] = {1.0f, 0.3f, 0.3f};
    GLfloat light1_specular[] = {1.0f, 0.8f, 0.8f, 1.0f};
    GLfloat light1_shiniess[] = {50.0};
    GLfloat light1_pos[] = {m.x, m.y, m.z};

    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0_spot_direction);

    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
    glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
    glLightfv(GL_LIGHT1, GL_SHININESS, light1_shiniess);
    glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // draw 
    glColor3f(1.f, 1.f, 1.f);
    glPushMatrix();
    glTranslatef(m.x, m.y, m.z);
    glutSolidSphere(0.25f, 120, 120);
    glPopMatrix();

    glBegin(GL_TRIANGLES);
    glVertex3f(-0.5f, 0.5f, -0.5f);
    glVertex3f(0.0f, 0.0f, -0.5f);
    glVertex3f(-1.0f, 0.0f, -0.5f);

    m.calculateNormal(-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -1.0f, 0.0f, -0.5f);
    glNormal3f(m.normalX, m.normalY, m.normalZ);

    glBegin(GL_TRIANGLES);
    glVertex3f(0.5f, 0.5f, -1.0f);
    glVertex3f(0.0f, 0.0f, -1.0f);
    glVertex3f(1.0f, 0.0f, -1.0f);

    m.calculateNormal(0.5f, 0.5f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f);
    glNormal3f(m.normalX, m.normalY, m.normalZ);
    glEnd();

    // swap buffer
    SwapBuffers(m_hDC);
}

调用glLight…发生在当前设置状态的上下文中(对于灯光最重要的是模型 View 矩阵)。灯光位置乘以模型 View 矩阵。如果使用 gluLookAt ,你所做的,调用glLightfv(GL_LIGHT<n>, GL_POSITION, …)必须在 gluLookAt 之后发生在绘制照明几何之前。

关于c++ - 如何跟踪光位的变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7460122/

相关文章:

c++ - OpenGL不考虑GL_DIFFUSE位置光的距离

c++ - LPCSTR 和 wchar_t 问题。由于参数不匹配导致的链接器错误

c++ - strncpy 和 strcat 没有按照我认为的方式工作 C++

c++ - 着色器限制

c - OpenGL 多线程比使用单线程慢

java - 如何实现java瓦片 map 灯?

c# - 在 C# + XNA 中应用掩码?

C++ WinAPI 使用 DWM 在自定义窗口框架上显示位图

c++ - O(1) 中的 extractMin 操作使用 2 个堆栈

c++ - 如何使用控制台窗口中的输入顶点在 glut 中绘制多边形?