我正在尝试制作一个非常简单的 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/