Как сохранить след изменения положения света? - PullRequest
0 голосов
/ 18 сентября 2011

Я пытаюсь сделать очень простое руководство по 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);
}

Ответы [ 2 ]

3 голосов
/ 18 сентября 2011

Вы никогда не должны помещать вызовы рисования в обработчик событий ввода. Это твоя главная проблема. Другая проблема - кажется, что вы путаете OpenGL с графом сцены.

OpenGL - это API рисования без какого-либо воспоминания о сцене. В вашем обработчике ввода вы устанавливаете некоторые переменные, запускаете событие перерисовки, а затем в обработчике события рисования отрисовываете из этих переменных. OpenGL, являющийся API рисования конечного автомата, также означает, что нет явной фазы инициализации. Функция типа setGL не имеет никакого смысла. То, что вы делаете в setGL, на самом деле относится к функции рисования. Это включает в себя настройку области просмотра и матрицы проекции!

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… происходит в контексте текущего установленного состояния (наиболее важным для источников света является матрица вида модели). Позиции освещения умножаются на матрицу вида модели. Если вы используете gluLookAt, что вы делаете, вызовы glLightfv(GL_LIGHT<n>, GL_POSITION, …) должны выполняться после gluLookAt и до рисования подсвеченной геометрии.

2 голосов
/ 18 сентября 2011
void CView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    ...
    CView::OnKeyDown(nChar, nRepCnt, nFlags);
}  

Как это не бесконечный рекурсивный вызов?Разве ваш компилятор не предупреждает вас об этом?

...